🔬 The principle
A sense–think–act loop, ~60 times per second. Under the front corners of the robot sit two light (IR reflectance) sensors, pointing at the floor. Every frame — about 60 times a second — the robot does three things:
- Sense: each sensor measures how dark the floor is beneath it. The line is dark; the floor around it is light.
- Think: the difference between the two readings is the error — a single number saying "the line sits more under sensor A" or "…more under sensor B". This is the robot's whole understanding of the world.
- Act: steering is commanded in proportion to the error — this is P-control (proportional control). The command goes to a differential drive: slow one wheel, speed the other, and the robot arcs toward the line.
Why P-control works: a small error needs a small correction and a big error needs a big one — proportionality is the natural reflex. The knob you tune is the gain Kp: how hard the robot reacts per unit of error. Too little gain and the robot cannot turn fast enough — the wheels never yaw quicker than Kp·e allows, so it drifts off the line ("Lost the line"). Too much gain and the steering slams hard; in this idealised sim it still holds the line, but on a real robot — where motors and sensors have lag — that overcorrection overshoots and wiggles down the track.
Where you see it in real engineering
Warehouse AGVs following floor tape, competition line-followers (some top out above 3 m/s doing exactly this maths), robot vacuums hugging walls with reflectance sensors — and every thermostat or cruise control, which are the same idea with different sensors.
🧮 The maths
D(d) = e−(d/18)² · e = DA − DB · w = Kp·e
d — perpendicular distance from a sensor to the line centre (px)
D — sensor darkness reading 0…1 (unitless; σ = 18 px sensing blur)
e — sensor error: difference of the two darkness readings (unitless)
w — steering (yaw) command (rad/s)
Kp — proportional gain (rad/s per unit error)
vA = v − w·L/2 · vB = v + w·L/2
v — forward speed (px/s) · L — wheelbase = 40 px
vA, vB — left/right wheel speeds (px/s) — w > 0 turns toward sensor A
the sensors sit 18 px ahead of the wheel axle (the "lead"), 30 px apart
to hold the curve at speed v, the gain must supply the yaw rate the curve demands:
Kp ≳ v · AMP·(2π/WL)² (≈ v/140 for this track)
AMP = 45 px, WL = 500 px — amplitude and wavelength of the sine track
the curve needs up to v·AMP·(2π/WL)² rad/s of yaw (1.0 at 140 px/s, 1.6 at 220, 2.1 at 300)
the controller can supply at most about Kp·1 rad/s (e saturates near 1) — less than needed → "Lost the line"
Worked example: sensor A reads more darkness than B by e = 0.5, with Kp = 2 and v = 140 px/s.
Steering w = Kp·e = 2·0.5 = 1 rad/s.
Wheels: vA = 140 − 1·40/2 = 120 px/s, vB = 140 + 20 = 160 px/s — the robot arcs toward A until the readings balance again.
And the speed limit: at v = 300 px/s the curve demands 2.13 rad/s of yaw, but Kp = 2 can supply at most ≈ 2 — the robot falls off the line, exactly as the sim shows. Kp = 3 rescues it.
Assumptions & limitations: no actuator or sensor latency (that's why this idealised robot does not oscillate at high gain — real robots with motor lag do, which is why "high gain = wiggle" is the classic failure there); no cross-talk between the sensors; wheel speeds respond instantly (no motor inertia or slip); the floor line is a known sine wave with a fixed 18 px sensing blur; pixel-world units (no physical metres); P-control only — no integral or derivative terms; the track error (lateral distance in px) is what you ultimately minimise, while the sensor error e is what the controller can actually see. This simulation is an educational approximation of a two-sensor reflectance line follower.
🕹 Simulation workspace
Controls
Too little gain → the robot can't yaw fast enough and drifts off the line ("Lost the line"). Too much gain → violent steering swings (watch the graph; on real hardware with motor lag that becomes wiggling). Find the sweet spot — and note it moves with speed.
Status
Ready
steering w = Kp × (darknessA − darknessB). Wheel speeds become v ∓ w·wheelbase/2, so the robot arcs toward the darker sensor. The red dots show each sensor's reading in real time.
Steering rate—
Sensor error |e|—
Avg |track error| (6 s)—
Laps—
Wheels A / B (px/s)—
the line (dark)
sensor A dot (red intensity = darkness)
sensor B dot
path trace
📈 Graphs
Steering command w recorded live while the robot runs (last ~10 s at 60 Hz). A calm, small-amplitude trace = good tuning; a slow drift with the robot leaving the line = gain too low for the speed; big slamming swings = aggressive gain (or big recovery errors).
🌍 Real-world applications
🏭 WarehousesAGV robots follow magnetic or printed tape with the same sense–think–act loop, moving tonnes of stock all day.
🏁 CompetitionsLine-follower contests: 3 m/s machines tuning exactly this Kp — gain vs speed is the whole game.
🏠 Home robotsVacuum robots use reflectance sensors for wall- and edge-following: same error → steering reflex.
🔧 Try it with hardwareArduino UNO R4 WiFi + 2× TCRT5000 IR reflectance sensors on A0/A1. In code: e = map(analogRead(A0)…) − map(analogRead(A1)…), then w = Kp*e, and drive a motor shield: left PWM = v − w·k, right PWM = v + w·k. An ESP32 + DRV8833 driver works identically. Tuning recipe: start Kp small, raise until the robot just begins to wiggle, then back off ~30 %.
✅ Check your understanding
📌 What you discovered
- A line follower is a feedback loop running ~60×/s: sense (two sensors) → think (error, gain) → act (differential wheels).
- w = Kp·e: gain is a yaw-rate budget — the track needs up to ≈ v/140 rad/s of steering, and the gain supplies up to ≈ Kp. Gain below the demand → "Lost the line"; gain far above → violent corrections (and, on real hardware with motor lag, wiggling).
- The 18 px lead (sensors ahead of the axle) turns "too late" into "in time" — the error builds before the body reaches the curve.
- Off the line with equal readings, a P-controller is blind: e ≈ 0 means "no correction", even when the robot is visibly lost.
- The right gain depends on speed — stock gain that wins at 140–220 px/s loses the line at 300 px/s.
➡ Engineering takeaway: a proportional controller measures the mistake and pushes back in proportion — tuning is finding the gain that corrects just fast enough, and re-finding it every time conditions (like speed) change.