Sensing · Lesson 05
Dead reckoning
This is the written walk-through of the lesson: the idea, stage by stage, plus the deeper asides. The interactive version, where you write real Python in the browser and drive a simulated robot, lives on the lesson page.
Guessing position from wheels
Your robot can drive anywhere by now, but it has no idea where it is. Teach it to keep a running guess, then watch that guess start to lie.
There is no GPS in this arena. The only thing the robot knows is what its own wheels were told to do, so it guesses: every tick it takes the commanded wheel speeds, works out the little move they imply, and adds it onto where it thought it was. Sailors called this dead reckoning. Roboticists call it odometry, and the running total is the robot’s belief.
The driving is not your job this time. Press Run and the sim steers a gentle, fixed loop on its own, the same loop every run. Your job is the guesser: the Odometry class in the editor. The solid bot is the truth; the hollow ghost is the engine’s own belief, computed from the same commands your class receives. Match it and you have written real odometry.
Integrate heading, then position
The integrator is two moves, in a careful order. Heading first: turning comes from the wheel difference. The gap between the two commanded speeds, spread over the 55 px between the wheels, is how fast the bot is turning, and one tick of that turn nudges self.theta. Mind the units: commands scale by 1.6 into px per second.
Then position: forward speed is the average of the two wheels, and it lands along the heading you just updated, cosine of theta for x, sine for y. Use the fresh heading, not the old one: the engine’s estimator turns first and then steps, and your class is graded on agreeing with it.
Stay glued to the ghost
Press Run and let the bot ride its loop. For the first eight seconds the wheels grip perfectly, so a correct integrator sits exactly on the engine’s: your estimate within 8 px of the ghost while the bot covers ground. That agreement latches the first gate.
If your guess curls away from the ghost, the heading math is off: check the wheelbase and the update order. If it tracks the shape but runs long or short, the speed scale. Small mismatches compound tick by tick, which is the whole character of this lesson.
Watch the estimate peel
At eight seconds, the lesson turns on the lie. From that moment the right wheel grips a little less than commanded (a fixed, calibrated amount, about 12 percent, the same in every run), and the encoders never notice. The commanded story and the true path quietly split. Watch the drift readout over the arena: the gap between truth and belief climbing past 30 px latches this gate.
Here is the uncomfortable part: your estimate still matches the ghost perfectly. Your math is right. Both of you are wrong together, because the information about the slip never arrived. No cleverer integrator can fix that.
Go deeper: why the encoders cannot see slip
An encoder counts how far the wheel turned, and the wheel really did turn that far. The lie happens below it, in the contact patch: the tire rotates through its full arc while the ground carries the robot a little less than that arc promised. Nothing in the signal chain records the shortfall. The measurement is honest about the shaft and blind about the floor.
That is why the fix is never a better integrator. Any math that runs on wheel data inherits wheel data’s blind spot. The fix is outside information, a reading that touches the world itself: a landmark, a beacon, a line on the floor. The last stretch of the course builds exactly that.
Let the lie grow
Now let it ride. Every tick adds a fresh little move onto a belief that is already wrong, so the error does not just sit there, it compounds. Watch the drift readout climb past 80 px and keep going. The belief never finds its way back on its own.
Press Reset and run it again. Same moment, same lie, same peel: the drift is a property of the world, not bad luck. Wheels alone lie over time, and fixing that takes a sensor that looks at the world instead of the wheels. That is exactly where the course is headed, and the Odometry class you just built is saved to your library on the way: a later lesson puts it back to work.
Ready to build it? The interactive lesson is where you write the code and watch the robot run.