[Project update] The drone now flies the building in total darkness on the light it carries, and decides by itself what to do when that light flickers, fails, runs out or goes (ROS 2 Jazzy, PX4 SITL, Gazebo Harmonic, CUDA MPPI)
(GIF: a deep flicker of the carried light 200 s into the flight. Left is Gazebo, the world as it is, lit only by the drone. Right is RViz: pink is the obstacle memory, grey is darkness the camera looked into and could not see, cyan the current stereo and time-of-flight returns, orange the route, white the drone's own position estimate, green the simulator's truth. LIGHT is what the test set the light to; SEES is the share of its sensing range the drone's own frame grants. Both fall and recover together.)
Previous update, three weeks ago: the stack flying the same building with no map, no GNSS, no magnetometer and no lidar, two cameras doing both the seeing and the localizing. I ended that post saying it had never been tested against bad seeing: the world was lit by a uniform fill and the cameras had no light to lose. This release is that test.
Everything is MIT, simulation-first, and none of it is validated for a real aircraft.
Release: https://github.com/formiat/px4-ros2-drone-nav/releases/tag/v0.5.0
Video of the whole flight, uncut, in real time: https://youtu.be/WlpePGmt19A
What changed in the world
The location's light is off for good. The vehicle carries a spot light (25 m range, quadratic falloff) in front of its stereo pair, and the evaluation drives that light through three profiles:
- moderate, the norm of every flight now: short outages every ten to thirty seconds, dark never longer than two seconds, each ramping down and up over a second;
- severe: outages growing from the twentieth second to 4.5 s of dark every 8 s, and staying that bad;
- lost: the light gone from the forty-fifth second.
Separately, the light can carry a charge in seconds, and the camera stream can lose frames or deliver them late. The sensors are the same as in v0.4.0: a forward stereo pair (1280 x 960, 120 degrees, 0.20 m baseline, 7.5 Hz) and two 8 x 8 time-of-flight sensors looking up and down (2.8 m), which work in the dark; the position and heading come from a stereo MSCKF on those images.
What the vehicle does about it
All of it is decided onboard from what the camera sees, nothing reads the test's light setting.
The braking contract reads the light. The frame's light headroom and the share of it that matched anything scale the range the forward sensor is trusted for; below 0.35 the frame is blind and the vehicle holds where it stood until it sees again. In the moderate flicker that is a slowdown every few seconds and nothing more.
Darkness is not unknown. This is the one idea I would keep from the whole item. Unexplored space, which nobody has looked at, stays traversable at no penalty, otherwise the planner never leaves the start. But space the camera looked into for 2.5 s and could not see is marked as observed unobservable: occupied evidence without free space, a prohibition like a wall, cleared when the vehicle sees through it again. The memory tells the two apart and RViz draws the dark grey beside the pink of real surfaces. Without this the vehicle flew into the dark at 2 m/s over a goal it had seen free while the light still reached it.
The light is judged by the camera. One outage longer than 3.5 s, or dark for 60 % of the last 120 s, and the light is unreliable: the mission monitor replaces the goal with the start through the same channel any goal enters by, and the vehicle flies home along the trail it flew out on, through the same failing light. In the recorded flight it turns at 76 s and is home 0.9 m from the pad.
The battery is weighed against the way home, all flight long: the charge must cover 1.1 times the estimate of the way back, which is 1.5 times the path flown over the mean speed plus 20 s. With 240 s of light the recorded flight turns at 72 s with 140 s left against 128 estimated, and is home with about 80 s to spare. A flight launched without a battery never gives its goal up for one.
The light gone. Past 1 s unaided the estimator keeps publishing a sound pose for 10 s more, declared as dead reckoning: its height held to the barometer's change, its horizontal velocity bounded by the rotors' drag. Three seconds into that the offboard descends the vehicle level at 0.5 m/s in the autopilot's velocity mode, holding no position (a position held on a dead-reckoned estimate tipped the landed vehicle over), and lands. An estimator that sees again first takes the flight back. In the recorded flight the light goes at 51 s, the word on the overlay changes to DEAD RECKONING, then LEVEL DESCENT, and LANDED at 59 s; the white estimate and the green truth part in those seconds, which is the drift the landing cuts short.
The acceptance series
Five point-to-point flights on one commit through the dark under the moderate flicker, each inspected before the next, speeds on simulation time, positions in the simulator's truth:
- 400 to 520 m of path at 1.58 to 1.77 m/s (r1205 to r1210)
- the true position 0.79 to 1.79 m from the goal at its acknowledgement (the capture radius is 2.0 m)
- no contact in any of them
That is slower than the 1.82 to 1.99 m/s the same flights made a day earlier. The difference is one law added on purpose, below.
Three findings that cost me flights
A floor touched in flight was a landing. The crash judge counted a level, slow contact of the body with a floor as a landing whenever it came. A flight sank onto the floor of the start area in flight, at 0.11 m/s, and the check passed it. It had kept 0.3 m above the floor by its own estimate; the estimate was 0.5 m high. Two changes: a floor contact is a landing only while the offboard's blind descent is going on, otherwise it is a crash; and the clearance law now measures the body's clearance where the estimate puts it and 0.5 m lower and higher, the least of the three, because the camera estimator's height runs 0.3 to 0.6 m from the truth over a flight with or without dead reckoning. That half metre is the price in the speeds above.
The ground's friction read as 21 m/s. A vehicle landed blind on a slope of 12 degrees stood level and whole, and four seconds later its estimate had run 100 m away and the autopilot had reset its position three times. The rotor drag model, which bounds the velocity in the dark by reading the accelerometer across the rotor axis, was reading the ground's friction holding the tilted body (2.3 m/s^2, constant for as long as it lay there) and solving it for a velocity. A reading beyond the drag of any flight is now left out. On flat floors the land detector fires and the autopilot disarms within seconds; on a slope it never fired, because the estimate it reads was still "descending".
The autopilot left offboard before my hold's landing. When the planner's
heartbeat is lost the offboard holds position and lands after 5 s; the branch
returned before publishing OffboardControlMode, so PX4 left offboard on its
own loss timeout first. Never hit in a flight, found by reading the code
against the real-vehicle safety list, fixed in a line.
Limitations, honestly
- The blind landing lands where the drone has drifted to. Nothing on the vehicle sees sideways in the dark, and the memory is exact only relative to the drifting estimate. Twelve blind landings in the dark in this release: nine stood; one met a ledge with a rotor; two came down level on uneven ground and tipped four seconds later. Kept as a known risk, recorded in the debt register with the numbers.
- The return on a goal proven unreachable (a topological proof over the memory, item 19) is implemented and unit-tested, but has never fired in a flight: every return flown was the light's or the battery's. Its flight test is item 18's smoke scenario, which is not built yet.
- The darkness marking keeps the memory's rule of never forgetting by time: what the dark marked stays until seen through again.
- The flights are recorded at a real-time factor of 0.6 for the screen capture (the simulator does not hold 1.0 beside three windows), and every frame of the video is re-timed to the simulation clock, so it plays in real time; the acceptance flights above ran at 1.0.
- Everything is Gazebo: the light, the noise, the IMU. Nothing of this has seen a real sensor.
Questions
- Is there a standard name for "observed unobservable" as a map state? I have seen it in smoke papers as a sensor-level flag, not as something the planner reads as occupancy.
- How do people land a multirotor blind on dead reckoning without a downward-looking sensor that works in the dark? A short-range ToF is what I have; it sees the floor, not the slope.