30 min

Forward kinematics: joint angles to hand pose

Forward kinematics is a pure function from joint angles to where the hand is, and that determinism is the reason a robot can repeat anything at all.

Where you are. You can build a transform, compose a chain of them and invert one. This lesson turns that machinery into the single function every robot arm evaluates thousands of times a second.

A lamp, a wall, and a pencil mark

Find one of those articulated desk lamps, the sort with two arms and a spring at each hinge. Aim it at a wall and mark the centre of the bright patch with a pencil.

Now fold the lamp flat against the desk. The mark stays on the wall; the lamp keeps nothing at all. Unfold it and try to put the light back on the mark by eye. You will get close, then fiddle, then get close again.

Try a different method. Before folding, stick a strip of tape across each hinge and draw a line where the two halves meet, so you can read the hinge angle back later. Fold the lamp flat. Unfold it and bring each hinge back to its own mark.

The bright patch lands on the pencil mark. Not near it. On it.

Nothing measured the wall. Nothing measured the light. Two angles were enough to put a point in the room back exactly where it was, and they will do it again tomorrow, and next year, as long as nobody bends the lamp.

That is what this lesson is about. It is also why a machine built in 1961 could work a full shift without a single sensor pointed at the world.

The idea in one paragraph

A serial robot is a chain of rigid links connected by motors, and the only thing it measures directly is the angle of each motor. Everything you actually care about lives somewhere else: is the gripper above the cup, is it facing down, has it arrived. Forward kinematics is the function that carries you from the first description to the second. Hand it the joint angles; it hands back the pose of the end-effector, meaning where it is and which way it points. It is a pure function - the same angles always give the same pose, there is no hidden state, no search, and no way for it to fail - and it is nothing more than the transform chain you built in composing transform chains with the current angles substituted in. The trip in the other direction, from a pose you want back to angles that achieve it, is a completely different animal, and most of the rest of this module is about how much harder it is.

forward kinematics Joint space θ = (θ1 … θn) straight off the encoders FK a pure function Task space pose = (x, y, φ) where the hand is, facing where same θ in, same pose out, always inverse kinematics none, one, two, or infinitely many answers · and you have to go looking
Forward kinematics maps a vector of joint angles to exactly one hand pose, while the return trip may have no answer, one, two, or infinitely many

Wider than the screen; scroll it sideways.

Walking the chain

You already have the whole recipe. Every link in the arm contributes two transforms, in this order:

  1. A constant transform describing how that link is bolted onto the previous one: its length, its mounting angle, any offset the mechanical designer chose. This never changes while the robot runs. It is the robot’s shape.
  2. A variable transform: the rotation of that link’s own joint by its current angle. This is the only thing that moves.

Start at the base frame with the identity transform, then multiply through those pairs, one joint at a time. Whatever transform you are holding when you run out of joints is the pose of the hand, expressed in the base frame.

base frame T = identity the fold starts here link 1 T_fix1 · Rz(θ1) bolted on, then turned link 2 T_fix2 · Rz(θ2) bolted on, then turned hand pose whatever T ended up as position and orientation one pair per joint · a 6-axis arm has six of these, a humanoid has thirty T = identity; then T ← T · T_fix · Rz(θ) for each joint, in order
Forward kinematics as a fold along the chain: start at the base frame, then for each joint multiply by a constant bolt-on transform followed by that joint's own rotation

Wider than the screen; scroll it sideways.

In Python, with Rz a rotation about the joint axis and T_fix the constant bolt-on transform for each link:

def fk(chain, tool, thetas):
    T = np.eye(4)
    for (T_fix, _axis), theta in zip(chain, thetas):
        T = T @ T_fix @ Rz(theta)
    return T @ tool

That is the entire algorithm, and it is the same handful of lines for a 2-joint toy and a 30-joint humanoid. Run it against the hand-derived trigonometry for the 2-link arm over twenty thousand random configurations and the two agree to about 4e-16, which is the noise floor of double-precision arithmetic rather than a real difference.

Why this direction is the easy one

Forward kinematics has four properties that its inverse does not, and it is worth naming them separately, because every one of them is a thing the inverse will take away from you.

It always has an answer. Any vector of joint angles you can name describes some physical configuration, and that configuration puts the hand somewhere. There is no such thing as an input the function cannot handle.

The answer is unique. One configuration, one pose. Never two.

It is cheap and bounded. A fixed number of matrix multiplies, growing linearly with the joint count. No iteration, so no convergence to worry about and no worst case that differs from the average case. This is what makes it safe to put inside a control loop that must finish in two milliseconds.

It is exact. Not statistically exact, not exact after enough samples. The arithmetic is closed-form.

ForwardInverse
Givenjoint anglesa pose you want
Returnsthe poseangles that achieve it
How many answersexactly onenone, one, two, or infinitely many
Costfixed, linear in jointsusually iterative, sometimes fails
Failure modenonetarget unreachable, or a solver that diverges

The reason the inverse misbehaves is a counting argument. Forward kinematics maps an nn-dimensional joint space into a task space of fixed dimension: three in the plane, six in 3D. When nn is smaller than the task dimension, most poses have no preimage at all. When nn equals it, poses typically have a small finite number of preimages, since several arm shapes can reach the same place. When nn is larger, as on your own seven-jointed arm, a whole continuum of configurations lands on the same pose. None of that ambiguity troubles the forward direction, because the forward direction never has to choose.

Forward kinematics is also a sensor

Here is the part that surprises people arriving from software. Forward kinematics is not only a planning tool; it is how the robot answers “where is my hand right now.”

Read the encoders. Feed the angles through forward kinematics. That is your measurement of end-effector pose, and on a well-built arm it is far more accurate and far faster than anything a camera will tell you. Every learned policy in Module 3 takes exactly this vector as its proprioceptive input.

Which means the accuracy of that measurement is the accuracy of your model, and models drift.

Δθ ≈ r · Δθ how far the tip is off elbow base arm at full stretch, r = 1.70 m · the angle here is exaggerated so you can see it at all shoulder off by 0.5° → tip off by 15 mm · 1° → 30 mm · 5° → 148 mm the same 1° at the elbow moves the tip only 12 mm: just 0.70 m of arm sits beyond it
A small angle error at the shoulder becomes a large position error at the tip: the wedge between the true arm and the believed arm widens with every centimetre of arm beyond the bad joint

Wider than the screen; scroll it sideways.

There is a related honesty worth stating now. Forward kinematics assumes rigid links and exact joint angles. Real links flex under load, real gearboxes have backlash, and a real encoder mounted before a gearbox reports the motor rather than the joint. Forward kinematics gives you the pose of an idealised robot; the gap between that and the real one is what calibration exists to shrink, and what force sensing exists to work around.

Check yourself

1. Why can forward kinematics never fail, while inverse kinematics can?

Every vector of joint angles describes a physical configuration, and every configuration puts the hand somewhere, so the forward map is defined on the whole of joint space. The inverse map is defined only on the image of that function, which is a strict subset of task space: a pose the arm’s geometry cannot produce has no preimage, so there is simply no answer to return.

2. The transform chain multiplies a constant transform and a joint rotation for each link. Which is the robot’s shape and which is its state?

The constant transforms are the shape: link lengths, mounting angles and offsets, fixed by the mechanical design and identical on every robot of that model. The joint rotations are the state, changing every control cycle. Robot description files such as URDF and MJCF serialise the first list; the encoders supply the second. That split is exactly why one generic routine can do forward kinematics for any serial robot.

3. Your arm has links of 1.00 m and 0.70 m and is stretched straight out. The shoulder encoder is miscalibrated by one degree. How far off is the gripper, and why is this hard to diagnose?

About 30 mm. The tip sits 1.70 m from the shoulder, and 1.70 m times one degree in radians (0.01745) is 0.0297 m. It is hard to diagnose because nothing errors out. Forward kinematics remains internally consistent and the robot misses by the same amount in the same direction every time, which looks exactly like a systematic bias in perception or grasping.

4. You have a fixed calibration budget and can only measure two joints properly. Which two, and why?

The two nearest the base. Tip error scales with the length of arm remaining beyond the bad joint, so the same angular error is worth the most at the shoulder and the least at the wrist. On the 1.00 and 0.70 arm, a one-degree error is 30 mm at the shoulder and 12 mm at the elbow. Wrist joints usually have almost no arm beyond them and are correspondingly forgiving in position, though they still dominate orientation error.

5. A seven-jointed arm reaches a pose. How many configurations reach that same pose, and what does that give you?

Infinitely many, forming a one-dimensional family. Seven joints map into a six-dimensional task space, so one dimension of joint motion leaves the pose untouched: the elbow can swing on a circle while the hand stays perfectly still. The payoff is that you can choose among those configurations to dodge an obstacle, stay away from joint limits, or keep the arm out of the camera’s view, all without moving the hand.

6. Why is it safe to call forward kinematics inside a 500 Hz control loop but risky to call inverse kinematics there?

Forward kinematics is a fixed number of matrix multiplies with no branches and no iteration, so its worst case equals its average case and fits comfortably in a two-millisecond budget. General inverse kinematics is iterative: its runtime depends on the starting guess and the target, it can take an unbounded number of steps near an awkward configuration, and it can fail to converge at all. Anything without a hard time bound does not belong in a hard-real-time loop.

Do this

Pencil and paper, about fifteen minutes. No new code.

1. Fold a three-link chain by hand. Links of 1.00, 0.70 and 0.40, joint angles of 0.3, 0.5 and -0.2 radians, all rotating about the same axis. Because the axes are parallel, the direction of each link is the running sum of the angles before it, so:

x=1.00cos(0.3)+0.70cos(0.3+0.5)+0.40cos(0.3+0.50.2)y=1.00sin(0.3)+0.70sin(0.3+0.5)+0.40sin(0.3+0.50.2)\begin{aligned} x &= 1.00\,\cos(0.3) + 0.70\,\cos(0.3+0.5) + 0.40\,\cos(0.3+0.5-0.2) \\ y &= 1.00\,\sin(0.3) + 0.70\,\sin(0.3+0.5) + 0.40\,\sin(0.3+0.5-0.2) \end{aligned}

You should get x=1.773165x = 1.773165, y=1.023526y = 1.023526, and a hand heading of 0.6 radians exactly. Check the last one against the sum of the three angles and convince yourself why it comes out that way.

2. Do the same fold as matrices, at least on paper: Rz(0.3)Tx(1.00)Rz(0.5)Tx(0.70)Rz(0.2)Tx(0.40)R_z(0.3)\,T_x(1.00)\,R_z(0.5)\,T_x(0.70)\,R_z(-0.2)\,T_x(0.40). You do not have to multiply it out. Say instead, in one sentence each, which factor moves when the elbow moves and which factors are properties of the machine rather than of its state.

3. Build an error budget. Suppose every encoder on a six-joint arm is good to 0.1 degrees, and the distances from each joint to the gripper are 0.30, 0.30, 0.25, 0.10, 0.06 and 0.04 metres. Compute the worst case, where every error points the same way, by summing each distance times 0.1 degrees in radians. You should land near 1.8 mm. Then answer the question that actually matters on a bench: is that better or worse than the accuracy you would get by pointing a webcam at the gripper?

What you can now do

You can compute the pose of any serial arm’s end-effector from its joint angles by folding one constant transform and one joint rotation per link. You can explain why the forward direction always has exactly one answer while the reverse has none, one, two or infinitely many; why forward kinematics is cheap enough to sit inside a hard real-time loop; and why an encoder that is half a degree out will make the robot miss by centimetres without a single error message.

What you can now do

You can compute the pose of a serial arm's end-effector from its joint angles, say why that direction is the easy one, and predict how a small angle error grows into a large position error.