这取决于您想如何处理收集到的数据,以及用户将如何使用口袋里的录音 iPhone。原因是欧拉角并不安全,尤其是没有独特的方式来表达旋转。考虑这样一种情况:用户将手机直立放入牛仔裤的后袋中,然后向左转大约 90°。因为 CMAttitude 与平放在桌子上的设备相关,所以根据此您有两个后续旋转 (pitch=x, roll=y, yaw=z)picture http://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MotionEvents/MotionEvents.html#//apple_ref/doc/uid/TP40009541-CH4-SW22:
- 俯仰 +90° 使手机直立 => (90, 0, 0)
- 滚动 +90° 左转 => (90, 90, 0)
但您可以通过以下方式获得相同的位置:
- 偏航 +90° 用于向左转动手机 (0, 0, 90)
- 俯仰 -90° 使手机直立 (-90, 0, 90)
您会看到两种不同的表示形式 (90, 90, 0) 和 (-90, 0, 90) 来实现相同的旋转,而且还有更多。因此,您按下“开始”按钮,进行一些奇特的旋转以将手机放入口袋中,然后您就会遇到麻烦,因为在执行更复杂的运动时(第 10 条),您不能依赖欧拉角。万向节锁 http://en.wikipedia.org/wiki/Gimbal_lock对此更头痛;-)
现在好消息:你是对的,线性代数可以完成这项工作。您可以做的就是强制用户将手机始终放在相同的位置,例如直立固定在右后口袋中,并通过构建计算相对于地面的角度点积 http://en.wikipedia.org/wiki/Dot_product#Geometric_interpretation的重力矢量CMDeviceMotion http://developer.apple.com/library/ios/documentation/CoreMotion/Reference/CMDeviceMotion_Class/Reference/Reference.html#//apple_ref/occ/instp/CMDeviceMotion/gravity g = (x,y,z)位置向量 p 是直立位置的 -Y 轴 (0, -1, 0):
g • x = x*0 + y*(-1) + z*0 = -y = ||g||*1*cos(阿尔法)
=> 阿尔法 = 反余弦 (-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'。听起来在实践中很容易出错。
总角度没有问题,因为我们可以用平均重力矢量 (pX, pY, pZ) 替换 (0, -1, 0):
g•p = xpX + ypY + zpZ = ||g||||p||*cos(alpha) = ||g||^2*cos(alpha)
阿尔法 = 反余弦 ((xpX + ypY + z*pZ) / 9.81^2)
还有两件事要记住:
- 不同的人穿不同的裤子和不同的口袋。因此,即使同一个人穿着其他衣服,重力矢量也会不同,您可能需要某种归一化
- CMMotionManager 不在后台工作,即用户不得按下待机按钮