Skip to content

The hedgehog test: why the mower needs to look down

Chris put it simply: "I don't know how you safely do this without lidar." RTK knows where the mower is. It knows nothing about what's in front of it. So Phase 3b gave the mower two lidars and an obstacle course, and asked one question: what does each lidar fail to see?

The physics budget, first

At 0.5 m/s, with about 0.15 s to notice (a 10 Hz lidar plus processing) and 1 m/s² of braking, the mower needs 0.075 + 0.125 ≈ 0.20 m to stop. So the safety field is a corridor the robot's width plus 10 cm, out to 0.7 m past the nose (stop the drive and the blade), with a slow-down field out to 1.5 m.

The safety gate

A new node, safety_gate, sits between every driver and the motors:

driver → /cmd_vel_raw, /blade/cmd_vel_raw → [safety_gate] → /cmd_vel, /blade/cmd_vel → robot

It can slow the robot, stop it, and stop the blade. It can never start the blade: it only passes through or zeroes what the driver asks for. On the real robot it's one layer above the hardware interlock, which doesn't trust it either.

The course

Six objects, one per run, 3 m ahead on the robot's path: a pole, a 20 cm toy box, a toddler lying across the path (25 cm tall), a 20 cm ball, a hedgehog (10 cm), and a garden hose (4 cm). Plus an empty control run, because a safety sensor that cries wolf gets switched off. Two lidars: - 2D: one horizontal scan plane in the nose, 15 cm above the grass. - 3D: 16 beams from −25° to +5°, 30 cm up, looking down at the lawn ahead.

Results (make obstacle-course)

Obstacle 2D lidar 3D lidar
pole stopped, 0.67 m to spare stopped, 0.67 m to spare
box (20 cm) stopped, 0.68 m stopped, 0.67 m
lying child (25 cm) stopped, 0.69 m stopped, 0.69 m
ball (20 cm) stopped, 0.68 m stopped, 0.67 m
hedgehog (10 cm) HIT, never seen stopped, 0.67 m
hose (4 cm) HIT, never seen stopped, 0.67 m (seen at 1.25 m)
nothing (control) no false stops no false stops

The 2D lidar's blind spot is everything shorter than its scan plane. On a lawn, that's exactly the stuff that matters: wildlife, hoses, toys, small children. A mower's safety lidar has to look down.

The bug that faked a miss

The first run said the pole wasn't seen, and the robot ended up 2.6 m past it. Gazebo's spawner ignores the pose written inside an SDF string and uses its own -x/-y/-z (default: the origin). The pole had spawned inside the robot. The report caught it because "clearance −2.61 m" isn't physically possible for a static pole.

The honest caveat

The simulated lawn is a perfectly flat plane, so "anything more than 3 cm above the ground" is a clean obstacle test. Real grass is 5–10 cm tall, bumpy and sloped. On a real lawn that rule sees obstacles everywhere. Separating grass from hedgehog is the actual hard problem, and it's next: realistic grass in the sim, ground segmentation, and a false-alarm rate as a first-class metric. Then moving obstacles: a dog crossing at full speed.