ArduPilot Vehicle Core¶
ArduPilot firmware specialization of the shared vehicle core. ArduPilotDrone (drone.py) adds ArduPilot's flight semantics — GUIDED-mode arming, the GUID_OPTIONS/WPNAV setpoint configuration, and native RTL-mode return-to-launch — on top of VehicleDrone; the transport-agnostic navigation, takeoff/land detection, GPS math, and PID control are inherited from the core. MavrosDrone and MavlinkDrone are the same vehicle reached over two different transports (mavros, mavlink).
This page documents only ArduPilot specifics. The shared navigation methods, reference frames, altitude sources, takeoff/land detection, GPS/EGM96 handling, and PID configuration — which apply to every vehicle — are in the vehicle core README. PX4 specifics are in PX4.
Architecture¶
classDiagram
class VehicleDrone {
<<abstract>>
+takeoff() land() move_to() move_to_gps() move_velocity() rtl()
}
class ArduPilotDrone {
+arm() _rtl_native() capabilities
+set_speed() do_servo() set_setpoint_config()
-_setpoint_config SetpointNavConfig
-_apply_setpoint_config() _prepare_position_setpoint()
}
class SetpointNavConfig {
<<dataclass>>
+guid_options speed speed_up speed_down accel radius jerk psc_jerk rfnd_use
+use_wpnav «property» from_yaml() from_dict() to_fcu_params()
}
VehicleDrone <|-- ArduPilotDrone
ArduPilotDrone o-- SetpointNavConfig
The full core class diagram (VehicleDrone, VehicleNavigator, VehicleTransport, transports) is in the vehicle core README.
Modules¶
| File | Responsibility |
|---|---|
drone.py |
ArduPilotDrone(VehicleDrone) — ArduPilot flight semantics: GUIDED arming, WPNAV/GUID_OPTIONS, native RTL, set_speed/do_servo. |
setpoint_config.py |
SetpointNavConfig — GUID_OPTIONS/WPNAV parameter handling (with 4.6/4.8 aliases). |
config/ |
Bundled PID + setpoint YAML presets (position_*.yaml, setpoint_*.yaml, including the *_sim_* SITL presets). |
Capabilities¶
ArduPilotDrone.capabilities is derived declaratively from the configured pose_source (see capabilities.py): outdoor adds GPS_NAV/GLOBAL_SETPOINT, indoor adds VISION_POSE. On top of the shared set it declares SERVO (ArduPilot's per-channel PWM do_servo path, which PX4 does not expose) plus ACTUATOR (DO_SET_ACTUATOR) and GRIPPER (DO_GRIPPER) for payloads (both shared with PX4). Capability-gated operations call _require(...), so do_servo / set_actuator / set_gripper raise CapabilityNotSupportedError on a drone that does not declare them; query with drone.supports(Capability.SERVO).
MAVLink and the FCU¶
MAVLink is the binary protocol between the flight controller (FCU), ground stations, and companion computers. The SDK sends velocity/position commands and reads sensor data over it — through MAVROS in one transport, through pymavlink directly in the other. The drone must be in GUIDED mode for offboard control.
Flight Modes¶
ArduPilot flight modes determine how the FCU interprets inputs. Modes used by this SDK:
| Mode | Description |
|---|---|
| GUIDED | Offboard control. Accepts position/velocity commands from the companion computer. Required for SDK navigation. |
| STABILIZE | Manual stabilized flight. Pilot controls via RC. |
| LOITER | GPS-based position hold. |
| RTL | Return to launch — fly back to home and land. |
| LAND | Auto-land at current position. |
Set via drone.set_mode(). See MAVLink flight mode protocol.
Arming (GUIDED)¶
ArduPilotDrone.arm() sets GUIDED mode, waits for the mode to reflect in state, optionally pushes the setpoint parameters (when apply_setpoint_params=True), commands arm, and polls is_armed to confirm. GUIDED is the offboard control mode and persists across navigation, so — unlike PX4 OFFBOARD — no continuous setpoint stream is required to stay in it.
EKF (Extended Kalman Filter)¶
The EKF is ArduPilot's state estimator. It fuses IMU, GPS, barometer, and optionally vision/rangefinder data into a position/velocity/attitude estimate. All altitude and position values in this SDK ultimately come from the EKF output, exposed by the transport as local_pose, gps, rel_alt, etc.
EKF Origin (Indoor Requirement)¶
The EKF local frame needs an origin — the (0,0,0) reference point. Outdoors, GPS sets this automatically. Indoors, set it manually before flight via Mission Planner ("Set EKF Origin Here") or the SET_GPS_GLOBAL_ORIGIN message. The actual lat/lon don't matter — the EKF just needs a defined origin to fuse vision data. Without it, the local pose is not published and FRAME_LOCAL_NED commands won't work.
Vision Systems (Indoor Position Source)¶
An external vision system feeds pose data to ArduPilot's EKF as VISION_POSITION_ESTIMATE. The EKF fuses it with IMU and outputs the local pose. The two transports inject this differently — see each transport README — but the vehicle behavior is identical.
Key ArduPilot parameters: EK3_SRC1_POSXY=6, EK3_SRC1_POSZ=6, EK3_SRC1_YAW=6 (ExternalNav), VISO_TYPE=1. See ArduPilot VIO setup, ROS VIO guide, and Non-GPS Position Estimation.
ArduPilot GUIDED Mode Position Controllers¶
When the SDK publishes a local position setpoint (NavigationMethod.POSITION / POSITION_GLOBAL, documented in the vehicle core README), ArduPilot's GUIDED mode routes it to one of two controllers, selected by the GUID_OPTIONS parameter:
| Controller | GUID_OPTIONS | SubMode | Trajectory | Speed Control |
|---|---|---|---|---|
| AC_PosControl (default) | bit 6 = 0 | SubMode::Pos |
Direct PID to target | Speed limits from WPNAV at init |
| AC_WPNav | bit 6 = 1 (value 64) | SubMode::WP |
S-curve path planning | Full WPNAV parameter set |
Source: mode_guided.cpp :: set_pos_NED_m() — use_wpnav_for_position_control() selects the sub-mode from GUID_OPTIONS bit 6.
- AC_PosControl (SubMode::Pos) — direct PID toward the target, no trajectory shaping. Speed limits read once at mode init. No internal arrival radius (the SDK's arrival check handles it). Suitable for continuous position streaming; can produce abrupt motion at high speed/long distance.
- AC_WPNav (SubMode::WP) — straight-line path with an S-curve speed profile; respects all
WPNAV_*parameters dynamically (includingWPNAV_RADIUSfor deceleration and arrival), supports object-avoidance path planning. Each new target triggers a full replan — best for point-to-point missions, not rapid retargeting.
WPNAV Parameters¶
ArduPilot v4.6.3 WPNAV_* parameters control navigation speed, acceleration, and precision:
| Parameter | Description | ArduPilot Default | Unit |
|---|---|---|---|
WPNAV_SPEED |
Horizontal speed | 1000 (10 m/s) | cm/s |
WPNAV_SPEED_UP |
Climb speed | 250 (2.5 m/s) | cm/s |
WPNAV_SPEED_DN |
Descent speed | 150 (1.5 m/s) | cm/s |
WPNAV_ACCEL |
Horizontal acceleration | 250 (2.5 m/s²) | cm/s/s |
WPNAV_RADIUS |
Waypoint arrival radius | 200 (2.0 m) | cm |
WPNAV_JERK |
Horizontal jerk | 1.0 | m/s/s/s |
WPNAV_RFND_USE |
Rangefinder terrain following | 1 (enabled) | bool |
In ArduPilot dev (v4.8+) these are renamed to
WP_*.SetpointNavConfiguses descriptive field names and carries aPARAM_ALIASESmap (WPNAV_SPEED→WP_SPD, etc.), so version changes only require the alias table.
The SDK also sets PSC_JERK_XY (4.6.3) / PSC_JERK_NE (4.8+) — position controller horizontal jerk, default 5.0 m/s³ — via SetpointNavConfig.psc_jerk. This controls AC_PosControl response speed in SubMode::Pos; SITL typically needs higher values (e.g. 50) for usable response.
Runtime effect of set_param per sub-mode: in SubMode::WP, all WPNAV_* are re-read on each new target (wp_nav->set_wp_destination()). In SubMode::Pos, speed/accel limits are set once at submode entry — use set_speed() for dynamic changes. The SDK's _prepare_position_setpoint() uses WPNav's re-read to update WPNAV_RADIUS from the precision argument on each POSITION/POSITION_GLOBAL call when WPNav is enabled and apply_setpoint_params=True.
Speed Control at Runtime¶
set_speed(speed, speed_type) sends MAV_CMD_DO_CHANGE_SPEED (178), which immediately updates AC_PosControl's active speed limits in both sub-modes:
drone.set_speed(0.5, "horizontal") # 0.5 m/s horizontal
drone.set_speed(0.3, "climb") # 0.3 m/s climb
drone.set_speed(0.3, "descent") # 0.3 m/s descent
drone.set_speed(-2, "horizontal") # revert to WPNAV_SPEED default
By contrast, set_param("WPNAV_SPEED", value) only takes effect on the next target (WP) or the next mode init (Pos).
RTL¶
rtl() defaults to RTLMethod.NAVIGATE (the shared SDK PID path to home — see Vehicle core). RTLMethod.NATIVE uses ArduPilot's own RTL flight mode:
- NATIVE: sets
RTL_ALT(return altitude, or 0 to keep the current altitude rather than ArduPilot's 15 m default) andRTL_ALT_FINAL(0 to auto-land, or the return altitude to hold above home), then sets modeRTL. Parameter names differ by version:RTL_ALT/RTL_ALT_FINAL(v4.6.3, cm) vsRTL_ALT_M/RTL_ALT_FINAL_M(v4.8+, m); the SDK tries the v4.6.3 name first and falls back automatically. See RTL Mode.
Parameter Handling¶
drone.set_param(name, value) forwards to the transport. Integers are sent as int, floats as double. ArduPilot persists PARAM_SET to storage, so values survive reboots.
drone.set_param("RTL_ALT", 1500) # int, cm
drone.set_param("WPNAV_SPEED", 200.0) # float, cm/s
drone.set_param("GUID_OPTIONS", 65) # int, bits 0 + 6
Version-dependent parameters (WPNAV/PSC, RTL) are written with the v4.6.3 name first and fall back to the v4.8+ alias on failure, using SetpointNavConfig.PARAM_ALIASES. How a set_param is confirmed depends on the transport (service result vs PARAM_VALUE echo) — see the transport READMEs. See Get/Set Parameters.
Setpoint Navigation Configuration¶
SetpointNavConfig controls GUIDED-mode behavior for NavigationMethod.POSITION / POSITION_GLOBAL: the position-controller sub-mode (AC_PosControl vs AC_WPNav) and the WPNAV/PSC parameters.
Lifecycle:
- On init:
_load_setpoint_config()loads fromsetpoint_config_file, else the bundledsetpoint_indoor.yaml/setpoint_outdoor.yamlbyis_indoor. Always loaded for SDK-side logic (e.g.use_wpnavchecks). - On arm (only if
apply_setpoint_params=True):_apply_setpoint_config()pushesGUID_OPTIONSand theWPNAV_*/PSC_JERK_*parameters to the FCU viaset_param(), logging each result. - On
move_to/move_to_gpswith a POSITION method (only ifapply_setpoint_params=Trueanduse_wpnav):_prepare_position_setpoint()syncsWPNAV_RADIUSwithprecision.
FCU persistence:
set_paramwrites to the autopilot's storage and survives reboots.apply_setpoint_paramsdefaults toFalse, so by default the SDK does not touch FCU parameters. Set itTrueto let the SDK own them (e.g. SITL).drone.set_setpoint_config(config)pushes on demand regardless of the flag (passapply=Falseto update the SDK-side config only).
Dataclass defaults (SI units; speed/accel/radius are converted to cm/s, cm by to_fcu_params()):
| Field | Default | ArduPilot Factory Default |
|---|---|---|
guid_options |
1 (bit 0) |
0 |
speed |
2.0 m/s | 10.0 m/s |
speed_up |
1.5 m/s | 2.5 m/s |
speed_down |
1.5 m/s | 1.5 m/s |
accel |
1.0 m/s² | 2.5 m/s² |
radius |
0.2 m | 2.0 m |
jerk |
1.0 m/s³ | 1.0 m/s³ |
psc_jerk |
5.0 m/s³ | 5.0 m/s³ |
rfnd_use |
1 | 1 |
guid_options is the GUID_OPTIONS bitmask; use_wpnav is True when bit 6 is set. Common values: 1 (arm from TX), 64 (WPNav only), 65 (arm from TX + WPNav). The SDK speed defaults are intentionally conservative versus ArduPilot's factory values to avoid aggressive motion.
Push to the FCU:
Update the SDK-side config only (apply=False):
PID Configuration¶
ArduPilot loads its PositionPIDConfig from the bundled presets (position_indoor.yaml / position_outdoor.yaml, plus the position_sim_*.yaml SITL presets) — the loading lifecycle and runtime overrides are shared and documented in the vehicle core README. Controller internals (gains, output clamps, integral handling) are in the PID module.
Transports¶
- MAVROS transport —
MavrosTransport: subscriptions → telemetry, service clients → commands, publishers → setpoints. Requires a runningmavros_node. - Direct MAVLink transport —
PymavlinkTransport: owns the FCU link, RX timer decode, directmav.*_send, built-in vision bridge.
References¶
MAVLink & ArduPilot¶
- MAVLink Basics · MAVLink common messages · MAV_FRAME
- ArduPilot Copter Documentation · Flight Modes · GUIDED Mode
- GUIDED Mode Commands · PosControl and Navigation Overview
- WPNAV Parameters (v4.6.3) · MAV_CMD_DO_CHANGE_SPEED
- Understanding Altitude · EKF Overview · RTL Mode
- Get/Set Parameters · Set/Get flight mode
ArduPilot Source¶
mode_guided.cpp— GUIDED sub-modes,pva_control_start(),set_pos_NED_m()AC_WPNav.cpp·AC_PosControl.h·GCS_MAVLink_Copter.cpp
Vision & Indoor Navigation¶
- VIO Tracking Camera · ROS VIO Setup · Non-GPS Position Estimation
- Shared navigation, frames, altitude, GPS/EGM96: vehicle core README