Euler Angles

Euler angles parameterize a rotation as three successive elemental rotations about coordinate axes. Each elemental rotation is a special case of Rodrigues’ Formula with equal to a standard basis vector.

For the Z-X-Z convention (proper Euler angles), a rotation is decomposed as:

For the Z-Y-X convention (Tait-Bryan / yaw-pitch-roll), used in aerospace:

where the elemental rotation matrices are:

There are 12 valid conventions: 6 proper Euler (repeat one axis: XYX, XZX, YXY, YZY, ZXZ, ZYZ) and 6 Tait-Bryan (all distinct axes: XYZ, XZY, YXZ, YZX, ZXY, ZYX). All suffer from gimbal lock — a singularity where two axes align and one degree of freedom is lost.

Intuition

Euler angles decompose one complicated rotation into three simple ones that a human (or a gimbal mechanism) can execute sequentially. Each elemental rotation moves within a single coordinate plane — the complexity is in how those planes chain together.

Intrinsic vs. extrinsic. The same three angles can be interpreted two ways:

ConventionReading orderFrame interpretation
Intrinsic (body-frame)Multiply left to right: Each rotation is about the current (body) frame axis
Extrinsic (fixed-frame)Multiply right to left: same productEach rotation is about the fixed (spatial) frame axis

A Z-X-Z intrinsic rotation is algebraically identical to a Z-X-Z extrinsic rotation with the angles applied in reverse order. This follows from associativity of matrix multiplication — the algebra doesn’t care which interpretation you prefer.

Why gimbal lock happens. Each Euler angle controls one axis. When the middle rotation aligns two axes (e.g., pitch hits in yaw-pitch-roll), the first and third rotations produce the same physical effect. Two parameters now control one DOF, and one DOF becomes uncontrollable. The mapping from angles to drops rank from 3 to 2.

This is topological, not a convention problem: no 3-parameter representation of can be singularity-free everywhere, because and you cannot smoothly parameterize it with .


Properties

Gimbal lock singularities by convention

ConventionSingularity conditionWhat aligns
Z-X-Z (proper) or First and third -axes coincide
Z-Y-X (yaw-pitch-roll)Yaw and roll axes coincide

At the singularity, (or ) can take any value as long as their sum is fixed — infinitely many angle triples map to the same rotation.

Angle extraction: Z-Y-X (yaw-pitch-roll)

Given , solve for using atan2 for quadrant-correctness:

Valid when (i.e. ). At the singularity, one can only determine or , and by convention one angle is set to zero.

Representation comparison

PropertyEuler anglesExponential coordsQuaternionsRotation matrix
Parameters33 ()4 (unit)9 (6 constraints)
Singularity?Yes (gimbal lock)Yes ()NoNo
CompositionPainful (recompute)Not additive in generalHamilton productMatrix multiply
InterpolationPoor (artifacts near lock)Okay (via SLERP in ball)SLERP (optimal)Wasteful
Human readabilityExcellentModeratePoorPoor

Connection to manipulator singularities

Gimbal lock previews a broader phenomenon: kinematic singularities in robot arms. In both cases, a parameter-space-to-configuration-space map loses rank, a Jacobian becomes singular, and the system loses controllability in some direction. The mathematical structure is identical — a rank-deficient derivative of a smooth map. This is covered further in 5.3. Singularities and Manipulability.


Examples

Example 1: Z-Y-X extraction from

Extract: . Then , .

Result: . A pure yaw of 90° — correct.

Example 2: Gimbal lock in yaw-pitch-roll

Set (nose straight up):

Only the difference appears — the system has collapsed from 3 DOF to 2. Physically, when pitch is , yawing the aircraft produces the same motion as rolling it. This is gimbal lock.

Implementation

import numpy as np
 
def euler_zyx_to_matrix(psi, theta, phi):
    """Yaw-pitch-roll (Z-Y-X intrinsic) to rotation matrix."""
    Rz = rodrigues(np.array([0,0,1]), psi)
    Ry = rodrigues(np.array([0,1,0]), theta)
    Rx = rodrigues(np.array([1,0,0]), phi)
    return Rz @ Ry @ Rx
 
def matrix_to_euler_zyx(R):
    """Rotation matrix to yaw-pitch-roll (Z-Y-X). Assumes cos(theta) != 0."""
    theta = -np.arcsin(np.clip(R[2,0], -1, 1))
    psi   = np.arctan2(R[1,0], R[0,0])
    phi   = np.arctan2(R[2,1], R[2,2])
    return psi, theta, phi

Note rodrigues() is defined in Rodrigues’ Formula. For production code, prefer scipy.spatial.transform.Rotation which handles all 12 conventions and singularity edge cases.