Where you are. You can compute where the hand is from the joint angles, build the Jacobian at any pose, and say what a singularity does to it. This lesson runs the whole thing backwards, which is the direction every real task needs.
Pin your fingertip to the table
Put your index fingertip on a spot on the table and press lightly, enough that you would feel it slide.
Now swing your elbow out to the side, then tuck it back against your ribs. Your shoulder rolls, your forearm turns, your elbow sweeps through most of a foot of arc, and the fingertip does not move. Nothing about that spot on the table told your arm what to do with the elbow.
Now slide the fingertip straight away from you until the arm is straight, and try to keep going. Nothing you do at the shoulder or the elbow buys another millimetre. Notice the last part of that journey too: in the final centimetre of reach, the elbow had to swing a long way to buy very little.
Three things happened in twenty seconds. One fingertip position, many arm configurations. A place where the configurations run out. And a neighbourhood just before it where the exchange rate between joint motion and hand motion goes bad. Every difficulty in this lesson is one of those three.
The idea in one paragraph
Forward kinematics is a function: angles in, exactly one pose out, no way to fail. Inverse kinematics is the same question backwards, and it is not a function. A pose can have several sets of joint angles that reach it, none at all, or a continuum. Two tools cover the ground. For a simple geometry like the two-link arm, trigonometry gives a closed form that hands you both answers exactly. For everything else you iterate: measure how far off you are, ask the Jacobian which joint motion closes the gap, take a fraction of the step it suggests, go round again. That loop is six lines long and knows nothing about the arm it drives, which is why it is the default. It has one dangerous failure mode - asking a nearly singular Jacobian for something it cannot deliver - and one extra term fixes it.
Forward is evaluation; backward is a solve
Those two words are the whole difficulty gap. is something you evaluate. is something you solve, and solving is a different class of problem.
The asymmetry shows in the return type. FK is typed angles -> pose. IK cannot be, because it has to be able to hand back nothing, or a set.
| What you asked for | What comes back | Why |
|---|---|---|
| A reachable pose | Several answers | Different configurations put the hand in the same place; two for the planar two-link arm, up to eight for a typical six-axis industrial arm |
| A pose outside the workspace | Nothing | No configuration exists, and the solver has to say so rather than return its best wrong guess |
| A reachable pose on a redundant arm | Infinitely many | More joints than the task constrains; your own seven-joint arm is the one you just felt at the table |
Wider than the screen; scroll it sideways.
The two-link arm is a triangle
Three points: the base, the elbow, and the target. Two of the distances between them are fixed by the hardware - base to elbow, elbow to target - and the third, , is fixed by where the target is. Three side lengths pin down a triangle up to a reflection, and that is the whole closed form. The rest is extracting angles.
Start with the law of cosines on the interior angle at the elbow, :
In words: the distance across a triangle grows as the angle facing it opens up. Rearrange for the angle, minding one detail. is the interior angle, but is measured from link 1 extended, so and :
Read it as a sentence: how far away the target is decides how bent the elbow must be. Direction does not appear. With and metres, every target at distance 1.1 needs .
Wider than the screen; scroll it sideways.
Now the shoulder. Let be the direction of the target from the base. Pointing link 1 straight along would put the hand off to one side, because link 2 leaves the elbow at an angle. So aim at the target, then back off by the angle link 2 steals:
Worked through for the target : , so and ; and , so . Forward kinematics on those two angles lands on to within 2.5e-16.
Why there are always two
returns the non-negative angle, but , so satisfies the same equation, and flipping the sign of also flips , moving to . Two complete answers: the elbow sits at in one and in the other, fingertip on the target in both, agreeing to within 1.2e-15 across 20,000 random reachable targets. Geometrically it is the triangle mirrored about the line from base to target, the paper version of what you felt with your fingertip pinned.
The branches are called elbow-up and elbow-down, and the names describe the sign of , not which way the elbow points. Positive always puts the elbow on the same side of that line, but for a target in front of the robot that side looks like down, and for one behind it, up.
Reachability comes free
has to lie in . Outside that range no triangle exists with those side lengths, which is the algebraic form of “you cannot reach it”. At the formula gives , at it gives . Both are refusals, and together they bound the reachable ring between and , the same annulus drawn in workspace and reachability.
Why the closed form runs out
Every step above used the fact that this arm is two links in a plane. Add a third and the base, two elbows and the target form a quadrilateral, which three side lengths do not pin down. Offset one joint axis by a centimetre and the derivation is scrap. So the general method has to know nothing about the geometry, and may assume only that you can compute and .
Run the Jacobian backwards
You are at , the hand is at , you want it at . The miss is a vector in hand space:
The Jacobian says a small joint step moves the hand by about . You want that motion to be , so solve , take part of that step, rebuild everything at the new pose, repeat.
Wider than the screen; scroll it sideways.
This is Newton’s method on , in a shape you already own: forward pass, error, local linear model, parameter update. The Jacobian plays the part the gradient plays when training a network.
The step fraction matters more than it looks. is a linear model of a curved map, honest only near the pose where you built it, so walking the full distance it recommends can land you somewhere it never described. Over 200 random reachable targets from one fixed seed:
| Step fraction | Converged to 1e-6 | Median iterations | Worst case |
|---|---|---|---|
| 200 / 200 | 64 | 73 | |
| 200 / 200 | 22 | 31 | |
| 187 / 200 | 7 | never converged |
The seed also chooses the branch, less reliably than folklore suggests. Seeded at and jumping cold to a random target, the solver landed on the branch 189 times out of 200. Tracking a target that moved 5 mm at a time, reseeded from the previous solution, it held the branch 200 out of 200. So “seed from the current configuration and keep the branch” is solid while you are following something, and only a tendency when you jump.
The damping term, and when it is actually working
Solving exactly means dividing by the Jacobian’s smallest singular value, and singularities is the lesson about what that costs. The short version: at , a hair off straight, the smaller singular value is 0.0038, so asking for 5 cm of hand motion along the arm’s own axis returns a joint step of 13.20 radians. At exactly the matrix is rank 1 and np.linalg.solve raises LinAlgError: Singular matrix.
So the loop does not ask for the exact answer. It asks for a nearby one:
Two things about are worth knowing before you tune it, and neither is obvious.
It is free until it is needed. Over the same 200 targets, , and all converged 200 / 200 with an identical median of 22 iterations. Only at do you pay, and barely: median 25, worst case 56. So pick for the worst pose you expect to visit, not the average one, because the average one is not charging you.
A reachable target near the edge does not trigger it. Aim the solver 0.001 inside the outer rim, about as close to a singularity as a reachable target gets, and run 100 fixed steps. Undamped and damped are identical: both peak at 1.14 radians per step, both land on the target to machine precision. The shipped experiment in code/ik_2link.py sets up exactly this case and then claims in its final line that the undamped run whips the joints. It does not, and the numbers it prints say so.
What actually separates them is an impossible request. Move that same target 0.05 past the rim and the undamped run winds through more than three full turns and finishes 2.449 from the target, while the damped one stretches to the rim and stops 0.065 short - the full measurement is the table in singularities. The lesson for IK specifically is that damping is what makes a wrong request degrade instead of explode, and wrong requests are the normal case: a perception error, a policy that has not learned the workspace, an operator typing a number.
That is the argument for running the closed form’s reachability test first. is one comparison, it is exact, and it separates “cannot be done” from “not converged yet” - a distinction the iterative solver cannot make about itself, because both look like a residual that stopped shrinking.
Review
Forward is evaluation; backward is a solve
Forward kinematics is a function: angles in, exactly one pose out, no way to fail. Inverse kinematics is the same question backwards, and it is not a function. A pose can have several sets of joint angles that reach it, none at all, or a continuum. The asymmetry shows in the return type. Forward is typed angles to pose; inverse cannot be, because it has to be able to hand back nothing, or a set. A reachable pose gives several answers, two for the planar two-link arm and up to eight for a typical six-axis industrial arm. A pose outside the workspace gives nothing, and the solver has to say so rather than return its best wrong guess. A redundant arm gives infinitely many, which is what you feel when you pin a fingertip to the table and swing your elbow through a foot of arc without moving it.
The two-link arm is a triangle
Three points: the base, the elbow and the target. Two of the distances between them are fixed by the hardware, the third is fixed by where the target is, and three side lengths pin down a triangle up to a reflection. That is the whole closed form; the rest is extracting angles. The law of cosines at the elbow reads as a sentence: how far away the target is decides how bent the elbow must be, and direction does not appear in it at all. The shoulder is then the direction to the target, minus the angle the second link steals. There are always two answers because cosine is even, so flipping the sign of the elbow angle satisfies the same equation; geometrically it is the triangle mirrored about the line from the base to the target. Reachability comes free, because a cosine outside minus one to one is the algebraic form of you cannot reach it.
When there is no closed form, iterate carefully
Add a third link and the derivation is scrap, so the general method assumes only that you can compute forward kinematics and the Jacobian. Measure the miss in hand space, ask the Jacobian which joint motion closes it, take a fraction of that step, rebuild everything at the new pose and go round again. It is Newton’s method, with the Jacobian playing the part the gradient plays when training a network. The step fraction matters more than it looks, because the Jacobian is a linear model of a curved map and is honest only near where you built it. Over two hundred targets, taking the full step converged in seven iterations and failed thirteen times, and those failures sat in the comfortable middle of the workspace, so that is overshoot rather than singularity. Halving the step costs three times the iterations and buys back all thirteen. Damping is the separate fix: instead of asking for the joint step that produces exactly this hand motion, ask for the one that gets closest without being large.
Check yourself
1. cos θ2 = (r² − l1² − l2²) / (2 l1 l2) contains no reference to the direction of the target. Why not, and what does that tell you about the solution set?
Because is an interior property of the triangle formed by base, elbow and target, and a triangle is determined by its three side lengths alone. Turning the whole triangle about the base moves the target without changing any side length, so cannot depend on direction. Every target at the same distance needs the same elbow bend; with and , everything at radius 1.1 needs . Direction is absorbed entirely by , through the term.
2. Where does the second solution come from algebraically, and what does it look like on the arm?
From . The formula fixes , and both and satisfy it, so you get two elbow angles. Flipping the sign of also flips , which moves by . Geometrically it is the triangle mirrored about the line from base to target: the elbow swings to the other side of that line while the fingertip stays put. For the target the two answers are and , with elbows at and . Forward kinematics puts the hand on the target in both, agreeing to 1.2e-15.
3. Your solver is converging on well-conditioned targets in the middle of the workspace and failing on about 6% of them. Damping is on. What do you look at first?
The step fraction, not the damping. Damping protects the near-singular case, and the middle of the workspace is not that case. Failures clustered away from the edges are overshoot: a step size near 1.0 walks past where the local linear model is valid, so the iteration wanders instead of settling. Measured: failed 13 of 200 at radii between 0.41 and 0.98, while converged 200 of 200 at the cost of going from a median of 7 iterations to 22.
4. You aim the solver at a target just inside the outer edge, and λ = 0 and λ = 0.01 print exactly the same numbers. Is your damping broken?
No. Both peak at 1.14 radians per step and both land on the target to machine precision, because the target is reachable and the iteration never has to ask for motion the arm cannot deliver. Damping only changes the answer when the requested motion has a real component in a direction whose singular value is small, and merely being near the rim is not enough - the solver has to be asking for something out there. Move the same target 0.05 past the rim and the two diverge immediately, 22.42 radians against 2.50. Being close to a singularity is not the trigger; asking a nearly singular Jacobian for something it cannot deliver is.
5. Your solver returns after 200 iterations with a residual of 0.05 and no error raised. What are the two explanations, and how do you tell them apart in one line?
Either the target is unreachable, or the iteration simply has not converged - a poor seed, too small a step, a limit in the way. The iterative solver cannot distinguish them about itself, because both look like a residual that stopped shrinking. The closed form can: compute and check , which for this arm is exactly the ring from 0.30 to 1.70. Run that before the solver. A system that reports “out of range” is a different system from one that reports joint angles for a pose it never actually reached.
6. If the closed form is exact and instant, why is the iterative method the one worth learning properly?
Because the closed form is a derivation, not an algorithm. It used the fact that this arm is two links in a plane; add a link, offset an axis, or use a wrist whose axes do not intersect and it has to be redone or may not exist. The iterative loop assumes only that you can compute and , so the same six lines drive any mechanism. Where a closed form does exist it is worth using - faster, exact, and it hands you every branch explicitly rather than whichever one the seed happened to find - which is why so many industrial arms are built with a spherical wrist that guarantees one.
Do this
Open code/ik_2link.py. It already has fk; the Jacobian functions are the ones from the Jacobian, so fill those in first if you have not.
-
Implement
ik_dls. Three lines inside the existing loop: build , solve withnp.linalg.solve, thenth += alpha * dth. Runpython ik_2link.py. You should see100/100 targets converged; median iterations 21, anddet J at θ2=0printing6.00e-17, which is a floating-point zero. -
Run the shipped singularity experiment and disbelieve it.
python ik_2link.py --singularitytargets a point0.001inside the outer edge and printsmax ‖Δθ‖ per stepfor and . Its closing line claims the undamped run whips the joints. Read the two numbers. Both are1.14. The claim does not reproduce, because the target is reachable and the iteration never has to ask for anything the arm cannot give. -
Find the setup that does reproduce it. Change the target in
singularity_experimenttoL1 + L2 + 0.05, just outside the workspace, and run again. You should get22.42against2.50on the max step, and final errors of2.45e+00against6.47e-02, which is the run singularities tabulates in full. Write one sentence explaining why moving the target 5 cm further away is what made damping matter. -
Add the closed form. Write
ik_analytic(target, elbow_up=True)from the two formulas in this lesson, returningNonewhen . Check three things: that forward kinematics on both branches lands on the target, that and both returnNone, and that your iterative solver’s answer matches one of the two branches. Then print the elbow position forelbow_up=Truewith the target at and again at , and satisfy yourself about what that flag really names. -
Sweep where it costs nothing. Give
eval_ikalamargument and run it at , , and . The first three are indistinguishable, all 100/100 at a median of 21 iterations; only moves, to 26. That is the point: damping is insurance you are not paying for until you need it.
Solution: solutions/ik_2link.py.
What you can now do
You can solve a two-link arm in closed form from the law of cosines, explain why the answer always arrives as a mirrored pair and pick the one you want, and read as an exact reachability test. You can write the damped least squares loop for any arm whose Jacobian you can compute, choose a step fraction for a reason rather than by feel, and say when the damping term is doing something and when it is idle. Most usefully, you can tell an unreachable target apart from an unconverged solver, which is the failure that actually shows up in a running system.