ArduPilot is safety-critical autopilot software used in real vehicles. Every contribution must be correct, well-tested, and clearly explained so that human maintainers can review and trust it. This page walks through the full contribution process — from forking to merge — and covers the coding style and CI checks your pull request must pass.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Ardupilot/ardupilot/llms.txt
Use this file to discover all available pages before exploring further.
Before you start
For any non-trivial change, open a discussion on discuss.ardupilot.org or the ArduPilot Discord before writing code. This is especially important if your change affects flight safety, refactors a core library, or touches a subsystem you are unfamiliar with. Maintainers may know of existing work or have opinions on the approach.Contribution workflow
Create a feature branch
Always work on a named branch, never directly on
master. Use a short descriptive name:Write and format your code
Follow the coding style rules below. Run
astyle on the files you modified (not the entire project) before committing.Build and test locally
Configure for SITL and build the affected vehicle. For a board-specific change, configure for that board instead.Then run the relevant SITL autotest suite:
Commit with a well-formed message
Write a commit message in
Subsystem: short description format (see below). One logical change per commit.Commit message format
ArduPilot’s CI rejects commits that do not follow the subsystem-prefix convention. Every first line must contain a colon:Examples
git log on the file you changed to see what prefix existing commits use.
Coding style
ArduPilot enforces C++ style viaastyle with the config in Tools/CodeStyle/astylerc.
| Rule | Convention |
|---|---|
| Indentation | 4 spaces, no tabs |
| Braces | Linux/K&R — opening brace on same line |
| Line endings | LF only, no CRLF |
| Header guards | #pragma once (never #ifndef) |
Single-line if/for | Always add braces |
| Class names | AP_ or AC_ prefix, PascalCase: AP_GPS, AC_PID |
| Method names | snake_case: get_altitude(), update_state() |
| Constants | UPPER_SNAKE_CASE: AP_MOTORS_MOT_1 |
| Feature guards | #if AP_<NAME>_ENABLED / #endif // AP_<NAME>_ENABLED |
AGENTS.md:
- Use
extern const AP_HAL::HAL& hal;in.cppfiles that need hardware access. - Prefer
is_zero(),is_positive(),is_negative()over direct float comparisons. - Use
GCS_SEND_TEXT()for user-visible messages, notprintf. - Use
AP_HAL::millis()/AP_HAL::micros()instead of platform-specific time functions. - Do not introduce platform-specific code in shared libraries — use the HAL.
- Never modify the
modules/submodule directory.
Tools/autotest/ and similar locations must pass flake8 (max line 127) and include the # AP_FLAKE8_CLEAN marker at the top of new files.
Testing
All changes must be tested. ArduPilot has three complementary test layers:- SITL autotest
- GTest unit tests
- Python tests
The primary integration test system. Tests launch a simulated vehicle, execute flight scenarios, and assert correct behaviour.Test suites are Python files in
Tools/autotest/: arducopter.py, arduplane.py, rover.py, ardusub.py.Never fabricate test results, log snippets, or claim testing that was not actually performed. Maintainers will ask for evidence, and falsified testing is grounds for immediate rejection.
CI checks
Every PR triggers the following automated checks. Run CI against your own fork first (push to your fork and check the Actions tab) before opening a PR against the main repository.SITL vehicle tests
SITL vehicle tests
Full autotest suites for ArduCopter, ArduPlane, Rover, ArduSub, AntennaTracker, and Blimp. A failure here means the change broke existing vehicle behaviour.
C++ unit tests (GCC + Clang)
C++ unit tests (GCC + Clang)
All GTest tests in
libraries/*/tests/ compiled with both GCC and Clang. Catches type errors and logic bugs.ChibiOS hardware board builds
ChibiOS hardware board builds
Builds for a matrix of real flight controller boards. Ensures the code compiles in a resource-constrained embedded environment.
astyle formatting check
astyle formatting check
Verifies C++ style matches
Tools/CodeStyle/astylerc. Even a single misplaced brace will fail this check.flake8 Python linting
flake8 Python linting
Runs on all Python files marked
AP_FLAKE8_CLEAN. Max line length is 127 characters.Commit message format
Commit message format
Rejects any commit missing a
: subsystem prefix, any merge commit, and any fixup! commit.Binary size tracking
Binary size tracking
Records the compiled binary size for key boards. Large unexpected increases will be flagged.
Pre-commit hooks
Pre-commit hooks
Checks for CRLF line endings, spelling errors (codespell), files larger than a threshold, and XML/YAML validity.
What not to do
- Do not change parameter index numbers in
AP_GROUPINFOmacros. The index is baked into user EEPROM and changing it silently corrupts stored configurations. - Do not modify the
modules/directory. Submodules are managed as separate upstream projects. - Do not add unnecessary dependencies. Every extra byte of RAM and flash affects the smallest supported boards.
- Do not generate speculative refactors. Keep changes minimal and targeted. Large restructuring PRs are difficult to review and are often closed.
- Do not remove or weaken existing tests without a documented reason.
- Do not move code without a reason. Preserve file structure to keep
git blamehistory useful.
Getting help
| Channel | Purpose |
|---|---|
| GitHub Issues | Bug reports and feature requests |
| GitHub Pull Requests | Code review and submission |
Discord #dev channel | Real-time developer chat |
| Discourse — Development | Longer design discussions |