And*_* G. 11 rotation quaternions ios gyroscope core-motion
我有一个应用程序,当用户在对象周围走动时记录角度,同时将设备(最好)指向对象的中心.角度会根据用户的命令重置 - 因此参考态度会重置.
使用欧拉角产生万向节锁,所以我目前使用四元数并以这种方式计算角度:
double angleFromLastPosition = acos(fromLastPositionAttitude.quaternion.w) * 2.0f;
Run Code Online (Sandbox Code Playgroud)
这样可以提供良好的精度,并且它可以很好地工作,因为设备的俯仰和偏航不会改变.换句话说,当角度显示360度时,我最终在与圆的开始相同的位置.
问题1:如果设备的偏航和俯仰稍微改变(用户不直接指向物体的中心),angleFromLastPosition也是如此.我理解这一部分,因为我的角度公式只显示了3D空间中两个设备态度之间的角度.
场景:
问题1是,如何仅使用四元数计算设备的滚动,并忽略其他两个轴的变化(至少在某个合理的度数范围内).
问题2:如果我旋转一点然后完全冻结设备(在三脚架上没有任何振动),angleFromLastPosition以大约10-20秒的1度漂移,并且看起来不是线性的.换句话说,它首先快速漂移,然后大幅减速.有时我根本没有漂移 - 如果设备静止,角度是坚如磐石的.这让我迷失了解正在发生的事情.
问题2,这里发生了什么,我该如何处理漂移?
我经历了不少文章和教程,目前四元数学已经超出了我的范围,希望有人能够提供一些提示,链接或几行代码.
我已经对此进行了测试,它似乎按照您在问题 1 中寻找的内容工作,Andrei。
我最初将 homeangle 设置为 0,并在第一次通过后立即将从 walkaroundAngleFromAttitude:fromHomeAngle: 返回的角度存储在 homeangle 中,以供将来使用。
我的测试包括使用参考系启动设备更新:
[_motionManager
startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical
toQueue:operationQueue
withHandler:handler];
Run Code Online (Sandbox Code Playgroud)
并使用处理程序中调用的以下方法:
- (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;
}
Run Code Online (Sandbox Code Playgroud)
这是使用一些修改和扩展的代码来查找法线向量到iOS设备
编辑以处理问题 2 和问题 2:
这可能无法解决。我在其他应用程序(例如 360 全景)中看到过它,并且读过有关陀螺仪等的错误读数的信息。如果您尝试对其进行补偿,那么当补偿代码抛出一些真实的旋转运动时,当然您最终会得到一种紧张的体验。就我过去几年的解释而言,这是一个基于硬件的问题。