Search code examples
c++qtopenglrotationquaternions

Quaternion to axis angles


I try to implement 3D object rotations according data taken from sensor. I have data as quaternions w,x,y,z but to use

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

I need rotation angles across x,y,z to obtain these with this tutorial and QQuaternion in Qt IDE I write below code:

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;
    }
}

However, when I rotate with above code, movements are not correct, directions are different and also even sensor move 90 degrees to left it move so much little to another direction.

When I search about quaternion and openGL, some gives advice about rotation could be done on camera on openGL by using glMultMatrixf(quaternion.toMatrix) but I could not convert quaternion to a matrix GLFloat which is requested as parameter in glMultMatrixf. QQuaternion class cloud convert quaternion to QVector4D and gives error variable casting. Maybe the way did is wrong which is below code:

    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 

To sum, how can i solve the issue with these quaternions for interpreting rotations on an object with openGL ?


Solution

  • I try out some other methods for implementation.I directly convert quaternions to X Y Z axis angles. I hope it will be useful for others also:

        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);