Analytic Two-Bone IK
An animator drops a target where they want a character's hand to land — on a doorknob, a coffee
cup, the rung of a ladder — and the arm just reaches it, shoulder and elbow bending into
place automatically. That reach is
the IK problem:
given where the end of a bone chain should go, find the joint angles that put it there. In general
IK is a search — you iterate toward the goal. But for the single most common case in every rig, a
two-bone limb (upper arm + forearm, thigh + shin), there is no search at all. The
answer is a closed-form formula, and its engine is a theorem you already know: the
law of cosines.
The reason it collapses to a formula is geometry. A shoulder, an elbow and a hand are three points;
the two bones and the straight shoulder-to-hand line form a triangle with two known
side lengths (the bone lengths L_1, L_2) and a
known third side (the distance d from shoulder to target). A triangle
with all three sides known has fixed angles — and the law of cosines hands them to us directly. No
Jacobian, no iteration, no convergence to babysit.
The elbow bend comes straight from the law of cosines
Put the shoulder at the origin and the target a distance d away. The
interior angle at the elbow — the angle between the two bones — is the one
knob that controls how far the hand reaches from the shoulder: straighten the elbow and the hand
stretches out to L_1 + L_2; fold it and the hand pulls in toward the
shoulder. We want the exact bend that makes the hand sit at distance d.
In the shoulder-elbow-hand triangle, the side opposite the elbow is the shoulder-to-hand
distance d, and the two sides meeting at the elbow are the bones
L_1 and L_2. The law of cosines relates them:
d^2 = L_1^2 + L_2^2 - 2 L_1 L_2 \cos\theta,
where \theta is the interior elbow angle. Solve for the cosine and the
whole "how much do I bend?" question is answered in one line:
- The interior (elbow) angle of a two-bone limb reaching a target at distance
d is
\displaystyle \theta = \arccos\!\frac{L_1^2 + L_2^2 - d^2}{2 L_1 L_2}.
- It is monotone in d: a farther target
(d \to L_1+L_2) drives \theta \to 180^\circ
(a straight arm); a nearer target (d \to |L_1-L_2|) drives
\theta \to 0^\circ (fully folded).
- It depends only on the distance d, never on the
direction to the target — direction is the shoulder's job, next.
Aiming the shoulder: point the whole chain at the target
The elbow bend fixes the arm's shape so the hand is the right distance out; now we rotate
that shape so it actually points at the target. Do it in two parts. First find the
base direction from the shoulder straight to the target,
\varphi = \operatorname{atan2}(t_y - s_y,\; t_x - s_x),
the angle of the shoulder-to-target line. If the arm were straight it would just point along
\varphi. But a bent arm's first bone does not aim right at the
target — it sits off to one side by the angle at the shoulder inside the triangle. That
shoulder-interior angle \alpha is another law-of-cosines drop-out, this
time on the side opposite L_2:
\alpha = \arccos\!\frac{L_1^2 + d^2 - L_2^2}{2 L_1 d}.
So the upper bone's world direction is the base direction plus (or minus) that offset,
\theta_{\text{shoulder}} = \varphi \pm \alpha, and the elbow lands at
e = s + L_1\big(\cos(\varphi \pm \alpha),\; \sin(\varphi \pm \alpha)\big).
From there the forearm simply closes the triangle to the hand — which, by construction, lands
exactly on the shoulder-to-target ray at distance d. The recipe is:
align the base direction, then add the elbow-plane rotation.
The \pm in \varphi \pm \alpha is not sloppiness
— it encodes a genuine ambiguity. For any reachable target the triangle can close
two ways: the elbow can jut up or down (a knee can point forward or backward). Both
put the hand exactly on target; both are perfectly valid solutions. The distance
d fixes the bend, the direction \varphi fixes
the aim, but which side the elbow swings to is left free.
In 3-D that free choice is a whole rotation about the shoulder-to-target axis — the
elbow can swivel anywhere on a circle around that line, and nothing in "reach the target" pins it
down. That is why every game and film rig gives a two-bone IK chain a pole vector
(also called a swivel or hint): a little locator the solver points the elbow toward. Knees
and elbows always need this hint, or they flip and pop unpredictably between frames. The pole vector
is the human telling the maths which of the infinitely many correct elbow positions looks right.
Worked example: the right-angle elbow
Take the cleanest possible case: two equal bones, L_1 = L_2 = 1, and a
target at distance d = \sqrt{2} from the shoulder. Plug straight into the
elbow formula:
\cos\theta = \frac{L_1^2 + L_2^2 - d^2}{2 L_1 L_2} = \frac{1 + 1 - (\sqrt{2})^2}{2\cdot 1 \cdot 1} = \frac{1 + 1 - 2}{2} = \frac{0}{2} = 0.
A cosine of 0 means \theta = 90^\circ: the two
bones meet at a right angle. And that must be right, by Pythagoras — two
perpendicular unit legs span a hypotenuse of
\sqrt{1^2 + 1^2} = \sqrt{2}, which is exactly the shoulder-to-hand
distance we asked for. The elbow bent to precisely the angle that lets the hand touch the target.
The shoulder offset checks out too:
\cos\alpha = \dfrac{L_1^2 + d^2 - L_2^2}{2 L_1 d} = \dfrac{1 + 2 - 1}{2\sqrt{2}} = \dfrac{2}{2\sqrt{2}} = \dfrac{1}{\sqrt{2}},
so \alpha = 45^\circ — the upper bone leans 45^\circ
off the shoulder-to-target line, exactly halving the right-angle bend, as symmetry between two equal
bones demands.
Solve it live
Here is a two-bone arm with L_1 = 2 and
L_2 = 1.2, its shoulder pinned at the origin. Drag the
target (the ✕) anywhere with the sliders and watch the closed-form solver place the
elbow and hand in a single step — no iteration. The faint outer circle is the reach limit
L_1 + L_2 = 3.2; the faint inner circle is the dead zone
|L_1 - L_2| = 0.8. Push the target past either and the hand can only get
as close as the boundary — the dashed line shows the shortfall. Flip the elbow side control
to send the elbow to the other solution (the pole choice) for the very same target.
Everything you see updates from two numbers (the target position) and one bit (the elbow side)
pushed through the formulas above. That is the whole appeal of analytic IK: it is
evaluation, not search — instant, deterministic, and exact.
Clamping: what to do when the target is out of reach
The triangle only closes when the target distance d is achievable. There
are exactly two failure zones:
- Too far: if d > L_1 + L_2 the arm cannot stretch to
the target even fully straight.
- Too close: if d < |L_1 - L_2| the target is inside
the fold — even fully folded, the shorter bone can't tuck in far enough.
- The hand can only reach targets in the annulus
|L_1 - L_2| \le d \le L_1 + L_2.
The robust fix is to clamp d into that range
before feeding it to the formulas:
d \leftarrow \operatorname{clamp}\big(d,\ |L_1 - L_2|,\ L_1 + L_2\big).
When the target is too far, clamping to L_1 + L_2 straightens the arm and
points the whole straight chain at the target (the closest it can get); when too close, clamping to
|L_1 - L_2| folds it maximally. The hand lands on the boundary of the
reachable annulus, aimed at the target — a graceful "reaching as far as I can" pose instead of a
crash.
Skip the clamp and the maths bites back. If d > L_1 + L_2, the numerator
L_1^2 + L_2^2 - d^2 goes so negative that
\dfrac{L_1^2 + L_2^2 - d^2}{2 L_1 L_2} drops below
-1 — outside the valid domain of arccosine. Feed a number below
-1 (or above +1) to
\arccos and you get NaN. That NaN then poisons the elbow
position, the segments, the mesh — a limb that vanishes or explodes for a single frame the instant
the target strays too far.
The cure is one line and belongs in every two-bone solver: clamp the cosine to
[-1, 1] (equivalently, clamp d to the
reachable annulus) before calling \arccos. Never hand
\arccos an unclamped ratio.
function elbowAngle(L1: number, L2: number, d: number): number {
const raw = (L1 * L1 + L2 * L2 - d * d) / (2 * L1 * L2);
const cos = Math.max(-1, Math.min(1, raw)); // clamp BEFORE acos, or NaN
return Math.acos(cos);
}
Because the triangle trick only works when the closed loop is a triangle — three points,
two known sides, one known base. That is precisely a two-bone chain. Add a third bone (a wrist, a
finger joint) and the shoulder-to-target span is spanned by three sides, which can flex into
a continuum of shapes — there is no longer a unique triangle to solve, so no closed form. That is
when solvers fall back to iterative methods (Jacobian-based, or heuristics like FABRIK) that crawl a
many-jointed chain toward the goal. Two bones is the sweet spot the whole industry leans on: arms and
legs are two bones, and analytic two-bone IK gives them a perfect, instant, iteration-free reach.