From b8c5f66af053f609c9269f1e3cda2a4955bb0df0 Mon Sep 17 00:00:00 2001 From: Gennaro Guidone <99129829+gguidone@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:59:52 +0200 Subject: [PATCH] feat(manual_control): replace stick override threshold with double-flick gesture (#27041) * feat(manual_control): trigger RC override on stick velocity COM_RC_STICK_OV is now a velocity threshold (1/s) instead of a deflection percentage. Default 3.0, range [1.0, 10.0]. A stick held statically cannot trigger override. * docs(manual_control): update COM_RC_STICK_OV description for velocity-based override * feat(manual_control): gate RC override with sign-consistency check * fix(ManualControl): lower threshold and filter constant for RC override, add tests for MovingDiff * refactor(commander): merge RC override params into COM_RC_OVR_SPEED Replace the COM_RC_OVERRIDE bitmask + COM_RC_STICK_OV threshold with a single float COM_RC_OVR_SPEED (stick override velocity, 0 = disabled). Override now applies uniformly in auto and offboard modes. - ManualControl: rename param, treat 0 as disabled (FLT_EPSILON guard) - Commander: drop the per-mode bitmask gate and the RcOverrideBits enum - param_translation: migrate COM_RC_OVERRIDE on import (enabled -> 1.0, disabled -> 0.0) and drop the unit-incompatible COM_RC_STICK_OV value - docs: collapse the two params into one across the mode pages * fix(manual_override): Move configuration to manual_control module with MAN_OVERRIDE_SPD parameter and a negative value disabling the feature. All other logic stays in Commander. * docs(releases): add release note for RC override rework (MAN_OVERRIDE_SPD) --------- Co-authored-by: Matthias Grob --- .../amovlabf410_drone_v1.15.4.params | 2 - docs/en/flight_modes/offboard.md | 3 +- docs/en/flight_modes/return.md | 7 +- docs/en/flight_modes_mc/hold.md | 7 +- docs/en/flight_modes_mc/land.md | 7 +- docs/en/flight_modes_mc/mission.md | 7 +- docs/en/flight_modes_mc/return.md | 5 +- docs/en/flight_modes_mc/takeoff.md | 7 +- docs/en/releases/main.md | 4 +- docs/en/ros/offboard_control.md | 2 +- msg/versioned/ManualControlSetpoint.msg | 2 +- src/lib/parameters/param_translation.cpp | 11 +++ src/modules/commander/Commander.cpp | 42 +++------ src/modules/commander/Commander.hpp | 6 -- src/modules/commander/commander_params.yaml | 32 +------ src/modules/commander/failsafe/framework.h | 5 - src/modules/manual_control/CMakeLists.txt | 3 +- src/modules/manual_control/ManualControl.cpp | 16 +++- src/modules/manual_control/ManualControl.hpp | 4 +- src/modules/manual_control/MovingDiff.hpp | 22 ++++- src/modules/manual_control/MovingDiffTest.cpp | 92 ++++++++++++++++--- .../manual_control/manual_control_params.yaml | 15 +++ .../multicopter_nudging_params.yaml | 2 +- 23 files changed, 182 insertions(+), 121 deletions(-) diff --git a/docs/assets/airframes/multicopter/amovlab_f410/amovlabf410_drone_v1.15.4.params b/docs/assets/airframes/multicopter/amovlab_f410/amovlabf410_drone_v1.15.4.params index 30c1d79876..ffea150d8c 100644 --- a/docs/assets/airframes/multicopter/amovlab_f410/amovlabf410_drone_v1.15.4.params +++ b/docs/assets/airframes/multicopter/amovlab_f410/amovlabf410_drone_v1.15.4.params @@ -318,8 +318,6 @@ 1 1 COM_RCL_EXCEPT 0 6 1 1 COM_RC_IN_MODE 3 6 1 1 COM_RC_LOSS_T 0.500000000000000000 9 -1 1 COM_RC_OVERRIDE 1 6 -1 1 COM_RC_STICK_OV 30.000000000000000000 9 1 1 COM_SPOOLUP_TIME 1.000000000000000000 9 1 1 COM_THROW_EN 0 6 1 1 COM_THROW_SPEED 5.000000000000000000 9 diff --git a/docs/en/flight_modes/offboard.md b/docs/en/flight_modes/offboard.md index 07c295cc82..4e7b61fc93 100644 --- a/docs/en/flight_modes/offboard.md +++ b/docs/en/flight_modes/offboard.md @@ -358,8 +358,7 @@ _Offboard mode_ is affected by the following parameters: | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [COM_OF_LOSS_T](../advanced_config/parameter_reference.md#COM_OF_LOSS_T) | Time-out (in seconds) to wait when offboard connection is lost before triggering offboard lost failsafe (`COM_OBL_RC_ACT`) | | [COM_OBL_RC_ACT](../advanced_config/parameter_reference.md#COM_OBL_RC_ACT) | Flight mode to switch to if offboard control is lost. | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md). This is not enabled for offboard mode by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default value of 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | | [COM_RCL_EXCEPT](../advanced_config/parameter_reference.md#COM_RCL_EXCEPT) | Specify modes in which RC loss is ignored and the failsafe action not triggered. Set bit `2` to ignore RC loss in Offboard mode. | ## Developer Resources diff --git a/docs/en/flight_modes/return.md b/docs/en/flight_modes/return.md index 9c97a5e008..61e637e890 100644 --- a/docs/en/flight_modes/return.md +++ b/docs/en/flight_modes/return.md @@ -18,8 +18,8 @@ The following topics should be read first if you're using these vehicle types: - Flying vehicles will failsafe if they lose the position estimate. - Mode requires home position is set. - Mode prevents arming (vehicle cannot be armed while this mode is selected). -- RC control switches can be used to change flight modes on any vehicle. -- RC stick movement in a multicopter (or VTOL in multicopter mode) will [by default](#COM_RC_OVERRIDE) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. +- RC switches can be used to change flight modes on any vehicle. +- Stick movement in a multicopter (or VTOL in hover) will [by default](#MAN_OVERRIDE_SPD) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. - A VTOL will return as MC or FW based on its mode at the point the return mode was triggered. In MC mode it will respect multicopter parameters, such as the landing "cone". In FW mode it will respect fixed-wing parameters (ignore the cone), but unless using a mission landing, will transition to MC mode and land at the destination after loitering at the descent altitude. @@ -221,7 +221,6 @@ The RTL parameters are listed in [Parameter Reference > Return Mode](../advanced | [RTL_MIN_DIST](../advanced_config/parameter_reference.md#RTL_MIN_DIST) | Within this distance from the return destination, the return altitude is calculated from the "cone" rather than directly from `RTL_RETURN_ALT`. | | [RTL_CONE_ANG](../advanced_config/parameter_reference.md#RTL_CONE_ANG) | Half-angle of the cone that defines the vehicle RTL return altitude. Values (in degrees): `0`, `25`, `45`, `65`, `80`, `90`. Note that `0` is "no cone" (always return at `RTL_RETURN_ALT` or higher), while `90` indicates an almost vertical cone, so the vehicle generally returns at its current altitude when close to the destination. The return altitude may still be constrained to avoid flying too low while approaching the destination. | | [RTL_APPR_FORCE](../advanced_config/parameter_reference.md#RTL_APPR_FORCE) | [VTOL FW only] If set, home or rally-point RTL destinations are only considered when a valid VTOL approach loiter is defined for that landing location. Mission landing patterns are unaffected. | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md) (unless prevented by the active failsafe state). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | | [RTL_LOITER_RAD](../advanced_config/parameter_reference.md#RTL_LOITER_RAD) | [Fixed-wing Only] The radius of the loiter circle (at [RTL_LAND_DELAY](#RTL_LAND_DELAY)). | | [MIS_TKO_LAND_REQ](../advanced_config/parameter_reference.md#MIS_TKO_LAND_REQ) | Specify whether a mission landing or takeoff pattern is _required_. Generally fixed-wing vehicles set this to require a landing pattern but VTOL do not. | diff --git a/docs/en/flight_modes_mc/hold.md b/docs/en/flight_modes_mc/hold.md index 3d5dd9ac26..261c1cf74d 100644 --- a/docs/en/flight_modes_mc/hold.md +++ b/docs/en/flight_modes_mc/hold.md @@ -18,7 +18,7 @@ It is usually activated with a pre-programmed switch. - Disarmed vehicles can switch to mode without valid position estimate but can't arm. - Mode requires wind and flight time are within allowed limits (specified via parameters). - RC control switches can be used to change flight modes on any vehicle. -- RC stick movement will [by default](#COM_RC_OVERRIDE) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. +- Stick movement will [by default](#MAN_OVERRIDE_SPD) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. @@ -29,7 +29,7 @@ It is usually activated with a pre-programmed switch. The vehicle stops and hovers, maintaining its position and altitude. The vehicle will first ascend to [NAV_MIN_LTR_ALT](#NAV_MIN_LTR_ALT) if the mode is engaged below this altitude. -RC stick movement will change the vehicle to [Position mode](../flight_modes_mc/position.md) (by [default](#COM_RC_OVERRIDE)). +Stick movement will change the vehicle to [Position mode](../flight_modes_mc/position.md) (by [default](#MAN_OVERRIDE_SPD)). ### Parameters @@ -38,8 +38,7 @@ Hold mode behaviour can be configured using the parameters below. | Parameter | Description | | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [NAV_MIN_LTR_ALT](../advanced_config/parameter_reference.md#NAV_MIN_LTR_ALT) | This is the minimum altitude above Home the system will always obey in Hold mode if switched into this mode without specifying an altitude (e.g. through switch on RC). | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default value of 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | diff --git a/docs/en/flight_modes_mc/land.md b/docs/en/flight_modes_mc/land.md index e91541a213..67890f9c17 100644 --- a/docs/en/flight_modes_mc/land.md +++ b/docs/en/flight_modes_mc/land.md @@ -13,7 +13,7 @@ The vehicle will disarm shortly after landing (by default). - Flying vehicles will failsafe if they lose the position estimate. - Mode prevents arming (vehicle cannot be armed while this mode is selected). - RC control switches can be used to change flight modes on any vehicle. -- RC stick movement in a multicopter (or VTOL in multicopter mode) will [by default](#COM_RC_OVERRIDE) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. +- Stick movement in a multicopter (or VTOL in hover) will [by default](#MAN_OVERRIDE_SPD) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. - The mode can be triggered using the [MAV_CMD_NAV_LAND](https://mavlink.io/en/messages/common.html#MAV_CMD_NAV_LAND) MAVLink command, or by explicitly switching to Land mode. @@ -25,7 +25,7 @@ The vehicle will disarm shortly after landing (by default). The vehicle will land at the location at which the mode was engaged. The vehicle descends at the rate specified in [MPC_LAND_SPEED](#MPC_LAND_SPEED) and will disarm after landing (by [default](#COM_DISARM_LAND)). -RC stick movement will change the vehicle to [Position mode](../flight_modes_mc/position.md) (by [default](#COM_RC_OVERRIDE)). +Stick movement will change the vehicle to [Position mode](../flight_modes_mc/position.md) (by [default](#MAN_OVERRIDE_SPD)). ### Parameters @@ -35,8 +35,7 @@ Land mode behaviour can be configured using the parameters below. | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [MPC_LAND_SPEED](../advanced_config/parameter_reference.md#MPC_LAND_SPEED) | The rate of descent during landing. This should be kept fairly low as the ground conditions are not known. | | [COM_DISARM_LAND](../advanced_config/parameter_reference.md#COM_DISARM_LAND) | Time-out for auto disarm after landing, in seconds. If set to -1 the vehicle will not disarm on landing. | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default value of 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | ## See Also diff --git a/docs/en/flight_modes_mc/mission.md b/docs/en/flight_modes_mc/mission.md index 5cbeb7deaa..b721fff592 100644 --- a/docs/en/flight_modes_mc/mission.md +++ b/docs/en/flight_modes_mc/mission.md @@ -11,8 +11,8 @@ The mission is typically created and uploaded with a Ground Control Station (GCS - The vehicle must be armed before this mode can be engaged. - This mode is automatic - no user intervention is _required_ to control the vehicle. - RC control switches can be used to change flight modes on any vehicle. -- RC stick movement will [by default](#COM_RC_OVERRIDE) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. - This is true for multicopters and VTOL in MC mode. +- Stick movement will [by default](#MAN_OVERRIDE_SPD) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. + This is true for multicopters and VTOL in hover. ::: @@ -108,8 +108,7 @@ General parameters: | Parameter | Description | | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [NAV_RCL_ACT](../advanced_config/parameter_reference.md#NAV_RCL_ACT) | RC loss failsafe mode (what the vehicle will do if it looses RC connection) - e.g. enter hold mode, return mode, terminate etc. | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) gives control back to the pilot in [Position mode](../flight_modes_mc/position.md). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default value of 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | Parameters related to [mission feasibility checks](#mission-feasibility-checks): diff --git a/docs/en/flight_modes_mc/return.md b/docs/en/flight_modes_mc/return.md index d41b369c08..79e78bd432 100644 --- a/docs/en/flight_modes_mc/return.md +++ b/docs/en/flight_modes_mc/return.md @@ -20,7 +20,7 @@ The default type is recommended. - Mode requires home position is set. - Mode prevents arming (vehicle cannot be armed while this mode is selected). - RC control switches can be used to change flight modes on any vehicle. -- RC stick movement will [by default](#COM_RC_OVERRIDE) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. +- Stick movement will [by default](#MAN_OVERRIDE_SPD) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. @@ -67,8 +67,7 @@ The parameters that are relevant to multicopter (assuming the [RTL_TYPE](../adva | [RTL_LAND_DELAY](../advanced_config/parameter_reference.md#RTL_LAND_DELAY) | Time to hover at `RTL_DESCEND_ALT` before landing (default: 0.5s) - by default this period is short so that the vehicle will simply slow and then land immediately. If set to -1 the system will loiter at `RTL_DESCEND_ALT` rather than landing. The delay is provided to allow you to configure time for landing gear to be deployed (triggered automatically). | | [RTL_MIN_DIST](../advanced_config/parameter_reference.md#RTL_MIN_DIST) | Within this distance from the home position, the return altitude is calculated from the "cone" rather than directly from `RTL_RETURN_ALT`. | | [RTL_CONE_ANG](../advanced_config/parameter_reference.md#RTL_CONE_ANG) | Half-angle of the cone that defines the vehicle RTL return altitude. Values (in degrees): `0`, `25`, `45`, `65`, `80`, `90`. Note that `0` is "no cone" (always return at `RTL_RETURN_ALT` or higher), while `90` indicates an almost vertical cone, so the vehicle generally returns at its current altitude when close to the destination. The return altitude may still be constrained to avoid flying too low while approaching the destination. | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md) (unless prevented by the active failsafe state). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default value of 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | ## See Also diff --git a/docs/en/flight_modes_mc/takeoff.md b/docs/en/flight_modes_mc/takeoff.md index ab6f6dca7a..bdd561f59d 100644 --- a/docs/en/flight_modes_mc/takeoff.md +++ b/docs/en/flight_modes_mc/takeoff.md @@ -12,7 +12,7 @@ The _Takeoff_ flight mode causes the vehicle to take off to a specified height a - Flying vehicles will failsafe if they lose the position estimate. - Disarmed vehicles can switch to mode without valid position estimate but can't arm. - RC control switches can be used to change flight modes. -- RC stick movement will [by default](#COM_RC_OVERRIDE) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. +- Stick movement will [by default](#MAN_OVERRIDE_SPD) change the vehicle to [Position mode](../flight_modes_mc/position.md) unless prevented by the active failsafe state. - The [Failure Detector](../config/safety.md#failure-detector) will automatically stop the engines if there is a problem on takeoff. @@ -23,7 +23,7 @@ The _Takeoff_ flight mode causes the vehicle to take off to a specified height a A multi rotor ascends vertically to the altitude defined in [MIS_TAKEOFF_ALT](../advanced_config/parameter_reference.md#MIS_TAKEOFF_ALT) and holds position. -RC stick movement will change the vehicle to [Position mode](../flight_modes_mc/position.md) (by [default](#COM_RC_OVERRIDE)). +Stick movement will change the vehicle to [Position mode](../flight_modes_mc/position.md) (by [default](#MAN_OVERRIDE_SPD)). ### Parameters @@ -33,8 +33,7 @@ Takeoff is affected by the following parameters: | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [MIS_TAKEOFF_ALT](../advanced_config/parameter_reference.md#MIS_TAKEOFF_ALT) | Target altitude during takeoff (default: 2.5m) | | [MPC_TKO_SPEED](../advanced_config/parameter_reference.md#MPC_TKO_SPEED) | Speed of ascent (default: 1.5m/s) | -| [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. | -| [COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled) | +| [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) | Speed (normalized stick travel per second) above which moving the sticks controlling a multicopter (or VTOL in hover) gives control back to the pilot by switching to [Position mode](../flight_modes_mc/position.md) (or Altitude mode if position is unavailable). At the default value of 1 a half-stick movement in ~0.5 s triggers it; lower is more sensitive. A stick held statically has zero speed and will not trigger. Set to -1 to disable. | ## See Also diff --git a/docs/en/releases/main.md b/docs/en/releases/main.md index c215bf157b..f055734846 100644 --- a/docs/en/releases/main.md +++ b/docs/en/releases/main.md @@ -22,7 +22,7 @@ Update these notes with features that are going to be in `main` (PX4 v1.18 or la ## Read Before Upgrading -- TBD +- The RC override parameters `COM_RC_OVERRIDE` and `COM_RC_STICK_OV` are replaced by a single [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) (minimum stick speed to take over, default `1`; negative disables). `COM_RC_OVERRIDE=0` is migrated to `MAN_OVERRIDE_SPD=-1`. The `COM_RC_STICK_OV` value is not auto-migrated because its unit changed, so re-tune `MAN_OVERRIDE_SPD` if you had customized it. Please continue reading for [upgrade instructions](#upgrade-guide). @@ -82,7 +82,7 @@ Please continue reading for [upgrade instructions](#upgrade-guide). ### RC -- TBD +- Merged the RC override parameters `COM_RC_OVERRIDE` and `COM_RC_STICK_OV` into a single [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) and made override reject erratic signal jumps. ([PX4-Autopilot#27041](https://github.com/PX4/PX4-Autopilot/pull/27041)). ### Multi-Rotor diff --git a/docs/en/ros/offboard_control.md b/docs/en/ros/offboard_control.md index 3f73400179..5e95d37017 100644 --- a/docs/en/ros/offboard_control.md +++ b/docs/en/ros/offboard_control.md @@ -14,7 +14,7 @@ There are two things you want to setup on the firmware side before starting offb ### Enable RC Override -In _QGroundControl_ you can set the [COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) parameter to automatically switch from offboard mode (or any mode) to Position mode if the RC sticks are moved. +In _QGroundControl_ the [MAN_OVERRIDE_SPD](../advanced_config/parameter_reference.md#MAN_OVERRIDE_SPD) parameter controls automatically switching from offboard (or autonomous) mode to Position mode when the remote sticks are moved. This is enabled by default; set it to -1 to disable. This is the best way to ensure that an operator can easily take control of the vehicle and switch to the safest flight mode. ### Map an RC switch to offboard mode activation diff --git a/msg/versioned/ManualControlSetpoint.msg b/msg/versioned/ManualControlSetpoint.msg index ddf902f00f..0d30cf7575 100644 --- a/msg/versioned/ManualControlSetpoint.msg +++ b/msg/versioned/ManualControlSetpoint.msg @@ -37,7 +37,7 @@ float32 aux4 float32 aux5 float32 aux6 -bool sticks_moving +bool sticks_moving # manual control override request in an auto or offboard mode, only gets true if feature is enabled uint16 buttons # From uint16 buttons field of Mavlink manual_control message diff --git a/src/lib/parameters/param_translation.cpp b/src/lib/parameters/param_translation.cpp index a78223c303..2676888314 100644 --- a/src/lib/parameters/param_translation.cpp +++ b/src/lib/parameters/param_translation.cpp @@ -244,6 +244,17 @@ param_modify_on_import_ret param_modify_on_import(bson_node_t node) } } + // 2026-06-12: merge COM_RC_OVERRIDE + COM_RC_STICK_OV into MAN_OVERRIDE_SPD + { + if ((node->type == bson_type_t::BSON_INT32) && (strcmp("COM_RC_OVERRIDE", node->name) == 0) && (node->i32 == 0)) { + node->d = -1.0; + node->type = bson_type_t::BSON_DOUBLE; + strcpy(node->name, "MAN_OVERRIDE_SPD"); + PX4_INFO("migrating %s -> %s (disabled)", "COM_RC_OVERRIDE", "MAN_OVERRIDE_SPD"); + return param_modify_on_import_ret::PARAM_MODIFIED; + } + } + // 2026-06-22: translate HEATER*_IMU_ID to HEATER*_SENS_ID // HEATER_MAX_INSTANCES == 3 (in heater.h) { diff --git a/src/modules/commander/Commander.cpp b/src/modules/commander/Commander.cpp index 3d771c00bc..f6084aa137 100644 --- a/src/modules/commander/Commander.cpp +++ b/src/modules/commander/Commander.cpp @@ -3121,38 +3121,22 @@ void Commander::manualControlCheck() _last_manual_throttle = manual_control_setpoint.throttle; if (isArmed()) { - // Abort autonomous mode and switch to position mode if sticks are moved significantly - // but only if actually in air. - if (manual_control_setpoint.sticks_moving - && !_vehicle_control_mode.flag_control_manual_enabled - && (_vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING) - ) { - bool override_enabled = false; + // Hand control back to the pilot when they override with the sticks (see MAN_OVERRIDE_SPD). + // Only applies to multicopters (incl. VTOLs in MC mode) in auto/offboard modes. + const bool rotary_wing = (_vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING); + const bool overridable_mode = _vehicle_control_mode.flag_control_auto_enabled || _vehicle_control_mode.flag_control_offboard_enabled; - if (_vehicle_control_mode.flag_control_auto_enabled) { - if (_param_com_rc_override.get() & static_cast(RcOverrideBits::AUTO_MODE_BIT)) { - override_enabled = true; + if (manual_control_setpoint.sticks_moving && rotary_wing && overridable_mode) { + // If no failsafe is active, directly change the mode, otherwise pass the request to the failsafe state machine + if (_failsafe.selectedAction() <= FailsafeBase::Action::Warn) { + if (_user_mode_intention.change(vehicle_status_s::NAVIGATION_STATE_POSCTL, ModeChangeSource::User, true)) { + tune_positive(true); + mavlink_log_info(&_mavlink_log_pub, "Pilot took over using sticks\t"); + events::send(events::ID("commander_rc_override"), events::Log::Info, "Pilot took over using sticks"); } - } - if (_vehicle_control_mode.flag_control_offboard_enabled) { - if (_param_com_rc_override.get() & static_cast(RcOverrideBits::OFFBOARD_MODE_BIT)) { - override_enabled = true; - } - } - - if (override_enabled) { - // If no failsafe is active, directly change the mode, otherwise pass the request to the failsafe state machine - if (_failsafe.selectedAction() <= FailsafeBase::Action::Warn) { - if (_user_mode_intention.change(vehicle_status_s::NAVIGATION_STATE_POSCTL, ModeChangeSource::User, true)) { - tune_positive(true); - mavlink_log_info(&_mavlink_log_pub, "Pilot took over using sticks\t"); - events::send(events::ID("commander_rc_override"), events::Log::Info, "Pilot took over using sticks"); - } - - } else { - _failsafe_user_override_request = true; - } + } else { + _failsafe_user_override_request = true; } } diff --git a/src/modules/commander/Commander.hpp b/src/modules/commander/Commander.hpp index 8ea172e458..59d9559f91 100644 --- a/src/modules/commander/Commander.hpp +++ b/src/modules/commander/Commander.hpp @@ -212,11 +212,6 @@ private: ALWAYS = 2 }; - enum class RcOverrideBits : int32_t { - AUTO_MODE_BIT = (1 << 0), - OFFBOARD_MODE_BIT = (1 << 1), - }; - /* Decouple update interval and hysteresis counters, all depends on intervals */ static constexpr uint64_t COMMANDER_MONITORING_INTERVAL{10_ms}; @@ -343,7 +338,6 @@ private: (ParamBool) _param_com_home_in_air, (ParamBool) _param_com_force_safety, (ParamInt) _param_com_prearm_mode, - (ParamInt) _param_com_rc_override, (ParamFloat) _param_com_spoolup_time, (ParamInt) _param_com_flight_uuid, (ParamFloat) _param_com_cpu_max, diff --git a/src/modules/commander/commander_params.yaml b/src/modules/commander/commander_params.yaml index 5788092a08..8e35eecdc4 100644 --- a/src/modules/commander/commander_params.yaml +++ b/src/modules/commander/commander_params.yaml @@ -171,8 +171,8 @@ parameters: long: |- Before entering failsafe (RTL, Land, Hold), wait COM_FAIL_ACT_T seconds in Hold mode for the user to realize. - During that time the user can switch modes, but cannot take over control via the stick override feature (see COM_RC_OVERRIDE). - Afterwards the configured failsafe action is triggered and the user may use stick override. + During that time the user can switch modes, but cannot take over control via the manual control override feature (see MAN_OVERRIDE_SPD). + Afterwards the configured failsafe action is triggered and the user may use manual control override. A zero value disables the delay. type: float @@ -268,34 +268,6 @@ parameters: 1: Deny arming 2: Warning only default: 2 - COM_RC_OVERRIDE: - description: - short: Enable manual control stick override - long: |- - When enabled, moving the sticks more than COM_RC_STICK_OV - immediately gives control back to the pilot by switching to Position mode and - if position is unavailable Altitude mode. - Note: Only has an effect on multicopters, and VTOLs in multicopter mode. - type: bitmask - bit: - 0: Enable override during auto modes (except for in critical battery reaction) - 1: Enable override during offboard mode - default: 1 - min: 0 - max: 3 - COM_RC_STICK_OV: - description: - short: Stick override threshold - long: |- - If COM_RC_OVERRIDE is enabled and the joystick input is moved more than this threshold - the pilot takes over control. - type: float - default: 30.0 - unit: '%' - min: 5 - max: 80 - decimal: 0 - increment: 0.05 COM_ARM_MIS_REQ: description: short: Require valid mission to arm diff --git a/src/modules/commander/failsafe/framework.h b/src/modules/commander/failsafe/framework.h index 06c2fdbd36..53375a7bf0 100644 --- a/src/modules/commander/failsafe/framework.h +++ b/src/modules/commander/failsafe/framework.h @@ -118,11 +118,6 @@ public: } } - enum class RcOverrideBits : int32_t { - AUTO_MODE_BIT = (1 << 0), - OFFBOARD_MODE_BIT = (1 << 1), - }; - struct State { bool armed{false}; uint8_t user_intended_mode{0}; diff --git a/src/modules/manual_control/CMakeLists.txt b/src/modules/manual_control/CMakeLists.txt index d51a711421..01da10e8ce 100644 --- a/src/modules/manual_control/CMakeLists.txt +++ b/src/modules/manual_control/CMakeLists.txt @@ -36,11 +36,11 @@ px4_add_module( MAIN manual_control COMPILE_FLAGS SRCS - ManualControl.cpp ManualControl.cpp ManualControl.hpp ManualControlSelector.hpp ManualControlSelector.cpp + MovingDiff.hpp MODULE_CONFIG manual_control_params.yaml DEPENDS @@ -50,3 +50,4 @@ px4_add_module( px4_add_functional_gtest(SRC ManualControlTest.cpp LINKLIBS modules__manual_control) px4_add_unit_gtest(SRC ManualControlSelectorTest.cpp LINKLIBS modules__manual_control) +px4_add_unit_gtest(SRC MovingDiffTest.cpp LINKLIBS modules__manual_control) diff --git a/src/modules/manual_control/ManualControl.cpp b/src/modules/manual_control/ManualControl.cpp index 1f387a5e08..ca4d5308fb 100644 --- a/src/modules/manual_control/ManualControl.cpp +++ b/src/modules/manual_control/ManualControl.cpp @@ -139,12 +139,18 @@ void ManualControl::processInput(hrt_abstime now) // User override by stick const float dt_s = (now - _timestamp_last_loop) / 1e6f; - const float minimum_stick_change = 0.01f * _param_com_rc_stick_ov.get(); + const float velocity_threshold = _param_man_override_spd.get(); - _selector.setpoint().sticks_moving = (fabsf(_roll_diff.update(_selector.setpoint().roll, dt_s)) > minimum_stick_change) - || (fabsf(_pitch_diff.update(_selector.setpoint().pitch, dt_s)) > minimum_stick_change) - || (fabsf(_yaw_diff.update(_selector.setpoint().yaw, dt_s)) > minimum_stick_change) - || (fabsf(_throttle_diff.update(_selector.setpoint().throttle, dt_s)) > minimum_stick_change); + _selector.setpoint().sticks_moving = + (velocity_threshold >= 0.f) && + ((fabsf(_roll_diff.update(_selector.setpoint().roll, dt_s)) > velocity_threshold + && _roll_diff.consecutiveSameSign() >= MIN_SIGN_CONSECUTIVE) + || (fabsf(_pitch_diff.update(_selector.setpoint().pitch, dt_s)) > velocity_threshold + && _pitch_diff.consecutiveSameSign() >= MIN_SIGN_CONSECUTIVE) + || (fabsf(_yaw_diff.update(_selector.setpoint().yaw, dt_s)) > velocity_threshold + && _yaw_diff.consecutiveSameSign() >= MIN_SIGN_CONSECUTIVE) + || (fabsf(_throttle_diff.update(_selector.setpoint().throttle, dt_s)) > velocity_threshold + && _throttle_diff.consecutiveSameSign() >= MIN_SIGN_CONSECUTIVE)); _selector.setpoint().timestamp = now; _manual_control_setpoint_pub.publish(_selector.setpoint()); diff --git a/src/modules/manual_control/ManualControl.hpp b/src/modules/manual_control/ManualControl.hpp index 3917ddee40..f36f94f811 100644 --- a/src/modules/manual_control/ManualControl.hpp +++ b/src/modules/manual_control/ManualControl.hpp @@ -135,6 +135,8 @@ private: MovingDiff _yaw_diff{}; MovingDiff _throttle_diff{}; + static constexpr uint8_t MIN_SIGN_CONSECUTIVE = 3; + perf_counter_t _loop_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")}; perf_counter_t _loop_interval_perf{perf_alloc(PC_INTERVAL, MODULE_NAME": interval")}; @@ -150,7 +152,7 @@ private: DEFINE_PARAMETERS( (ParamInt) _param_com_rc_in_mode, (ParamFloat) _param_com_rc_loss_t, - (ParamFloat) _param_com_rc_stick_ov, + (ParamFloat) _param_man_override_spd, (ParamBool) _param_man_arm_gesture, (ParamFloat) _param_man_kill_gest_t, (ParamBool) _param_com_arm_swisbtn, diff --git a/src/modules/manual_control/MovingDiff.hpp b/src/modules/manual_control/MovingDiff.hpp index 7fa2b8c8be..2fca4a30b7 100644 --- a/src/modules/manual_control/MovingDiff.hpp +++ b/src/modules/manual_control/MovingDiff.hpp @@ -45,25 +45,45 @@ public: return NAN; } - _difference_filter.setParameters(dt_s, .1f); + _difference_filter.setParameters(dt_s, .05f); // Leave _diff at 0.0f if we don't have a _last_value yet. if (PX4_ISFINITE(_last_value)) { const float new_diff = (value - _last_value) / dt_s; _difference_filter.update(new_diff); + + // Count consecutive same-sign raw-velocity samples (rejects random noise). + const int8_t s = (new_diff > 0.f) ? 1 : (new_diff < 0.f) ? -1 : 0; + + if (s != 0) { + if (s == _last_sign && _consecutive_same_sign < UINT8_MAX) { + _consecutive_same_sign++; + + } else { + _consecutive_same_sign = 1; + } + + _last_sign = s; + } } _last_value = value; return _difference_filter.getState(); } + uint8_t consecutiveSameSign() const { return _consecutive_same_sign; } + void reset() { _difference_filter.reset(0.f); _last_value = NAN; + _last_sign = 0; + _consecutive_same_sign = 0; } private: AlphaFilter _difference_filter; float _last_value{NAN}; + int8_t _last_sign{0}; + uint8_t _consecutive_same_sign{0}; }; diff --git a/src/modules/manual_control/MovingDiffTest.cpp b/src/modules/manual_control/MovingDiffTest.cpp index 3f70be76fa..1c6aa85a88 100644 --- a/src/modules/manual_control/MovingDiffTest.cpp +++ b/src/modules/manual_control/MovingDiffTest.cpp @@ -34,16 +34,86 @@ #include "MovingDiff.hpp" #include -TEST(MovingDiffTest, RcInputContinuous) +// Sustained movement in one direction: filter converges to true velocity +// and consecutiveSameSign accumulates past the override threshold (3). +TEST(MovingDiffTest, ConsistentMovement) { - MovingDiff _diff; - EXPECT_FLOAT_EQ(_diff.update(0.0f, 0.0f), 0.f); // 0,0,0 - EXPECT_FLOAT_EQ(_diff.update(1.0f, 1.0f), 0.f); // 1*,0,0 - EXPECT_FLOAT_EQ(_diff.update(0.0f, 1.0f), 0.f); // 1,-1*,0 - EXPECT_FLOAT_EQ(_diff.update(0.0f, 1.0f), 0.f); // 0,-1,0* - EXPECT_FLOAT_EQ(_diff.update(0.0f, 1.0f), 0.f); // 0*,-1,0 - EXPECT_FLOAT_EQ(_diff.update(1.0f, 1.0f), 0.f); // 0,1*,0 - EXPECT_FLOAT_EQ(_diff.update(0.0f, 1.0f), 0.f); // 0,1,-1* - EXPECT_FLOAT_EQ(_diff.update(2.0f, 1.0f), 1.f); // 2*,1,-1 - EXPECT_FLOAT_EQ(_diff.update(4.0f, 1.0f), 2.f); // 2,2*,-1 + MovingDiff diff; + diff.update(0.f, 1.f); // first sample, no diff yet + EXPECT_NEAR(diff.update(1.f, 1.f), 1.f, .1f); // diff=+1, ~0.952 + EXPECT_NEAR(diff.update(2.f, 1.f), 1.f, .01f); // ~0.998 + EXPECT_NEAR(diff.update(3.f, 1.f), 1.f, .001f); // ~0.9999 + EXPECT_NEAR(diff.update(4.f, 1.f), 1.f, .001f); + EXPECT_NEAR(diff.update(5.f, 1.f), 1.f, .001f); + EXPECT_FLOAT_EQ(diff.update(6.f, 1.f), 1.f); // fully settled + EXPECT_GE(diff.consecutiveSameSign(), 6); +} + +// Erratic same-sign signal at realistic RC rate (50 Hz): every 3rd sample +// spikes to +3/s, the rest are near-zero (+0.05/s), all positive. Raw diff +// peaks above the override threshold (1/s) yet the filter never crosses it, +// which shows the magnitude check adds necessary protection over sign alone. +TEST(MovingDiffTest, ErraticSameSignFilterStaysBelowThreshold) +{ + MovingDiff diff; + const float dt = 0.02f; // 50 Hz + diff.update(0.f, dt); // first sample + + float val = 0.f; + + for (int i = 0; i < 100; i++) { + val += (i % 3 == 0) ? 0.04f : 0.001f; // diffs sometimes exceed with +2/s but are usually +0.05/s + EXPECT_LT(diff.update(val, dt), 1.f); // filter never reaches override threshold + } + + EXPECT_GT(diff.consecutiveSameSign(), 3); // consistently same sign throughout +} + +// A single-sample outlier (spike up, immediately returns) must not build up +// consecutiveSameSign past 1, so it cannot trigger the override gate (threshold = 3). +TEST(MovingDiffTest, SingleSampleOutlier) +{ + MovingDiff diff; + diff.update(0.f, 1.f); // first sample, no diff yet + EXPECT_EQ(diff.consecutiveSameSign(), 0); + + diff.update(0.f, 1.f); // diff=0, sign=0, no update + EXPECT_EQ(diff.consecutiveSameSign(), 0); + + diff.update(1.f, 1.f); // outlier spike: diff=+1, consecutive=1 + EXPECT_EQ(diff.consecutiveSameSign(), 1); + + diff.update(0.f, 1.f); // returns: diff=-1, opposite sign resets consecutive to 1 + EXPECT_EQ(diff.consecutiveSameSign(), 1); + + diff.update(0.f, 1.f); // diff=0, no update + EXPECT_EQ(diff.consecutiveSameSign(), 1); +} + +// Switching RC source to a joystick held at a different position produces a single large +// diff followed by zero-diffs (static hold). consecutiveSameSign must stay at 1 so the +// step does not trigger the override gate (threshold = 3). +TEST(MovingDiffTest, SignalStepOnSourceSwitch) +{ + MovingDiff diff; + diff.update(0.2f, 1.f); // first sample, no diff yet + EXPECT_EQ(diff.consecutiveSameSign(), 0); + + diff.update(0.2f, 1.f); // diff=0 + EXPECT_EQ(diff.consecutiveSameSign(), 0); + + diff.update(0.2f, 1.f); // diff=0 + EXPECT_EQ(diff.consecutiveSameSign(), 0); + + diff.update(-0.8f, 1.f); // source switch: single large step diff=-1.0, consecutive=1 + EXPECT_EQ(diff.consecutiveSameSign(), 1); + + diff.update(-0.8f, 1.f); // joystick static: diff=0, no sign update + EXPECT_EQ(diff.consecutiveSameSign(), 1); + + diff.update(-0.8f, 1.f); // diff=0 + EXPECT_EQ(diff.consecutiveSameSign(), 1); + + diff.update(-0.8f, 1.f); // diff=0 + EXPECT_EQ(diff.consecutiveSameSign(), 1); } diff --git a/src/modules/manual_control/manual_control_params.yaml b/src/modules/manual_control/manual_control_params.yaml index 4885788268..e903882d5a 100644 --- a/src/modules/manual_control/manual_control_params.yaml +++ b/src/modules/manual_control/manual_control_params.yaml @@ -40,3 +40,18 @@ parameters: max: 1 decimal: 2 increment: 0.01 + MAN_OVERRIDE_SPD: + description: + short: Manual control override speed threshold + long: >- + Stick velocity above which the pilot regains control by switching to Position + mode (or Altitude if position is unavailable). Unit: normalized stick travel + per second — at 1.0, moving a stick half its range in ~0.5s triggers it. + A negative value disables the feature. Only applies to multicopters and VTOLs in MC mode. + type: float + default: 1 + unit: '1/s' + min: -1 + max: 10.0 + decimal: 1 + increment: 0.5 diff --git a/src/modules/mc_pos_control/multicopter_nudging_params.yaml b/src/modules/mc_pos_control/multicopter_nudging_params.yaml index bf14c9241f..add0e0b381 100644 --- a/src/modules/mc_pos_control/multicopter_nudging_params.yaml +++ b/src/modules/mc_pos_control/multicopter_nudging_params.yaml @@ -12,7 +12,7 @@ parameters: stick centered - MPC_LAND_SPEED stick full down - 2 * MPC_LAND_SPEED - Manual override during auto modes has to be disabled to use this feature (see COM_RC_OVERRIDE). + Manual override has to be disabled to use this feature (MAN_OVERRIDE_SPD -1). type: enum values: 0: Nudging disabled