Where you are. You know forward kinematics is a fold over the chain. This lesson runs that fold end to end on the one arm this course will keep coming back to, and finds the first thing that genuinely surprises people.
A coin, a table, and your own arm
Put your forearm flat on a table, elbow down, palm down. Keep it there; the whole point is that nothing lifts. What you now have is a two-joint arm working in a plane: your shoulder turning your upper arm, your elbow turning your forearm, both swivelling about vertical axes.
Put a coin on the table about half an arm’s length away and touch it with your fingertip.
Now look at the shape your arm is making, and where your elbow sits relative to the straight line from shoulder to coin. Lift your hand, swing your elbow to the other side of that line, and put your fingertip back on the same coin. It goes. Same shoulder, same coin, a visibly different arm.
Try for a third. There isn’t one. Two shapes reach that coin and no others, and you cannot slide smoothly from one to the other without the fingertip leaving the coin. If yours seems to glide between them, your wrist and shoulder are cheating by adding freedom the idealised two-joint arm does not have; and if one of the two feels impossible, that is a joint limit, which gets a lesson of its own.
Two more things while you are down there. Slide the coin all the way out until you can only just touch it: at that distance there is exactly one way to reach it, arm dead straight, no elbow swing left. And slide the coin all the way in, close to your shoulder: below some radius there is no arm shape that gets your fingertip onto it at all, because your forearm is in the way.
One point, two answers. One ring where the two answers collapse into one. And a hole in the middle with no answer. Everything in the next four lessons is a formalisation of what your arm just did on that table.
The idea in one paragraph
The 2-link planar arm is two rigid links and two rotating joints, all in one flat plane. It is the fruit fly of robotics: small enough that you can derive every equation by hand in a page, rich enough that it already exhibits multiple inverse solutions, a workspace with a hole in it, a singular boundary where control blows up, and a Jacobian worth looking at. Its forward kinematics falls out of school trigonometry in three lines, and those three lines are also what you get by multiplying four homogeneous transforms together, which is the moment where the abstract machinery of the last three lessons starts paying rent. Every method you build on this arm carries over to a 6-axis industrial robot; the industrial robot just has more factors in the same product.
Wider than the screen; scroll it sideways.
The convention that bites everybody
That last definition is not a formality. It is the single most common bug in hand-written kinematics, and it is worth spending a paragraph on before any algebra.
Joint angles on a serial arm are relative. says how far link 2 is turned away from link 1, because that is what the elbow motor physically does: it rotates one link with respect to the other. It knows nothing about the world. If you turn the shoulder and leave the elbow motor completely alone, does not change, but link 2 swings through the world all the same.
So the direction link 2 points in the world is . The angles add because both joints rotate about the same axis, out of the plane, and rotations about a shared axis compose by adding.
Wider than the screen; scroll it sideways.
Three lines of trigonometry
Now the derivation, which is genuinely small. Walk the chain.
The elbow sits at the far end of link 1, which points along :
Link 2 starts there and points along , so add its contribution:
In words: the fingertip is the elbow plus a step of length in the direction link 2 is pointing, and the hand’s heading is whatever both joints have added up to. That is the whole of the 2-link arm’s forward kinematics.
Now the same thing as a transform product, in the notation of the last two lessons:
Read it left to right as instructions to a person walking the arm: turn by , march forward, turn by , march forward. Each factor is a 4x4 matrix from your own transforms library. Multiply them and the translation column of the result reproduces the two trigonometric lines exactly, and the rotation block encodes .
This is not a claim to take on trust. Run both over ten thousand random configurations and they agree to 8.9e-16, which is double-precision rounding rather than any real disagreement. That “two independent implementations must agree” pattern is how kinematics gets tested for real, forever after: a hand-derived closed form on one side, a general routine on the other, and a property test in between.
One point, two arms
Drag that widget to a point and switch elbow branches, and you have the thing your own arm did on the table.
Take the target (0.90, 0.60), comfortably inside the reachable ring. Exactly two configurations put the fingertip there:
| hand heading | |||
|---|---|---|---|
| Branch A | -5.4° | +103.2° | +97.9° |
| Branch B | +72.7° | -103.2° | -30.5° |
Wider than the screen; scroll it sideways.
The two values are equal and opposite; that is not a coincidence, and it falls out of the law of cosines when you do inverse kinematics in a few lessons. The sign of decides which side of the straight line from base to fingertip the elbow sits on: positive puts it on the clockwise side, negative on the counterclockwise side. Those are the two branches, and textbooks call them elbow-up and elbow-down.
Look again at the third column of that table. The hand heading differs by more than 128 degrees between the two branches, and you did not get to choose it. Two joints buy you two numbers of control, and you spent both on x and y. Orientation is whatever falls out. That is not a limitation of the solver; it is a property of the mechanism, and it is the subject of the next lesson.
Why a toy is the right thing to study
Two links in a plane is not a simplification you will outgrow. It is the case that isolates the phenomena.
Throughout this course the arm has and . Unequal lengths on purpose: with equal links a special case appears at the centre of the reachable area that would hide behind the general result. The numbers are unitless, and you can read them as metres for a large industrial arm or as decimetres for something desk-sized. Nothing in the mathematics cares.
Check yourself
1. Why do θ1 and θ2 simply add to give the hand’s heading, and when would that stop working?
Both joints rotate about the same axis, perpendicular to the plane, and rotations about a shared axis compose by adding their angles. It stops working the moment two joint axes are not parallel, which is the normal case in 3D: a wrist twisting about x after a shoulder turning about z composes by full matrix or quaternion multiplication, and no scalar addition shortcut exists. The planar arm is the special case where rotation happens to be one-dimensional.
2. With l1 = 1.00 and l2 = 0.70, what is the fingertip pose at θ = (0°, 0°), and at (90°, -90°)?
At (0°, 0°) the arm lies straight along +x, so the fingertip is at (1.70, 0.00) with heading 0°. At (90°, -90°) link 1 points straight up to the elbow at (0.00, 1.00), then the elbow turns back by 90° so link 2 points along +x again: the fingertip is at (0.70, 1.00) with heading 0°. Sketch the second one; it is the classic L-pose, and it is a good check that you are treating as relative.
3. Someone writes x = l1·cos θ1 + l2·cos θ2. Their unit test at θ1 = 0 passes. What has slipped through, and how big is it?
They dropped the relative-angle convention: link 2’s world direction is , not . At the two expressions are identical, which is why the test passes. Away from zero the error is real: at , the fingertip is 0.48 out of position, on an arm whose full reach is 1.70. Any test suite for kinematics must exercise every joint at a non-zero angle simultaneously.
4. Two configurations reach (0.90, 0.60). Why can you not simply pick whichever is nearer to where the arm is now?
You often can, and that is a reasonable default. But not always: the nearer branch may put a joint past its limit, may drive the elbow through an obstacle or through the arm’s own base, and may be on the far side of the straight-arm boundary, where crossing between branches requires passing through a configuration that the controller handles badly. Branch selection is a real decision with real consequences, not a tiebreak.
5. Both branches reach the same point, but the hand headings differ by more than 128°. What does that tell you about what two joints can buy?
Two joints give you two degrees of freedom, and planar task space has three: x, y and heading. Spend both of them on position and the heading is fully determined; it is an output, not an input. The only choice left is which of the two branches to take, and that offers exactly two headings out of a possible 360. Controlling position and orientation independently in the plane needs a third joint.
6. Why is checking a hand-derived formula against a general transform product a stronger test than checking either one against a handful of hand-computed poses?
Because the two implementations fail in different ways. A dropped in the trigonometry and a transposed rotation block in the matrix code are unrelated mistakes, so agreement across ten thousand random configurations is real evidence rather than a coincidence. Hand-computed test poses, by contrast, are usually the easy poses, and the easy poses are exactly the ones where common bugs are invisible.
Do this
Work code/fk_2link.py. Budget half an hour.
-
Implement
fk_trig(t1, t2)straight from the three trigonometric lines above. Return(x, y, phi). -
Implement
fk_transforms(t1, t2)as the four-factor productRz(t1) · Tx(L1) · Rz(t2) · Tx(L2), using the transforms library you completed earlier. Pullxandyout of the translation column, and recoverphifrom the rotation block withatan2(R[1,0], R[0,0]). -
Run
python fk_2link.py. The built-in cross-check compares the two implementations over ten thousand random angle pairs and asserts they agree to within 1e-9. When it passes, the numbers you get should be the ones in this lesson:(0°, 0°)gives(1.700, 0.000)and(90°, -90°)gives(0.700, 1.000). -
Deliberately break it. Change
cos(t1 + t2)tocos(t2)in the trigonometric version only, and watch which configurations the cross-check reports. Confirm that the failure vanishes whent1 = 0. This is the bug from the gotcha above, and having watched it hide from you once is worth more than reading about it.
Solution: solutions/fk_2link.py. Read it only after step 3 passes.
What you can now do
You can derive the 2-link planar arm’s forward kinematics from trigonometry and from a product of homogeneous transforms, and show the two agree to machine precision. You can explain why joint angles are relative and what it costs when someone forgets, why a single fingertip position corresponds to two different arm shapes, and why on a two-joint arm the hand’s heading is something you receive rather than something you request.