MSP-over-MAVLink tunnel#11718
Conversation
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
This #11472 PR has been split into a sequence of PR's by inav-claude for easier review and handling, but i'll include a whole laydown of what it entails as final product here.
Upstream PRs can't base on fork branches, so all 7 target What this isA ground-up rework of INAV's MAVLink implementation: from a single-port, single-file telemetry bolt-on into a modular MAVLink subsystem with:
Routing design follows ArduPilot's Developed on ArchitectureThe monolithic
Headers: built against the checked-in STorM32 dialect (337-message STorM32/ArduPilot/common superset) because it carries OlliW's mLRS-specific messages. The regen moved the merged Feature laydownMulti-port
Routing
Streams & protocol services
Telemetry detail
Missions
Command parity (MAVLink + MSPv2 + Programming Framework)
mLRS integration
High latency
MSP-over-MAVLink tunnel
SITL/simulator fixes
Design decisions worth remembering
Verification
Known limits / non-goals
|
05a5372 to
867ff1b
Compare
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.
MSP transport over MAVLink TUNNEL (private payload type 0x8001, MAVLink 2 only) so the Configurator can talk MSP over an existing MAVLink telemetry link. Reuses the MSP parser/encoder through narrow msp_serial seams; replies are fragmented and returned on the ingress port only; MSPv1/v2 framing symmetry is preserved end-to-end. Reboot post-processing is allowed; serial passthrough and ESC 4-way are rejected before dispatch. Malformed payload lengths are dropped and stale partial frames time out. Reply/frame buffers are file-scope, not task stack. Companion configurator branch adds the MAVLink Tunnel wireless option. Full mavlink_unittest suite: 86/86 passing. Final PR of the mavlink_multiport2 stack: tree now matches the feature branch (remaining deltas are upstream maintenance-10.x drift only).
docs/Mavlink.md documents the full MAVLink stack: multiport + routing,
datastream groups and CLI settings, identity/capabilities, mLRS
integration, supported outgoing/incoming messages and commands, mode
mappings, mission behavior and MSP parity gaps, MSP-over-MAVLink
tunnel, and high-latency mode. Updated from the development branch to
cover flight-mode-change STATUSTEXT notices and reworded for mainline.
docs/Settings.md regenerated from settings.yaml (picks up the per-port
mavlink_port{1-4}_* settings).
End-to-end live harness against a running SITL/FC MAVLink endpoint: API version, FC variant/version, build info, EEPROM write, reboot over the tunnel, and reconnect recovery after reboot.
Part 7/7 of the mavlink_multiport2 stack — final part; the tree now carries the complete feature set.
MSP-over-MAVLink tunnel
MSP transport over the MAVLink Tunnel service (private payload type
0x8001, MAVLink 2 only), so the INAV Configurator can talk MSP over an existing MAVLink telemetry link — typically a radio that exposes no separate MSP transport. The companion configurator PR adds a "MAVLink Tunnel" option under Wireless mode with SYSID selection for multi-vehicle networks.msp_serialseams (byte parser, encode-to-buffer, command processing) — no duplicate MSP framing logic.TUNNELmessages and returned on the ingress port only;target_component = 0is accepted for local delivery but never fanned out to other ports.MSP_REBOOTpost-processing is supported over the tunnel; serial passthrough and ESC 4-way passthrough are rejected before dispatch.Documentation
This PR also lands the complete user-facing
docs/Mavlink.md(multiport/routing, datastream groups and CLI settings, mLRS integration, supported messages/commands, mode mappings, mission behavior and MSP parity gaps, tunnel, high-latency mode) and regeneratesdocs/Settings.mdfor the per-portmavlink_port{1-4}_*settings.Testing
mavlink_unittestsuite: 86/86 passing (tunnel cases: malformed-length rejection, pre-dispatch passthrough rejection, reboot ingress-port handling, stale-frame reset, multi-message reply fragmentation).src/test/mavlink/tunnel/) covering that same sequence against a running SITL/FC.Companion PRs:
inav-configurator:mavlink_multiport2(tunnel UI + wrapping),mspapi2:mavlink_multiport2.