从坐标列表中提取运动数据

发布于 2024-11-09 01:45:22 字数 883 浏览 9 评论 0原文

我有一系列带时间戳坐标的 CSV 文件(X、Y 和 Z,单位为毫米)。从中提取运动数据的最简单方法是什么?

可测量的

信息我想提取包括以下内容:

  1. 方向变化的次数
  2. 第一个和最后一个运动的初始加速度
  3. ......以及这些运动的方位(角度)
  4. 非静止时的平均速度

理想情况下,我最终希望能够对运动模式进行分类,因此对于任何能够提出这样做​​的方法的人来说都是加分的。让我惊讶的是,我可以做到这一点的一种方法是从坐标生成运动的图片/视频,并要求人们对它们进行分类——非常欢迎关于我如何做到这一点的建议。

噪声

一个复杂的事实是读数受到噪声污染。为了克服这个问题,每次录音前都会有至少 20 秒的静止时间,这可以作为一种“噪音轮廓”。但我不确定如何实现这一点。

具体细节

如果有帮助的话,记录的运动是一个人的手在简单的抓取任务中的运动。数据是使用附在手腕上的磁性运动跟踪器生成的。另外,我使用的是 C#,但我想数学与语言无关。

编辑

赏金

对于赏金,我真的很想看到一些(伪)代码示例。

I have a series of CSV files of timestamped coordinates (X, Y, and Z in mm). What would be the simplest way to extract motion data from them?

Measurables

The information I'd like to extract includes the following:

  1. Number of direction changes
  2. Initial acceleration of the first and last movements
  3. ...and the bearing (angle) of these movements
  4. Average speed whilst non-stationary

Ideally, I'd eventually like to be able to categorise patterns of motion, so bonus points for anyone who can suggest a way of doing this. It strikes me that one way I could do this would be to generate pictures/videos of the motion from the coordinates and ask humans to categorise them - suggestions as to how I'd do this are very welcome.

Noise

A complication is the fact that the readings are polluted with noise. In order to overcome this, each recording is prefaced with at least 20 seconds of stillness which can serve as a sort of "noise profile". I'm not sure how to implement this though.

Specifics

If it helps, the motion being recorded is that of a persons hand during a simple grabbing task. The data is generated using a magnetic motion tracker attached to the wrist. Also, I'm using C#, but I guess the maths is language agnostic.

Edits

Bounty

For the bounty, I'd really like to see some (pseudo-)code examples.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心的位置 2024-11-16 01:45:22

让我们看看可以用您的示例数据做什么。

免责声明:我没有阅读您的硬件规格(tl;dr:))

为了方便起见,我将在 Mathematica 中解决这个问题。相关算法(不多)将作为链接提供。

第一个观察结果是,所有测量在时间上都是等间隔的,这对于简化方法和算法来说是最方便的。我们将方便地表示“时间”或“刻度”(测量),因为它们是等效的。

让我们首先按轴绘制您的位置,看看问题是什么:

(* This is Mathematica code, don't mind, I am posting this only for 
   future reference *)
ListPlot[Transpose@(Take[p1[[All, 2 ;; 4]]][[1 ;;]]), 
 PlotRange -> All,
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Position (X,Y,Z)", Medium, Bold]}]

在此处输入图像描述

现在,

  • 有 两个观察结果:运动从刻度 1000 左右开始
  • 您的运动不是从 {0,0,0} 开始,

因此,我们将稍微转换您的数据,减去零位置并从刻度 950 开始。

ListLinePlot[
 Drop[Transpose@(x - Array[Mean@(x[[1 ;; 1000]]) &, Length@x]), {}, 950], 
 PlotRange -> All,
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Position (X,Y,Z)", Medium, Bold]}]

在此处输入图像描述

由于曲线有足够的噪声破坏计算,我们将其与 高斯内核对其进行降噪:

kern = Table[Exp[-n^2/100]/Sqrt[2. Pi], {n, -10, 10}];
t = Take[p1[[All, 1]]];
x = Take[p1[[All, 2 ;; 4]]];

x1 = ListConvolve[kern, #] & /@ 
   Drop[Transpose@(x - Array[Mean@(x[[1 ;; 1000]]) &, Length@x]), {}, 
    950];

enter image此处描述

因此,您可以在下面看到原始和平滑后的轨迹:

在此处输入图像描述

在此处输入图像描述

现在我们准备对速度和加速度进行导数。我们将对一阶和二阶导数使用四阶近似。我们还将像以前一样使用高斯核对它们进行平滑:

Vel = ListConvolve[kern, #] & /@ 
   Transpose@
    Table[Table[(-x1[[axis, i + 2]] + x1[[axis, i - 2]] - 
         8 x1[[axis, i - 1]] + 
         8 x1[[axis, i + 1]])/(12 (t[[i + 1]] - t[[i]])), {axis, 1, 3}], 
    {i, 3, Length[x1[[1]]] - 2}];

Acc = ListConvolve[kern, #] & /@ 
   Transpose@
    Table[Table[(-x1[[axis, i + 2]] - x1[[axis, i - 2]] + 
         16 x1[[axis, i - 1]] + 16 x1[[axis, i + 1]] - 
         30 x1[[axis, i]])/(12 (t[[i + 1]] - t[[i]])^2), {axis, 1,  3}], 
   {i, 3, Length[x1[[1]]] - 2}];

然后我们绘制它们:

Show[ListLinePlot[Vel,PlotRange->All,
     AxesLabel->{Style["Ticks",Medium,Bold],
                 Style["Velocity (X,Y,Z)",Medium,Bold]}],
    ListPlot[Vel,PlotRange->All]]

Show[ListLinePlot[Acc,PlotRange->All,
     AxesLabel->{Style["Ticks",Medium,Bold],
                 Style["Acceleation (X,Y,Z)",Medium,Bold]}],
     ListPlot[Acc,PlotRange->All]]

在此处输入图像描述
在此处输入图像描述

现在,我们还有速度和加速度模数:

ListLinePlot[Norm /@ (Transpose@Vel), 
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Speed Module", Medium, Bold]}, 
 Filling -> Axis]
ListLinePlot[Norm /@ (Transpose@Acc), 
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Acceleration Module", Medium, Bold]},
 Filling -> Axis]       

在此处输入图像描述
在此处输入图像描述

标题,作为速度的方向:

Show[Graphics3D[
 {Line@(Normalize/@(Transpose@Vel)),
 Opacity[.7],Sphere[{0,0,0},.7]},
 Epilog->Inset[Framed[Style["Heading",20],
        Background->LightYellow],{Right,Bottom},{Right,Bottom}]]]

在此处输入图像描述

我认为这足以让您开始。如果您在计算特定参数时需要帮助,请告诉我。

哈!

编辑

举个例子,假设您要计算手不静止时的平均速度。因此,我们选择速度超过截止值的所有点(例如 5),并计算平均值:

Mean@Select[Norm /@ (Transpose@Vel), # > 5 &]
-> 148.085

该幅度的单位取决于您的时间单位,但我没有在任何地方看到它们指定。

请注意,截止速度并不“直观”。您可以通过绘制平均速度与截止速度的关系来搜索适当的值:

ListLinePlot[
 Table[Mean@Select[Norm /@ (Transpose@Vel), # > h &], {h, 1, 30}], 
 AxesLabel -> {Style["Cutoff Speed", Medium, Bold], 
               Style["Mean Speed", Medium, Bold]}]

在此处输入图像描述

所以您会看到 5 是一个合适的值。

Let's see what can be done with your example data.

Disclaimer: I didn't read your hardware specs (tl;dr :))

I'll work this out in Mathematica for convenience. The relevant algorithms (not many) will be provided as links.

The first observation is that all your measurements are equally spaced in time, which is most convenient for simplifying the approach and algorithms. We will represent "time" or "ticks" (measurements) on our convenience, as their are equivalent.

Let's first plot your position by axis, to see what the problem is about:

(* This is Mathematica code, don't mind, I am posting this only for 
   future reference *)
ListPlot[Transpose@(Take[p1[[All, 2 ;; 4]]][[1 ;;]]), 
 PlotRange -> All,
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Position (X,Y,Z)", Medium, Bold]}]

enter image description here

Now, two observations:

  • Your movement starts around tick 1000
  • Your movement does not start at {0,0,0}

So, we will slightly transform your data subtracting a zero position and starting at tick 950.

ListLinePlot[
 Drop[Transpose@(x - Array[Mean@(x[[1 ;; 1000]]) &, Length@x]), {}, 950], 
 PlotRange -> All,
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Position (X,Y,Z)", Medium, Bold]}]

enter image description here

As the curves have enough noise to spoil the calculations, we will convolve it with a Gaussian Kernel to denoise it:

kern = Table[Exp[-n^2/100]/Sqrt[2. Pi], {n, -10, 10}];
t = Take[p1[[All, 1]]];
x = Take[p1[[All, 2 ;; 4]]];

x1 = ListConvolve[kern, #] & /@ 
   Drop[Transpose@(x - Array[Mean@(x[[1 ;; 1000]]) &, Length@x]), {}, 
    950];

enter image description here

So you can see below the original and smoothed trajectories:

enter image description here

enter image description here

Now we are ready to take Derivatives for the Velocity and Acceleration. We will use fourth order approximants for the first and second derivative. We also will smooth them using a Gaussian kernel, as before:

Vel = ListConvolve[kern, #] & /@ 
   Transpose@
    Table[Table[(-x1[[axis, i + 2]] + x1[[axis, i - 2]] - 
         8 x1[[axis, i - 1]] + 
         8 x1[[axis, i + 1]])/(12 (t[[i + 1]] - t[[i]])), {axis, 1, 3}], 
    {i, 3, Length[x1[[1]]] - 2}];

Acc = ListConvolve[kern, #] & /@ 
   Transpose@
    Table[Table[(-x1[[axis, i + 2]] - x1[[axis, i - 2]] + 
         16 x1[[axis, i - 1]] + 16 x1[[axis, i + 1]] - 
         30 x1[[axis, i]])/(12 (t[[i + 1]] - t[[i]])^2), {axis, 1,  3}], 
   {i, 3, Length[x1[[1]]] - 2}];

And the we plot them:

Show[ListLinePlot[Vel,PlotRange->All,
     AxesLabel->{Style["Ticks",Medium,Bold],
                 Style["Velocity (X,Y,Z)",Medium,Bold]}],
    ListPlot[Vel,PlotRange->All]]

Show[ListLinePlot[Acc,PlotRange->All,
     AxesLabel->{Style["Ticks",Medium,Bold],
                 Style["Acceleation (X,Y,Z)",Medium,Bold]}],
     ListPlot[Acc,PlotRange->All]]

enter image description here
enter image description here

Now, we also have the speed and acceleration modulus:

ListLinePlot[Norm /@ (Transpose@Vel), 
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Speed Module", Medium, Bold]}, 
 Filling -> Axis]
ListLinePlot[Norm /@ (Transpose@Acc), 
 AxesLabel -> {Style["Ticks", Medium, Bold], 
               Style["Acceleration Module", Medium, Bold]},
 Filling -> Axis]       

enter image description here
enter image description here

And the Heading, as the direction of the Velocity:

Show[Graphics3D[
 {Line@(Normalize/@(Transpose@Vel)),
 Opacity[.7],Sphere[{0,0,0},.7]},
 Epilog->Inset[Framed[Style["Heading",20],
        Background->LightYellow],{Right,Bottom},{Right,Bottom}]]]

enter image description here

I think this is enough to get you started. let me know if you need help in calculating a particular parameter.

HTH!

Edit

Just as an example, suppose you want to calculate the mean speed when the hand is not at rest. so, we select all points whose speed is more than a cutoff, for example 5, and calculate the mean:

Mean@Select[Norm /@ (Transpose@Vel), # > 5 &]
-> 148.085

The units for that magnitude depend on your time units, but I don't see them specified anywhere.

Please note that the cutoff speed is not "intuitive". You can search an appropriate value by plotting the mean speed vs the cutoff speed:

ListLinePlot[
 Table[Mean@Select[Norm /@ (Transpose@Vel), # > h &], {h, 1, 30}], 
 AxesLabel -> {Style["Cutoff Speed", Medium, Bold], 
               Style["Mean Speed", Medium, Bold]}]

enter image description here

So you see that 5 is an appropriate value.

春庭雪 2024-11-16 01:45:22

解决方案可以像状态机一样简单,其中每个状态代表一个方向。运动序列由方向序列表示。仅当传感器的方向不随运动而变化时,此方法才有效,否则在计算方向序列之前,您需要一种将运动转换为正确方向的方法。

另一方面,你可以使用各种人工智能技术,尽管我不知道你到底会使用什么。

要获取任意两个坐标之间的速度:

               _________________________________
Avg Speed =   /(x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2
            --------------------------------------
                 (t2-t1)

要获取整个运动的平均速度,假设您有 100 个带时间戳的坐标,请使用上面的公式计算 99 个速度值。然后将所有速度相加,然后除以速度数 (99)

为了得到加速度,需要三个时刻的位置,或者两个时刻的速度。

Accel X = (x3 - 2*x + x1) / (t3 - t2)
Accel Y = (y3 - 2*y + y1) / (t3 - t2)
Accel Z = (z3 - 2*z + z1) / (t3 - t2)

e solution could be as simple as a state machine, where each state represents a direction. Sequences of movements are represented by sequences of directions. This approach would only work if the orientation of the sensor doesn't change with respect to the movements, otherwise you'll need a method of translating the movements into the correct orientation, before calculating sequences of directions.

On the other end, you could use various AI techniques, although exactly what you'd use is beyond me.

To get the speed between any two coordinates:

               _________________________________
Avg Speed =   /(x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2
            --------------------------------------
                 (t2-t1)

To get the average speed for the whole motion, say you have 100 timestamped coordinates, use the above equation to calculate 99 speed values. Then sum all the speeds, and divide by the number of speeds (99)

To get the acceleration, the location at three moments is required, or the velocity at two moments.

Accel X = (x3 - 2*x + x1) / (t3 - t2)
Accel Y = (y3 - 2*y + y1) / (t3 - t2)
Accel Z = (z3 - 2*z + z1) / (t3 - t2)
沦落红尘 2024-11-16 01:45:22

注意:这一切都假设每轴计算:我没有两轴粒子运动的经验。

如果您首先将位置测量转换为速度测量,那么您会更轻松地完成此操作。

第一步:消除噪音。正如你所说,每段录音都有 20 秒的静止时间。因此,要找到实际测量值,请搜索位置不发生变化的 20 秒间隔。然后,直接进行测量。

第二步:使用以下公式计算速度:(x2 - x1)/(t2 - t1);斜率公式。该间隔应与录音的间隔相匹配。

计算:

方向改变:

方向改变发生在加速度为零的地方。使用数值积分来找到这些时间。从0开始积分,直到积分结果为零。记录一下这次。然后,从上一次开始积分,直到再次为零。重复直到到达数据末尾。

初始加速度:

再次使用斜率公式计算得出,用 v 代替 x

平均速度:

平均速度公式就是斜率公式。 x1 和 t1 应对应于第一个读数,x2 和 t2 应对应于最终读数。

Note: This all assumes per axis calculations: I have no experience with two-axis particle motion.

You will have a much easier time with this if you first convert your position measurements to velocity measurements.

First step: Remove the noise. As you said, each recording is prefaced with 20 seconds of stillness. So, to find the actual measurements, search for 20 second intervals where the position doesn't change. Then, take the measurement directly after.

Second step: Calculate velocities using: (x2 - x1)/(t2 - t1); the slope formula. The interval should match the interval of the recordings.

Calculations:

Direction change:

A direction change occurs where the acceleration is zero. Use numeric integration to find these times. Integrate from 0 until a time when the result of the integration is zero. Record this time. Then, integrate from the previous time until you get zero again. Repeat until you hit the end of the data.

Initial accelerations:

These are found using the slope formula again, substituting v for x.

Average speed:

The average speed formula is the slope formula. x1 and t1 should correspond to the first reading, and x2 and t2 should correspond to the final reading.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文