Where you are. You have a scene, an arm that grasps, and a script that drives the gripper from A to B. Every motion you have written so far has assumed nothing is in the way. This lesson is the space in which that assumption is checked.
The couch on the stairs
You are carrying a couch up a stairwell that turns through ninety degrees at a landing. It is stuck. Your friend at the bottom is offering advice.
Notice what you are both actually reasoning about. Neither of you is thinking about the couch’s shape, or the wall’s, or the handrail’s. You have reduced the whole problem to three numbers: how far along the landing the couch has got, how far across, and how far it has been turned. Every argument on that staircase is about those three numbers. Turn it more before you push. No, come back a foot first, then turn.
Some triples of numbers are fine. Some put a corner of the couch through the plaster. Getting the couch upstairs is finding a route from one legal triple to another without passing through an illegal one, and the reason it is hard is that the legal ones are a strange shape you cannot see.
Your arm has the same problem, and one great advantage: for a 2-link arm the strange shape fits on a page.
The idea in one paragraph
Give the arm one axis per joint, and any pose it can be in is a single point in the resulting space. A 2-link arm’s poses are points in a square; a 6-joint arm’s are points in a six-dimensional box. Obstacles do not appear in that space as obstacles. They appear as forbidden regions: the set of joint values at which some part of the arm overlaps something. That set is not shaped like the obstacle, it is not usually connected to itself, and there is no formula for it - the only way to know whether a point is in it is to put the arm at those joint values and check. What is left over is free space, and a motion is a curve through free space from where the arm is to where you want it. Everything the rest of this module and the whole of classical planning does happens inside that picture.
Wider than the screen; scroll it sideways.
What an obstacle turns into
Put four discs on the bench: one close in, three out near the rim. Then sweep both joints over a 360 by 360 grid and colour each cell by whether the arm hits anything. That is 129,600 collision checks, and it takes about nine seconds on this laptop.
The result has two kinds of feature in it, and each one is worth reading.
Wider than the screen; scroll it sideways.
The vertical band. The near disc sits 0.81 from the base, which is inside the upper arm’s reach. Whether the upper arm hits it depends on the shoulder angle and nothing else - the elbow can be anywhere at all and the upper arm is unmoved. So the forbidden set is a full-height stripe: a range of shoulder values, every elbow value.
The curved slivers. The rim discs sit 1.42 to 1.45 out, beyond the upper arm’s 1.00 plus its own thickness, so only the forearm can reach them. Whether the forearm hits one depends on both joints together, which is why those regions bend. Slide the shoulder a little and the elbow value that puts the fingertip into the disc slides too.
That picture also settles a question your straight-line motions have been quietly assuming away. Free space is 78.82% of this configuration space, so most poses are fine. But over 2,000 random pairs of free poses, driving from one to the other in a straight joint-space line runs through something 974 times.
| what was measured | value |
|---|---|
| free fraction of configuration space | 0.7882 |
| straight lines that hit something | 974 / 2000 |
| straight lines that were fine | 1026 / 2000 |
n = 2000 trials · two free configurations drawn at random, joined by a straight line in joint space, checked at 120 samples · 2026-08-10
Half. Interpolating between two joint targets is the move every one of your scripts has made so far, and in a scene with four objects in it, it is a coin flip.
The square is really a torus
There is one more thing the picture is hiding. A joint that turns all the way round has no left edge and no right edge: shoulder and shoulder are the same pose. So the left edge of the square is glued to the right edge, the bottom to the top, and the space is a doughnut rather than a sheet of paper.
Wider than the screen; scroll it sideways.
This is not a curiosity. Take the shoulder from to radians with the elbow held still. Read the square as a sheet and that is 5.800 radians of travel, straight through the band and all three slivers, blocked at 54 of 200 samples. Read it as a torus and the same move is 0.483 radians off one edge and back on the other, and it is free.
Reachable, free, and connected are three different words
Module 1’s workspace lesson gave you the arm’s reachable set: a ring from 0.30 to 1.70, with a hole in the middle nobody puts on the datasheet. That lesson answered can the fingertip get to this point. Configuration space answers two harder questions on top of it.
The first is whether the pose is free. A point can be inside the ring and still have every configuration that reaches it fouled by something on the bench.
The second is whether it is connected to where you are now, and this is the one that surprises people. Add one more disc to the scene - a fifth one, close enough in that the upper arm can reach it - and re-run the flood fill.
| scene | free space | connected components | largest holds |
|---|---|---|---|
| four discs | 0.7882 | 1 | 100.0% of free space |
| the same, plus one disc within the upper arm’s reach | 0.6970 | 2 | 79.5% of free space |
n = 129600 trials · flood fill over free cells of a 360 by 360 configuration-space grid, wrapping at both edges · 2026-08-10
One disc cost nine points of free space directly. It also cut the remaining free space in two, and a fifth of what survived is now somewhere the arm can hold a pose but can never arrive at. Both bands run the full height of the square, because a near obstacle blocks a range of shoulder angles regardless of the elbow, and two full-height bands cut the shoulder circle into two arcs that cannot reach each other.
The bill for building it
Notice what the picture cost. Two joints, five degrees per cell, 129,600 checks, nine seconds. For that price you got the whole truth: every free pose, every forbidden one, and an exact answer to what is connected to what.
Hold on to how good that deal is, because you are about to lose it. Your SO-101 has six joints. The same grid at the same resolution has 72 to the sixth cells, which is 139 billion, and the next lesson starts with what that number does to you.
Check yourself
1. The near disc produces a forbidden region that runs the full height of the square, while the rim discs produce curved slivers. What is the mechanism behind the difference?
Which link can reach the disc. The near disc is within the upper arm’s reach, and the upper arm’s position depends only on the shoulder angle, so for the shoulder angles that swing it into the disc, every elbow value collides. That is a full-height band. The rim discs are out past the upper arm entirely, so only the forearm can hit them, and the forearm’s position depends on both joints together. The forbidden set is then a region that bends as the shoulder moves, because the elbow value that puts the fingertip inside the disc moves with it.
2. A colleague says “the obstacle is a circle, so its shadow in configuration space should be a circle too”. What is wrong with that?
Configuration space is not a picture of the workspace with different axes on it. A point in it is a set of joint values, and a point is forbidden when some part of the arm overlaps something. The mapping from joint values to the arm’s occupied region is nonlinear and many-to-one, so shape is not preserved in either direction: a round disc can become a stripe, a sliver, or two disconnected blobs, and a connected obstacle can produce a disconnected forbidden region. The only property that survives is membership, which is exactly why you compute it by sampling rather than by transforming the geometry.
3. Why does the wrap-around matter, and what does forgetting it cost?
Because a joint that turns freely has no ends: shoulder and shoulder are the same configuration, so the configuration space is a torus and the square is only a way of printing it. Forgetting it means computing joint differences on the number line, which makes the route from to look like 5.800 radians of travel instead of 0.483. In this scene the long route is also blocked, so the planner spends its budget failing to find a way through obstacles it never needed to approach. The fix is to wrap every joint difference into before using it.
4. Free space fell from 78.8% to 69.7% when a disc was added, but the more serious cost was somewhere else. Where, and why is it worse?
Free space split into two components, and the smaller one holds 20.5% of what remained. Those configurations are still collision-free and still inside the reachable ring, so every check you might run on a single pose passes: forward kinematics returns a fine answer, the collision checker says free, the workspace plot shows the point comfortably inside. They are simply not connected to where the arm is, so no continuous motion reaches them. Losing free space costs you options. Disconnecting it costs you options that still look available.
5. You have a 6-joint arm and you want the same picture. What stops you, and what does that suggest a planner will have to do instead?
Cell count. At five degrees per joint the grid is , about 139 billion configurations, and the collision checker is the expensive part of every one of them. You cannot build the set, store it, or sweep it. So a planner cannot be something that examines free space; it has to be something that samples it, asking the collision checker about individual configurations and individual short moves, and assembling an answer from a number of questions that is small compared with the size of the space.
Do this
Open code/cspace_2link.py. Three TODO(you) markers: the distance from a point to a segment, the collision test that uses it, and the wrap-aware straight line. About forty minutes including the follow-ups.
python module-02-simulation/code/cspace_2link.py # ~35 s, writes cspace.png
python module-02-simulation/code/cspace_2link.py --wrap # instant
python module-02-simulation/code/cspace_2link.py --split # ~20 s
python module-02-simulation/code/cspace_2link.py --sweep # ~25 s
1. Predict the picture before you look at it. Write down, for each of the four discs, whether you expect a full-height band or a bent sliver, and why. Then open cspace.png. Getting this right once is the whole lesson; getting it wrong once is better.
2. Move a disc and watch its region move. Change the near disc’s position in BENCH from (0.15, -0.80, 0.22) to (-0.15, 0.80, 0.22), so it sits on the opposite side of the base, and re-run. Predict first where the band lands on the shoulder axis. It is not arbitrary: the band is centred on the direction from the base to the disc.
3. Push a disc out of the upper arm’s reach. The band exists only while the disc is closer than the upper arm’s length plus both radii, which here is . Move the near disc out to a distance of 1.20, then 1.32, and watch the band become a sliver as it crosses that line. Write one sentence on what physically changed.
4. Find the resolution you can trust. --sweep reports the free fraction at 60, 120, 240 and 480 cells per axis: my run gave 0.7922, 0.7925, 0.7891 and 0.7906, wobbling in the third decimal while the time went from about a third of a second to about seventeen. Decide which of those you would report, and write down the rule you used. It is the same question a simulation timestep asks, and it does not have a clean answer.
What you can now do
You can take any pose of an arm and say which single point of configuration space it is, and take any point and put the arm there. You can predict which obstacles produce full-height bands and which produce bent slivers, from nothing but how far out the obstacle sits. You can explain why the space wraps and what forgetting that costs. And you can separate three claims that sound alike and are not: that a pose is reachable, that it is free, and that the arm can actually get to it from where it is standing.