Sign in or create a free account to continue.

ROB-210 · Lesson 3 of 12 · 30 min

Euler angles, roll-pitch-yaw, axis-angle and quaternions

A rotation matrix uses nine numbers to describe three degrees of freedom. That is perfect for arithmetic but awkward everywhere else: it wastes bandwidth in messages, it is hard for people to read and type, and it gives no intuitive handle for interpolating smoothly from one orientation to another. Robotics therefore uses several compact representations alongside the matrix. Euler angles and their aerospace cousins roll, pitch and yaw are intuitive but suffer from a singularity called gimbal lock. Axis-angle and its exponential-coordinate form connect rotations to angular velocity. Unit quaternions, four numbers with no singularities, are the standard in ROS, game engines and spacecraft. This lesson explains each, how to convert between them, and when to use which.

Euler angles

Leonhard Euler showed that any orientation can be reached by three successive rotations about coordinate axes, provided no two consecutive axes are the same. There are twelve possible axis sequences: six proper Euler sequences that repeat the first axis, such as Z-Y-Z or Z-X-Z, and six Tait–Bryan sequences that use all three axes, such as Z-Y-X or X-Y-Z. Each sequence can be applied about moving axes (intrinsic) or fixed axes (extrinsic), and an intrinsic sequence equals the extrinsic sequence with the axes in reverse order. With twenty-four conventions in use, the first rule of Euler angles is to never accept three angles without knowing exactly which convention produced them.

The Z-Y-Z convention is common for describing the wrists of industrial arms, because many spherical wrists literally rotate about z, then y, then z. With angles \( (\alpha, \beta, \gamma) \) about moving axes:

\[R_{ZYZ}(\alpha, \beta, \gamma) = R_z(\alpha)\,R_y(\beta)\,R_z(\gamma)\]

Roll, pitch and yaw

The most widely used Tait–Bryan convention in mobile robotics and aviation is roll-pitch-yaw. Roll \( \phi \) is rotation about the forward x-axis, pitch \( \theta \) about the sideways y-axis and yaw \( \psi \) about the vertical z-axis. ROS (REP 103) defines them as rotations about fixed axes applied in the order roll, then pitch, then yaw, which is the same as intrinsic rotations in the order yaw, pitch, roll. Either way the matrix is:

\[R = R_z(\psi)\,R_y(\theta)\,R_x(\phi)\]

Multiplying out gives a matrix in which the pitch angle appears alone in the bottom-left corner, \( r_{31} = -\sin\theta \), which makes extracting the angles from a matrix straightforward:

\[\theta = -\arcsin r_{31}, \qquad \phi = \operatorname{atan2}(r_{32},\, r_{33}), \qquad \psi = \operatorname{atan2}(r_{21},\, r_{11})\]

The two-argument arctangent atan2(y, x) returns an angle in the correct quadrant over the full range \( (-\pi, \pi] \), unlike the ordinary arctangent of a ratio, which cannot tell (1, 1) from (−1, −1). Always use atan2 when recovering angles in kinematics.

Worked problem

Extracting roll, pitch and yaw

A drone's attitude matrix has \( r_{11} = 0.813 \), \( r_{21} = 0.470 \), \( r_{31} = -0.342 \), \( r_{32} = 0.163 \), \( r_{33} = 0.925 \). Find its roll, pitch and yaw.

Show solution
  1. Pitch: \( \theta = -\arcsin(-0.342) = 20.0^\circ \).
  2. Roll: \( \phi = \operatorname{atan2}(0.163, 0.925) = 10.0^\circ \).
  3. Yaw: \( \psi = \operatorname{atan2}(0.470, 0.813) = 30.0^\circ \).

Answer: Roll 10°, pitch 20° (nose up in this convention) and yaw 30°. Running the angles back through \( R_z R_y R_x \) reproduces the matrix, a good habit when debugging conversions.

Gimbal lock

Every three-number representation of orientation has at least one singularity, a set of orientations where the parameters stop behaving well. For roll-pitch-yaw it occurs at pitch = ±90°. There \( \cos\theta = 0 \), so \( r_{11} \), \( r_{21} \), \( r_{32} \) and \( r_{33} \) all vanish, and the formulas for roll and yaw become atan2(0, 0), which is undefined. Physically, when the nose points straight up, the roll and yaw axes line up, and only their sum or difference affects the orientation. One degree of freedom is lost, and there are infinitely many angle combinations for the same attitude.

The name comes from mechanical gimbals, nested rings that hold a gyroscope or camera. When the middle ring turns 90°, the inner and outer rings align and the mount can no longer rotate in one direction. The Apollo spacecraft's inertial platform used a three-gimbal design and had to avoid a gimbal-lock zone; the guidance computer warned the crew as it approached. For software, gimbal lock causes sudden jumps in roll and yaw near the singularity and makes rates blow up, since small attitude changes require huge angle changes. For a Z-Y-Z wrist the singularity is at \( \beta = 0 \), where the first and third rotation axes coincide; this is one of the wrist singularities of lesson 11.

Two drawings of three nested gimbal rings around a central arrow. In the left drawing the rings are at right angles and three distinct rotation axes are marked. In the right drawing the middle ring has turned 90 degrees so the outer and inner rings lie in the same plane, and their rotation axes coincide; a label marks the lost degree of freedom.
Gimbal lock: at pitch ±90° two of the three rotation axes align and one degree of freedom is lost.

Axis-angle and Euler's rotation theorem

Euler also proved that any rotation, however it was produced, is equivalent to a single rotation by some angle \( \theta \) about some fixed unit axis \( \hat{\boldsymbol{\omega}} \). This axis-angle representation is the most physical description of a rotation: it is what you would see if you watched the turn happen at constant speed. Rodrigues' formula converts axis-angle to a rotation matrix:

\[R = I + \sin\theta\,[\hat{\boldsymbol{\omega}}] + (1 - \cos\theta)\,[\hat{\boldsymbol{\omega}}]^2, \qquad [\hat{\boldsymbol{\omega}}] = \begin{bmatrix} 0 & -\omega_3 & \omega_2 \\ \omega_3 & 0 & -\omega_1 \\ -\omega_2 & \omega_1 & 0 \end{bmatrix}\]

The matrix \( [\hat{\boldsymbol{\omega}}] \) is the skew-symmetric matrix of the axis, defined so that \( [\mathbf{a}]\mathbf{b} = \mathbf{a} \times \mathbf{b} \). It turns cross products into matrix products, and it reappears in the screw theory of lesson 7 and the Jacobians of lesson 10. Going the other way, the angle comes from the trace of the matrix and the axis from its antisymmetric part:

\[\cos\theta = \frac{\operatorname{tr}R - 1}{2}, \qquad \hat{\boldsymbol{\omega}} = \frac{1}{2\sin\theta} \begin{bmatrix} r_{32} - r_{23} \\ r_{13} - r_{31} \\ r_{21} - r_{12} \end{bmatrix}\]

The axis is undefined at \( \theta = 0 \), where there is no rotation at all, and needs special handling near \( \theta = 180^\circ \), where \( \sin\theta \) vanishes and the axis must be recovered from the diagonal instead. Multiplying the unit axis by the angle gives a single 3-vector, \( \boldsymbol{\omega}\theta \), called the rotation vector or exponential coordinates. Its direction is the axis and its length the angle. It is the representation used by OpenCV for camera poses (rvec) and it connects directly to angular velocity: rotating at constant angular velocity \( \boldsymbol{\omega} \) for one second produces the rotation with exponential coordinates \( \boldsymbol{\omega} \).

Worked problem

Axis and angle from a matrix

Find the axis and angle of \( R = R_x(90^\circ)R_z(90^\circ) = \begin{bmatrix} 0&-1&0\\0&0&-1\\1&0&0 \end{bmatrix} \) from lesson 2.

Show solution
  1. Trace: \( 0 + 0 + 0 = 0 \), so \( \cos\theta = (0 - 1)/2 = -0.5 \) and \( \theta = 120^\circ \).
  2. \( \sin 120^\circ = 0.866 \), so \( 2\sin\theta = 1.732 \).
  3. Axis: \( \frac{1}{1.732}(0 - (-1),\; 0 - 1,\; 0 - (-1)) = \frac{1}{1.732}(1, -1, 1) = (0.577, -0.577, 0.577) \).

Answer: A single 120° rotation about \( (1, -1, 1)/\sqrt{3} \). Two 90° turns about perpendicular axes always combine into a 120° turn about a body diagonal, which is why cube puzzles cycle three faces at a time.

Unit quaternions

A quaternion is a four-component number \( q = w + x\,\mathbf{i} + y\,\mathbf{j} + z\,\mathbf{k} \), invented by William Rowan Hamilton in 1843, with multiplication rules \( \mathbf{i}^2 = \mathbf{j}^2 = \mathbf{k}^2 = \mathbf{ijk} = -1 \). Quaternions of length one, unit quaternions, represent rotations neatly. The rotation by angle \( \theta \) about unit axis \( \hat{\boldsymbol{\omega}} \) corresponds to:

\[q = \left( \cos\tfrac{\theta}{2},\; \hat{\boldsymbol{\omega}}\sin\tfrac{\theta}{2} \right) = (w, x, y, z), \qquad w^2 + x^2 + y^2 + z^2 = 1\]

Composing two rotations is quaternion multiplication, and rotating a vector \( \mathbf{v} \) is \( q\,\mathbf{v}\,q^{*} \), where \( q^{*} = (w, -x, -y, -z) \) is the conjugate and \( \mathbf{v} \) is treated as a quaternion with zero scalar part. In practice software converts to a matrix for rotating many vectors. Quaternions have big advantages: four numbers instead of nine, no singularities anywhere, cheap composition, easy renormalization (divide by the length) and smooth interpolation by spherical linear interpolation (slerp), which moves at constant angular speed along the shortest arc between two orientations.

They have two quirks. First, \( q \) and \( -q \) represent the same rotation, because rotating by \( \theta \) about \( \hat{\boldsymbol{\omega}} \) is the same as rotating by \( 360^\circ - \theta \) about \( -\hat{\boldsymbol{\omega}} \). This double cover means two quaternions can be numerically far apart while describing nearly the same orientation, so before interpolating or averaging, flip one if their dot product is negative. Second, component order differs between libraries: ROS messages and Eigen's storage use (x, y, z, w), while many textbooks, SciPy's scalar_first option and some engines use (w, x, y, z). Mixing them produces wrong orientations that are hard to spot, because the result is still a valid unit quaternion.

Worked problem

Quaternion for a 90° yaw

Write the unit quaternion for a 90° rotation about z, in ROS order, and check that it rotates the x-axis to the y-axis.

Show solution
  1. \( \theta/2 = 45^\circ \), so \( w = \cos 45^\circ = 0.7071 \) and \( z = \sin 45^\circ = 0.7071 \).
  2. In ROS order (x, y, z, w): \( (0, 0, 0.7071, 0.7071) \).
  3. Converting to a matrix gives \( R_z(90^\circ) \), whose first column is \( (0, 1, 0) \), the y-axis.

Answer: (0, 0, 0.7071, 0.7071) in (x, y, z, w) order. The identity is (0, 0, 0, 1) in ROS order; a quaternion of all zeros is invalid and is a common bug in uninitialized messages.

Choosing a representation

Rotation representations compared.
RepresentationNumbersSingularitiesBest for
Rotation matrix9NoneComputation: composing, rotating vectors, kinematics
Euler or roll-pitch-yaw angles3Gimbal lock (pitch ±90° for RPY)Human input and display, small attitude changes
Axis-angle4 (axis plus angle)Axis undefined at zero angleUnderstanding and specifying single turns
Rotation vector (exponential coordinates)3Wraps at 180°Optimization, camera calibration, angular velocity
Unit quaternion4None (double cover)Storage, messages, interpolation, attitude filters

In ROS 2, orientation fields in messages such as geometry_msgs/Pose are quaternions; tf2 and the tf_transformations or scipy.spatial.transform libraries convert to and from matrices and Euler angles. Configuration files and user interfaces often expose roll-pitch-yaw because people can visualize it. A good pattern is to accept Euler angles at the human boundary, convert once to a quaternion or matrix, and never convert back unless you need to display a value.

Converting between representations and seeing gimbal lock numerically
import numpy as np
from math import atan2, asin, degrees, radians, cos, sin
def Rx(t): c, s = cos(t), sin(t); return np.array([[1,0,0],[0,c,-s],[0,s,c]])
def Ry(t): c, s = cos(t), sin(t); return np.array([[c,0,s],[0,1,0],[-s,0,c]])
def Rz(t): c, s = cos(t), sin(t); return np.array([[c,-s,0],[s,c,0],[0,0,1]])
def rpy(R): return [degrees(a) for a in (atan2(R[2,1], R[2,2]), -asin(R[2,0]), atan2(R[1,0], R[0,0]))]
def quat_from_R(R):                    # returns (x, y, z, w), ROS order; assumes w is not tiny
    w = 0.5*np.sqrt(1 + np.trace(R))
    return np.array([(R[2,1]-R[1,2])/(4*w), (R[0,2]-R[2,0])/(4*w), (R[1,0]-R[0,1])/(4*w), w])
R = Rz(radians(30)) @ Ry(radians(20)) @ Rx(radians(10))
print("roll, pitch, yaw =", [round(a, 2) for a in rpy(R)])
print("quaternion xyzw  =", np.round(quat_from_R(R), 4))
# near gimbal lock: two different angle sets, (almost) the same attitude
A = Rz(radians(40)) @ Ry(radians(89.999)) @ Rx(radians(10))
B = Rz(radians(70)) @ Ry(radians(89.999)) @ Rx(radians(40))
print("difference near pitch 90:", f"{np.abs(A - B).max():.1e}")
Output
roll, pitch, yaw = [10.0, 20.0, 30.0]
quaternion xyzw  = [0.0381 0.1893 0.2393 0.9515]
difference near pitch 90: 8.2e-06

The last line shows gimbal lock numerically: yaw 40° with roll 10° and yaw 70° with roll 40° differ by 30° in both angles, yet near pitch 90° they produce matrices that differ only in the fifth decimal place. Only the difference between yaw and roll matters there.

Interpolating orientations

Robots constantly move from one orientation to another: a tool reorienting between waypoints, a camera panning, a drone turning. Interpolating Euler angles component by component produces curved, uneven motion and can swing the long way round. Slerp between quaternions produces the natural motion, a constant-speed rotation about a single fixed axis:

\[\operatorname{slerp}(q_0, q_1, t) = \frac{\sin((1-t)\Omega)}{\sin\Omega}\,q_0 + \frac{\sin(t\Omega)}{\sin\Omega}\,q_1, \qquad \cos\Omega = q_0 \cdot q_1\]

For very small angles, where \( \sin\Omega \) approaches zero, implementations fall back to normalized linear interpolation. Trajectory generators for arms, covered in ROB-350, use slerp or its smooth spline extensions for the orientation part of Cartesian paths.

Common mistakes

  • MistakeUsing Euler angles without stating the axis sequence and whether rotations are intrinsic or extrinsic.

    InsteadDocument the convention, for example "ROS RPY: fixed-axis X then Y then Z, R = Rz Ry Rx".

  • MistakeRecovering angles with arctan of a ratio.

    InsteadUse atan2(y, x) to get the correct quadrant.

  • MistakeIgnoring gimbal lock near pitch ±90°.

    InsteadUse quaternions or matrices internally; avoid Euler rates near the singularity.

  • MistakeMixing (x, y, z, w) and (w, x, y, z) quaternion orders.

    InsteadCheck each library's convention; ROS messages use x, y, z, w.

  • MistakeInterpolating or averaging quaternions without checking sign.

    InsteadFlip one quaternion if the dot product is negative, then slerp.

Summary and key terms

  • Euler angles describe orientation by three rotations about coordinate axes; there are 24 conventions.
  • ROS roll-pitch-yaw uses R = Rz(ψ) Ry(θ) Rx(φ), recovered with arcsin and atan2.
  • Every three-parameter representation has singularities; for RPY, gimbal lock is at pitch ±90°.
  • Any rotation equals one turn about a fixed axis; Rodrigues' formula converts axis-angle to a matrix.
  • Exponential coordinates combine axis and angle into one 3-vector linked to angular velocity.
  • Unit quaternions use four numbers, have no singularities and interpolate smoothly with slerp; q and −q are the same rotation.
  • Use matrices or quaternions internally and Euler angles only at the human interface.
Euler angles
Three angles of successive rotations about coordinate axes that specify an orientation.
Roll, pitch, yaw
Rotations about the forward, sideways and vertical axes.
Gimbal lock
A singularity where two rotation axes align and a degree of freedom is lost.
atan2
The two-argument arctangent that returns an angle in the correct quadrant.
Axis-angle
A representation of a rotation as an angle about a unit axis.
Rodrigues' formula
The formula converting axis-angle to a rotation matrix.
Skew-symmetric matrix
A matrix [a] such that [a]b = a × b.
Exponential coordinates
A 3-vector whose direction is the rotation axis and length the angle.
Unit quaternion
A four-component number of length one representing a rotation.
Slerp
Spherical linear interpolation between orientations at constant angular speed.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. A matrix has \( r_{31} = -0.5 \). What is the RPY pitch?

    Show answer

    30°.

  2. What is atan2(−1, −1) in degrees?

    Show answer

    −135°.

  3. At what pitch angle does RPY gimbal lock occur?

    Show answer

    ±90°.

  4. A rotation matrix has trace 1. What is its angle?

    Show answer

    \( \cos\theta = 0 \), so 90°.

  5. Write the quaternion (w, x, y, z) for 180° about x.

    Show answer

    \( (0, 1, 0, 0) \).

  6. Write the ROS-order identity quaternion.

    Show answer

    (0, 0, 0, 1).

  7. Do q = (0.6, 0, 0.8, 0) and −q represent the same rotation?

    Show answer

    Yes; q and −q are the same rotation.

  8. What rotation vector corresponds to 90° about y?

    Show answer

    \( (0, \pi/2, 0) \approx (0, 1.571, 0) \).

  9. Compute \( [\mathbf{a}]\mathbf{b} \) for \( \mathbf{a} = (0,0,1) \), \( \mathbf{b} = (1,0,0) \).

    Show answer

    \( \mathbf{a} \times \mathbf{b} = (0, 1, 0) \).

  10. Two unit quaternions have dot product 0.5. What angle separates the orientations?

    Show answer

    \( \Omega = 60^\circ \), so the rotation between them is \( 2\Omega = 120^\circ \).

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz