This Python module provides conversion functions between quaternions and other rotation parameterizations (axis-angle, rotation matrix, Euler angles).
See also the pure-python package quaternionic.
Choosing how to represent the orientation of a solid in three-dimensional space is a fairly complex problem. The aim is to arrive at a compact (no dependent elements) and unique way of describing the orientation of the solid, while guaranteeing numerical stability. The scientific literature presents several choices for parameterizing the orientation of a rigid body: Cardan angles, Euler angles, Cartesian rotation vectors, rotation matrix, Rodrigues parameters, etc.
To avoid the gimbal lock phenomenon (representation singularity) that occurs for some of the above parameterizations, quaternions can be used as rotation parameters.
Introduced by Irish mathematician William R. Hamilton (1843), quaternions are hypercomplex numbers using 4 variables (a scalar real part and 3 imaginary components) to represent the orientation of a rigid body. This representation introduces a holonomic constraint equation related to the normalization of the quaternion.
Quaternion is given by the quadruplet :
- Axis of rotation:
- Angle of rotation
$\theta$ :
- Quaternion normalization equation:
Compact writing compared to the rotation matrix ● Numerical stability ● No singularity (Cardan blocking)
Let
Knowing the axis and angle of a rotation
The axisAngleToQuaternion()
function in the quaternion.py
module performs this conversion.
Given a quaternion p = ⟨e0, e1, e2, e3⟩, the axis of rotation u and the angle of rotation θ can be obtained from the following equations:
The quaternionToAxisAngle()
function in the quaternion.py
module performs this conversion.
Given a quaternion
The quaternionToRotationMatrix()
function in the quaternion.py
module performs this conversion.
Consider the following rotation matrix R:
The quaternion defining the orientation equivalent to this rotation matrix can be defined in 2 steps.
Step 1: We first compute
Step 2: Identify the signs by finding the largest absolute value of
The reason for this ambiguity over the signs of the quaternion components is that the quaternions rotationMatrixToQuaternion()
function in the quaternion.py
module performs this conversion.
Introduced by Swiss mathematician and physicist Leonhard Euler, the three Euler angles (roll, pitch, yaw) are used to define the orientation of a rigid body. Roll can be defined as the orientation with respect to the X axis, pitch as the orientation with respect to the Y axis, and yaw as the orientation with respect to the Z axis.
There are dozens of mutually exclusive ways of defining Euler angles (Conventions XYX, XYZ, XZX, XZY, YXY, YXZ, YZX, YZY, ZXY, ZXZ, ZYX, ZYZ). We therefore need to define which convention is used in our code.
We have used the following definition of Euler angles in the developed software.
- Variant of Tait-Bryan angles
- Yaw-pitch-roll rotation order (ZYX convention), rotating respectively around axes Z, Y and X axes
- Intrinsic rotation (axes move with each rotation)
- Active rotation (the point is rotated, not the coordinate system)
- Direct coordinate system (right-hand rule for vector product)
Based on this definition, let u (roll angle), v (pitch angle) and w (yaw angle) define a given orientation, the equivalent quaternion is determined as follows:
The eulerAnglesToQuaternion()
function in the quaternion.py
module performs this conversion.
The conversion of a quaternion into Euler angles (using the definition of Euler angles given in the previous paragraph) is given by the following equations:
Euler angles are susceptible to Cardan blocking (singularity of representation). The preceding equations provide a general solution for determining Euler angles. In the special case where the pitch angle v is equal to +90° or -90°, it becomes impossible to calculate the other 2 angles (roll and yaw), as the function atan2()
is not defined for the two null arguments. This is because, for a pitch angle of +90° or -90°, the roll and yaw axes are aligned. There is no single solution in this configuration: any orientation can be described using an infinite number of combinations of yaw and roll angles.
To manage the Cardan lock, we first determine the value of the pitch angle. Depending on whether it is +90° or -90°, we calculate the other 2 angles.
The quaternionToEulerAngles()
function in the quaternion.py
module performs this conversion.
Key notes: Of the rotation parameterizations presented, only Euler angles are susceptible to Cardan blocking, quaternions and rotation matrices are not.