The Inertia Tensor and Angular Velocity
Toss a book into the air — spine held shut with a rubber band — and give it a spin. Flip it about its
long axis or its short axis and it spins clean, like a top. But flip it end-over-end about the
middle axis and something eerie happens: after half a turn it suddenly flips its face over,
wobbles, flips back, over and over, even though nothing touched it. The same trick works with a phone,
a tennis racket, or a spinning wingnut floating in a spacecraft. Cosmonaut Vladimir Dzhanibekov
filmed exactly this in orbit in 1985, and it spooked mission control.
Nothing about that motion makes sense if you think of rotation the way you think of straight-line
motion — where mass is a single number and pushing an object always makes it move the way you push.
Rotation is richer. The "mass" of a spinning body is not a number but a matrix: the
inertia tensor. Getting it right is the difference between a rigid-body simulator
that tumbles convincingly and one where everything spins like a boring gyroscope. This page builds the
inertia tensor from scratch, shows why a spinning body's angular momentum and angular velocity usually
point in different directions, and explains the flipping book.
Mass tells force how to move; the inertia tensor tells torque how to spin
For straight-line motion, momentum is mass times velocity, \mathbf{p} = m\mathbf{v}.
Mass m is a scalar, so \mathbf{p} and
\mathbf{v} always point the same way: push a puck and it slides straight
along the push. The rotational analogue relates angular velocity
\boldsymbol{\omega} (how fast, and about which axis, the body turns) to
angular momentum \mathbf{L}:
\mathbf{L} = I\,\boldsymbol{\omega}.
- I is a symmetric 3×3 matrix — six independent
numbers, not one — that measures how a body's mass is spread out around a point.
- It maps the angular-velocity vector to the angular-momentum vector,
\mathbf{L} = I\boldsymbol{\omega}, exactly as mass maps velocity to
momentum.
- Because it is a matrix, \mathbf{L} and
\boldsymbol{\omega} are generally not parallel: a body
can spin about one axis while its momentum points somewhere else entirely.
Written out, with the body's angular velocity
\boldsymbol{\omega} = (\omega_x, \omega_y, \omega_z):
\begin{pmatrix} L_x \\ L_y \\ L_z \end{pmatrix} = \begin{pmatrix} I_{xx} & I_{xy} & I_{xz} \\ I_{xy} & I_{yy} & I_{yz} \\ I_{xz} & I_{yz} & I_{zz} \end{pmatrix} \begin{pmatrix} \omega_x \\ \omega_y \\ \omega_z \end{pmatrix}.
The diagonal entries (the moments of inertia) say how hard the body resists spinning about
each axis; the off-diagonal entries (the products of inertia) are what tilt
\mathbf{L} away from \boldsymbol{\omega}. A long
thin rod is easy to spin about its length and hard to spin end-over-end — one object, two very
different resistances. That is why a single number cannot do the job.
Principal axes: the directions where spinning is clean
A symmetric matrix can always be diagonalised:
there is a special set of three perpendicular directions — the principal axes — in
which the inertia tensor becomes diagonal,
I = \begin{pmatrix} I_1 & 0 & 0 \\ 0 & I_2 & 0 \\ 0 & 0 & I_3 \end{pmatrix},
with no products of inertia at all. These axes are the eigenvectors of
I and the three moments I_1, I_2, I_3 are its
eigenvalues. Spin the body about a principal axis and
\mathbf{L} = I_k\boldsymbol{\omega} is a plain scalar multiple of
\boldsymbol{\omega} — momentum and spin point the same way, the rotation is
"clean", and left alone the body spins steadily forever. Off a principal axis, the two vectors
diverge and the body wobbles.
- The principal axes are the eigenvectors of the symmetric matrix
I; the principal moments I_1,I_2,I_3 are its
eigenvalues.
- In the principal frame I is diagonal — the products
of inertia vanish.
- \mathbf{L} \parallel \boldsymbol{\omega} exactly when
\boldsymbol{\omega} lies along a principal axis; otherwise they point
in different directions.
Any object with a bit of symmetry hands you its principal axes for free: for a box they are the three
directions perpendicular to its faces. This is why simulators love boxes, spheres and capsules — their
inertia tensors are diagonal from the start.
Seeing the two arrows diverge
Take a flat, plate-like body whose principal moments differ:
I_1 about the horizontal axis is small, I_2 about
the vertical axis is larger. Spin it about a direction that is not a principal axis and watch
the two vectors. The blue arrow is the spin axis \boldsymbol{\omega} you
chose; the orange arrow is the resulting angular momentum
\mathbf{L} = I\boldsymbol{\omega}. Because the vertical axis is "heavier",
\mathbf{L} is tugged toward it and lags the spin axis. Only when
\boldsymbol{\omega} lines up with a principal axis (slider at the far ends)
do the arrows coincide.
Worked example: a box spun off its axes
Take a solid box of mass m = 1 with distinct side lengths
a = 2 (x), b = 1 (y),
c = 3 (z). Its inertia tensor about the centre, in the body frame lined up
with the edges, is diagonal with
I_{xx} = \tfrac{1}{12}m(b^2 + c^2) = \tfrac{1}{12}(1 + 9) = 0.833,
I_{yy} = \tfrac{1}{12}m(a^2 + c^2) = \tfrac{1}{12}(4 + 9) = 1.083,
I_{zz} = \tfrac{1}{12}m(a^2 + b^2) = \tfrac{1}{12}(4 + 1) = 0.417.
Three different numbers — the box resists spinning about each edge differently. Now spin it about a
direction wedged between the x and y edges,
\boldsymbol{\omega} = (1, 1, 0). The angular momentum is
\mathbf{L} = I\boldsymbol{\omega} = (I_{xx}\cdot 1,\; I_{yy}\cdot 1,\; I_{zz}\cdot 0) = (0.833,\; 1.083,\; 0).
Compare the directions. \boldsymbol{\omega} sits at exactly
45^\circ from the x-axis. But
\mathbf{L} sits at
\arctan(1.083 / 0.833) \approx 52.4^\circ — a 7.4° gap.
The momentum leans toward the y-edge because the box is harder to spin that way. Feed
\boldsymbol{\omega} straight down a single edge instead
((1,0,0)) and the gap collapses to zero:
\mathbf{L} = (0.833, 0, 0) is parallel to
\boldsymbol{\omega}. That is a principal axis at work.
The tensor lives in the body frame — and must be rotated to the world each step
Here is the subtlety that trips up every first rigid-body engine. The inertia tensor
I_{\text{body}} is constant in the body's own frame: the
mass never moves relative to the object, so its principal moments never change. But the body
tumbles in the world, so the tensor as the world sees it changes every frame. If
R is the body's current orientation (a rotation matrix taking body
coordinates to world), then
I_{\text{world}} = R\, I_{\text{body}}\, R^{\mathsf{T}}.
Reading it right to left: R^{\mathsf{T}} takes a world-frame
\boldsymbol{\omega} back into the body, where the constant
I_{\text{body}} acts, and R carries the result
back out to the world. Because engines actually need \boldsymbol{\omega}
from \mathbf{L} (angular momentum is what is conserved and integrated), they
store the constant inverse I_{\text{body}}^{-1} once and
rebuild the world inverse each step:
I_{\text{world}}^{-1} = R\, I_{\text{body}}^{-1}\, R^{\mathsf{T}}, \qquad \boldsymbol{\omega} = I_{\text{world}}^{-1}\,\mathbf{L}.
interface Mat3 { /* 3x3, row-major */ m: number[] }
// Stored ONCE at setup: the body-frame inverse inertia (constant, diagonal for a box).
const invIbody: Mat3 = diag(1 / Ixx, 1 / Iyy, 1 / Izz);
// Every substep: rebuild the world inverse from the current orientation R.
function angularVelocity(R: Mat3, L: Vec3): Vec3 {
const invIworld = mul(mul(R, invIbody), transpose(R)); // R · I_body⁻¹ · Rᵀ
return apply(invIworld, L); // ω = I_world⁻¹ · L
}
Storing the inverse in the body frame means the expensive part (the inversion, and often the
diagonalisation) happens once, offline; the per-step cost is just two matrix products.
Euler's equations: why a free body tumbles
Write the rotational dynamics in the body's own principal frame and, with no external torque, you get
Euler's equations:
\begin{aligned} I_1\dot{\omega}_1 &= (I_2 - I_3)\,\omega_2\,\omega_3, \\ I_2\dot{\omega}_2 &= (I_3 - I_1)\,\omega_3\,\omega_1, \\ I_3\dot{\omega}_3 &= (I_1 - I_2)\,\omega_1\,\omega_2. \end{aligned}
Look at the right-hand sides. If the body spins purely about one principal axis — say
\boldsymbol{\omega} = (\omega_1, 0, 0) — every product
\omega_i\omega_j vanishes, so all the
\dot{\omega} are zero and the spin holds steady. But once two components are
nonzero, they drive each other: the coupling terms pump angular velocity between the axes even
though total angular momentum \mathbf{L} is perfectly conserved in the
world. That energy-shuffling between axes is the non-trivial tumbling you see when you toss any
irregular object — a phone, a remote, a hammer.
(1) The inertia tensor is NOT constant in world space. Only
I_{\text{body}} is constant. As the body rotates, the world-space tensor is
I_{\text{world}} = R\,I_{\text{body}}\,R^{\mathsf{T}} and changes every
frame. Plugging the fixed body-frame tensor straight into world-space equations gives the wrong
\boldsymbol{\omega}, wrong torques, and a simulation that leaks or invents
energy. Always rotate the tensor (or its inverse) into the current orientation first.
(2) L and ω are not interchangeable. They are only parallel on a principal axis. Code
that treats "the spin axis" and "the angular momentum" as the same vector will look fine for a sphere
and fall apart for a tumbling box.
(3) Spinning about the intermediate axis is unstable — objects flip. This is the
Dzhanibekov effect (the tennis-racket theorem). Order the principal moments
I_1 < I_2 < I_3. Euler's equations make spin about the largest
(I_3) and the smallest (I_1) axes
stable — a tiny wobble stays tiny — but spin about the middle axis
I_2 is unstable: the smallest perturbation grows exponentially and
the body periodically flips end over end. It is not numerical error; it is real physics, and a correct
simulator will reproduce it. If your engine's book/phone/racket refuses to flip, your torque handling
is probably wrong.
In 1985 Vladimir Dzhanibekov unscrewed a wingnut aboard the Salyut-7 station and flicked it off its
bolt. It sailed across the cabin spinning quietly — then, without anything touching it, snapped around
180°, spun a while, snapped back, and kept doing so at regular intervals. The Soviets classified the
footage for a decade, half-wondering if it hinted at something deep and cosmic. It was Euler's
equations from 1765, hiding in plain sight: the nut was spinning near its intermediate axis, and the
instability flipped it over and over. The maths had been on the books for two centuries; it just took
a weightless wingnut to make it visible.