How the error grows

Noise walks, bias marches, scale stretches, and a heading error rotates everything after it.

U3.3Odometry and driftUniversity30 min

Do this lesson in the simulator

Dead reckoning is exact arithmetic on inexact numbers. What matters is not that there is error but how it accumulates, and the different kinds accumulate differently.

Noise: a random walk

Zero-mean noise on each reading adds up as a random walk. After n steps the expected error is proportional to the square root of n, not to n, because the errors partly cancel.

Practically: noise is annoying and survivable. Doubling the run length multiplies the noise error by about 1.4. Averaging more readings, or running the loop faster, both help.

Bias: a march

A constant offset does not cancel. A gyro reading 0.4 deg/s too high, integrated for a minute, is 24 degrees of heading error, in the same direction, every run. The error grows linearly with time, and linear beats square root very quickly.

from bugbot import *
connect()

rates = []
for i in range(60):
    rates.append(imu()[1])
    wait(0.1)

mean = sum(rates) / len(rates)
spread = (sum((r - mean) ** 2 for r in rates) / len(rates)) ** 0.5
print("bias:", round(mean, 2), "deg/s")
print("noise:", round(spread, 2), "deg/s one sigma")
print("after 60 s that bias alone is", round(mean * 60, 1), "degrees")

Run this in the simulator

Standing perfectly still, the gyro insists the robot is turning. That is the single most expensive number in this module, and it is measurable in six seconds.

Scale: a stretch

The flow sensor reads a few percent high or low, fixed for this robot on this mat. Every centimetre is consistently long or short, so the error is proportional to distance travelled: 4 percent is 4 cm in a metre, 40 cm in ten.

Heading error: the multiplier

The expensive one. A heading error e does not just make the heading wrong, it rotates every step taken afterwards. Drive d centimetres with a heading error of e radians and you end up roughly d * e to one side.

Ten metres at 3 degrees off is 52 cm sideways. The same 3 degrees costs you nothing at all if you do not move.

from bugbot import *
import math
connect()

for deg in (1, 3, 10):
    print(deg, "degrees over 200 cm puts you", round(200 * math.radians(deg), 1), "cm to one side")

Run this in the simulator

The ranking

For a ground robot with this sort of hardware, over a run of a minute or two:

  1. Heading bias, by a distance.
  2. Scale error on the translation.
  3. Wheel or flow slip, which is unmodelled and unpredictable.
  4. Noise, which mostly averages away.

That ranking tells you what to do, and it is the plan for the next two lessons: calibrate the bias, calibrate the scale, and get a fix from outside before the rest matters.

Task: measure the gyro bias

Without moving the robot at all, print this gyro's bias as bias: 0.31, in degrees per second.

from bugbot import *
connect()

rates = []

Challenges

  1. Measure the bias five times. Is it the same number each time? Is the noise?
  2. Run set_noise(3) and measure again. Which changes, the bias or the spread?
  3. Work out how long the robot can dead reckon before the bias alone costs it 10 cm, at 20 cm/s.