Conversion between quaternions and Euler angles

Spatial rotations in three dimensions can be parametrized using both Euler angles and unit quaternions. This article explains how to convert between the two representations. Actually this simple use of "quaternions" was first presented by Euler some seventy years earlier than Hamilton to solve the problem of magic squares. For this reason the dynamics community commonly refers to quaternions in this application as "Euler parameters".
Definition.
For the rest of this article, the JPL quaternion convention shall be used. A unit quaternion can be described as:
We can associate a quaternion with a rotation around an axis by the following expression
where α is a simple rotation angle (the value in radians of the angle of rotation) and cos(β"x"), cos(β"y") and cos(β"z") are the "direction cosines" of the angles between the three coordinate axes and the axis of rotation. (Euler's Rotation Theorem).
Intuition.
To better understand how "direction cosines" work with quaternions:
If the axis of rotation is the "x"-axis:
If the axis of rotation is the "y"-axis:
If the axis of rotation is a vector located 45° ( radians) between the "x" and "y" axes:
Therefore, the "x" and "y" axes "share" influence over the new axis of rotation.
Tait–Bryan angles.
Similarly for Euler angles, we use the Tait Bryan angles (in terms of flight dynamics):
where the X-axis points forward, Y-axis to the right and Z-axis downward. In the conversion example above the rotation occurs in the order heading, pitch, bank.
Rotation matrices.
The orthogonal matrix (post-multiplying a column vector) corresponding to a clockwise/left-handed (looking along positive axis to origin) rotation by the unit quaternion formula_14 is given by the inhomogeneous expression:
or equivalently, by the homogeneous expression:
If formula_17 is not a unit quaternion then the homogeneous form is still a scalar multiple of a rotation matrix, while the inhomogeneous form is in general no longer an orthogonal matrix. This is why in numerical work the homogeneous form is to be preferred if distortion is to be avoided.
The direction cosine matrix (from the rotated Body XYZ coordinates to the original Lab xyz coordinates for a clockwise/lefthand rotation) corresponding to a post-multiply Body 3-2-1 sequence with Euler angles (ψ, θ, φ) is given by:
Euler angles to quaternion conversion.
By combining the quaternion representations of the Euler rotations we get for the Body 3-2-1 sequence, where the airplane first does yaw (Body-Z) turn during taxiing onto the runway, then pitches (Body-Y) during take-off, and finally rolls (Body-X) in the air. The resulting orientation of Body 3-2-1 sequence (around the capitalized axis in the illustration of Tait–Bryan angles) is equivalent to that of lab 1-2-3 sequence (around the lower-cased axis), where the airplane is rolled first (lab-x axis), and then nosed up around the horizontal lab-y axis, and finally rotated around the vertical lab-z axis (lB = lab2Body):
Other rotation sequences use different conventions.
Source code.
Below code in C++ illustrates above conversion:
struct Quaternion
 double w, x, y, z;
Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
 // Abbreviations for the various angular functions
 double cy = cos(yaw * 0.5);
 double sy = sin(yaw * 0.5);
 double cp = cos(pitch * 0.5);
 double sp = sin(pitch * 0.5);
 double cr = cos(roll * 0.5);
 double sr = sin(roll * 0.5);
 Quaternion q;
 q.w = cr * cp * cy + sr * sp * sy;
 q.x = sr * cp * cy - cr * sp * sy;
 q.y = cr * sp * cy + sr * cp * sy;
 q.z = cr * cp * sy - sr * sp * cy;
 return q;
Quaternion to Euler angles conversion.
The Euler angles can be obtained from the quaternions via the relations:
Note, however, that the arctan and arcsin functions implemented in computer languages only produce results between −π/2 and π/2, and for three rotations between −π/2 and π/2 one does not obtain all possible orientations. To generate all the orientations one needs to replace the arctan functions in computer code by atan2:
Source code.
The following C++ program illustrates conversion above:
struct Quaternion {
 double w, x, y, z;
struct EulerAngles {
 double roll, pitch, yaw;
EulerAngles ToEulerAngles(Quaternion q) {
 EulerAngles angles;
 // roll (x-axis rotation)
 double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
 double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
 angles.roll = std::atan2(sinr_cosp, cosr_cosp);
 // pitch (y-axis rotation)
 double sinp = 2 * (q.w * q.y - q.z * q.x);
 if (std::abs(sinp) >= 1)
 angles.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
 else
 angles.pitch = std::asin(sinp);
 // yaw (z-axis rotation)
 double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
 double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
 angles.yaw = std::atan2(siny_cosp, cosy_cosp);
 return angles;
Singularities.
One must be aware of singularities in the Euler angle parametrization when the pitch approaches ±90° (north/south pole). These cases must be handled specially. The common name for this situation is gimbal lock.
Code to handle the singularities is derived on this site: www.euclideanspace.com
Vector rotation.
Let us define scalar formula_22 and vector formula_23 such that formula_24.
Note that the canonical way to rotate a three-dimensional vector formula_25 by a quaternion formula_26 defining an Euler rotation is via the formula
where formula_28 is a quaternion containing the embedded vector formula_25, formula_30 is a conjugate quaternion, and formula_31 is the rotated vector formula_32. In computational implementations this requires two quaternion multiplications. An alternative approach is to apply the pair of relations
where formula_35 indicates a three-dimensional vector cross product. This involves fewer multiplications and is therefore computationally faster. Numerical tests indicate this latter approach may be up to 30% faster than the original for vector rotation.
Proof.
The general rule for quaternion multiplication involving scalar and vector parts is given by
Using this relation one finds for formula_37 that
and upon substitution for the triple product
where anti-commutivity of cross product and formula_40 has been applied. By next exploiting the property that formula_41 is a unit quaternion so that formula_42, along with the standard vector identity 
one obtains
which upon defining formula_33 can be written in terms of scalar and vector parts as 