从坐标列表中提取运动数据
Posted
技术标签:
【中文标题】从坐标列表中提取运动数据【英文标题】:Extracting motion data from a list of coordinates 【发布时间】:2011-08-30 06:59:15 【问题描述】:我有一系列带时间戳的坐标(X、Y 和 Z,单位为毫米)的 CSV 文件。从中提取运动数据的最简单方法是什么?
可衡量的
我想提取的信息包括:
-
换向次数
第一个和最后一个动作的初始加速度
...以及这些运动的方位(角度)
非静止时的平均速度
理想情况下,我最终希望能够对运动模式进行分类,因此任何可以提出这样做的方法的人都会获得奖励积分。让我感到震惊的是,我可以做到这一点的一种方法是从坐标生成运动的图片/视频,并要求人类对其进行分类 - 关于我如何做到这一点的建议非常受欢迎。
噪音
一个复杂的事实是读数被噪音污染。为了克服这一点,每个录音都以至少 20 秒的静止作为开头,这可以作为一种“噪声配置文件”。不过我不确定如何实现。
细节
如果有帮助,记录的动作是人手在简单抓取任务中的动作。数据是使用附在手腕上的磁性运动跟踪器生成的。另外,我使用的是 C#,但我猜数学与语言无关。
编辑
磁跟踪器规格:http://www.ascension-tech.com/realtime/RTminiBIRD500_800.php 样本数据文件:http://tdwright.co.uk/sample.csv赏金
对于赏金,我真的很想看看一些(伪)代码示例。
【问题讨论】:
您想获取每个轴的运动信息吗? 啊,对不起。正如你回复的那样,我删除了我以前的 cmets。 别担心,您的改写很有用。想一想,我只真正关心 XY 平面中的运动 - 原点上方/下方的高度不太有趣。 好的。您想分别检测 x 轴和 y 轴的运动变化吗?或者,您想检测直线运动的推导(即同时考虑 x 轴和 y 轴) 根据我对录音的观察,似乎同时考虑两者会更好:通常方向变化非常微妙。 【参考方案1】:让我们看看可以用您的示例数据做什么。
免责声明:我没有阅读您的硬件规格 (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]]
由于曲线有足够的噪声破坏计算,我们将其与Gaussian Kernel 进行卷积以对其进行去噪:
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];
所以你可以在下面看到原始和平滑的轨迹:
现在我们已经准备好对速度和加速度进行导数了。我们将使用fourth order approximants 作为一阶和二阶导数。我们还将像以前一样使用高斯核对它们进行平滑:
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]
以及Heading,作为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]]]
我认为这足以让您入门。如果您在计算特定参数时需要帮助,请告诉我。
HTH!
编辑
举个例子,假设您想计算手不静止时的平均速度。因此,我们选择所有速度大于截止点的点,例如 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 是一个合适的值。
【讨论】:
很好的答案,但你已经成功地引起了一些严重的 Mathematica 嫉妒!打算尝试为 C# 找到一个好的高斯核算法... @Tom 高斯过滤器是一个不错的过滤器,但也许其他过滤器也可以。不要被它困住。 我认为贝利撒留真的应该得到赏金! @gpu_drug 我完全同意。谢谢@belisarius! @Tom 感谢您的赏金。如果您需要进一步说明,请告诉我【参考方案2】:e 解决方案可以像状态机一样简单,其中每个状态代表一个方向。运动序列由方向序列表示。这种方法只有在传感器的方向不随运动改变时才有效,否则在计算方向序列之前,您需要一种将运动转换为正确方向的方法。
另一方面,您可以使用各种 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)
【讨论】:
速度总是标量。速度是一个向量。 规范是一个冗长而枯燥的文档——你想要什么信息?如果有帮助,我会上传一个示例数据文件。 如果起点和终点相同,您的平均速度(可以进一步推广到包括 z 坐标)将不起作用。它可以应用于每一步(坐标对),但这仍然不能解释不运动的时刻。【参考方案3】:注意:这一切都假设每轴计算:我没有两轴粒子运动的经验。
如果您首先将位置测量值转换为速度测量值,您会更轻松地完成此操作。
第一步:去除噪音。正如你所说,每段录音都以 20 秒的静止开始。因此,要找到实际测量值,请搜索位置不变的 20 秒间隔。然后,直接进行测量。
第二步:计算速度使用:(x2 - x1)/(t2 - t1);斜率公式。间隔应与录音的间隔相匹配。
计算:
方向变化:
方向改变发生在加速度为零的地方。使用数值积分来查找这些时间。从 0 开始积分,直到积分结果为零。记录这一次。然后,从上一次积分直到再次归零。重复直到到达数据的末尾。
初始加速度:
再次使用斜率公式找到这些,将v
替换为x
。
平均速度:
平均速度公式是斜率公式。 x1 和 t1 应该对应第一个读数,x2 和 t2 应该对应最终读数。
【讨论】:
就像我说的,这不适用于二维运动。希望比我更擅长数学的人可以将其应用于二维运动:)以上是关于从坐标列表中提取运动数据的主要内容,如果未能解决你的问题,请参考以下文章