7

我的申请有一个记录会话。当用户开始记录会话时,我开始从设备的 CMMotionManager 对象中收集数据并将它们存储在 CoreData 上以供稍后处理和呈现。我正在收集的数据包括 gps 数据、加速度计数据和陀螺仪数据。数据频率为10Hz。

目前我正在努力用运动数据计算设备的倾斜角度。可以使用重力数据计算设备的哪一侧是陆地,但我想计算用户与地面之间的右角或左角,无论行进方向如何。

这个问题需要一些线性代数知识来解决。例如,对于某个点的计算,我必须在计算平面上计算 3D 线的方程。我正在研究这个一天,它变得越来越复杂。我一点也不擅长数学。一些与该问题相关的数学示例也值得赞赏。

4

2 回答 2

10

这取决于您想对收集的数据做什么,以及用户将如何使用她/他的口袋里的录音 iPhone。原因是欧拉角不是安全的,尤其是没有唯一的方式来表达旋转。考虑这样一种情况,用户将手机直立放入牛仔裤的后口袋,然后向左转约 90°。因为 CMAttitude 与平放在桌子上的设备有关,所以根据这张图片,您有两个后续旋转 (pitch=x, roll=y, yaw=z) :

  • 俯仰 +90° 让手机直立 => (90, 0, 0)
  • roll +90° 左转 => (90, 90, 0)

但是您可以通过以下方式获得相同的位置:

  • yaw +90° 左转手机 (0, 0, 90)
  • 俯仰 -90° 使手机直立 (-90, 0, 90)

您会看到两种不同的表示 (90, 90, 0) 和 (-90, 0, 90) 用于获得相同的旋转,并且还有更多。所以你按下开始按钮,做一些花哨的旋转把手机放进口袋里,你就有麻烦了,因为在做更复杂的动作时你不能依赖欧拉角(s.万向节锁更让人头疼;-)

现在好消息:你说得对,线性代数可以胜任。您可以做的是强迫您的用户将手机始终放在相同的位置,例如直立固定在右后袋中,并通过构建来自 CMDeviceMotion g = (x , y, z)和位置向量 p,它是 -Y 轴 (0, -1, 0) 在直立位置:

g • x = x*0 + y*(-1) + z*0 = -y = ||g||*1*cos (alpha)

=> alpha = arccos (-y/9.81)作为总角度。请注意,重力加速度 g 始终约为 9.81

为了获得左右倾斜角度和前后角度,我们使用切线:

alphaLR = arctan (x/y)

alphaFB = arctan (z/y)


[更新:]

如果您不能将手机置于上述等式中的 (0, -1, 0) 之类的预定义位置,则只能计算总角度,而不能计算特定的 alphaLR 和 alphaFB。原因是你只有一个新坐标系的轴,你需要其中的两个。然后,新的 Y 轴y'将被定义为平均重力矢量,但您不知道新的 X 轴,因为垂直于 y' 的每个矢量都是有效的。

因此,您必须提供更多信息,例如让用户在一个方向上走更长的距离而不偏离,并使用 GPS 和磁力计数据来获得第二轴 z'。在实践中听起来很容易出错。

总角度没有问题,因为我们可以将 (0, -1, 0) 替换为平均重力矢量 (pX, pY, pZ):

g•p = x pX + y pY + z pZ = ||g|| ||p||*cos(alpha) = ||g||^2*cos(alpha)

alpha = arccos ((x pX + y pY + z*pZ) / 9.81^2)


还有两点要记住:

  • 不同的人穿不同的裤子,不同的口袋。因此,即使对于同一个人穿着其他衣服,重力矢量也会有所不同,您可能需要某种归一化
  • CMMotionManager 在后台不起作用,即用户不得按下待机按钮
于 2012-07-25T13:15:27.663 回答
4

如果我理解您的问题,我认为您有兴趣了解您的设备的态度。您可以使用从对象attitude属性中获得的对象CMDeviceMotion属性来执行此操作。 deviceMotionCMMotionManager

您可能对CMAttitude课程感兴趣的两个不同角度: rollpitch。如果您将您的设备想象成一架螺旋桨位于顶部(耳机插孔所在的位置)的飞机,那么俯仰是飞机/设备在飞机爬升或俯冲时与地面形成的角度。同时,侧倾是“机翼”与地面形成的角度,如果飞机要倾斜或处于中桶侧倾状态。

(顺便说一句,我认为第三个角度称为偏航与您的问题无关。)

角度将以弧度给出,但如果这是您想要的,将它们转换为度数很容易(乘以 180,然后除以pi)。

假设我明白你想要什么,好消息是你可能不需要了解任何线性代数来捕捉和使用这些角度。(如果我遗漏了什么,请澄清,我很乐意提供进一步的帮助。)

更新(基于评论):

对象中的姿态值CMAttitude是相对于地面的(即默认参考系的 Z 轴是垂直的,即指向与重力相反的方向),因此您不必担心抵消重力。因此,例如,如果您将设备放在平坦的桌面上,然后将其卷到一边,rollCMAttitude 对象的属性将从 0 变为正负 90 度(+- .5pi 弧度),具体取决于你把它滚到哪一边。同时,如果您开始将其平放,然后逐渐将其竖起,则pitch财产也会发生同样的情况。

虽然您可以根据需要直接使用俯仰角、滚动角和偏航角,但您也可以设置不同的参考系(例如,“向上”的不同方向)。为此,只需在“校准”步骤中捕获该方向的姿态,然后使用 CMAttitude 的 multiplyByInverseOfAttitude:方法将您的姿态数据转换为新的参考系。

即使您的问题仅提到捕获“倾斜角度" (与地面),您可能希望捕获 3 个姿态角中的至少 2 个(例如,俯仰和滚动或偏航,取决于它们在做什么),如果设备要在一个人的口袋里。(例如,如果口袋是宽松的,该设备可以在口袋中以各种方式旋转。)不过,在大多数情况下,我认为你可能只能依赖三个中的两个(除非您会在整个录音过程中看到偏航的根本变化)。例如,在我的牛仔裤口袋里,电话通常几乎是垂直的。因此,对我来说,当我走路、坐着时,音高会发生很大变化或跑步。每当我改变我面对的方向时,滚动都会改变。同时,偏航不会有太大变化(除非我做卡丁车,我不能!)。所以偏航对我来说可能可以忽略不计。

总结要点:要使用这些姿态角,您不需要做任何线性代数,也不需要担心重力(当然,您可能希望将其用于其他目的)。

更新 2(基于 Kay 的新帖子):

Kay 刚刚回答并展示了如何使用重力和线性代数来确保您的角度是唯一的。(而且,顺便说一句,我认为你应该给那个帖子赏金,fwiw。)

根据您想要做的事情,您可能想要使用这个数学。如果您需要一种标准化的方式来“谈论”和/或在录音过程中比较态度,您会想要使用线性代数和重力。如果您只是想将它们可视化,您可能仍然可以不使用增加的复杂性。(例如,可视化 (pitch=90, roll=0, yaw=0) 应该与可视化 (pitch=0, roll=90, yaw=90) 相同。)在我上面的方法中,虽然您可以有多种方法提到“相同”的态度,它们本身实际上都没有。他们仍然会给你相对于地面的角度。

但是陀螺仪可以从一种有效的姿态描述切换到另一种这一事实意味着我在上面写的关于仅使用 3 个组件中的 2 个就可以逃脱的事实需要更正:因此,您将需要捕获所有三个组件,无论如何。对不起。

于 2012-07-23T03:04:43.887 回答