This week was about getting from zero to a working simulation stack. By Friday evening, an iris-claudedrone was sitting in a Gazebo warehouse_v2 world, ArduPilot SITL was emitting MAVLink heartbeats, and a ROS 2 Jazzy node was receiving them via MAVROS. That’s the threshold where simulation work becomes possible — before this point, every test required real hardware that didn’t exist yet.
What landed
- ArduPilot SITL installation on the dev host (D2, RTX 5070 / Ubuntu 24.04).
sim_vehicle.pyrunning, MAVLink stream on UDP 14550, framecopter-iris-claudedroneselected. See the host-PC setup guide for the full sequence: installation/01-host-pc-setup. - Gazebo Harmonic + ROS 2 Jazzy bringup. The harder piece —
ros_gz_bridgetopic remapping, world-file conventions, and the dance between ArduPilot’s FDM port and Gazebo’s plugin-side socket. Details in simulation/sitl/ardupilot-sitl-setup. - First MAVLink heartbeat received in MAVROS. This is the Hello World of any SITL setup — when MAVProxy stops printing “Waiting for heartbeat” and the heartbeat actually arrives, the stack is wired up correctly.
- indoor.parm parameter file for ArduCopter — tuned for sub-meter precision in confined spaces. Indoor flight requires aggressive
PSC_*andWPNAV_*tuning compared to outdoor defaults. Full parameter breakdown: arducopter-params-indoor.
What didn’t work the first time
The week’s main scar was three layered causes of “Waiting for heartbeat” — a single MAVProxy symptom that turned out to be three independent bugs, each masking the next:
- Orphan UDP 9002 race. Two
gz simprocesses had bound to the same FDM port because an earlierdaemon.sh stophadn’t reaped cleanly.lsof -i :9002made it obvious; killing the orphan fixed it. - Cyrillic comments in
indoor.parm. ArduPilot’sAP_Param.cppreads parameters with a 100-bytefgetsbuffer. UTF-8-encoded Cyrillic comments straddled the boundary, the parameter parser saw a corrupted line, declared the file invalid, and entered an infinite reload loop. The fix was ASCII-only comments. The lesson was: mixed-encoding config files are landmines. --consoleflag launching matplotlib.sim_vehicle.py --consoleopens MAVProxy with a matplotlib-backed status console, and on a fresh Ubuntu 24.04 install matplotlib’s import path emits a deprecation warning that hangs in some terminals. Dropping--consolewas the fastest fix; properly suppressing the warning was a yak-shave we deferred.
Full incident report (it deserved a proper writeup): troubleshooting/sitl-waiting-for-heartbeat.
Why this matters
Without this week, no later RL work is possible. The simulation pipeline is the substrate everything else runs on. We don’t yet have a physical drone; the simulator is the drone for the next 3-4 months.
The other thing worth noting: every one of the three “Waiting for heartbeat” bugs would have been faster to find with better diagnostic tooling. We don’t have that tooling yet. Building it (a pre-flight-check script, port-conflict detector, encoding linter) is on the backlog — not glamorous, but the kind of work that pays dividends every week from here on.
Where this leads
- Week 2 picks up with the first RL training run on top of this pipeline: Week 2 — First RL training
- The Gazebo simulation overview is the right place to start if you want to understand what we built, not just how we debugged it
- The host-PC setup guide is the reproducible recipe for someone trying to get this running themselves