8

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

可衡量的

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

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

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

噪音

一个复杂的事实是读数被噪音污染。为了克服这一点,每个录音都以至少 20 秒的静止开始,这可以作为一种“噪音分布”。我不确定如何实现这一点。

细节

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

编辑

赏金

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

4

3 回答 3

7

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

免责声明:我没有阅读您的硬件规格(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];

在此处输入图像描述

所以你可以在下面看到原始和平滑的轨迹:

在此处输入图像描述

在此处输入图像描述

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

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 是一个合适的值。

于 2011-05-30T00:40:47.247 回答
1

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

另一方面,您可以使用各种 AI 技术,尽管您将使用的具体内容超出了我的范围。

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

               _________________________________
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)
于 2011-05-21T16:32:53.027 回答
0

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

如果您首先将位置测量值转换为速度测量值,您将在此过程中轻松得多。

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

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

计算:

方向变化:

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

初始加速度:

这些是再次使用斜率公式找到的,代替v.x

平均速度:

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

于 2011-05-21T17:01:26.907 回答