20 min

Where things are, and what that even means

A position is never a property of an object; it is a reading taken against something else, and the something else has to be said out loud.

Where you are. You can describe a robot as a sense-decide-act loop and name the parts of an arm. This lesson adds the question every number inside that loop has to answer before it means anything.

A bit to the left

You are carrying a sofa up a stairwell. You have the top end and you are walking backwards. Your friend has the bottom end and is facing you. You can see the newel post you are about to catch. They cannot.

“Left,” you say. “A bit to the left.”

They shift their end to their left, which is your right. The sofa swings the wrong way and the post takes a bite out of the arm.

Neither of you made a mistake. You said left and meant it. They moved left and meant it. The trouble is that “left” does not name a direction. It names a direction and a person, and only one of those two got said out loud. One extra word, “your left”, and the instruction would have been complete.

That missing word is the whole subject of this module. Everything that follows is that word, made precise enough to compute with.

your left you facing down the stairs facing the sofa facing your friend facing up the stairs your friend’s left
Two people at opposite ends of one sofa, facing each other, with the word left pointing in opposite directions for each of them

Wider than the screen; scroll it sideways.

The idea in one paragraph

A position is not a property of an object. It is a reading, taken against something else, and it is meaningless until you say what the something else was. “The cup is at 0.45, 0.22, 0.05” is not a fact about the cup. It is a fact about the cup, plus a corner of a table that somebody chose as zero, plus a decision about which way counts as forward. Robots are built out of readings like this, taken by half a dozen devices that each measure against themselves, and a large part of robotics software is nothing but converting between them without losing track of which is which. Most beginner bugs, and a healthy share of expert ones, are the sofa on the stairs: the right number, measured against the wrong thing.

What had to be agreed

Two things had to be settled before “left” could work, and they are exactly the two things every measurement needs.

The first is where zero is. “Two feet from the wall” is not a location until we agree which wall. Every position is counted out from some starting point, and different starting points give different counts for the same object standing perfectly still.

The second is which way is which. You and your friend had no dispute about the starting point; the sofa was between you and you were both looking straight at it. You disagreed because you were facing opposite ways. Directions have to be pinned down as firmly as the starting point, and there is nothing natural or self-evident about any particular choice of them.

Nothing in a robot speaks a common language

Now put a robot in the picture. A cup sits on a table. Three devices know exactly where it is, and all three are working perfectly.

The robot’s own base measures from the plate it is bolted to, along directions its designer stamped into it: 0.39 metres out, 1 centimetre to one side, 5 centimetres up. A camera on the ceiling measures from its own lens: 5 centimetres across the image, 8 down the image, and 1.05 metres away along the line of sight. A small camera on the robot’s wrist, close in and tilted down at the cup, has its own answer again.

the cup never moves all three are correct the robot’s own base says (0.39, 0.01, 0.05) m the camera on the ceiling says (0.05, 0.08, 1.05) m the camera on the wrist says (-0.02, 0.08, 0.26) m
One cup reported three ways: the robot base says 0.39, 0.01, 0.05; the ceiling camera says 0.05, 0.08, 1.05; the wrist camera says minus 0.02, 0.08, 0.26

Wider than the screen; scroll it sideways.

Read the three triples and notice that they share nothing. Not the magnitudes, not the signs, not even which of the three numbers is the big one. There is no averaging them and no sense in which they roughly agree. Each is an exact and complete description of the same motionless cup, and each is written in a private language.

The reference is bolted to something, and some of those things move

Every reference in a robot is attached to a physical object. That is not a figure of speech. The ceiling camera’s reference is the camera; unbolt it, shift it ten centimetres, screw it back down, and every number it has ever produced now means something different, with no code changed and no test failing.

Which means references inherit motion. The wrist camera’s reference rides on the wrist. The cup has not moved in ten minutes; the wrist camera’s numbers for it change every millisecond, because the thing they are measured against is swinging through the air.

Nor are these references a flat list. Each one is described in terms of another. The gripper is described relative to the last link; that link relative to the one before it; the whole chain relative to the base; the base relative to the room. What you get is a tree.

the room fixed the table fixed the cup moves when moved the robot’s base fixed once bolted the six joints one each, all moving the gripper moves with the arm the wrist camera moves with the arm the overhead camera fixed
The references in one robot scene arranged as a tree rooted at the room, with the table and cup on one branch and the robot base, joints, gripper and wrist camera on another

Wider than the screen; scroll it sideways.

The tree is what makes the problem tractable. Nobody writes down the relationship between the wrist camera and the table directly, because it changes constantly and nobody could measure it. You write down each short local relationship instead, each one either fixed hardware you can measure once with a ruler or a joint angle an encoder reports live, and then walk the path between any two nodes, combining as you go.

Now the word

Everything above has been circling one idea, so here it is with its name attached.

A frame is not something you can point at. It is a decision, written down and then honoured. Nothing in the physical world enforces it. The only thing that keeps it honest is a naming discipline, which is why the next lesson spends as much effort on notation as on arithmetic.

Which way it faces is half the job

Notice that a frame carries directions and not only an origin, and that this is not decoration.

Consider picking up a mug by the handle. Putting the gripper in exactly the right place is not enough; arrive with the fingers turned ninety degrees off and you close on air, or on the handle sideways, and the mug goes over. Position gets you to the neighbourhood. Orientation is what makes contact work.

So when we attach a frame to the gripper, we get its facing for free: the frame’s directions are which way the fingers point and how the wrist is rolled. That is why frames rather than bare points are the right unit to build on. Three numbers say where the gripper is; a frame says where it is and how it is turned, which is what any real task needs.

The habit to start today

There is one habit worth adopting before you write a single line of robotics code, and it costs nothing.

Put the frame in the name. Never cup_pos. Always cup_pos_cam or cup_pos_base. The bare name is a bug incubator: the moment two frames coexist inside one function, an unlabelled vector will eventually be used in the wrong one, and it will not announce itself when it happens.

Instead ofWrite
cup_poscup_pos_cam - the cup, as the camera sees it
targettarget_base - the goal, in the robot’s base frame
TT_base_cam - the camera frame, given in the base frame
gripper_xyzgripper_xyz_world

Robotics codebases treat this suffix the way careful numeric code treats units: mandatory, boring, load-bearing. It reads as pedantry right up to the first afternoon it saves you.

Everything from here is machinery for doing the conversions that suffix implies. The next lesson does it with real numbers in two dimensions, where you can check every step by hand.

Check yourself

1. A teammate messages you: “the cup is at (0.30, 0.10, 0.50)”. What is your first question, and what are the two different wrong assumptions you might make if you skip it?

“In which frame?” The first wrong assumption is that the numbers were taken against the same origin you are working in; camera-frame numbers used as base-frame numbers put the gripper somewhere else entirely. The second is subtler: even with the right origin, the axis directions may differ, so you can be in the right neighbourhood pointing the wrong way. Origin and directions are two separate agreements, and you can get one right while getting the other wrong.

2. The cup has not moved for ten minutes. Why do the wrist camera’s numbers for it keep changing, while the base’s numbers do not?

Because a reference is bolted to a physical object and inherits that object’s motion. The wrist camera’s reference rides on the wrist, so every joint move changes the thing its numbers are measured against. The base is bolted to the table, so nothing about its reference changes while the arm moves. Same cup, same reality, very different shelf lives on the two numbers, purely because of what each was measured against.

3. Why arrange the references as a tree instead of storing the relationship between every pair?

Because most pairs are hard to measure and constantly changing, while every parent-to-child pair is easy: either it is fixed hardware you measure once with a ruler, or it is a joint angle the encoder reports live. With a tree you declare only the easy local relationships and compute any long-range one by walking the path. Storing all pairs would also mean updating a combinatorial number of entries every time a single joint moved.

4. Why attach a whole frame to the gripper instead of just tracking its position?

Because orientation is half the task. Position is three numbers and gets the gripper to the right neighbourhood; grasping also needs to know which way the fingers point and how the wrist is rolled, and those are directions, not a point. A frame carries directions by construction, so attaching one gives you the facing for free. Approach a mug handle from the right position with the wrong orientation and you still fail.

5. Your vision pipeline works perfectly on the bench. In the cell, the arm reaches about 15 centimetres to the left of every object, consistently, whatever the object. What class of bug is this, and why is “consistently” the clue?

It has the signature of a frame bug: a fixed offset applied to everything. Random per-object error points at noise or detection quality. A constant offset in a constant direction points at one link in the chain of references being wrong in a fixed way; the camera was remounted, a mounting offset was typed with a sign flipped, or two parts of the code disagree about which frame the numbers are in. Noise moves around. A bad frame relationship sits still.

6. Someone proposes one global list of every object’s position, “so we do not need all this conversion”. What breaks?

Nothing measures in the global frame. Every device reports against itself, so the numbers have to be converted before they can go into the list, which is the work the proposal was trying to avoid. Worse, the list goes stale the instant a joint moves, and it discards the one piece of information that makes an entry checkable: what it was measured against. You still need the tree. The global list is only a cache of it with the provenance thrown away.

Do this

No code today. Two things, about fifteen minutes, both of which build the reflex the rest of the module leans on.

1. Take a census of one room. Sit somewhere and pick a nearby object: a mug, a light switch, a door handle. Write down its position four times, in plain language, measured against four different things - the corner of the room, your own body, your phone lying on the table, and the object itself. Four descriptions, one object. Note that the fourth is always the same: measured against itself, everything sits at zero. Now mark which of your four references would change if someone moved the table, and which would change if you simply turned around.

2. Find the missing reference in code you have already written. Open anything you have that handles positions, offsets, timestamps or paths: a bounding box, a scroll offset, a diff hunk, a relative import. For each one, write the sentence “this number is measured against ___” and fill in the blank. Then check whether the variable name says so. Most will not. That gap is exactly the gap this lesson is about, and you have been living with it comfortably in a domain where the mistakes are cheap.

What you can now do

You can take any position in a robotics system and name the physical thing it was measured against. You can say why two correct numbers for the same object disagree completely, why a reference bolted to a moving part makes its numbers perishable, and why the references in a scene form a tree rather than a list. You can recognise the signature of a frame bug, a constant offset in a constant direction, and you have the naming habit that prevents most of them.

What you can now do

You can take any number in a robot, name the physical thing it was measured against, and recognise the bug where two numbers were measured against different things.