Contributing Guide
ADOS Mission Control and ADOS Drone Agent are open-source under GPLv3. Contributions are welcome. This guide covers the dev setup for both repos, the patterns for adding common feature types, and the pull request process.Dev environment setup
Mission Control (GCS)
1
Clone the repo
2
Install dependencies
3
Start the dev server
http://localhost:4000. Turbopack provides fast hot module replacement.4
Launch demo mode
Open the app in your browser. The welcome modal offers a “Try Demo” button that starts 7 simulated drones. No hardware needed.
SITL testing
To test with a real ArduPilot simulator:1
Build ArduPilot from source
Follow the ArduPilot build docs. The SITL tool expects the ArduPilot repo at
~/.ardupilot.2
Launch SITL
ws://localhost:5760.3
Connect from Mission Control
In Mission Control, click Connect > WebSocket and enter
ws://localhost:5760. You now have a real autopilot with simulated GPS, IMU, and battery.crates/; Python carries AI and vision, the plugin runtime, setup, HAL detection, and the residual web API. A full dev setup needs both a Rust toolchain and Python.
1
Clone the repo
2
Create a Python virtual environment
uv works too if you prefer it.)3
Build the Rust services
crates/.4
Run the CLI
5
Run the terminal status page
Adding a configure panel (Mission Control)
Configure panels are the most common contribution. Each panel lets the user adjust a group of flight controller parameters.1
Create the component
Add a new file in
src/components/configure/:2
Register the panel
Add the panel to the navigation in
src/components/configure/DroneConfigureTab.tsx:3
Test with SITL
Launch SITL, connect, and verify the panel loads, reads parameters, and writes them back.
usePanelParams hook handles all protocol details. It works with MAVLink native parameters (ArduPilot, PX4) and MSP virtual parameters (Betaflight) without any changes to your panel code.
Adding a MAVLink decoder (Mission Control)
When you need to handle a new MAVLink message type:1
Add constants
In
src/lib/protocol/mavlink-crc-extra.ts, add the message ID, CRC_EXTRA, and payload length:2
Add the decoder
In
src/lib/protocol/mavlink-adapter.ts, add a case to handleMessage():3
Add the callback to DroneProtocol
In
src/lib/protocol/drone-protocol.ts:4
Subscribe in DroneManager
In
src/stores/drone-manager.ts inside bridgeTelemetry():Adding a Zustand store (Mission Control)
1
Create the store
2
Use selectors in components
persist middleware with a version number:
Adding a board profile (Drone Agent)
1
Create the YAML profile
model_patterns are matched against /proc/device-tree/model and /proc/cpuinfo for auto-detection.2
Test detection
On the target board, run:This prints setup, service, board, and runtime status for inspection.
Adding an agent service (Drone Agent)
New long-running or safety-critical services are written as Rust crates undercrates/ and run a binary from /opt/ados/bin/. An ancillary Python-backed service is still fine for ecosystem-bound work (AI, drivers, setup glue); the steps below show the Python case. Either way, the unit is registered in the supervisor catalog.
1
Create the service module
Add a new file in
src/ados/services/my_service/:2
Create the systemd unit
Add
data/systemd/ados-my-service.service:3
Register in the supervisor
Add the unit to the
SERVICE_REGISTRY in crates/ados-supervisor/src/registry.rs with its category (core, hardware, on-demand), its profile gate, and any ground-station role gate. The supervisor drives the unit through systemctl; it does not spawn the process itself.Pull request guidelines
Before submitting
- Run
tsc --noEmitfor Mission Control (zero errors required) - Run
python -m py_compileon any modified Python files - Run
cargo fmt --check,cargo clippy, andcargo testfor any Rust crate changes - Check for em dashes in any user-facing strings (there should be none)
- Test with demo mode or SITL for Mission Control changes
- Bump the version in
src/ados/__init__.pyfor agent changes
PR format
Branch naming
feature/short-descriptionfor new featuresfix/short-descriptionfor bug fixesdocs/short-descriptionfor documentation
Review process
- Open a PR against
main - Automated checks run (TypeScript build, linting)
- A maintainer reviews the code
- Once approved, the maintainer merges
Code style
Mission Control: Follow the existing patterns. Zustand for state,usePanelParams for configure panels, selectors for subscriptions. Tailwind for styling. No CSS modules.
Drone Agent (Python): Use structlog for logging, asyncio for async code, Pydantic for config models. Type hints on all function signatures. black for formatting.
Drone Agent (Rust): Format with cargo fmt, lint with cargo clippy, and keep the IPC wire contracts defined in the ados-protocol crate as the single source of truth.
Getting help
- Discord for questions, architecture discussion, and PR review
- GitHub Issues for bug reports and feature requests with a clear use case