用核心运动计算倾斜angular

我的应用程序有一个logging会话。 当用户启动logging会话时,我开始从设备的CMMotionManager对象收集数据,并将它们存储在CoreData上,以便稍后进行处理和呈现。 我收集的数据包括GPS数据,加速计数据和陀螺仪数据。 数据的频率是10Hz。

目前我正在努力计算运动数据中设备的倾斜angular度。 可以使用重力数据计算设备的哪一侧是土地,但是我想要计算用户和地面之间的左右angular度,而不pipe行进方向如何。

这个问题需要一些线性代数知识来解决。 例如,对于某点的计算,我必须计算一个计算平面上的3D线的方程。 我正在为这一天工作一天,情况越来越复杂。 我一点都不擅长math。 一些与这个问题有关的math例子也是值得赞赏的。

这取决于您想要对收集的数据进行什么操作,以及用户使用何种方式将iPhone录制在自己的口袋中。 原因在于欧拉angular是不安全的,特别是没有独特的旋转方式。 考虑一下这样的情况,用户将手机竖直放入牛仔裤后袋,然后左转90°。 因为CMAttitude与平躺在桌子上的设备有关,所以根据这张图片 ,你有两个后续的旋转(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),以获得相同的轮换,并有更多的。 所以你按下开始button,做一些花哨的旋转把手机放import袋,你有麻烦,因为你不能依靠欧拉angular度做更复杂的动作(更多的头痛在这个万向锁 😉

现在好消息是:你是对的,线性代数就可以胜任。 你可以做的是强迫你的用户把手机放在同一个位置,例如固定在右后袋中,通过build立CMDeviceMotion的重力vector的点积来计算相对于地面的angular度( g)=(x ,y,z)和位置为-Y轴(0,-1,0 的位置vectorp:

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

=> alpha = arccos(-y / 9.81)作为总angular度。 请注意,重力加速度g一直在9.81左右

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

alphaLR = arctan(x / y)

alphaFB = arctan(z / y)


[更新:]

如果您不能依靠上述公式中的(0,-1,0)等预定义位置的电话,则只能计算总angular度,而不能计算特定的αLR和alphaFB。 原因是你只有一个新坐标系的轴,你需要两个坐标系。 新的Y轴y'将被定义为平均重力vector,但是你不知道你的新的X轴,因为每个vector与y'相关将是有效的。

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

总的angular度是没有问题的,因为我们可以用平均重力vector(pX,pY,pZ)代替(0,-1,0):

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

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


还有两件事要记住:

  • 不同的人穿着不同的口袋不同的trowers。 所以即使是穿着其他衣服的同一个人,重力vector也是不同的,你可能需要某种正常化
  • CMMotionManager不能在后台工作,即用户不能按下待机button

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

有两个不同的angular度,你可能会感兴趣的CMAttitude类: 滚动沥青 。 如果您将设备想象为螺旋桨位于顶部(耳机插孔的位置)的飞机,那么如果飞机处于爬升或俯冲状态,俯仰是指飞机/设备与地面形成的angular度。 同时,如果飞机在飞机上或在中筒滚动,那么“机翼”将与地面成angular度。

(顺便说一句,有一个叫做偏航的angular度,我认为这与你的问题无关。)

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

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

更新 (基于评论):

CMAttitude对象中的姿态值是相对于地面的(即,默认参考坐标系中的Z轴垂直,即与重力相反的方向),所以您不必担心消除重力。 因此,例如,如果您将设备放置在平坦的桌面上,然后将其卷到其侧面,则CMAttitude对象的roll属性将从0变为正或负90度(±0.5pi弧度),取决于你将它滚到哪一边。 与此同时,如果你开始平躺,然后逐渐站起来,同样会发生在pitch

虽然您可以直接使用俯仰angular,俯仰angular和偏航angular,但您也可以设置不同的参考坐标系(例如“向上”的不同方向)。 要做到这一点,只需在“校准”步骤中捕捉该方向的姿态,然后使用CMAttitude的multiplyByInverseOfAttitude:方法将姿态数据转换为新的参考坐标系。

即使你的问题只提到捕捉“倾斜angular度 ”(与地面),你可能会想要捕捉3个姿态angular度中的至less2个(例如,俯仰,滚动或偏航,取决于他们在做什么),如果该设备将在一个人的口袋里,可能全部三个。 (例如,如果口袋是宽松的,该设备可以以各种方式在口袋中旋转)。但是,大部分情况下,我认为你可能只能依靠三个中的两个(除非你看到整个录音过程中的偏航)。 例如,在我的牛仔裤口袋里,手机通常几乎是垂直的。 因此,对我而言,如我所说,走路,坐着或跑步,场地会变化很多。 每当我改变我面对的方向时,滚动会有所不同。 同时,偏航不会有太大的变化(除非我做卡丁车,我不能!)。 所以我们可能会忽略偏航。

总结一下主要观点:使用这些姿态angular度,不需要做任何线性代数,也不用担心引力(当然也可以用它来做其他用途)。

更新2 (基于凯的新职位):

凯刚回答,并展示了如何使用重力和线性代数来确保你的angular度是独一无二的 。 (顺便说一下,我认为你应该把这个职位给予这个职位,)。

根据你想要做什么,你可能想要使用这个math。 如果你需要一个标准化的“谈论”方式和/或比较你的logging过程中的态度,你会想要使用线性代数和重力。 如果你只是想把它们想象出来,那么你可能仍然不愿意使用复杂性的增加。 (例如,可视化(pitch = 90,roll = 0,yaw = 0)应该与可视化相同(pitch = 0,roll = 90,yaw = 90)。)在上面的方法中,虽然可以有多种方式提到“一样”的态度,其中没有一个本身是错的 。 他们仍然会给你相对于地面的angular度。

但陀螺仪可以从一种态度的有效描述切换到另一种意味着,我上面写到的关于逃离3个部件中的2个的内容需要纠正:因此,您需要捕获所有三个部件,无论如何。 抱歉。