态度变化 – angular度和轴问题 – 四元math

我有一个应用程序loggingangular度,当用户在一个对象周围走动时,指向设备(最好)在对象的中心。 angular度根据用户的指令重置 – 参考姿态得到重置。

使用欧拉angular产生的Gimbal锁,所以我目前正在使用四元数和计算angular度这样:

double angleFromLastPosition = acos(fromLastPositionAttitude.quaternion.w) * 2.0f; 

这发出了良好的精度,它完美的工作,如果设备的俯仰和偏航不会改变。 换句话说,当angular度显示360度时,我最终会在圆圈的起始位置。

问题1:如果设备的偏航和俯仰发生轻微变化(用户不直接指向对象的中心),angleFromLastPosition也是如此。 我理解这一部分,因为我的angular度公式只是显示了3D空间中两个设备态度之间的angular度。

场景:

  • 我标记旋转姿态的开始,并开始围绕对象在一个圆圈中指向中心
  • 我停在45度,并通过指向更高或更低来改变设备的音高。 angular度相应地改变。
  • 我想看到的是:即使俯仰或偏航改变,angular度仍然保持在45度。

问题1是,我怎样才能使用四元数来计算设备的滚动量,而忽略其他两个坐标轴的变化(至less在一定的合理度数内)。

问题2:如果我旋转一下,然后完全冻结设备(在三脚架上,所以根本没有晃动),angleFromLastPosition以大约10-20秒的速度漂移1度,而且看起来不是线性的。 换句话说,它起初漂移很快,然后大大减缓。 有时我完全没有漂移 – 如果设备静止,angular度是坚如磐石的。 这让我迷失在了解正在发生的事情上。

问题2,这里发生了什么,我该如何照顾漂stream?

我经历了不less篇文章和教程,现在四元math已经超越了我,希望有人能够帮助提示,链接或几行代码。

我已经testing过了,它似乎在问题1中find了什么,Andrei。

我最初设置了0angular度,在第一遍之后立即存储从walkaroundAngleFromAttitude返回的angular度:fromHomeAngle:在homeangle中,供将来使用。

我的testing包括使用参考帧开始设备更新:

 [_motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:operationQueue withHandler:handler]; 

并使用处理程序中调用的以下方法:

 - (CMQuaternion) multiplyQuanternion:(CMQuaternion)left withRight:(CMQuaternion)right { CMQuaternion newQ; newQ.w = left.w*right.w - left.x*right.x - left.y*right.y - left.z*right.z; newQ.x = left.w*right.x + left.x*right.w + left.y*right.z - left.z*right.y; newQ.y = left.w*right.y + left.y*right.w + left.z*right.x - left.x*right.z; newQ.z = left.w*right.z + left.z*right.w + left.x*right.y - left.y*right.x; return newQ; } -(float)walkaroundRawAngleFromAttitude:(CMAttitude*)attitude { CMQuaternion e = (CMQuaternion){0,0,1,1}; CMQuaternion quatConj = attitude.quaternion; quatConj.x *= -1; quatConj.y *= -1; quatConj.z *= -1; CMQuaternion quat1 = attitude.quaternion; CMQuaternion quat2 = [self multiplyQuanternion:quat1 withRight:e]; CMQuaternion quat3 = [self multiplyQuanternion:quat2 withRight:quatConj]; return atan2f(quat3.y, quat3.x); } -(float)walkaroundAngleFromAttitude:(CMAttitude*)attitude fromHomeAngle:(float)homeangle { float rawangle = [self walkaroundRawAngleFromAttitude:attitude]; if (rawangle <0) rawangle += M_PI *2; if (homeangle < 0) homeangle += M_PI *2; float finalangle = rawangle - homeangle; if (finalangle < 0) finalangle += M_PI *2; return finalangle; } 

这是使用从寻找法向量到iOS设备的一些修改和扩展代码

编辑处理问题2和问题2:

这可能无法解决。 我曾在其他应用程序(例如360全息图)中看到它,并阅读了陀螺仪等读取错误的内容。 如果你试图弥补这个问题的话,那么当一些真实的旋转运动被补偿代码扔掉时,你当然会感到紧张不安。 就我所了解的最近几年而言,这是一个硬件问题。