Skip to content

2026

Grass is not an obstacle (it took nine stops to get there)

Until tonight the sim lawn was a flat green plane. Real grass is 5 to 10 cm tall, and our 3D-lidar safety gate stopped for anything 3 cm above the ground. So we grew grass the lidar can see, and the robot never left the dock. Seventeen runs later it mows a whole zone in 7 cm grass, over bumps and a 25 cm mound, with zero false stops. Every fix in between came from a stop the robot explained itself.

The end-of-line test, and the robot that kept driving

A factory doesn't ship a product because each part passed its own test. At the end of the line, one last test checks the assembled thing: every sensor, every motor, every way it can stop. Our robot now has one: a single script, make eol-run, that drives the robot through 33 checks and prints PASS or FAIL. It found two real problems on its first two runs, in a simulator we thought we knew well.

Going home: a battery that runs down, a dock that has to be hit to 4 cm

A mower that mows until the battery dies in the middle of the lawn isn't a product. This milestone gave the simulated mower a battery that drains by what it's actually doing, a dock with charging contacts, and a mission that goes home when it must, charges, and comes back to exactly where it stopped. It took three runs, and the two failures were both about the last few centimetres.

Mowing patterns: five runs to mow a lawn without touching the flowerbed

Phase 4 is the one Chris was waiting for: the robot plans a mowing pattern for a lawn and mows it. A planner turns the lawn (a GeoJSON polygon with keep-outs) into a path, a follower drives it on the RTK pose, and a report says, with ground truth, what got cut and whether anything went wrong. The first run finished the lawn. It also drove into the flowerbed 24 times. This post is about the four fixes between that run and a clean one, and about the tool that made the last fixes take seconds instead of minutes.