Click & WhirrAll lessons

State Estimation · Lesson e3

Navigate on your estimate

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.

Everything this branch built, closed-loop. The route from lesson 8 is on the mat and the slip from e1 is in the wheels, but out here the API will not tell you where you are: only the towers’ noisy fixes, and an aim_from that steers from whatever pose you hand it. The starter hands it raw dead reckoning and misses the finish while believing it is on-route. Hand it your Estimator’s belief instead, and bring the real robot home.

A robot that feels fine and is wrong

Until now, every drive you coded had ground truth somewhere in the loop: a line under the sensor, a bearing to a goal the API computed for you. This run has none of that. The route from lessons 7 and 8 is on the mat, the slip from e1 is in the wheels, and the only things your code will ever be told are the two towers’ noisy fixes and whatever you choose to remember.

Press Run with the starter and watch closely: the robot sets off convinced. In its head (raw dead reckoning) it is tracing the route perfectly. On the mat, the slipping right wheel bends every straight into a curve, and the aim it computes from its imaginary pose steers the real robot further from the real route. It misses the finish without ever noticing anything was wrong. A robot that steers on an uncorrected belief does not feel lost; it feels fine, which is worse.

Put your Estimator in the loop

The repair is everything this branch built. Your Estimator already knows how to hold a belief on the truth through this exact slip: integrate the commands, correct position and heading from the tower fixes. The starter is even handed both fixes every tick and throws them away.

Two edits. In __init__, build Estimator(x, y, theta) instead of Odometry. In update, pass the fixes through: self.est.update(vl, vr, range_a, bear_a, range_b, bear_b, dt). The aiming line does not change at all, and that is the point: aim_from steers from whatever pose you hand it. Hand it the truth, as best you can compute it.

Bring the real robot home

Run it. The wheels still slip, the fixes are still noisy, and the real robot glides the route anyway, because a good estimate is indistinguishable from knowing where you are. The checkpoints grade the hidden true pose: reach the finish, and keep the real robot near the real route the whole way.

If the corners cut wide or the straights snake, the tuning is the pursuit pair you already know: lookahead and base in the signature, edit and re-run. And that is the course’s deepest trick, finished: back in lesson 5 you watched a ghost peel off the truth and could do nothing. Now the ghost is the one driving, and it holds the road.

Go deeper: The estimate is the robot

Every serious mobile robot is built the way you just wired this one: the planner and controller never touch the sensors, they read a pose from the estimator, and the estimator is the only thing that reads the sensors. That separation is why a warehouse robot can lose its laser for half a second and keep driving on odometry, or reject a glitched GPS fix without the steering ever knowing.

It also names the risk you saw in the starter: the control loop is only ever as honest as the belief it steers on. In the trade the failure is called confident divergence, and the defenses are the two moves this branch taught: keep repairing the belief against the world, and judge every repair before you accept it.

Ready to build it? The interactive lesson is where you write the code and watch the robot run.