Tutorial · Intermediate · 25 min

Stopping at an Edge: Latency and Braking Distance

A cliff sensor buys you a fixed number of millimetres. Where they go: reaction distance you spend on latency, braking distance the floor charges you.

The budget is in millimetres, not milliseconds

A robot with a downward sensor gets one piece of information — white, now — and a fixed distance in which to act on it. A mini sumo ring gives 25 mm of border. A table edge gives whatever your sensor’s forward mounting offset happens to be. Either way it is a distance, and the robot spends it in two very different ways:

overshoot = v × t_latency  +  v² / (2a)

The first term is bought and paid for before any braking begins. The second is what the floor charges once it does.

They behave completely differently as speed rises, and knowing which one you are paying is the difference between fixing this in an afternoon and rewriting your control loop for nothing.

Two stacked plots. The upper one shows overshoot past the line in millimetres against speed, as two stacked filled bands: a lower amber band for the reaction distance which grows linearly, and an upper cyan band for the braking distance which grows as a square. Dashed horizontal lines mark 25 millimetres for the border alone and 65 millimetres including a sensor mounted 40 millimetres forward, with an arrow marking 0.98 metres per second where the total curve crosses 65 millimetres. The lower plot shows the fastest safe speed falling as total sense-to-brake latency rises from zero to 60 milliseconds, for a silicone tyre at friction 1.2 and a plastic wheel at friction 0.7.
Top: at 25 ms of latency and µ 1.2, a robot doing 1 m/s runs 67 mm past the line — 25 mm reacting and 42 mm braking. The two bands are equal at 0.59 m/s; above that, braking dominates. Bottom: at 25 ms, silicone buys 0.98 m/s and hard plastic only 0.79 m/s. Download SVG

Where the latency actually goes

“Latency” is not the sensor. It is everything between the photons changing and the tyres making force in the other direction, and it is nearly always dominated by a term nobody measured:

Stage Typical
IR emitter and phototransistor settling ~1 ms
Waiting for the next pass of your loop up to 20 ms
Decision and PWM write <1 ms
Motor current actually reversing ~3 ms
Crossing gearbox backlash before torque reaches the wheel ~1 ms
Total, worst case ~25 ms

The loop period is four fifths of that, and it is the only line you can fix for free.

A sensor you read at 50 Hz is a sensor you are ignoring for 20 ms at a time. The usual cause is not a slow processor — it is a blocking call. One pulseIn() on an ultrasonic sensor is up to 30 ms of complete blindness, and a delay(20) for a servo is the same thing spelled differently. Reading the edge sensor every pass of a non-blocking loop costs nothing and removes most of the reaction distance.

The last row is the one that surprises people. Reversing the motors does not reverse the wheels until the gears have crossed their play, so gearbox backlash is free travel at the worst possible moment: 4° of output play on a 32 mm wheel is 1.1 mm of coasting before any braking torque arrives.

Braking is a friction problem, not a motor problem

The second term looks like it should depend on how strong the motors are. It does not.

Those same motors that can deliver 25 N of push force would decelerate a 500 g robot at 50 m/s². The floor allows µg — 11.8 m/s² on silicone, 6.9 m/s² on hard plastic. The drivetrain has four times the authority it is permitted to use, so stopping distance is set entirely by the tyres, and a bigger motor shortens it by exactly nothing.

That is why the bottom panel has two curves rather than one. At 25 ms of latency, going from plastic to silicone raises the safe speed from 0.79 to 0.98 m/s — a 24% gain from a component that also gives you 72% more push.

One honesty adjustment: µ measured by dragging a stationary robot is the static coefficient, and a hard reversal slides the wheels, which puts you on the kinetic one — typically 10–20% lower. Treat the computed speed as an optimistic bound and run at about 80% of it.

Which term dominates, and therefore what to fix

Set the two terms equal and the crossover is clean:

v × t = v² / 2a   →   v = 2at

At 25 ms and µ 1.2 that is 0.59 m/s.

  • Below it, you are latency-bound. Halving the loop period buys more than any tyre. This is where a searching robot lives, and it is the good news: the fix is a software change.
  • Above it, you are traction-bound. Grip and mass distribution matter more than loop rate, and past a point the only remaining answer is to go slower.

Most robots that fall off things are in the first regime and are being tuned as though they were in the second.

Give yourself more millimetres

The budget is not fixed. It is the border width plus the distance the sensor is mounted ahead of the wheels, and that second term is a free design variable:

budget = border + sensor lead

A sensor 40 mm ahead of the drive axle turns 25 mm of border into 65 mm of stopping room, which is the difference between 0.60 m/s and 0.98 m/s. Solve it the other way when you have a target speed:

budget = v·t + v²/(2a)

Practical limits on how far forward you can go:

  • It has to see the border, not the ring outside it. Mounted too far forward it is looking past the line while the robot is still safe, which costs you speed for no reason.
  • Mount low and shroud it. An IR reflectance sensor at 3 mm is reading the surface; at 15 mm it is reading the surface plus the room lights. This is the same threshold and calibration problem a line follower has, with a much worse failure mode.
  • Put one at each front corner. A single central sensor tells you the edge is somewhere ahead. Two tell you which way to turn away from it, at no extra latency.
  • Do not forget the rear. A robot being pushed backwards crosses the border going the wrong way, and the front sensors will never see it.

Reverse first, turn second

Given a fixed budget, the order of operations matters more than the tuning.

Full reverse, immediately. Not coasting — a coasting robot decelerates only at rolling resistance, which is a small fraction of µg, and the overshoot roughly triples. Not braking gently either: this is the one moment where a motion profile is the wrong instinct, because the constraint is distance rather than smoothness.

Then turn, once you have stopped. Turning while still moving forwards converts your straight-line problem into an arc that carries a corner of the robot further out than its centre. Stop first, then reorient — and remember that a pivot turn is scrubbing the tyres sideways the whole time.

Latch the detection. A single sample of white is enough. Waiting for two consecutive readings to confirm it doubles your worst-case reaction distance, and the false-positive it protects against is much cheaper than the fall.

Measuring your own latency

The number in the table is a starting estimate. Yours is measurable in about fifteen minutes.

From inside. Record micros() when the sensor crosses threshold and again on the line that writes the reversed PWM. That captures the software half, which is the half you can fix. Print the worst value seen over a hundred detections, not the average — the worst case is the one that decides whether the robot falls off.

From outside. Film it at 240 fps with a phone. Count frames between the sensor passing the line and the wheels visibly reversing; each frame is 4.2 ms. This catches the electrical and mechanical delay the software cannot see, and it is the only way to confirm the total.

End to end. Drive at a known speed at a taped line and measure how far past it the robot stops. Subtract the computed braking distance v²/2a and what remains is v × t — total latency, measured with a ruler.

The last one takes five minutes and it is worth doing before any tuning at all, because it tells you which of the two terms you are actually paying.

When it goes wrong

Symptom Usually
Stops reliably slow, falls off fast Working as designed — you are past the speed the budget allows
Overshoots by a consistent amount Latency; measure it end to end and shorten the loop
Overshoots by a variable amount A blocking call somewhere — the loop period is not what you think
Sees the line late Sensor mounted too high or too far back, or threshold set for a different room
Detects the border that is not there Reflective floor or ambient IR; shroud the sensor and re-calibrate
Stops in time, then drives off anyway The turn-away happened while still moving; stop first
Falls off backwards No rear sensors

The same arithmetic covers a table-edge robot, a stair-avoiding vacuum and an obstacle stop — only the budget changes. The obstacle avoidance simulator exposes exactly this stopping-distance geometry with a forward-looking sensor instead of a downward one, and the mini sumo project is where it has to work against an opponent trying to make you fail.

Explore the graph

Part of these builds

Projects and learning paths that include this tutorial.

Further reading

References