One Cable to the Sky: The MAVLink Bridge
Every autonomous behavior on ASCENT-1 — the waypoint laps, the search sweep, the reposition onto a target, the return-to-launch — travels over one serial link between the Jetson and the Cube Orange+. If that link lies, drops packets, or gets confused about who is talking, the drone does the wrong thing at 150 feet with spinning propellers. This milestone was about making that link trustworthy, and most of what we learned came from bugs the bench never showed us. (One early field lesson set the tone: a link that receives perfectly can still be transmit-dead — our downlink worked while every uplink command silently vanished, until a loopback proved the Jetson header's TX pin had died.)
The first piece is a dead-man switch. ArduPilot's GCS failsafe triggers return-to-launch when ground-station heartbeats stop, so we repurpose it as a companion-computer watchdog: the Jetson sends a heartbeat, and if our mission process crashes mid-flight the drone flies home on the autopilot's own battle-tested failsafe. The catch was that pymavlink defaults to system ID 255 — the same ID Mission Planner uses — so the laptop's heartbeats masked a dead Jetson entirely. Giving the Jetson its own sysid (254) and pointing the failsafe at it fixed the mask, and we proved it by killing the process in flight and watching the Cube declare failsafe and RTL within seconds.
Two more rules earned their place. One reader per serial port, ever: two threads calling recv on the same
stream steal each other's packets, so a single TelemetryPump ingests everything and everyone else reads cached state. And we
never fire-and-forget — mode changes are re-sent every second until the flight controller's own heartbeat reports the
new mode, and a mission upload is only trusted after we re-read the stored item count off the Cube and confirm it matches
what we sent. The nastiest bug of the whole bring-up hid here: on the real airframe, commanding GUIDED occasionally landed
the Cube in AUTOTUNE, because a peripheral's heartbeat flipped pymavlink's vehicle-type guess between our lookup and our
send. We now lock the mode map to the autopilot's heartbeat at connect time, and GUIDED has been GUIDED ever since.