New Feature: Dual switchable receivers#11748
Draft
xznhj8129 wants to merge 11 commits into
Draft
Conversation
- 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.
- Document per-peer reconnect STATUSTEXT/arming re-announcement - Fix STATUSTEXT severity: arming-disable and mode notices are NOTICE only - Correct MSP-parity LAND/RTH rows: leg speed and RTH land flag are captured on upload, dropped on download - Restrict stream-rate CLI settings to port 1 (ports 2-4 have none) - Complete upload-translator list (RTH/SET_POI/SET_HEAD) and DO_REPOSITION param4 heading - Note downloads always reply MISSION_ITEM_INT - Fix dead MSP-Navigation-Messages.md link -> Navigation.md wp section
Review feedback on the reconnect STATUSTEXT commit: - Track heartbeat presence per peer in the route table instead of one timestamp per port, so a steady peer cannot mask a newly joining one behind the same port, and a peer failing over to another port registers as a reconnect there. If the route table is full the new peer degrades to broadcast-only behavior. - Rate-limit arming snapshots per port so a peer heartbeating slower than the gap threshold cannot elicit a resend on every beat. - Drop the enable-transition snapshot: it fired into a port nobody had connected to yet (boot) and duplicated the first-heartbeat snapshot on shared-port enable. Reconnect is now driven purely by the heartbeat signal; the enable transition still resets per-port one-shot state via the port reset path.
The release/9.1 merge (iNavFlight#11727) hit a conflict in taskSystem() where two independent fixes for the SITL load-accounting bug (iNavFlight#11710) — one from release/9.1, one from the mavlink stack — were concatenated instead of one being chosen. The result nested a duplicate '#if defined(SITL_BUILD)' block inside the '#else' branch, leaving the outer '#if' with no matching '#endif' and failing every SITL build with 'unterminated #else'. Remove the duplicated block, restoring the single intended (release/9.1) version. No functional change to load accounting; unit builds were unaffected (UNIT_TEST, not SITL_BUILD).
…ver) Adds a second receiver that runs alongside the primary. Both links stay active for telemetry, but only one drives RC control at a time. When the primary link enters failsafe, control passes to the secondary; the main failsafe now only triggers when both links are down. - Gated by CLI `dual_rx_enabled` (default OFF); new secondary PG_RX_CONFIG settings (receiver_type_secondary, serialrx_provider_secondary, serialrx_inverted_secondary, serialrx_halfduplex_secondary, sbus_sync_interval_secondary). - New serial function FUNCTION_RX_SERIAL_SECONDARY reuses the free FUNCTION_UNUSED_1 bit (1 << 13) so identical protocols can bind to distinct UARTs. All serial RX drivers take a port-function argument. - rxLink_e runtime abstraction with per-link state each cycle and the rxGetActiveLink/rxSetActiveLink/rxIsLinkReceivingSignal/rxIsPrimaryFailsafe APIs; LOGIC_CONDITION_RX_SELECT_OVERRIDE to force a link. - OSD OSD_ACTIVE_RX_LINK element (RX:P / RX:S, blinks on secondary/no-link) and a "PRI RX FS" multifunction warning. Widened the multifunction warning bitfield to 16 bits to fit the added warning. - MSP2_INAV_MISC reports the active link (activeRX byte). - rx_rx_unittest rewritten for the dual-link API (primary->secondary failover, secondary-active start, main-failsafe only when both down). Regenerated docs/Settings.md and the MSP enum/message docs.
…afe fix Addresses review findings on the dual RX feature: - Bump PG_RX_CONFIG version 13->14. The new secondary receiver fields change the stored rxConfig_t layout, so without a version bump an upgrade would reinterpret old EEPROM with the new layout and corrupt RX config. - Make the CRSF and SBUS drivers hold per-link parser and channel state so a primary and secondary receiver of the same type run independently instead of aliasing shared module buffers. Primary stays index 0, leaving the single-RX path unchanged. Remaining serial drivers still share state, so rxInit() refuses dual RX when both links use the same not-yet-instance-safe provider. - Gate the LOGIC_CONDITION_RX_SELECT_OVERRIDE link override on the forced link actually having signal; otherwise fall back to automatic selection so a dead forced link can't hold control on stale data with failsafe suppressed. - Remove the unused rxReceiverRole_e enum and document the activeRX MSP field with the real rxLink_e type; regenerate MSP docs.
Guard on the backing driver rather than the raw provider value so provider pairs that share one driver are also caught: FBUS + FPORT2 both use the fport2 driver, and the SBUS variants share the sbus driver. Prevents an aliasing pair (e.g. FBUS primary + FPORT2 secondary) from slipping past the equality check.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dual RX: primary/secondary receivers with automatic failover
WIP, requires more elaboration on switchover states, hysteresis and dwell time, receiver configurations and telemetry
Summary
Adds a second receiver that runs alongside the primary. Both links stay active for
telemetry, but only one drives RC control at a time. When the primary link enters
failsafe, control passes to the secondary; the main failsafe only triggers when
both links are down.
dual_rx_enabled(default OFF); auto-disabled if either link is an MSP RX(MSP RC can arrive on any MSP port, so a dedicated secondary link makes no sense there).
FUNCTION_RX_SERIAL_SECONDARYserial function.main-failsafe-only-when-both-down.
Configuration / CLI
New gate and secondary receiver settings in
PG_RX_CONFIG:dual_rx_enabled— bool, default OFF.receiver_type_secondary— default NONE.serialrx_provider_secondary— default per target.serialrx_inverted_secondary— default OFF.serialrx_halfduplex_secondary— default AUTO.sbus_sync_interval_secondary— default 3000 µs (range 500–10000).Serial function masks (assigned with
serial <idx> <mask> ..., additive when a port is shared):FUNCTION_RX_SERIAL(64)FUNCTION_RX_SERIAL_SECONDARY(8192 =1 << 13, reusing the previouslyunused serial-function bit)
Runtime / selection / failsafe
rxLink_eabstraction with per-link runtime state (channels, link quality, stats,timing) maintained every cycle for both PRIMARY and SECONDARY, plus the APIs
rxGetActiveLink,rxSetActiveLink,rxIsLinkReceivingSignal,rxIsPrimaryFailsafe.primary stays selected but marked invalid. Main failsafe fires only when both links
are down.
secondary UART; CRSF writes link statistics through the per-link runtime pointer.
LOGIC_CONDITION_RX_SELECT_OVERRIDE(operation 63) lets the programming frameworkforce the active link (PRIMARY/SECONDARY) via the
OVERRIDE_RX_LINKglobal flag.OSD / UI
OSD_ACTIVE_RX_LINKelement (default position (3,5), CMS-exposed) showingRX:1or
RX:2; blinks when running on the secondary link or when no link is valid.secondary still has signal. The multifunction warning bitfield was widened from 8 to
16 bits to accommodate the added warning.
MSP
MSP2_INAV_MISCreply appends a trailingactiveRXbyte (rxLink_e) reporting thecurrent active link; older clients that stop reading before it are unaffected.
Known limitations
per-link parser/channel state, so a primary and secondary receiver of the same type run
independently. The remaining serial drivers (Spektrum, SUMD, IBUS, JETI, FPORT/FPORT2,
SRXL2, GHST) still keep parser state in shared module storage, so running the same one
of those on both links would corrupt both.
rxInit()therefore refuses dual RX only whenboth links are
SERIALwith the same, not-yet-instance-safeserialrx_provider(it fallsback to single-RX), mirroring the existing MSP guard. Two different providers always run
independently. Making the remaining drivers instance-safe (same pattern as CRSF/SBUS) is a
follow-up.
valid signal, with no dwell time or blending across the switch. A marginal primary link
can cause the active link to flap frame-to-frame; a hold-off timer is a sensible future
refinement.
PG_RX_CONFIGversion bumped (13 → 14) because the new secondary fields change thestored
rxConfig_tlayout — RX config resets to defaults on upgrade.Docs
docs/Settings.mdand the MSP enum/message docs (docs/development/msp/) regenerated.Configurator companion
The INAV Configurator companion lives on
feature/dualrx(based onmavlink_multiport2)and adds the secondary-receiver UI, the RX_SERIAL_SECONDARY port function, the
activeRXMSP read, and the "Select RX link" programming operator (id 63).Tests / verification
rx_rx_unittest(RxDualLinkTest) rewritten for the dual-link API — 3/3 pass.Build/run the unit test: