30 min

Configuration space: the arm is a point

Every pose of an arm is one point in a space with one axis per joint, obstacles in the world become forbidden regions in that space, and planning is finding a route through what is left.

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.

workspace: the arm occupies a region obstacle base elbow one point configuration space: the arm is a dot shoulder θ1 elbow θ2 q = (0.90, 1.30) every legal pose of the arm is somewhere in this square both axes run from -π to +π
The same arm pose drawn twice: on the left two links reaching past a disc in the workspace, on the right a single dot at the matching shoulder and elbow angles in a square of side two pi

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.

the bench, seen from above the reachable ring from Module 1 A B C D A is 0.81 from the base: the upper arm reaches it B, C and D are 1.42 to 1.45 out: only the forearm does configuration space, shaded where the arm hits something A B C D shoulder, -π to +π elbow A becomes a band the upper arm's position depends on the shoulder alone, so every elbow value is blocked B, C, D become slivers only the forearm reaches them, and the forearm depends on both joints, so the region bends D crosses the right edge and returns on the left: the space wraps
The configuration space of the 2-link arm: one full-height vertical band produced by the disc the upper arm can reach, and three curved slivers produced by the discs only the forearm can reach

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 measuredvalue
free fraction of configuration space0.7882
straight lines that hit something974 / 2000
straight lines that were fine1026 / 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 π-\pi and shoulder +π+\pi 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.

same edge re-enters here across the picture 5.800 rad, and it runs through the band same edge off the edge 0.483 rad of shoulder travel, and free Both joints turn all the way round, so shoulder -π and shoulder +π are the same pose. The space is a torus; it only prints flat.
The configuration-space square with its left edge glued to its right and its bottom to its top, so a route that leaves one side re-enters on the other

Wider than the screen; scroll it sideways.

This is not a curiosity. Take the shoulder from +2.90+2.90 to 2.90-2.90 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.

scenefree spaceconnected componentslargest holds
four discs0.78821100.0% of free space
the same, plus one disc within the upper arm’s reach0.6970279.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 π-\pi and shoulder +π+\pi 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 +2.90+2.90 to 2.90-2.90 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 [π,π)[-\pi, \pi) 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 72672^6, 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 1.00+0.22+0.04=1.261.00 + 0.22 + 0.04 = 1.26. 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.

What you can now do

You can build the configuration space of the 2-link arm, say why a round obstacle becomes a curved band in it, and separate what the arm can reach from what it can reach without lifting off the bench.