这取决于您希望如何使用收集的数据以及用户将如何携带记录iPhone。原因是欧拉角不是安全的,特别是不是唯一表示旋转的方式。考虑这样一种情况,用户将手机竖直放入牛仔裤后口袋,然后向左旋转90度。因为CMAttitude与设备平放在桌子上有关,所以根据此
picture,您需要两个连续的旋转(pitch=x, roll=y, yaw=z)来表示:
- pitch +90°,使手机竖立 => (90, 0, 0)
- roll +90°,向左旋转 => (90, 90, 0)
但是您也可以通过以下方式获得相同的位置:
- yaw +90°,向左旋转手机 (0, 0, 90)
- pitch -90°,使手机竖立 (-90, 0, 90)
你会看到两种不同的表示方法 (90, 90, 0) 和 (-90, 0, 90) 来实现相同的旋转,还有更多。所以当你按下开始按钮,进行一些花哨的旋转将手机放入口袋时,你可能会遇到麻烦,因为在进行更复杂的运动时不能依靠欧拉角(参见
万向节锁以获得更多头痛;-))。
现在好消息是:你说得对,线性代数可以完成这项工作。你可以强制用户将手机放在相同的位置,例如右后口袋内垂直固定,并通过构建
点积从
CMDeviceMotiong = (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'。在实践中,这听起来相当容易出错。
总角度没有问题,因为我们可以用平均重力向量(pX,pY,pZ)替换(0,-1,0):
g•p = xpX + ypY + zpZ = ||g||||p||*cos(alpha) = ||g||^2*cos(alpha)
alpha = arccos ((xpX + ypY + z*pZ) / 9.81^2)
还有两件事情需要记住:
- 不同的人穿着不同的裤子,带有不同的口袋。因此,即使是同一个人穿其他衣服,重力向量也会有所不同,您可能需要一些归一化处理。
- CMMotionManager不在后台工作,即用户不能按下待机按钮。