Forward Kinematics
A rigged character is a hierarchy of bones: the hand hangs off the forearm, the
forearm off the upper arm, the upper arm off the shoulder, and so on up to the root. When an animator
poses that arm, they don't type in world coordinates for the fingertip — they rotate the
shoulder, then the elbow, then the wrist, and the fingertip goes wherever those rotations carry
it. Forward kinematics (FK) is the machinery that answers the resulting question:
given every joint angle, where does each bone — and the fingertip at the end — actually end
up?
It is the most natural way to pose a skeleton, and it has a lovely property: the answer is
cheap (a handful of matrix multiplies) and unique (one set of angles
gives exactly one pose). That neatness is the whole reason its harder sibling —
inverse
kinematics, which starts from a target and hunts for the angles — is a separate, much
thornier module.
Walking down the chain
Each joint i carries a local transform
M_i(\theta_i): a rotation about that joint's axis by its
angle \theta_i, composed with the fixed bone offset that
slides you along the parent bone to where the next joint sits. Because each joint lives in the
coordinate frame of its parent — this is exactly a
transform
hierarchy — you reach the end-effector by multiplying the chain from the root outward:
p_{\text{end}} \;=\; M_0(\theta_0)\, M_1(\theta_1)\, M_2(\theta_2)\cdots M_n(\theta_n)\; p_{\text{local}}.
Read it right-to-left: a point p_{\text{local}} given in the last bone's
own frame (the fingertip, say, at the tip of the last bone) is lifted into its parent's frame by
M_n, then that parent's into its parent by
M_{n-1}, and so on until it lands in world space. Want the elbow's world
position instead of the fingertip? Stop the product early — the partial product
M_0 M_1 already places the elbow. Every joint's world position and
orientation falls out of the same running product.
- FK is the map f from the vector of joint parameters
\theta = (\theta_0,\dots,\theta_n) to the world position (and
orientation) of every joint and the end-effector.
- It is evaluated by the ordered matrix product
M_0(\theta_0)\cdots M_n(\theta_n), each
M_i being a local joint rotation times a fixed bone offset.
- FK is well-posed: for any joint vector there is exactly one pose, computed in
time linear in the number of joints.
Worked example: the planar 2-link arm
Strip the idea down to a flat, two-bone arm — the canonical FK example. Bone one has length
L_1 and swings from the shoulder (fixed at the origin) by an angle
\theta_1 measured from the x-axis. Bone two has
length L_2 and bends at the elbow by \theta_2,
measured relative to bone one. The elbow sits at
(x_e,\,y_e) = \big(L_1\cos\theta_1,\; L_1\sin\theta_1\big),
and because \theta_2 is measured relative to the first bone, the second
bone points in the summed direction \theta_1+\theta_2 in world
space. Add its contribution to the elbow to reach the hand:
x = L_1\cos\theta_1 + L_2\cos(\theta_1+\theta_2), \qquad y = L_1\sin\theta_1 + L_2\sin(\theta_1+\theta_2).
That angle addition is the chain product in disguise: composing two 2-D rotations adds their
angles. Let's put numbers in. Take L_1 = 2,
L_2 = 1, \theta_1 = 30^\circ,
\theta_2 = 60^\circ, so \theta_1+\theta_2 = 90^\circ:
x = 2\cos 30^\circ + 1\cos 90^\circ = 2(0.866) + 0 = 1.732,
y = 2\sin 30^\circ + 1\sin 90^\circ = 2(0.5) + 1 = 2.000.
So the hand lands at (1.732,\, 2.000). Notice how directly it dropped out —
no solving, no iteration, just plug the angles into f. That is FK's whole
personality: evaluation, not search.
Pose it yourself
Here is the 2-link arm with L_1 = 2 and L_2 = 1.4.
Drag \theta_1 to swing the whole arm from the shoulder, and
\theta_2 to bend the elbow. Watch the hand (the end-effector) trace out
wherever the two angles send it — that swept region is the arm's reachable workspace. This is
forward kinematics running live: two numbers in, one pose out, instantly.
Everything you see is the chain product in motion: the elbow point is
M_0(\theta_1) applied to the first bone tip, and the hand is
M_0(\theta_1)M_1(\theta_2) applied to the second. Rotate the shoulder and
the elbow rides along automatically — that carrying-along is the hierarchy.
FK as a function — and why IK is hard
Package the two hand equations as a single vector function of the joint vector
\theta = (\theta_1,\theta_2):
f(\theta) = \begin{pmatrix} L_1\cos\theta_1 + L_2\cos(\theta_1+\theta_2) \\ L_1\sin\theta_1 + L_2\sin(\theta_1+\theta_2) \end{pmatrix}.
This f is nonlinear — angles enter through sines and
cosines — but it is trivial to evaluate. The hard direction is the other way: given a target
hand position (x^\star, y^\star), find angles with
f(\theta) = (x^\star, y^\star). That inverse can have two solutions
(elbow-up and elbow-down), none (target out of reach), or a whole continuum (a redundant
arm) — which is precisely why inverse kinematics needs its own module. The tool IK reaches for is the
Jacobian J = \partial f / \partial \theta, the derivative
of this very f: it says how the hand moves for a small twist of each joint,
and IK inverts it repeatedly to crawl toward the target. So FK isn't just the easy warm-up —
it is the function whose derivative every IK solver leans on.
Because animators think in goals, not angles. "Put the hand on the doorknob," "keep both feet
planted while the hips sway," "grab the falling cup" — these are all statements about where the
end of a chain should be, and FK gives you no lever on that directly: you'd have to dial in
shoulder and elbow angles by trial and error until the hand happened to land right. IK automates that
search. In practice rigs blend both: the spine and broad gestures are keyed in FK (natural for
sweeping motion), while hands and feet are driven by IK targets (natural for contact and planting).
FK is the honest, cheap evaluator underneath; IK is the goal-seeker built on top of it.
FK only works if you apply each joint rotation in hierarchy order (root first, then
down the chain) and in that joint's own local frame. Two classic ways to wreck a
pose:
- Wrong order. Matrix multiplication doesn't commute:
M_0 M_1 \neq M_1 M_0 in general. Bending the elbow before
swinging the shoulder, or multiplying the chain the wrong way round, sends the hand to a completely
different place.
- Wrong frame. The elbow angle must rotate the forearm about the elbow, in the
upper arm's frame. Apply \theta_2 as a rotation about the world
origin instead of the local joint, and the forearm swings around the character's feet — garbage.
The fix is baked into the chain product: each M_i is expressed in its
parent's frame and the parents multiply on the left, so every child inherits its parent's
transform automatically. Respect the product order and the local frames, and the pose is correct;
break either and it isn't.