All posts

Graph SLAM

A robot walks, gets a little lost with every step, then fixes its whole map in one go. Watch how.

Walking with your eyes closed

The robot counts its steps. Every count is a tiny bit wrong, and the mistakes add up.

Slide the wobble. A rougher count drifts further, and the lap never closes.

Nodes: a pin for every step

Each time the robot moves, it drops a pin. A pin is a guess: where am I, and which way am I facing?

The first pin is the start of the map. Every other pin is measured from it.
=
xi: pin number i

One node of the graph. It holds the robot's guess for step i.

Bigger i: later in the trip.

Smaller i: earlier in the trip.

x: how far along

Distance from the start, sideways on the map.

Bigger x: further to the right.

Smaller x: further to the left.

y: how far up

Distance from the start, up the map.

Bigger y: further up.

Smaller y: further down.

θ: which way it faces

The heading, as an angle.

Bigger θ: turned more to the left.

Smaller θ: turned more to the right.

Edges: a string between two pins

The odometer says what happened between two steps. Tie a string between the pins to hold that fact. If the pins drift away from what the sensor said, the string stretches and pulls them back.

Blue is what the sensor said. Green is what the pins say now. Red is the gap between them.
= − ( , )
eij: the error

How far the string is stretched. Zero means the pins agree with the sensor.

Bigger: the pins disagree with the sensor more.

Smaller: the string is more relaxed.

zij: what the sensor said

The measured move from pin i to pin j: how far, and how much it turned.

Bigger: the sensor says the robot moved further.

Smaller: the sensor says it barely moved.

h: what the pins say

The move from i to j that you get from where the two pins sit right now.

Bigger: the pins are further apart.

Smaller: the pins are closer together.

xi: the first pin

Where the move started. Move this pin and h changes.

Shifted: the whole string moves with it.

Held still: only pin j can ease the stretch.

xj: the second pin

Where the move ended. The optimiser slides this pin until e shrinks.

Further from the sensor's answer: e grows.

Closer to the sensor's answer: e shrinks.

How sure is each string?

Two strings can disagree. The pin goes nearer the string we trust more. That trust is called information, and it is the second part of every edge.

Strings 1 and 2 disagree by a metre. Slide the trust and watch where the pin settles.
=
= diag( , , )
Fij: the price of this string

One number: how unhappy this string is.

Bigger: the string is stretched, or we trust it a lot.

Smaller: the string is relaxed, or we barely trust it.

eT: the error, lying down

The same error as before, written as a row so it can be multiplied.

Bigger error: the price grows with its square.

Smaller error: the price falls fast.

Ω: how much we trust the string

Stiffness. It weighs the error before it is added to the price.

Bigger: a stiff string. It wins the tug of war.

Smaller: a loose string. It gives way.

e: the error

The stretch from the last page, multiplied by itself and by Ω.

Bigger: the price grows with its square.

Smaller: the price falls fast.

Ω: a table of three trusts

One trust for each thing a pin holds: x, y and the heading.

Bigger numbers: a sharper, more trusted sensor.

Smaller numbers: a noisy sensor.

σx: the sensor's usual miss in x

How wrong the sensor tends to be sideways, in metres.

Bigger σ: a sloppier sensor, so 1/σ² is small and Ω is loose.

Smaller σ: a precise sensor, so Ω is stiff.

σy: the usual miss in y

The same, for the other direction.

Bigger σ: loose in y.

Smaller σ: stiff in y.

σθ: the usual miss in heading

How wrong the sensor tends to be about which way it faces, in radians.

Bigger σ: loose in heading.

Smaller σ: stiff in heading.

Loop closure: "I have been here!"

Look at the strings before the robot returns: all relaxed, and yet the map is wrong. Then the robot recognises the start. One new string joins the last pin to the first, and that string is very stretched. Every pin on the way gets pulled a little, and the lap snaps shut.

Play it, or drag the time bar. Red strings are stretched, grey ones are relaxed.

One price for the whole map

Every string charges a price for being stretched. Add the prices up and you get one number for the whole map. The best map is the one with the lowest total.

Four pins, four strings. The last string is a little too long, so someone has to give. Try to beat the computer.
=
= x
F(x): the total price of a map

x is every pin at once. F says how unhappy all the strings are with it.

Bigger: a worse map. Strings are stretched.

Smaller: a better map. Strings are relaxed.

Σ: add them all up

Go through every string, from pin i to pin j, and add its price.

More strings: more facts to respect, and a bigger total.

Fewer strings: less to respect, so the map is easier to fool.

eT: the stretch, as a row

The error from before, turned on its side so it can be multiplied.

Bigger stretch: the price grows with its square.

Smaller stretch: the price shrinks fast.

Ω: how much we trust this string

It decides how loudly this string complains.

Bigger: even a small stretch costs a lot.

Smaller: the string can stretch for free.

e: the stretch of this string

The gap between what the sensor said and what the pins say.

Bigger: the pins disagree more.

Smaller: the pins agree.

x*: the best map

The star means the best one. This is the answer we are after.

Higher price at x*: the sensors disagree with each other.

Price near zero at x*: every string is happy.

argmin: the choice that makes it smallest

Try every possible map. Keep the one with the lowest price.

Bigger search: more pins, more to try.

Smaller search: fewer pins, faster.

F(x): the price we are minimising

The same total as above. The optimiser slides pins to make it fall.

Going up: the last move was a bad one.

Going down: the map is getting better.

Rolling down to the best map

The price is a bowl, and the best map is at the bottom. The computer cannot see the whole bowl, only the bit under its feet. So it looks at the slope here, draws a simple curve that hugs the bowl, jumps to the bottom of that curve, and looks again.

One pin and its price. Four jumps are enough. Move the start and see how fast it gets there.
= −
=
= Σ
← +
H: how steep the bowl is here

The curve of the bowl. It says how fast the slope itself changes.

Bigger: a steep, narrow bowl, so take a short careful jump.

Smaller: a wide, flat bowl, so take a long jump.

Δx: the jump

How far to slide every pin, all at once, in this step.

Bigger: still far from the bottom.

Smaller: nearly there. Stop when it is tiny.

b: the slope under your feet

Which way is downhill, and how steep.

Bigger: far up the bowl wall.

Zero: you are at the bottom.

H: built from every string

Add one piece for each string. Strings we trust make the bowl steeper.

More or stiffer strings: a steeper bowl.

Fewer or looser strings: a flatter bowl.

Σ: add the strings

Each string adds its own piece to H, and its own piece to b.

More strings: more pieces to add.

Fewer strings: a smaller table.

JT: the slope table, turned

The same table as J, flipped so it can carry the error back to the pins.

Bigger: the pins push the error strongly.

Smaller: the pins barely matter to this string.

Ω: trust

The same stiffness as before. It weighs this string.

Bigger: this string counts for more.

Smaller: this string counts for less.

J: how the error reacts to a nudge

Nudge a pin a tiny bit and see how much the stretch changes. One row per string.

Bigger: this pin controls the string a lot.

Smaller: moving this pin hardly changes the string.

b: the push on every pin

Every string pushes on the pins it is tied to, by its stretch.

Bigger: the strings are pulling hard.

Zero: the pulls cancel out.

JT: carries the stretch to the pins

Turns the stretch of a string into a push on the pins it joins.

Bigger: a stronger push.

Smaller: a weaker push.

Ω: trust

A trusted string pushes harder.

Bigger: pushes harder.

Smaller: pushes softly.

e: the stretch

The gap between what the sensor said and what the pins say.

Bigger: a bigger push.

Zero: no push.

x: all the pins, after the jump

The new map. Then we measure everything again and repeat.

More rounds: closer to the bottom.

Fewer rounds: a rougher map.

x: all the pins, before the jump

The map we have now.

Far from the best: expect a big jump.

Close to the best: expect a small jump.

Δx: the jump we just worked out

Added to every pin.

Bigger: the pins move a lot.

Smaller: the pins barely move.

Watch the lap settle

The same jumps, on the whole lap. The price drops fast at first, then slows down. After a handful of steps the pins stop moving.

Each step is one jump of every pin. The price chart is on a log scale, so a straight line down means the price shrinks by the same factor every step.

Why we pin the first dot

Every string only knows the gap between two pins. It has no idea where the pins are on the page. So the whole map can slide or spin and the price stays the same. To stop that, we nail the first pin down.

Drag the map or turn it. Then pin the first dot and try again.
= ( − ) T ( − )
Fpin: the price of moving the pin

One more string. It ties the first pin to the place we say it belongs.

Bigger: the first pin has been dragged from its place.

Zero: the first pin is where we said it would be.

x0: the first pin, as the solver has it

The pin the optimiser is allowed to move.

Further from x̄: a bigger price.

Closer to x̄: a smaller price.

x̄0: where we say it belongs

A fixed choice, often the origin. Everything else is measured from here.

Moved: the whole map moves with it.

Kept: the map stays put.

Ω0: how hard it is nailed

A huge number, so the first pin cannot really move.

Bigger: nailed down. It will not budge.

Smaller: a loose nail, and the map can drift again.

x0: the first pin, again

It appears twice because the price is a square: the gap, times the gap.

Bigger gap: the price grows with its square.

Smaller gap: the price falls fast.

x̄0: where we say it belongs

The same fixed place as before.

Moved: the whole map moves with it.

Kept: the map stays put.

How sure is each pin?

A good map says more than where things are. It also says how sure it is. Each pin wears a cloud: the place it might really be. The cloud grows with every step of counting, and shrinks when a loop closure ties the ends together.

The clouds come from the same strings as the map, just read the other way round.
=
Σ: the size of the cloud

How far from its guess a pin might really be. One cloud per pin.

Bigger: a bigger cloud, so the pin is less sure.

Smaller: a tight cloud, so the pin is sure.

H: all the strings together

The same table as before. It measures how firmly the strings hold each pin.

Bigger: more or stiffer strings hold the pin.

Smaller: few or loose strings hold the pin.

−1: flip it over

Held firmly means a small cloud. Held loosely means a big cloud.

Bigger H: the flip makes the cloud smaller.

Smaller H: the flip makes the cloud bigger.

When a string lies

Sometimes the robot is fooled. Two corridors look the same, so it ties a string between two places that are far apart. One liar can crush the whole map. The fix: a string that is stretched far too much is probably lying, so listen to it less and less.

Press the buttons. Each one plays the fix again from the start.
= ½ ( 1 + ( / )2)
ρ(e): the robust price of a string

It replaces the plain price e². For small stretches it is almost the same. For huge ones it hardly grows.

Bigger stretch: the price rises, but more and more slowly.

Smaller stretch: the same as the plain price.

δ²: the scale of the price

Sets how big the price can be before it flattens.

Bigger: the price keeps rising for longer.

Smaller: it flattens quickly, so everything is cheap.

ln: the flattener

The log curve rises fast, then bends over. That is what stops a liar winning.

Bigger input: only a small rise in price.

Smaller input: close to a straight line.

e: how stretched the string is

Measured in how many "usual misses" it is off.

Bigger: the string is probably lying.

Smaller: the string is probably honest.

δ: how patient we are

A stretch about this big is where we start to doubt a string.

Bigger: more patient. Even odd strings are believed.

Smaller: quick to doubt. Good strings may be ignored too.

The whole recipe

That is all of Graph SLAM. Go round this list again for every new step.

  1. Drop a pinfor every step the robot takes.
  2. Tie a stringfrom the last pin to the new one.
  3. Say how sureeach string is. A sure string is stiff.
  4. Spot an old placeand tie a string back to its pin.
  5. Add up the pricesof all the stretched strings.
  6. Roll downhilluntil the price stops falling.
  7. Doubt liarsand keep a cloud of doubt on every pin.

Want to see it on a real map? Open the mapping demo.