四元数到轴的角度

Quaternion to axis angles

我尝试根据从传感器获取的数据实现 3D 对象旋转。我有四元数 w,x,y,z 的数据,但要使用

   glRotatef(xRot,1,0,0);
   glRotatef(yRot,0,1,0);
   glRotatef(zRot,0,0,1);

我需要 x、y、z 的旋转角度来获得这些 this 教程和 Qt 中的 QQuaternion IDE 我写下面的代码:

void quaternion2angle(float w,float x,float y,float z)
{
    // Code for quaternion to rotation around axis X Y Z
    QQuaternion ql;
    ql.setScalar(w);
    ql.setX(x);
    ql.setY(y);
    ql.setZ(z);

    if (ql.scalar()>1) ql.normalize();
    angle= 2 * acos(ql.scalar());
    s= sqrt(1-ql.scalar()*ql.scalar());
    if (s<0.001) {
        xRot=ql.x();
        yRot=ql.y();
        zRot=ql.z();
    }else
    {
        xRot=ql.x()/s;
        yRot=ql.y()/s;
        zRot=ql.y()/s;
    }
}

然而,当我用上面的代码旋转时,运动不正确,方向不同,甚至传感器向左移动 90 度,它向另一个方向移动的很少。

当我搜索四元数和 openGL 时,一些人给出了关于可以在 openGL 上使用 glMultMatrixf(quaternion.toMatrix) 在相机上完成旋转的建议,但我无法将四元数转换为矩阵 GLFloat,它在 glMultMatrixf 中作为参数请求。 QQuaternion class 云将四元数转换为 QVector4D 并给出错误变量转换。可能做的方法不对,代码如下:

    void paintGL()
         {
          glEnable(GL_DEPTH_TEST);
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          glLoadIdentity();
       // adjust camera
          glTranslatef(0.0f, 0.0f, -8.0f);
          glMultMatrixf(quMatrix.constData());
          glRotatef(90,0,1,0);

       // no need below
         //glRotatef(xRot,1,0,0);
         //glRotatef(yRot,0,1,0);
         //glRotatef(zRot,0,0,1);


         obj.Draw();
         glDisable(GL_DEPTH_TEST);
         }

    void setquMatrix(QVector4D qvec)
        {
        // read data w,x,y,z
        qvec=quaternionRotation(w,x,y,z);
        quMatrix=qvec;
        }

    // Using quaternion and glMultMatrixf
    QVector4D quaternionRotation(float w,float x,float y,float z)
        {
            QQuaternion qlm;
            qlm.setScalar(w);
            qlm.setX(x);
            qlm.setY(y);
            qlm.setZ(z);
            qlm.normalize();
            return qlm.toVector4D();
        }
    // after taking value above I set matrix which is multiplied with glMultMatrixf 

总而言之,我如何解决这些四元数的问题,以便使用 openGL 解释对象上的旋转?

您不应该转换为轴角度,而是直接创建旋转矩阵并使用 glMultMatrix。

可以通过以下方式将四元数转换为矩阵:(sourced from my previous code)

inline QMatrix4x4 quatToMat(QQuaternion q)
{
    //based on algorithm on wikipedia
    // http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
    float w = q.scalar ();
    float x = q.x();
    float y = q.y();
    float z = q.z();

    float n = q.lengthSquared();
    float s =  n == 0?  0 : 2 / n;
    float wx = s * w * x, wy = s * w * y, wz = s * w * z;
    float xx = s * x * x, xy = s * x * y, xz = s * x * z;
    float yy = s * y * y, yz = s * y * z, zz = s * z * z;

    float m[16] = { 1 - (yy + zz),         xy + wz ,         xz - wy ,0,
                         xy - wz ,    1 - (xx + zz),         yz + wx ,0,
                         xz + wy ,         yz - wx ,    1 - (xx + yy),0,
                               0 ,               0 ,               0 ,1  };
    QMatrix4x4 result =  QMatrix4x4(m,4,4);
    result.optimize ();
    return result;
}

然后您可以使用 constData 成员传递到 multMatrix 中:

QMatrix4x4 rotation = quatToMat(quat);
glMultMatrix(rotation.constData());

我尝试了一些其他方法 implementation.I 直接将四元数转换为 X Y Z 轴角度。我希望它对其他人也有用:

    float q0 = q0Buffer.at(i);
    float q1 = q1Buffer.at(i);
    float q2 = q2Buffer.at(i);
    float q3 = q3Buffer.at(i);

    float angle_rad = acos(q0) * 2;
    float angle_deg = angle_rad * 180 / PI;
    float x = q1 / sin(angle_rad/2);
    float y = q2 / sin(angle_rad/2);
    float z = q3 / sin(angle_rad/2);