Ethan Sheehan
All work — 2026

Optimal Line-Following Drone

Codename BOLD

A reinforcement-learning path planner for the MathWorks Minidrone Competition Europe 2026: a Parrot Mambo follows a red line and lands on the marker, with the policy shipped as baked weights and zero toolbox dependency.

RoleRL path-planning policy, the team's primary submission
Tracking RMS
0.0438 m
Unseen seeds
12/12
Landing
3-20 mm
01

The competition

MathWorks Minidrone Competition Europe 2026, Round 1, flown in simulation. A Parrot Mambo takes off, follows a red line of two to seven straight sections across a 4 × 4 m arena, finds the red circular marker and lands with at least a fifth of its body inside it, all inside a 100 s window. Scoring is lexicographic: C code generation gates everything, then sections navigated, then path accuracy including the landing, then time. Our team, BristolOptimisedLine-FollowingDrone, replaced the hand-tuned path-planning block in the supplied Simulink project with a trained reinforcement-learning policy. I owned that policy. It was the team's primary submission.

The published BOLD automated-control demo: telemetry overlay for pose, velocity, pitch/roll, heading and cross-track, wind field adjustable mid-flight.
Grid of generated line-following tracks, each a red polyline of straight sections ending at a landing circle
Gallery of generated training and holdout tracks.
02

The policy

Eleven inputs at 5 Hz: line error, look-ahead heading as sine and cosine, marker error, body velocity, height error. One output, a bounded step on the north/east position reference, ±0.360 m per 200 ms cycle. The bound lives in the output layer, so the action is safe by construction. 11 → 128 → 128 → 2, ReLU, tanh squash. SAC from scratch plateaued, so I warm-started by imitating a recreation of the UNISANNIO 2020 winner, then fine-tuned under domain randomisation. It ships as baked weights and three matrix multiplies, zero RL or deep-learning toolbox dependency. On held-out surrogate tracks it beats the recreated winner on tracking RMS, 0.0438 m against 0.0462 m, at equal sections and landings; UNISANNIO is faster.

Learning curve of episode return against training progress for the imitation warm-start plus SAC fine-tuning run
Learning curve, round-4 beat evidence.
Bar and trajectory panels comparing arm-gate configurations for the landing marker
Arm-gate configuration comparison.
Heatmap of hidden-layer activations over time along a campaign flight, aligned with the flown track
Hidden-layer activations along a campaign flight, seed 300044: what the network attends to.
Several agents racing the same track, winner highlighted.
RL against the recreated UNISANNIO 2020 winner, same track, head to head.
Bar chart of tracking RMS for the RL policy against the recreated UNISANNIO winner on held-out tracks
Tracking RMS comparison: 0.0438 m against 0.0462 m.
Scatter of completion time against tracking accuracy showing the accuracy frontier for both controllers
Accuracy frontier, round-4 beat evidence.
Overlaid flown trajectories of the two controllers on several held-out tracks
Overlaid trajectories, RL and UNISANNIO.
03

Flights

The numbers that matter come from the real Simulink model, scored on ground truth rather than the drone's own estimate. Three campaign flights on held-out generated tracks: real Unreal footage with the flown path, surveyed track and landing circle composited on. Twelve seeds the policy was never tuned against went 12 of 12 at the 0.20 m pad gap. Landings sit 3-20 mm from pad centre. The five small plots are ground-truth flyovers rendered from the saved logs. The last clip is the downward camera bus, logged from the running model and pushed back through the deployed front-end, so the overlay is exactly what the policy saw.

Campaign flight, seed 300044, 0.20 m pad gap. Real Unreal footage with the ground-truth path, surveyed track and landing circle composited on.
Campaign flight, seed 90590, 0.30 m pad gap.
Campaign flight, seed 300010, 0.30 m pad gap.
Ground-truth flyover, seed 300044, 0.20 m gap. Rendered from the saved logs.
Ground-truth flyover, seed 90590, 0.30 m gap.
Ground-truth flyover, seed 300010, 0.30 m gap.
Ground-truth flyover, seed 194732, 0.20 m gap.
Ground-truth flyover, seed 300000, 0.20 m gap.
The downward camera bus logged from the running model and pushed back through the deployed front-end. The overlay is exactly what the policy saw.
04

Failures → mechanisms

Every mechanism answers a measured failure. A healthy-looking 100 s flight followed the line beautifully, never armed LAND, then re-flew the route backwards; doubling the coast window across the pad gap fixed it. A perfect landing was rejected when scored off the estimator: ground truth put the miss at 9 mm, the estimator said 347 mm, so scoring moved to ground truth. The arena's yellow decoy square nearly passed for the marker; a colour test now refuses it. An early archive shipped without any of the runtime functions. Code generation is the gating criterion, so it would have scored zero. Hence verification at the archive level. Wind beyond what the policy trained on degrades it; the sweeps show where.

The pre-fix failure, 1 August: excellent line following, never arms LAND, re-flies the route backwards. The reason the coast fix exists.
Arena trajectory from the estimator, camera inset from ground truth, live cross-track error. Late in the flight they disagree by about 0.2 m.
The probeDecoy scene flown: the yellow square scores 19.0 against a marker threshold of 100 on real frames.
Wind stepped 0 to 3 m/s² (trained to 0.35): clean to 1, degrading through 1.5-2, gone by 3. Blue landed, red failed.
Robustness sweep of success and tracking error against wind disturbance
Robustness sweep: wind.
Robustness sweep of success and tracking error against observation latency
Robustness sweep: observation latency.
Robustness sweep of success and tracking error against camera noise
Robustness sweep: camera noise.
Bar chart of success rate on out-of-distribution six- and seven-section tracks for both arms
Out-of-distribution 6-7-section tracks: success 0.867, both arms.
Row of panels showing touchdown positions relative to the landing circle
Touchdown accuracy.
05

Vision

120 × 160 RGB frames, toolbox-free. Red is isolated by channel difference. The line is read through an annulus, the crown, whose forward cone acts as corner memory. The marker is found by exact erosion with a colour test that refuses the yellow decoy. The loop is the onboard camera with the crown overlay drawn on. The policy trained against domain-randomised frames, so the textured sim3d floor was never a surprise.

Onboard camera with the crown look-ahead overlay.
Four-stage strip of the vision pipeline: red isolation, erosion, crown look-ahead, marker test
The full pipeline: red isolation, erosion, crown, marker test.
Montage of domain-randomised camera frames with varied floor texture, lighting and line appearance
Domain-randomisation samples the policy trained against.
Real sim3d camera frames beside the surrogate's clean binary mask, side by side
Real frames against the surrogate's clean mask.
06

The real aircraft

The physical Mambo flies: piloted hops with the live downward camera and FreeFlight telemetry, and a steady hover seen from outside. Hardware preflight passes 13 of 15 checks. Autonomous deployment is blocked on one thing, an Embedded Coder install, not on the controller.

Real Mambo bring-up: onboard camera and FreeFlight telemetry over the live video link.
The airframe holding a hover.
07

Report

The LaTeX technical report: system, dynamics model, vision simulation, reward, training and results. The archive that went to MathWorks carries a shorter ALGORITHM.md; this is the long version, with the surrogate benchmark and the caveats that also went into SUBMISSION.md.