-
Notifications
You must be signed in to change notification settings - Fork 2
Autopilot Support
CanaryGC targets both ArduPilot and PX4. The two stacks encode flight modes
differently on the wire, so src/lib/flight-modes.ts isolates the difference
behind a strategy interface and the rest of the app works in terms of a small
set of intent-level modes. Betaflight and INAV boards connect over MSP rather
than MAVLink; their telemetry, control, and mission handling live in
Firmware.
The UI and mission logic use six modes:
type FlightMode = 'GUIDED' | 'AUTO' | 'RTL' | 'LOITER' | 'LAND' | 'POSCTL';POSCTL is the stick-flying position hold that gamepad control switches into
(Position mode on PX4, Loiter on ArduPilot).
interface AutopilotStrategy {
setModeParams(mode: FlightMode): [number, number, number]; // DO_SET_MODE params
decodeCustomMode(customMode: number): string;
supportsLocalSetpoint: boolean;
}setModeParams returns the MAV_CMD_DO_SET_MODE parameters
[baseMode, customMode, customSubMode]. decodeCustomMode turns a telemetry
custom_mode back into a readable label. supportsLocalSetpoint reports whether
the stack accepts a local-frame position setpoint.
ArduPilot Copter puts the mode number directly in customMode with
customSubMode unused. decodeCustomMode maps the number to a Copter mode name
(STABILIZE, LOITER, AUTO, RTL, LAND, and the rest). Local-frame setpoints are
supported, so set_position_local is available.
PX4 packs the main mode into bits 16 to 23 and the auto sub-mode into bits 24 to
31 of customMode. The strategy maps the intent modes to AUTO main mode with
the matching sub-mode (LOITER, MISSION, RTL, LAND) and decodes telemetry by
shifting those fields back out. PX4 does not take the local-frame setpoint used
by ArduPilot, so set_position_local warns and no-ops on PX4.
The autopilot is chosen from the vehicle model string in telemetry:
-
isPX4(model)is true when the model containsPX4. -
strategyFor(model)returns the matching strategy. -
decodeMode(customMode, model)decodes a telemetry mode for the current stack. -
isArmed(baseMode)tests theMAV_MODE_FLAG_SAFETY_ARMEDbit (128). -
isAutoLabel(label)andisGuidedLabel(label)classify a decoded label as "mission running" or "hold" across both families, which the mission-progress and control gates rely on. -
isAirVehicle(type),isSubmarine(type), andisGroundOrSurface(type)classify the vehicle from itsMAV_TYPEname so the dashboard shows the right vertical control.
The dashboard go-to control adapts to the vehicle class:
- Air vehicles get Go to Altitude with Altitude Up and Down, targeting the
altitude the stack accepts: a local-NED height in GUIDED
(
set_position_local) on an ArduPilot copter, a global target altitude (set_altitude) on an ArduPlane, and a relative reposition (DO_REPOSITION) on PX4. - Submarines get Go to Depth with Ascend and Descend. Depth is an altitude
below the surface, commanded in ArduSub's ALT_HOLD depth-hold mode as a
SET_POSITION_TARGET_GLOBAL_INTwith lat/lon masked and a negative altitude (set_depth), so the sub holds depth on its barometer without a horizontal position source. - Rovers and boats move only in the surface plane, so they show no vertical control.
Max Speed sends DO_CHANGE_SPEED: an airspeed setpoint for a fixed wing and a
groundspeed setpoint for every other class.
Implement AutopilotStrategy for the new stack, add a detection branch to
isPX4 / strategyFor keyed on the model string, and the UI, mode buttons, and
mission gates work unchanged.