Skip to content

ROS2 multi-drone PX4, ArduPilot control of quads and VTOLs, with YOLO, LiDAR, Dockerized and WSLg simulation, JetPack deployment

License

Notifications You must be signed in to change notification settings

JacopoPan/aerial-autonomy-stack

Repository files navigation

aerial-autonomy-stack

Aerial autonomy stack (AAS) is a software stack to:

  1. Develop end-to-end drone autonomy with ROS2
  2. Simulate perception and control in SITL, with YOLOv8, LiDAR and PX4 or ArduPilot
  3. Deploy in real drones with JetPack on NVIDIA Orin
aerial-autonomy-stack-v2.mp4

Features

  • Support for multiple quadrotors and VTOLs based on either PX4 or ArduPilot
  • Vehicle-agnostic ROS2 action-based autopilot interface (via XRCE-DDS and MAVROS)
  • Support for YOLOv8 (with ONNX GPU Runtimes) and LiDAR Odometry (with KISS-ICP)
  • Dockerized simulation based on nvcr.io/nvidia/cuda:12.8.1-cudnn-runtime-ubuntu22.04
  • Dockerized deployment based on nvcr.io/nvidia/l4t-jetpack:r36.4.0
  • Windows 11 compatibility with GPU support via WSLg
  • 3D worlds for PX4 and ArduPilot software-in-the-loop (SITL) simulation
  • Zenoh inter-vehicle ROS2 bridge
  • Support for PX4 Offboard mode (e.g. CTBR/VehicleRatesSetpoint for agile, GNSS-denied flight)
  • Support for ArduPilot Guided mode (i.e. setpoint_velocity, setpoint_accel references)
  • Logs analysis with flight_review (.ulg), MAVExplorer (.bin), and PlotJuggler (rosbag)
  • Support for Gazebo's wind effects plugin
  • Steppable simulation

Read about the rationale for AAS in the supplementary/ material

AAS leverages the following frameworks: (click to expand)

Ubuntu 22.04 (LTS, ESM 4/2032), nvidia-driver-580 (latest as of 9/2025), Docker Engine v28 (latest as of 9/2025), ROS2 Humble (LTS, EOL 5/2027), Gazebo Sim Harmonic (LTS, EOL 9/2028), PX4 1.16 interfaced via XRCE-DDS, ArduPilot 4.6 interfaced via MAVROS, YOLOv8 on ONNX Runtime 1.22 (latest stable releases as of 8/2025), L4T 36 (Ubuntu 22-based)/JetPack 6 (for deployment only, latest major release as of 8/2025), WSLg (for simulation and development on Windows 11 only)


How-to Part 1: Installation

Important

AAS is developed using Ubuntu 22.04 with nvidia-driver-580 on an i9-13 with RTX 3500 and an i7-11 with RTX 3060—an NVIDIA GPU is required for ideal performance

To setup the requirements: (i) Ubuntu, (ii) NVIDIA driver, (iii) Docker Engine, and (iv) NVIDIA Container Toolkit (with NVIDIA NGC API Key), read REQUIREMENTS_UBUNTU.md

Windows 11 support is available via WSLg, read REQUIREMENTS_WSL.md

# Install dependencies (git, Git LFS, Xterm)
sudo apt update
sudo apt install -y git git-lfs xterm xfonts-base
git lfs install # Without this, the `git clone` command will not download the large files in `simulation_resources/`

# Clone this repo
mkdir -p ~/git && cd ~/git
git clone https://github.com/JacopoPan/aerial-autonomy-stack.git

# Build the Docker images
cd ~/git/aerial-autonomy-stack/scripts
./sim_build.sh # The first build takes ~25', subsequent ones will take seconds to minutes thanks to the Docker cache

Latest weekly builds with sim_build.sh: simulation-image amd64 aircraft-image amd64

Warning

The 1st build takes ~45GB of space and ~25' with good internet (Ctrl + c and restart if needed)


How-to Part 2: Simulation and Development

# Start a simulation
cd ~/git/aerial-autonomy-stack/scripts
AUTOPILOT=px4 NUM_QUADS=1 NUM_VTOLS=1 WORLD=swiss_town ./sim_run.sh # Check the script for more options (note: ArduPilot SITL takes ~40s to be ready to arm)

Note

On a low-mid range laptop—i7-11 with 16GB RAM and RTX 3060—AAS simulates three PX4 quads with camera and LiDAR at 99% real-time-factor (note that ArduPilot faster physics updates and more complex worlds have higher computational demands). Make sure you run sudo prime-select nvidia and rebooted to effectively leverage GPU compute.

worlds

Available WORLDs:

  • apple_orchard, a GIS world created using BlenderGIS
  • impalpable_greyness, (default) an empty world with simple shapes
  • shibuya_crossing, a 3D world adapted from cgtrader
  • swiss_town, a photogrammetry world courtesy of Pix4D / pix4d.com

To advance the simulation in discrete time steps, e.g. 1s, from a terminal on the host, run:

docker exec simulation-container bash -c " \
  gz service -s /world/\$WORLD/control \
    --reqtype gz.msgs.WorldControl --reptype gz.msgs.Boolean \
    --req 'multi_step: 250, pause: true'" # Adjust multi_step based on the value of max_step_size in the world's .sdf (defaults: 250 for PX4, 1000 for ArduPilot)

To add or disable wind effects, from a terminal on the host, run:

docker exec simulation-container bash -c " \
  gz topic -t /world/\$WORLD/wind/ -m gz.msgs.Wind \
  -p 'linear_velocity: {x: 0.0 y: 3.0}, enable_wind: true'" # Positive X blows from the West, positive Y blows from the South

docker exec simulation-container bash -c " \
  gz topic -t /world/\$WORLD/wind/ -m gz.msgs.Wind \
  -p 'enable_wind: false'" # Disable WindEffects

Fly a Mission

cd ~/git/aerial-autonomy-stack/scripts
AUTOPILOT=px4 NUM_QUADS=1 ./sim_run.sh # Or `ardupilot`, or `NUM_VTOLS=1`

# In aircraft 1's terminal
ros2 run mission mission --conops yalla \
  --ros-args -r __ns:=/Drone$DRONE_ID -p use_sim_time:=true # This mission is a simple takeoff, followed by an orbit, and landing for any vehicle

# Finally, in the simulation's terminal
/simulation_resources/patches/plot_logs.sh # Analyze the flight logs at http://42.42.1.99:5006/browse or in MAVExplorer

To create a new mission, read the banner comments in ardupilot_interface.hpp and px4_interface.hpp for command line examples of takeoff, orbit, reposition, offboard, land

Once flown from CLI, implemented your mission in MissionNode.conops_callback()

interface

Development within Live Containers

Launching the sim_run.sh script with MODE=dev, does not start the simulation and mounts folders simulation_resources, aircraft_resources, and ros2_ws/src as volumes to more easily track, commit, push changes while building and testing them within the containers

cd ~/git/aerial-autonomy-stack/scripts
MODE=dev ./sim_run.sh # Starts one simulation-image and one aircraft-image where the ros2_ws/src/ and *_resources/ folders are mounted from the host

To build changes made on the host in either simulation_ws/src or aircraft_ws/src

cd ros2_ws/ # In the simulation and/or in the aircraft container
colcon build --symlink-install

To start the simulation (by default, this is a single PX4 quad, configure using sim_run.sh)

tmuxinator start -p /simulation.yml.erb # In the simulation container
tmuxinator start -p /aircraft.yml.erb # In the aircraft container

Once done, detach Tmux with Ctrl + b, then d; kill everything with tmux kill-server && pkill -f gz

Tip

AAS Structure (click to expand)
aerial-autonomy-stack
│
├── aircraft
│   ├── aircraft_ws
│   │   └── src
│   │       ├── autopilot_interface # Ardupilot/PX4 high-level actions (Takeoff, Orbit, Offboard, Land)
│   │       ├── mission             # Orchestrator of the actions in `autopilot_interface` 
│   │       ├── offboard_control    # Low-level references for the Offboard action in `autopilot_interface` 
│   │       ├── state_sharing       # Publisher of the `/state_sharing_drone_N` topic broadcasted by Zenoh
│   │       └── yolo_inference      # GStreamer video acquisition and publisher of YOLO bounding boxes
│   │
│   └── aircraft.yml.erb            # Aircraft docker tmux entrypoint
│
├── scripts
│   ├── docker
│   │   ├── Dockerfile.aircraft     # Docker image for aircraft simulation and deployment
│   │   └── Dockerfile.simulation   # Docker image for Gazebo and SITL simulation
│   │
│   ├── deploy_build.sh             # Build `Dockerfile.aircraft` for arm64/Orin
│   ├── deploy_run.sh               # Start the aircraft docker on arm64/Orin
│   │
│   ├── sim_build.sh                # Build both dockerfiles for amd64/simulation
│   └── sim_run.sh                  # Start the simulation
│
└── simulation
    ├── simulation_resources
    │   ├── aircraft_models
    │   │   ├── alti_transition_quad # ArduPilot VTOL
    │   │   ├── iris_with_ardupilot  # ArduPilot quad
    │   │   ├── sensor_camera
    │   │   ├── sensor_lidar
    │   │   ├── standard_vtol        # PX4 VTOL
    │   │   └── x500                 # PX4 quad
    │   └── simulation_worlds
    │       ├── apple_orchard.sdf
    │       ├── impalpable_greyness.sdf
    │       ├── shibuya_crossing.sdf
    │       └── swiss_town.sdf
    │
    ├── simulation_ws
    │   └── src
    │       └── ground_system        # Publisher of topic `/tracks` broadcasted by Zenoh
    │
    └── simulation.yml.erb           # Simulation docker tmux entrypoint
Tmux and Docker Shortcuts (click to expand)
  • Move between Tmux windows with Ctrl + b, then n, p
  • Move between Tmux panes with Ctrl + b, then arrow keys
  • Enter copy mode to scroll back with Ctrl + [, then arrow keys, exit with q
  • Split a Tmux window with Ctrl + b, then " (horizontal) or % (vertical)
  • Detach Tmux with Ctrl + b, then d
tmux list-sessions # List all sessions
tmux attach-session -t [session_name] # Reattach a session
tmux kill-session -t [session_name] # Kill a session
tmux kill-server # Kill all sessions

Docker hygiene:

docker ps -a # List containers
docker stop $(docker ps -q) # Stop all containers
docker container prune # Remove all stopped containers

docker images # List images
docker image prune # Remove untagged images
docker rmi <image_name_or_id> # Remove a specific image
docker builder prune # Clear the cache system wide

How-to Part 3: Jetson Deployment

Important

These instructions are tested on a Holybro Jetson Baseboard (Pixhawk 6X + NVIDIA Orin NX 16GB)

To setup (i.a) PX4's DDS client or (i.b) ArduPilot MAVLink bridge, (ii) JetPack 6, (iii) Docker Engine, and (iv) NVIDIA Container Toolkit (with NVIDIA NGC API Key) on Orin, read SETUP_AVIONICS.md

# Install dependencies (git, Git LFS)
sudo apt update
sudo apt install -y git git-lfs
git lfs install # Without this, the `git clone` command will not download the large files in `simulation_resources/`

# Clone this repo
mkdir -p ~/git && cd ~/git
git clone https://github.com/JacopoPan/aerial-autonomy-stack.git

# On Jetson Orin NX, build for arm64 with TensorRT support
cd ~/git/aerial-autonomy-stack/scripts
./deploy_build.sh # The first build takes ~1h (mostly to build onnxruntime-gpu from source)

Latest weekly build with deploy_build.sh: aircraft-image arm64

# On Jetson Orin NX, start and attach an aircraft-container (e.g., from ssh)
DRONE_TYPE=quad AUTOPILOT=px4 DRONE_ID=1 CAMERA=true LIDAR=false ./deploy_run.sh
docker exec -it aircraft-container tmux attach

Warning

The 1st run of ./deploy_run.sh requires ~4' to build the TensorRT cache


Future Work / Ideas for Contributions


You've done a man's job, sir. I guess you're through, huh?