Hyoungseo Son

Part 1 · Mathematical Foundations

Rotations: SO(3), Quaternions, and the Exponential Map

6 min read

Position is easy: three numbers, add them, done. Orientation is the part of rigid-body state that needs its own chapter, because the set of 3D rotations is a curved space, not a vector space.

The rotation group

A 3D rotation is a 3×33\times3 matrix RR that preserves lengths and handedness:

RR=I,detR=+1.R^{\top} R = I, \qquad \det R = +1 .

These matrices form the group SO(3)SO(3). It is 3-dimensional (a rotation has three degrees of freedom) but it lives inside R9\mathbb{R}^{9} with six constraints, and crucially it is not flat: you cannot add two rotations and get a rotation. That single fact is why every representation below is a compromise.

Four ways to store a rotation

  • Euler angles (θx,θy,θz\theta_x, \theta_y, \theta_z). Three numbers, minimal, and intuitive. But the map from angles to SO(3)SO(3) is singular: at certain angles two of the axes line up and a degree of freedom vanishes. That is gimbal lock, below.
  • Rotation matrix. Nine numbers, no singularities, composition is a matrix multiply, but you must fight numerical drift away from RR=IR^{\top}R = I.
  • Unit quaternion qS3q \in S^{3}. Four numbers, one constraint q=1\lVert q\rVert = 1, no gimbal lock, cheap to compose and to renormalize. This is what engines store internally. (It double-covers SO(3)SO(3): qq and q-q are the same rotation.)
  • Axis-angle / exponential coordinates ϕ=θn^\phi = \theta\,\hat n. Three numbers again, but interpreted as "rotate by θ\theta about axis n^\hat n." This is the natural home for angular velocity and for integrating rotation.

Angular velocity and the exponential map

Angular velocity ωR3\omega \in \mathbb{R}^{3} is not the time derivative of any of those storage formats directly. It relates to the matrix through the skew-symmetric operator []×[\,\cdot\,]_\times:

R˙=[ω]×R,[ω]×=[0ωzωyωz0ωxωyωx0].\dot R = [\omega]_\times\, R, \qquad [\omega]_\times = \begin{bmatrix} 0 & -\omega_z & \omega_y \\ \omega_z & 0 & -\omega_x \\ -\omega_y & \omega_x & 0 \end{bmatrix}.

The skew-symmetric matrices are the Lie algebra so(3)\mathfrak{so}(3), the flat tangent space at the identity. The exponential map takes a vector there back onto the group,

R=exp ⁣([ϕ]×)=I+sinθθ[ϕ]×+1cosθθ2[ϕ]×2,θ=ϕ,R = \exp\!\big([\phi]_\times\big) = I + \frac{\sin\theta}{\theta}[\phi]_\times + \frac{1 - \cos\theta}{\theta^{2}}[\phi]_\times^{2}, \qquad \theta = \lVert\phi\rVert,

which is just Rodrigues' formula. This is how an engine advances orientation without leaving the manifold: integrate ω\omega in the flat algebra, then map back with exp\exp. For quaternions the same step is q˙=12ωq\dot q = \tfrac12\,\omega\,q (quaternion product), followed by renormalizing.

Gimbal lock, live

The clearest way to feel why Euler angles are dangerous is to watch three gimbals collapse. Drag pitch toward ±90\pm 90^{\circ}:

Gimbal lock · Euler angle singularityinteractive
loading gimbals…
Three independent axes. Drag pitch toward ±90° to collapse them.

Drag the scene to orbit.

Outer ring = yaw about Y, middle = pitch about X, inner = roll about Z. At pitch = ±90° the roll axis aligns with the yaw axis; two sliders now produce the same motion and the orientation cannot rotate freely in the lost direction.

An engine that stored orientation as Euler angles would hit this singularity in the middle of a simulation: near it, small angular velocities demand enormous angle rates, and the integrator explodes. That is why the state you actually find inside MuJoCo, PhysX, or Bullet is a unit quaternion, and why the integrator works in so(3)\mathfrak{so}(3) through the exponential map. The next piece packages this together with linear motion into the 6D spatial-vector notation the articulated-body algorithms are written in.