Skip to content

feat: add drone (ArduPilot SITL + Gazebo) simulation - #77

Open
RadAlpaca11 wants to merge 2 commits into
mainfrom
feature/drone-sim
Open

feat: add drone (ArduPilot SITL + Gazebo) simulation#77
RadAlpaca11 wants to merge 2 commits into
mainfrom
feature/drone-sim

Conversation

@RadAlpaca11

Copy link
Copy Markdown
Member

Summary

Adds a drone option to the sim CLI for flying an S500-class quadcopter
(ArduCopter SITL simulating a Pixhawk 2.4.8) in Gazebo Harmonic via the
ardupilot_gazebo plugin,
flown through QGroundControl instead of RViz/Joint GUI.

(Documentation also added)

  • sim gazebo setup-drone — one-time build of ArduPilot SITL (pinned to
    Copter-4.3.7 to match real flight-controller firmware) and the
    ardupilot_gazebo plugin from source, kept separate from the Docker
    image build. Works around several environment gaps: Ubuntu 24.04 isn't
    supported by this ArduPilot release's own prereqs script, its vendored
    waf predates Python 3.12, and a couple of its C++ files are missing a
    standard header under GCC 13.
  • gazebo/drone_description / gazebo/drone_bringup — hand-authored SDF
    world + launch file (the drone isn't generated via the OnShape
    pipeline like arm/chassis). Needs the Imu/NavSat/Sensors system
    plugins plus a <scene> element for the IMU sensor to actually
    produce data, and runs Gazebo's server+GUI in a single process
    (combined_gui) since a split-process server has no render context
    for its Sensors system.
  • robots.json gains a type field to distinguish non-OnShape robots.
  • SITL's MAVLink output targets the container's own default gateway
    (read from /proc/net/route at launch), since QGroundControl runs on
    the host and ArduPilot's serial-device parser can't resolve hostnames
    or listen for incoming connections.

  • Also fixes two unrelated pre-existing bugs found along the way: a
    stray backslash in docker-compose-gpu.yml's venv setup command that
    broke the NVIDIA devcontainer's sim CLI install, and missing runtime
    dependencies (pypresence, trimesh, pyfqmr, requests) in
    pyproject.toml that only surfaced in an isolated venv rather than
    system/pixi Python.

Setup required (documented in docs/gazebo/drone.mdx)

  • Run sim gazebo setup-drone once before the drone sim works
  • Host firewall must allow inbound UDP 14550 (e.g. sudo ufw allow 14550/udp) -
    QGroundControl and SITL communicate directly over the host network

Test plan

  • sim gazebo setup-drone builds ArduCopter SITL + the plugin
  • sim gazebo drone renders the quadcopter in Gazebo
  • ArduCopter SITL receives real IMU/position data from the plugin
  • QGroundControl auto-connects and shows live telemetry
  • Verify sim gazebo arm / sim gazebo chassis are unaffected (regression check)

Adds a `drone` option to `sim gazebo` for flying an S500-class quadcopter
(ArduCopter SITL matching a Pixhawk 2.4.8) in Gazebo Harmonic via the
ardupilot_gazebo plugin, flown through QGroundControl.

- `sim gazebo setup-drone`: clones and builds ArduPilot SITL (pinned to
  Copter-4.3.7 to match real flight-controller firmware) and the
  ardupilot_gazebo plugin from source into .native/, separately from the
  Docker image. Handles several environment gaps along the way: Ubuntu
  24.04 isn't supported by this ArduPilot release's own prereqs script,
  its vendored waf predates Python 3.12, and a couple of its C++ files
  need a missing standard header under GCC 13.
- `gazebo/drone_description` / `gazebo/drone_bringup`: custom SDF
  world + launch file (not generated via the OnShape pipeline like arm/
  chassis) that starts Gazebo and ArduCopter SITL together. The world
  needs the Imu/NavSat/Sensors system plugins and a <scene> element for
  the drone's IMU sensor to actually produce data, and the GUI runs in
  the same process as the server (`combined_gui`) since a split-process
  server has no render context for its Sensors system to use.
- `robots.json` gains a `type` field to distinguish non-OnShape robots
  from the existing arm/chassis entries.
- SITL's MAVLink output is pointed at the container's own default
  gateway (read from /proc/net/route at launch time) so QGroundControl,
  running on the host, can reach it - ArduPilot's serial-device parser
  has no listening/server UDP mode and can't resolve hostnames, so this
  has to be a real IP resolved on our side.
- Also fixes two unrelated pre-existing bugs hit while getting this
  working: a stray backslash in docker-compose-gpu.yml's venv setup
  command that broke the NVIDIA devcontainer's `sim` install, and
  missing runtime dependencies (pypresence, trimesh, pyfqmr, requests)
  in pyproject.toml that only surfaced when installed into an isolated
  venv instead of system/pixi Python.
@RadAlpaca11 RadAlpaca11 self-assigned this Aug 3, 2026
@RadAlpaca11 RadAlpaca11 added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request labels Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant