这取决于您想对收集的数据做什么,以及用户将如何使用她/他的口袋里的录音 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 在后台不起作用,即用户不得按下待机按钮