用核心运动计算精益角度

时间:2012-07-20 09:20:21

标签: iphone ios math linear-algebra core-motion

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

目前我正在努力用运动数据计算设备的倾斜角度。可以通过使用重力数据来计算设备的哪一侧着陆,但我想计算用户与地面之间的左右角度而不管行进方向。

这个问题需要一些线性代数知识才能解决。例如,对于某些点的计算,我必须计算计算平面上的3D线的方程。我正在为这一天工作一天,而且变得越来越复杂。我根本不擅长数学。一些与此问题相关的数学例子也很受欢迎。

2 个答案:

答案 0 :(得分:10)

这取决于您想要对收集的数据做什么,以及用户将哪些方式用于将iPhone录制在她/她的口袋中。原因是欧拉角不安全,尤其没有表达旋转的独特方式。考虑一种情况,用户将手机直立放入牛仔裤的后袋,然后向左转90°。因为CMAttitude与平躺在桌面上的设备相关,所以根据此picture,您有两个后续旋转(pitch = x,roll = y,yaw = z):

  • 音高+ 90°,让手机竖立=> (90,0,0)
  • 滚动+ 90°左转=> (90,90,0)

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

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

你会看到两个不同的表示(90,90,0)和(-90,0,90)来获得相同的旋转,并且它们中有更多。所以你按下“开始”按钮,进行一些花哨的旋转将手机放入口袋,你就会遇到麻烦,因为在进行更复杂的动作时你不能依赖欧拉角(s gimbal lock对此有更多的麻烦; - )

现在好消息:你是正确的线性代数将完成这项工作。您可以做的是强迫您的用户将手机放在相同的位置,例如直立固定在右后袋中并通过构建dot product g =(x,y,z)CMDeviceMotion来计算相对于地面的角度>和位置向量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

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

alphaLR = arctan(x / y)

alphaFB = arctan(z / y)


<强> [UPDATE:]

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

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

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

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

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


还要记住两件事:

  • 不同的人穿着不同口袋的不同的抹布。因此,即使对于穿着其他衣服的同一个人,重力矢量也会不同,你可能需要某种规范化
  • CMMotionManager无法在后台运行,即用户不得按下待机按钮

答案 1 :(得分:4)

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

您可能对CMAttitude类感兴趣有两个不同的角度: roll pitch 。如果您将设备想象为顶部有螺旋桨的飞机(耳机插孔所在的位置),则俯仰是指飞机在爬升或俯冲时平面/设备与地面形成的角度。与此同时,如果飞机正在倾斜或处于中间滚动状态,则滚动是“机翼”与地面形成的角度。

(顺便说一句,还有一个叫做 yaw 的第三个角度,我认为与你的问题无关。)

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

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

更新(根据评论):

CMAttitude物体中的姿态值是相对于地面的(即,默认参考框架的Z轴是垂直的,指向与重力相反的方向),所以你不要不得不担心抵消重力。因此,例如,如果您将设备放在平坦的桌面上,然后将其向上滚动到侧面,则CMAttitude对象的roll属性将从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个的问题需要纠正:因此,你需要捕获这三个组成部分,无论如何。抱歉。