Reading and display settings

Appearance

System follows your operating system and keeps following it, even if you change it later. The header's sun, moon and monitor cycle the same three options.

Text size (%) 100%

Default. Scales every text size on the site, equations and tables included.

Reading width 70ch

How much text runs across one line of prose. Narrower is easier to track; wider fits more on screen.

Line spacing 1.6

The leading on body text. Taller leading helps a tired eye stay on the line.

Density

Padding and gaps around controls, cards, and tables — how much breathing room the layout leaves itself.

Motion

System follows your operating system. Reduced removes every transition on this site. Full keeps them on unless your system asks for less.

1

Rodrigues' formula from geometry

Split, rotate the part that moves, reassemble

🎯 Goal: rotate a vector about an axis by hand, splitting it into a part along the axis, which stays put, and a part perpendicular to it, which sweeps a circle, then write the answer as a matrix.

Write the rotation vector as $\omega = \theta k$, with unit axis $k$ and angle $\theta = \lVert\omega\rVert$. To rotate $v$ about $k$, split it in two:

$$ v_\parallel = (k\cdot v)\,k, \qquad v_\perp = v - v_\parallel = -[k]_\times^2\, v. $$

The parallel part is on the axis and does not move. The perpendicular part, together with $k\times v$, spans the plane of rotation: two perpendicular vectors of equal length, like the hands of a clock. Ordinary 2D rotation in that plane gives

$$ Rv = v_\parallel + \cos\theta\, v_\perp + \sin\theta\,(k\times v). $$

Substitute $v_\parallel = v - v_\perp$, write the cross products with $[k]_\times$, and everything collects into one matrix acting on $v$. That matrix is Rodrigues' rotation formula:

$$ \operatorname{Exp}(\theta k) = I + \sin\theta\,[k]_\times + (1-\cos\theta)\,[k]_\times^2. $$

The demo draws all three pieces. The circle traced by the tip lies in a plane perpendicular to $k$; its radius $\lVert v_\perp\rVert$ never changes; and $k\cdot v$ is the same before and after.

axis k v∥ (fixed) v⊥ and k×v v Rv
2

The same formula from the power series

One identity collapses an infinite sum

🎯 Goal: sum $\exp([\omega]_\times)$ exactly, using the single identity $[k]_\times^3 = -[k]_\times$, and see how many terms a truncated series needs.

The matrix exponential is the same power series as for numbers: $\exp(A) = \sum_n A^n/n!$. With $A = \theta[k]_\times$, everything hinges on one fact: for a unit vector, $[k]_\times^3 = -[k]_\times$. You can check it by taking the cross product with $k$ three times. Every power therefore reduces to $\pm[k]_\times$ or $\pm[k]_\times^2$:

$$ \exp(\theta[k]_\times) = I + \Bigl(\theta - \tfrac{\theta^3}{3!} + \tfrac{\theta^5}{5!} - \cdots\Bigr)[k]_\times + \Bigl(\tfrac{\theta^2}{2!} - \tfrac{\theta^4}{4!} + \cdots\Bigr)[k]_\times^2 = I + \sin\theta\,[k]_\times + (1-\cos\theta)\,[k]_\times^2. $$

So "Exp" is not a metaphor: Rodrigues' formula is the matrix exponential, summed in closed form. In terms of the unnormalized $\omega$, which is how code stores it,

$$ \operatorname{Exp}(\omega) = I + \frac{\sin\theta}{\theta}[\omega]_\times + \frac{1-\cos\theta}{\theta^2}[\omega]_\times^2, \qquad \theta = \lVert\omega\rVert. $$

The chart shows the error of the truncated series for each number of terms. The closed form costs one sine and one cosine; the series needs more terms as $\theta$ grows. Truncated series still turn up in real code as small-angle approximations, and the chart shows what they cost.

$\log_{10}\lVert \sum_{n\le N}[\omega]_\times^n/n! - \operatorname{Exp}(\omega)\rVert$ for each $N$. The highlighted bar is the current $N$. The dashed line is double-precision round-off.

3

The logarithm: reading off axis and angle

Trace for the angle, skew part for the axis

🎯 Goal: invert Rodrigues' formula. The trace gives the angle, the skew-symmetric part gives the axis.

Take the trace of Rodrigues' formula. $\operatorname{tr}[k]_\times = 0$ and $\operatorname{tr}[k]_\times^2 = -2$, so $\operatorname{tr}R = 1 + 2\cos\theta$. Take the skew part: $R - R^\top = 2\sin\theta\,[k]_\times$. That gives two formulas:

$$ \theta = \arccos\frac{\operatorname{tr}R - 1}{2}, \qquad \operatorname{Log}(R) = \omega = \frac{\theta}{2\sin\theta}\,\bigl(R - R^\top\bigr)^\vee. $$

Build any rotation with the yaw, pitch and roll sliders (Euler angles are fine as an input device). The readout runs the logarithm step by step, then feeds the answer back through Exp to confirm it reproduces $R$. The principal logarithm always returns $\theta\in[0,\pi]$: every rotation by more than $180^\circ$ is reported as the shorter rotation the other way.

The gray frame is the identity, the colored frame is $R$. The magenta arrow is $\operatorname{Log}(R)$: the axis to turn about, with length equal to the angle (drawn at 0.4 of scale). The arc shows the turn itself. Drag to orbit.

4

Two numerical traps

Near zero and near π, the textbook formula fails

🎯 Goal: watch the textbook Log lose all its digits at the two ends of $[0,\pi]$, understand why, and see the branches that robust implementations add.

The Log formula divides $\theta$ by $2\sin\theta$. That goes wrong at both ends of the range.

Near $\theta = 0$: numerator and denominator both vanish, and their ratio tends to $\tfrac12$. Because that ratio barely depends on $\theta$, the formula stays accurate for a surprisingly long way down. But once $\theta$ drops below about $10^{-8}$, $\operatorname{tr}R$ rounds to exactly $3$, $\arccos$ returns exactly $0$, and the formula returns $0/0$, a NaN. That is a crash rather than an inaccuracy, at the identity, the most common input of all (every optimizer's converged step, every stationary IMU sample). The fix is to replace the ratio by its Taylor expansion $\theta/(2\sin\theta)\approx \tfrac12 + \theta^2/12$ below a threshold, and to compute $\theta$ with $\operatorname{atan2}(\lVert(R-R^\top)^\vee\rVert/2,\ (\operatorname{tr}R-1)/2)$, which is accurate at every angle.

Near $\theta = \pi$: $\sin\theta\to 0$ but $\theta$ does not, so the formula divides a vanishing skew part by a vanishing number, and round-off in $R-R^\top$ is magnified without bound. The axis has to come from the symmetric part instead. From Rodrigues' formula, $\tfrac12(R + R^\top) = \cos\theta\,I + (1-\cos\theta)\,kk^\top$, so

$$ kk^\top = \frac{\tfrac12(R+R^\top) - \cos\theta\, I}{1-\cos\theta}, $$

and $k$ is read off the largest diagonal entry, with its sign taken from the (tiny but still meaningful) skew part. The demo builds rotations at a controlled distance from each trap and measures the relative error $\lVert\operatorname{Log}(R) - \omega\rVert/\lVert\omega\rVert$ of the recovered rotation vector for both implementations. It uses exactly the code in the next listing.

Relative error of Log against distance from the trap (log–log). Magenta: textbook formula. Blue: robust branches. Left panel: θ → 0. Right panel: θ → π.

// SO(3) Log that is accurate at every angle (as in assets/js/lie-viz.js)
function log(R) {
  const c  = (trace(R) - 1) / 2;
  const sv = vee(R - Rᵀ);                  // = 2 sinθ · k
  const th = atan2(norm(sv) / 2, clamp(c, -1, 1));
  if (th < 1e-4)                           // near 0: Taylor, no acos
    return sv * (0.5 + th*th/12);
  if (π - th < 1e-3) {                     // near π: axis from the symmetric part
    const B = (sym(R) - c·I) / (1 - c);    // = k kᵀ
    let k = column of B with the largest diagonal, normalised;
    if (dot(k, sv) < 0) k = -k;            // sign from the skew part
    return th * k;
  }
  return sv * th / (2 sin th);
}

The same care applies to Exp. $(1-\cos\theta)/\theta^2$ suffers catastrophic cancellation for small $\theta$ (two nearly equal numbers subtracted), so robust code switches to $\tfrac12 - \theta^2/24$ below a threshold. Every Lie library (Sophus, GTSAM, manif) carries these branches, and so should any implementation you write.

5

The shape of SO(3): a ball of radius π

Every rotation once, with the surface glued

🎯 Goal: picture all of $SO(3)$ at once as the set of rotation vectors of length at most $\pi$, and see why a steadily spinning body's Log jumps across the ball.

The principal Log sends each rotation to a vector $\omega$ with $\lVert\omega\rVert\le\pi$. Inside the ball the correspondence is one-to-one. On the surface, $\pi k$ and $-\pi k$ are the same rotation (a half-turn is the same in either direction), so the two antipodal points are identified. $SO(3)$ is exactly this ball with opposite surface points glued together. It is a compact, curved, three-dimensional space.

Spin a body steadily about a fixed axis and follow $\operatorname{Log}(R(t))$. It travels out along the axis to the surface, reappears at the opposite point, and comes back in to the centre after a full turn. A smooth motion in the group produces a jump in coordinates, which is the 3D version of the $\pm\pi$ cut on the circle. For a wobbling path, the random-walk button shows the same jumps happening wherever the path crosses the surface.

The sphere of radius π. The path is $\operatorname{Log}(R(t))$; segments that jump across the ball are drawn dashed. The frame at the right is $R(t)$ itself. Drag to orbit.

6

Measuring how far apart two rotations are

Geodesic angle versus chordal distance

🎯 Goal: define the natural distance on $SO(3)$ with Log, and relate it to the cheaper Frobenius "chordal" distance.

Log gives the natural distance between two rotations: the angle of the rotation that takes one to the other,

$$ d_{\text{geo}}(R_1,R_2) = \bigl\lVert\operatorname{Log}(R_1^\top R_2)\bigr\rVert \in [0,\pi], \qquad d_{\text{chord}}(R_1,R_2) = \lVert R_1 - R_2\rVert_F = 2\sqrt2\,\sin\!\tfrac{d_{\text{geo}}}{2}. $$

They agree to first order ($2\sqrt2\sin(\theta/2)\approx\sqrt2\,\theta$) and are monotonically related, so for ranking or thresholding either works. For averaging they differ, because the chordal distance saturates at large angles and so weights outliers less. Part 10 uses exactly this difference in rotation averaging. The table gives both for common angles.

Geodesic angle θ1°10°45°90°180°
$\lVert R_1-R_2\rVert_F$0.02470.24651.08242.00002.8284
$\sqrt2\,\theta$ (first-order)0.02470.24681.11072.22144.4429
7

Check your understanding

0/5 answered