Axis-Angle and Rodrigues' Formula

Gimbal lock punished us for stacking three rotations about three fixed axes. The cure is to stop stacking and rotate once, about whatever axis we like. Every rotation in 3-D — no matter how complicated — is equivalent to a single turn through some angle \theta about a single axis \hat{a}. This is the axis-angle view, and it comes with one clean formula, due to Rodrigues, that rotates any vector directly.

The setup: an axis and an angle

Specify a rotation by a unit axis \hat{a} (with \lVert \hat{a} \rVert = 1) and an angle \theta measured by the right-hand rule. We want a formula for v_{\text{rot}}, the result of turning a vector v by \theta about \hat{a}. The trick is to split v into a piece the rotation ignores and a piece it spins, handle each, and add them back.

Deriving Rodrigues' formula

Step 1 — peel off the part along the axis. A rotation about \hat{a} leaves anything pointing along \hat{a} untouched. The component of v along the axis is its dot-product projection:

v_\parallel = (\hat{a} \cdot v)\,\hat{a}.

This piece is fixed by the rotation — it just rides along the axis.

Step 2 — what is left is perpendicular. Subtract the parallel part to get the component lying in the plane the rotation actually spins:

v_\perp = v - v_\parallel = v - (\hat{a} \cdot v)\,\hat{a}.

By construction \hat{a} \cdot v_\perp = 0: it is orthogonal to the axis, so it lives entirely in the plane of rotation.

Step 3 — build a second axis inside that plane. To rotate v_\perp within its plane we need a "sideways" direction at right angles to it. The cross product supplies it: \hat{a} \times v is perpendicular to both \hat{a} and v, it lies in the rotation plane, and — because \hat{a} is a unit vector perpendicular to v_\perp — it has the same length as v_\perp:

\lVert \hat{a} \times v \rVert = \lVert v_\perp \rVert, \qquad (\hat{a}\times v) \perp v_\perp.

So \{\, v_\perp,\ \hat{a}\times v \,\} is an orthogonal pair of equal length — a perfect set of axes for the spinning plane, exactly like (\cos, \sin) coordinates.

Step 4 — rotate within the plane. Turning a vector by \theta in a plane with orthonormal-style axes v_\perp (the "x") and \hat{a}\times v (the "y") is just trigonometry — keep \cos\theta of the first and add \sin\theta of the second:

(v_\perp)_{\text{rot}} = v_\perp \cos\theta + (\hat{a} \times v)\,\sin\theta.

Step 5 — add the fixed part back. Reassemble the rotated vector from the spun perpendicular piece plus the untouched parallel piece:

v_{\text{rot}} = (v_\perp)_{\text{rot}} + v_\parallel = v_\perp \cos\theta + (\hat{a} \times v)\,\sin\theta + (\hat{a}\cdot v)\,\hat{a}.

Step 6 — substitute v_\perp = v - (\hat{a}\cdot v)\hat{a} and collect. Expanding the first term gives v\cos\theta - (\hat{a}\cdot v)\hat{a}\cos\theta; the (\hat{a}\cdot v)\hat{a} pieces combine into (1 - \cos\theta):

v_{\text{rot}} = v\cos\theta + (\hat{a}\times v)\sin\theta + \hat{a}\,(\hat{a}\cdot v)\,(1 - \cos\theta).

That is Rodrigues' rotation formula — a single closed-form expression that rotates any vector about any axis, built from nothing but a dot product, a cross product, and a sine and cosine. No three nested rings, and so no gimbal to lock.

Any 3-D rotation is a single turn through an angle \theta about a unit axis \hat{a}. To rotate a vector v:

Rodrigues' formula is the bridge to quaternions. Notice the rotation is built from \sin\theta and 1 - \cos\theta. Both are secretly half-angle quantities:

\sin\theta = 2\sin\tfrac{\theta}{2}\cos\tfrac{\theta}{2}, \qquad 1 - \cos\theta = 2\sin^2\tfrac{\theta}{2}.

Every term in Rodrigues carries a factor of \sin\tfrac{\theta}{2} or \cos\tfrac{\theta}{2}. That is no accident: the unit quaternion that performs this very rotation is

q = \cos\tfrac{\theta}{2} + \sin\tfrac{\theta}{2}\,(a_x i + a_y j + a_z k),

packaging the axis \hat{a} and the half-angle \theta/2 into four numbers. Rodrigues told us a rotation needs only an axis and an angle; the quaternion is the most efficient way to store and compose them.

Spin a vector about an axis

The grey arrow is the fixed input vector v; the dashed line is the chosen axis \hat{a}. The faint pieces show the split: the component v_\parallel along the axis (which never moves) and the perpendicular part v_\perp that does all the spinning. Drag the \theta slider and the coloured arrow v_{\text{rot}} sweeps a cone around the axis — its tip rides a circle, while v_\parallel stays pinned. Swing the axis with the tilt slider to see how it controls the cone.