Skip to content

MAVLink and MSP command-control parity#11717

Open
xznhj8129 wants to merge 8 commits into
iNavFlight:maintenance-10.xfrom
xznhj8129:mav/06-command-guided
Open

MAVLink and MSP command-control parity#11717
xznhj8129 wants to merge 8 commits into
iNavFlight:maintenance-10.xfrom
xznhj8129:mav/06-command-guided

Conversation

@xznhj8129

Copy link
Copy Markdown
Contributor

⚠ Part 6/7 of the mavlink_multiport2 split — depends on #11716.
GitHub can't base an upstream PR on a fork branch, so this targets maintenance-10.x and its diff also contains the earlier parts of the stack. Review only this part's own commits:

  • `57cb25ba5` Add MAVLink and MSP command-control parity

This part in isolation: xznhj8129/inav@mav/05-mission...mav/06-command-guided
Merge order: parts 1 → 7 in sequence.

Part 6/7 of the mavlink_multiport2 stack.

Command-control parity between MAVLink, MSP, and the Programming Framework, so GCS and companion software can arm, navigate, and land through standard commands.

Arming

  • MAV_CMD_COMPONENT_ARM_DISARM and MSP2_INAV_ARM_DISARM (0x2227) go through the normal INAV arming/disarming path and ACK success only when the requested state is actually reached.

RTH

  • MAV_CMD_NAV_RETURN_TO_LAUNCH, the ArduPilot-style MAV_CMD_DO_SET_MODE RTL request, MSP2_INAV_ACTIVATE_RTH (0x2225), and Programming Framework operation 61 all enter the normal INAV RTH mode path via activateRTHMode(), which adds a temporary BOXNAVRTH source to the RC mode selector. This deliberately does not use the failsafe/geozone forced-RTH latch — live testing showed activateForcedRTH() is not equivalent to switching into RTH mode. The temporary source clears on a pilot RC flight-mode change or disarm, so a command-triggered RTH cannot survive into a later arming attempt.

Pause / position hold

  • MAV_CMD_DO_SET_MODE also accepts ArduPilot pause-style modes (PLANE_MODE_LOITER, COPTER_MODE_LOITER, COPTER_MODE_POSHOLD, COPTER_MODE_BRAKE) and enters normal INAV PosHold at the current position/altitude/heading via a temporary BOXNAVPOSHOLD source (this is what QGC's Pause button sends). Other GCS mode changes remain UNSUPPORTED.

Landing

  • MAV_CMD_NAV_LAND, MSP2_INAV_ACTIVATE_LANDING (0x2224), and PF operation 62 perform a normal waypoint-style landing at the current position through a transient waypoint — the uploaded mission is not modified, and this is not emergency landing. Mission LAND items keep their supplied coordinates; direct LAND commands ignore coordinate fields.

Home, time, guided

  • MAV_CMD_DO_SET_HOME uses the existing waypoint-0 backend (param1 = 1 = current GNSS position; explicit global location otherwise) and retains all native WP#0 safety gates. MSP set-home remains MSP_SET_WP waypoint 0 — no duplicate command added.
  • MSP2_INAV_TIMESYNC (0x2228) returns the same monotonic nanosecond boot clock as MAVLink TIMESYNC.
  • SET_POSITION_TARGET_GLOBAL_INT / _LOCAL_NED guided handling (waypoint 255 / altitude-only requests, gated on valid GCS navigation).
  • MAV_CMD_CONDITION_YAW heading changes while the nav state has yaw control.
  • Temporary fixed-wing PosHold loiter-radius override: MAV_CMD_DO_REPOSITION.param3 in meters, or int32 loiterRadius (cm) appended to MSP2_INAV_SET_GLOBAL_TARGET (17-byte payload; 13-byte payload = no change; 0 clears). MSP2_INAV_NAV_TARGET reports the active override. Volatile: cleared on disarm/reboot, applied only while the nav FSM is in PosHold so RTH/mission/autoland loiter keeps configured defaults.
  • Explicit MAV_CMD_NAV_TAKEOFF stub returning UNSUPPORTED (foundation for later takeoff work, no behavior introduced).
  • OSD flight-mode element shows GCSN while GCS-assisted navigation is actually active.

All float command parameters are validated (finite/range) before integer conversion.

Companion PR: mspapi2:mavlink_multiport2 (synchronized message metadata + arm/RTH/land/timesync helpers).

Testing

  • Unit slice: 81/81 passing (mavlink_unittest).
  • Full SITL build, warnings-as-errors, clean. MSP dev docs regenerated.
  • X-Plane + QGC SITl test successful

@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

Rewritten mission protocol replacing the old ad-hoc counters (absent
since the modular split): owned transfers tracking initiating system,
component and ingress port; upload retries and timeouts; one-item
retransmission; final MISSION_ACK; out-of-sequence recovery; explicit
cancellation; legacy MISSION_REQUEST answered with MISSION_ITEM_INT.
Uploads are staged and committed only on success, QGC planned-home item
0 is skipped, modifier items (speed/delay/altitude) fold onto the
correct INAV waypoint, and persistence failures restore the previous
mission. Successful uploads and clears update nonvolatile storage.
Adds 1 Hz MISSION_CURRENT, active-item download flags, and
MISSION_ITEM_REACHED broadcast from a navigation-side reached latch.

Includes the live SITL mission test rig (src/test/mavlink/missions) and
routing compliance harness (src/test/mavlink/routing).
Unit slice: 58/58 passing.

Mission translation to INAV's MSP waypoint model is lossy; downloads
are best-effort reconstruction, not canonical mission backups.
Standalone 8-check pass/fail rig against a self-started SITL with the
known-good multiport serial layout: MSP on UART1, MAVLink receiver
telemetry and RC override on UART2, GCS heartbeat, mission upload and
readback, stream-rate and message-rate control on UART3. Previously
lived only in the development workspace and was never committed.
NAV_STATE_WAYPOINT_RTH_LAND success maps straight to
NAV_STATE_WAYPOINT_FINISHED, bypassing NAV_STATE_WAYPOINT_NEXT where the
reached latch is normally set, and a mission LAND item that hands off to
the fixed-wing autoland FSM terminates in NAV_STATE_FW_LANDING_FINISHED
without touching either path. In both cases a mission terminated by
NAV_WP_ACTION_LAND never fired MISSION_ITEM_REACHED for its final item
and MISSION_CURRENT stayed NOT_STARTED after touchdown.

Mark the item in the simple-landing success branch, and in
FW_LANDING_FINISHED when the autoland was entered from a mission LAND
item (fwLandState.landWp), using landState to guard the self-looping
re-entry. The aborted-landing paths intentionally do not mark.
…ad encoder

MISSION_CLEAR_ALL now denies a sender that is not the owning partner of
an in-progress transfer, matching MISSION_COUNT and MISSION_REQUEST_LIST;
previously any local-target sender could cancel another partner's
transfer mid-flight.

Downloads always answer MISSION_ITEM_INT (per MAVLink deprecation
guidance for MISSION_REQUEST), so the float MISSION_ITEM response
encoder was unreachable - removed, with a comment explaining why legacy
requests get INT replies. Upload-side float support is unaffected.
Two ways the completion signal could be lost or misreported:

- mavlinkSendPendingMissionItemReached() consumed the one-slot reached
  latch before checking for an active port. A shared MAVLink port that
  closes on disarm right after landing destroyed the final item's
  MISSION_ITEM_REACHED and left missionCompleted false. Check for a
  delivery target first; the latch stays pending until a port can send.

- MISSION_CURRENT ranked WP-mode activity above completion, and
  NAV_STATE_WAYPOINT_FINISHED still maps to NAV_WP_MODE, so a landed
  vehicle reported ACTIVE until the pilot left WP mode. Completion now
  outranks activity, and missionCompleted is cleared on the WP-mode
  rising edge so a re-flown mission reports ACTIVE, not stale COMPLETE.
Covers the fixes in the previous commits:
- MISSION_CURRENT completion outranks WP-mode activity and clears on a
  fresh WP-mode engagement
- the reached latch survives cycles with no active MAVLink port
- MISSION_CLEAR_ALL from a non-owning sender is denied and leaves the
  owner's transfer usable; the owning sender can still cancel its own
- MAV_CMD_COMPONENT_ARM_DISARM and MSP2_INAV_ARM_DISARM through the
  normal arming path, succeeding only when the requested state is
  reached
- RTH via a temporary BOXNAVRTH source on the RC mode selector
  (activateRTHMode) instead of the failsafe/geozone forced-RTH latch;
  wired to MAV_CMD_NAV_RETURN_TO_LAUNCH, ArduPilot DO_SET_MODE RTL,
  MSP2_INAV_ACTIVATE_RTH, and Programming Framework operation 61.
  Cleared by a pilot flight-mode change or disarm
- QGC/ArduPilot pause: DO_SET_MODE Loiter/PosHold/Brake enters normal
  PosHold at the current position via a temporary BOXNAVPOSHOLD source
- Normal current-position LAND (transient waypoint, uploaded mission
  untouched) via MAV_CMD_NAV_LAND, MSP2_INAV_ACTIVATE_LANDING, PF op 62
- MAV_CMD_DO_SET_HOME through the native waypoint-0 backend
- MSP2_INAV_TIMESYNC returning the MAVLink TIMESYNC boot clock
- Temporary fixed-wing loiter-radius override: DO_REPOSITION.param3
  (meters) or int32 loiterRadius appended to MSP2_INAV_SET_GLOBAL_TARGET
  (cm); volatile, cleared on disarm/reboot, only active in PosHold
- SET_POSITION_TARGET_GLOBAL_INT / _LOCAL_NED guided handling
- MAV_CMD_CONDITION_YAW; explicit unsupported MAV_CMD_NAV_TAKEOFF stub
- GCSN OSD flight-mode element while GCS navigation is active

Unit slice: 81/81 passing.
A command-triggered landing (MAV_CMD_NAV_LAND / MSP direct land) borrows
NAV_STATE_WAYPOINT_RTH_LAND and the FW autoland FSM with a transient
waypoint, while activeWaypointIndex still points at whatever mission item
was last active. The unconditional reached-marking added for mission LAND
items would emit MISSION_ITEM_REACHED for that stale index and could mark
a loaded mission complete. Capture forcedLandingActivated before the
existing clears and skip the marking for commanded landings at both
finish sites.
@xznhj8129
xznhj8129 force-pushed the mav/06-command-guided branch from efd562a to 0cc2e89 Compare July 19, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant