Search code examples
3drotationquaternions

Efficient quaternion angular velocity


I have an orientation expressed with a quaternion and an angular velocity expressed as either a quaternion or a number (radians per second around the original orientation). I understand how to do this using conversion to axis-angle but that method is rather computationally expensive and is not a realistic option. How would I go about modifying the orientation quaternion given a time interval (in seconds)? I need a solution for both cases (the quaternion and the number). However, converting one case into the other is acceptable and may be preferable depending on the computational complexity of the various algorithms/formulae required for conversions.


Solution

  • For update of orientation , you require to multiply current orientation by delta rotation. This is comparable expensive operation with axis angle conversion.

    Common way to represent angular velocity is "exponential map", the 3d vector parallel with rotation axis and magnitude of rotation velocity (radians per second). The conversion to delta rotation quaternion looks like

    Quaternion deltaRotation(const Vector3& angVel, double deltaTime)
    {
       Vector3 ha = angVel * (deltaTime * 0.5); // vector of half angle
       double l = ha.norm(); // magnitude
       if (l > 0) {
          ha *= sin(l) / l;
       }
       return Quaternion(cos(l), ha.x(), ha.y(), ha.z());
    }
    

    If your deltaTime is small and rotation speed is small, you can use approximation by 1st Taylor series multiplier. But you should normalize result quaternion to avoid numerical instability more often.

    Quaternion deltaRotationAppx1(const Vector3& em, double deltaTime)
    {
       Vector3 ha = em * deltaTime * 0.5; // vector of half angle
       return Quaternion(1.0, ha.x(), ha.y(), ha.z());
    }
    

    And update of orientation usually looks

    orientation = orientation * deltaRotation;
    orientation.normalize();