态度变化 - 角度和轴问题 - 四元数学

时间:2013-05-13 21:16:23

标签: ios rotation quaternions gyroscope core-motion

我有一个应用程序,当用户在对象周围走动时记录角度,同时将设备(最好)指向对象的中心。 角度会根据用户的命令重置 - 因此参考态度会重置。

使用欧拉角产生万向节锁定,所以我目前使用四元数并以这种方式计算角度:

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

这样可以提供良好的精度,并且如果设备的俯仰和偏航不会改变,它可以很好地工作。换句话说,当角度显示360度时,我最终会与圆圈的开始位于同一位置。

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

情景:

  • 我标记了旋转姿态的开始,并在指向中心的同时开始围绕物体旋转
  • 我停在45度,并通过指向更高或更低来改变设备的音高。角度会相应变化。
  • 我希望看到的是:即使俯仰或偏航发生变化,角度也会保持在45度。

问题1是,如何仅使用四元数计算设备的滚动,并忽略其他两个轴的变化(至少在某个合理的度数范围内)。

问题2:如果我旋转一点然后完全冻结设备(在三脚架上没有任何震动),angleFromLastPosition以每10-20秒左右1度的速度漂移,并且它似乎不是线性的。换句话说,它首先快速漂移,然后大幅减速。有时我根本没有漂移 - 如果设备静止,角度是坚如磐石的。这让我迷失了解正在发生的事情。

问题2,这里发生了什么,我该如何处理漂移?

我经历了相当多的文章和教程,目前四元数学已超出我的范围,希望有人能够提供一些提示,链接或几行代码。

1 个答案:

答案 0 :(得分:4)

我已经对此进行了测试,它似乎可以根据您在问题1中找到的工作,Andrei。

我将homeangle设置为0,并在第一次传递后立即存储walkaroundAngleFromAttitude:fromHomeAngle:homeangle中返回的角度,以备将来使用。

我的测试包括使用参考框架启动设备更新:

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

并使用在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;
}

这是使用Finding normal vector to iOS device

中的一些修改和扩展代码

编辑处理问题2&amp;问题2:

这可能无法解决。我已经在其他应用程序(例如360 pano)中看到了它,并且已经阅读了有关陀螺仪等错误读数的信息。如果你试图弥补它,当然,当一些真实的旋转运动被补偿代码抛出时,你最终会有一种紧张的经历。就我过去几年的口译而言,这是一个基于硬件的问题。