Aerie Architecture

Control Panel | API Docs

What is Aerie?

Aerie is a REST/WebSocket API that wraps MAVSDK-Python in a FastAPI server. It lets you control a drone (real or simulated) over HTTP — arm, takeoff, fly to coordinates, run missions, stream telemetry — with auto-generated OpenAPI documentation.

System Architecture

Browser (:8000) ──HTTP/WS──> Aerie (FastAPI + MAVSDK-Python) │ MAVLink UDP :14540 │ ┌─────▼──────────────────────┐ Browser (:6080) <──noVNC── │ Docker Container │ │ ┌───────┐ ┌──────────┐ │ │ │ PX4 │<──>│ Gazebo │ │ │ │ (SITL) │ │ (physics │ │ │ └───┬───┘ │ + 3D) │ │ │ │ └────┬─────┘ │ │ MAVLink renders to │ │ out :14540 Xvfb :99 │ │ │ │ │ x11vnc :5900 │ │ │ │ │ noVNC :6080 │ └────────────────────────────┘

Component Deep Dive

PX4 Autopilot (Flight Controller)

PX4 is open-source flight controller firmware that runs on real drone hardware. In SITL (Software-In-The-Loop) mode, it runs on a normal computer and simulates the flight controller. It exposes a MAVLink interface on UDP port 14540 — the same binary protocol used by real drones.

PX4 receives commands (arm, takeoff, goto) and sends back telemetry (GPS, battery, attitude). It handles all the low-level flight control: PID loops, sensor fusion, safety checks.

Gazebo (Physics Engine + 3D Renderer)

Gazebo serves two roles:

  1. Physics simulation — simulates gravity, motor thrust, aerodynamics, collisions. PX4 sends motor commands to Gazebo; Gazebo computes what happens physically and sends back simulated sensor data (GPS, IMU, barometer).
  2. 3D rendering — renders the drone and world as a 3D scene. This is what you see in the Gazebo window.

The physics and rendering are separate concerns. The "headless" Docker image runs physics without rendering. Our custom image enables both.

VNC (Virtual Network Computing)

The challenge: Gazebo renders a GUI, but it's running inside a Docker container with no monitor. The solution is a 3-layer chain:

  1. Xvfb (X Virtual Framebuffer) — creates a fake "monitor" in memory. Gazebo renders to this virtual display (display :99). It's a standard X11 display server, just without physical hardware.
  2. x11vnc — captures the virtual framebuffer and serves it over the VNC protocol (port 5900). VNC is a decades-old remote desktop protocol that transmits screen updates as compressed image rectangles.
  3. noVNC + websockify — noVNC is a JavaScript VNC client that runs in a browser. websockify translates between VNC's raw TCP protocol and WebSocket, which browsers can connect to. This is served on port 6080.

So the chain is: Gazebo → Xvfb (fake screen) → x11vnc (capture) → websockify (TCP→WebSocket) → your browser.

Aerie API Server

A Python FastAPI application that translates HTTP requests into MAVLink commands:

The API uses a DroneManager singleton that holds the MAVSDK System instance. All routes depend-inject this via FastAPI's Depends().

Running on Different Platforms

macOS (current setup)

Requires Docker Desktop for Mac. Everything else runs natively.

# Install
python3 -m venv .venv && source .venv/bin/activate
pip install -e .

# Run
./start.sh

Windows

Requires Docker Desktop for Windows with WSL2 backend enabled.

# In PowerShell or Windows Terminal:

# 1. Install Docker Desktop and enable WSL2 backend
#    (Settings > General > "Use the WSL 2 based engine")

# 2. Clone the repo and set up Python
python -m venv .venv
.venv\Scripts\activate
pip install -e .

# 3. Build and start the simulation container
docker compose up -d --build

# 4. Wait ~30 seconds for PX4 to initialize, then start Aerie
set PYTHONPATH=src
uvicorn aerie.main:app --host 0.0.0.0 --port 8000

Then open:

Note: The Docker container runs Linux (ARM64/AMD64). Docker Desktop handles the translation layer automatically. If you're on an AMD64/Intel machine, remove platform: linux/arm64 from docker-compose.yml or change it to linux/amd64.

Linux

Same as macOS. Install Docker Engine (not Desktop), Python 3.8+, then:

python3 -m venv .venv && source .venv/bin/activate
pip install -e .
./start.sh

On AMD64 Linux, change platform: linux/arm64 to linux/amd64 in docker-compose.yml.

API Reference Summary

Full interactive docs at /docs (Swagger UI).

EndpointMethodDescription
/api/v1/connection/connectPOSTConnect to drone ({"address": "udpin://0.0.0.0:14540"})
/api/v1/connection/disconnectPOSTDisconnect
/api/v1/connection/statusGETCheck connection state
/api/v1/action/armPOSTArm motors
/api/v1/action/disarmPOSTDisarm motors
/api/v1/action/takeoffPOSTTakeoff ({"altitude_m": 5.0})
/api/v1/action/landPOSTLand at current position
/api/v1/action/gotoPOSTFly to GPS position ({"latitude_deg", "longitude_deg", "altitude_m"})
/api/v1/action/return-to-launchPOSTReturn to home
/api/v1/action/holdPOSTHold position
/api/v1/action/killPOSTEmergency motor kill
/api/v1/missionPOSTUpload mission waypoints
/api/v1/missionGETDownload current mission
/api/v1/missionDELETEClear mission
/api/v1/mission/startPOSTStart mission
/api/v1/mission/pausePOSTPause mission
/api/v1/mission/progressGETCurrent waypoint progress
/api/v1/telemetry/positionGETGPS position
/api/v1/telemetry/attitudeGETRoll/pitch/yaw
/api/v1/telemetry/batteryGETBattery voltage/remaining
/api/v1/telemetry/healthGETSensor health checks
/api/v1/telemetry/flight-modeGETCurrent flight mode
/api/v1/telemetry/allGETFull telemetry snapshot
ws://.../api/v1/ws/telemetryWSReal-time telemetry stream

Key Files

FilePurpose
src/aerie/main.pyFastAPI app entry point, CORS, exception handlers, lifespan
src/aerie/config.pyPydantic settings (env vars: DRONE_ADDRESS, PORT, etc.)
src/aerie/core/drone.pyDroneManager singleton wrapping MAVSDK System
src/aerie/api/routes/action.pyAction endpoints (arm, takeoff, land, goto, etc.)
src/aerie/api/routes/mission.pyMission CRUD + start/pause/progress
src/aerie/api/routes/telemetry.pyREST telemetry polling endpoints
src/aerie/api/websockets/telemetry.pyWebSocket telemetry streaming with subscription model
src/aerie/services/telemetry_service.pyBridges MAVSDK async telemetry to WebSocket broadcasts
sim/DockerfileExtends headless PX4 image with VNC for GUI access
sim/entrypoint.shStarts Xvfb, x11vnc, noVNC, then PX4+Gazebo
docker-compose.ymlContainer orchestration (ports, env vars, shared memory)

Aerie — MAVSDK REST API for drone control