使用CMDeviceMotion和CMAttitude隔离垂直或水平加速度

我试图隔离垂直或水平的加速度分量,假设设备的方向可能会不断变化。

在使用陀螺仪数据和CMAttitude之前,这是不可能的,因为我们只有加速度数据。 既然加速度是通过CMAttitude进行的用户加速度和方向,似乎应该可以通过姿态数据来调整加速度数据,以隔离特定的加速度绝对方向。 这与使用参考框架有点不同,因为我期望设备方向不断变化。 认为臂章等…在我的情况下,

我希望能够捕获严格垂直或严格水平的加速度值,而不pipe设备方向如何变化。 这个几何是比我稍微多一点,我会很感激一些build议。

我不熟悉iOS API,但是我可以给出math答案。

  1. 用陀螺仪+加速度计传感器融合确定方向。 我希望iOS有一个API,因为它相对复杂(如果不让我们知道,我会详细说明)。 这似乎就是你所说的CMAttitude。 方向应表示为四元数或matrix,它表示固定参考帧(最可能是东北向下,但取决于API)和附加到设备的本地参考帧之间的旋转。
  2. 从加速度计(在本地参考坐标系中)读取vector,并以相反的方向旋转它。 旋转的反面是四元数共轭或matrix转置。 旋转vector是通过四元数乘法或matrix乘法完成的。 这给你在固定参考系中的加速度vector。
  3. 固定参考系中加速度的Z分量是垂直加速度。 XY分量(sqrt(x ^ 2 + y ^ 2))的范数是水平加速度。 不要忘记从垂直加速度中减去重力。 这再次假设了一个东北向下的参考系,但是大多数其他的固定参考系只需要你适当地交换X,Y,Z。

如果iOS拥有正确的API,那么实现将是微不足道的。 如果你有select更喜欢四元数matrix,因为执行速度会更快。 让我们知道怎么回事。

我刚刚实现了marcv81的答案。

-(void)isolateHorizontalMotionFromMotionData:(CMDeviceMotino *)newMotion { //Quaternion Conjugation CMQuaternion quaternion = newMotion.attitude.quaternion; GLKQuaternion original_quaternion = GLKQuaternionMake(quaternion.x, quaternion.y, quaternion.z, quaternion.w); GLKQuaternion conjugated_quaternion = GLKQuaternionConjugate(original_quaternion); //Rotation of Accelerometer vector with quanternion GLKVector3 acceleromationVector = GLKVector3Make(newMotion.userAcceleration.x, newMotion.userAcceleration.y, newMotion.userAcceleration.z); GLKVector3 accelerometionVector_toReferenceFrame = GLKQuaternionRotateVector3(conjugated_quaternion, acceleromationVector); //Horizontal Acceleration float horizontalAcceleration = sqrtf(powf(accelerometionVector_toReferenceFrame.x,2)+powf(accelerometionVector_toReferenceFrame.y,2)); }