I am working with ArduCopter 4.6.2 on a large hydrogen-powered hexacopter platform, and I would like to ask for advice before modifying the arming/disarming stick gesture logic.
Current behavior in ArduCopter:
As far as I understand, the current Copter rudder arming logic is:
throttle low + full right yaw for about 2 seconds to arm;
throttle low + full left yaw for about 2 seconds to disarm;
disarming by rudder is only allowed when ARMING_RUDDER=2;
the normal ArduPilot arming checks and PreArm checks still apply.
In Copter 4.6.2, this appears to be handled in:
ArduCopter/motors.cpp
inside:
Copter::arm_motors_check()
My goal:
I would like to add an optional DJI-style / consumer-drone-style two-stick CSC gesture, such as “sticks inward” for arming and “sticks outward” for disarming, or a similar configurable two-stick gesture.
The intention is not to bypass ArduPilot safety checks. I only want to change the RC stick gesture that triggers the existing arming/disarming calls.
Important safety requirements:
Do not bypass arming.arm() or arming.disarm().
Do not bypass PreArm checks.
Do not directly control motor outputs.
Keep the existing ARMING_RUDDER behavior unless a new optional CSC mode is explicitly enabled.
The feature should be disabled by default, or controlled by a new parameter.
Disarming should be much more restricted than arming. For this aircraft, I would prefer CSC disarming to be allowed only when the vehicle is landed, for example when ap.land_complete == true and throttle is low.
I do not want a normal CSC gesture to be able to stop motors in flight.
The implementation should respect RCMAP_ROLL, RCMAP_PITCH, RCMAP_THROTTLE, and RCMAP_YAW.
The implementation should use calibrated control_in values instead of raw PWM values.
The timer should reset immediately if any part of the gesture is released.
Questions:
Is modifying Copter::arm_motors_check() in ArduCopter 4.6.2 the correct place to implement this, or is there a better architecture for this kind of feature?
Would the ArduPilot community prefer this to be implemented as a new parameter, for example an optional “arming gesture type”, rather than changing the existing rudder arming behavior?
Is it acceptable to keep using AP_Arming::Method::RUDDER for this gesture, or should a new arming method be added for CSC-style arming?
Are there any existing safety checks I should preserve or extend, especially for disarming?
For newer ArduPilot versions, I noticed similar rudder arming/disarming logic appears to be in libraries/RC_Channel/RC_Channels.cpp::rudder_arm_disarm_check(). Should a new implementation target that common RC layer instead of Copter-specific code?
Has anyone already implemented or discussed a two-stick CSC arming gesture for ArduPilot?
My preferred behavior:
Default ArduPilot behavior remains unchanged.
Optional CSC mode can be enabled by parameter.
Arming gesture: throttle low + yaw full right + pitch/roll corner gesture, held for about 2 seconds.
Disarming gesture: throttle low + opposite two-stick corner gesture, held for about 2 seconds.
Disarming rejected unless the vehicle is landed.
All PreArm and normal arming checks remain active.
If any stick leaves the required position, the gesture timer resets.
This is for a large hydrogen-powered test aircraft, so I want to be conservative and avoid any unsafe in-flight disarm behavior. I would appreciate advice on the safest and most maintainable way to implement this.
I don’t recall hearing any incidents with in flight disarm on multirotors caused by stick gesture disarming.
AFAIK currently stick disarming is as conservative as you can get without significant risk of failure to disarm after landing. In manual throttle modes (ACRO and STABILIZE) 0 throttle must bypass landed check as it assumed to possibly be unreliable (you may be recovering from loss of vertical state estimate).
Personally I would recommend using Arm/Motor Emergency Stop auxiliary function preferably with momentary positive action (pull to actuate) lever switch. It arms (respecting arming checks) when the switch goes high and stops motors when switched to LOW but disarm happens only after a delay giving the pilot chance to recover from accidental activation.
I think adding extending arming rudder range is the best way if you want to implement dual stick gesture, for consistency 3 should be arm only and 4 arm or disarm.
Thanks for the detailed explanation. That makes sense.
I did some additional bench testing on a small hexacopter test platform with all propellers removed. With my current prototype implementation, the two-stick CSC gesture works as expected when CSC_ENABLE=1 and ARMING_RUDDER=2.
One behavior I observed is related to land_complete: after arming with the inward-stick gesture, if I move the throttle up slightly a few times while the vehicle is still on the ground and without props, the vehicle may transition to a “not landed” state. In that case, my current CSC disarm implementation rejects the outward-stick disarm with the message “CSC disarm rejected: not landed”. If I bring throttle back to zero, return roll/pitch to neutral, and wait for about 3 seconds, the vehicle appears to regain the landed state and the outward-stick disarm works again. I tested this three times and it was consistent.
Based on your explanation, I now understand why the current rudder disarm behavior in manual throttle modes may need to bypass the landed check when throttle is at zero, especially if the vertical state estimate is not reliable. My extra land_complete requirement for CSC disarm is more conservative for my local test aircraft, but I can see that it may not be the best behavior for a general upstream implementation because it could increase the risk of failure to disarm after landing.
I also agree with your recommendation about using the Arm/Motor Emergency Stop auxiliary function for operational use, preferably with a momentary positive-action switch. For the real aircraft, I will consider using that as the primary operational safety control or at least as a backup.
For the dual-stick CSC gesture implementation, I think your suggestion to extend the existing ARMING_RUDDER range is cleaner than adding a separate CSC_ENABLE parameter. So the mapping would be something like:
ARMING_RUDDER=0: stick arming/disarming disabled
ARMING_RUDDER=1: existing yaw/rudder arm only
ARMING_RUDDER=2: existing yaw/rudder arm and disarm
ARMING_RUDDER=3: dual-stick CSC arm only
ARMING_RUDDER=4: dual-stick CSC arm and disarm
Does this mapping sound consistent with what you had in mind?
Two follow-up questions:
For the dual-stick CSC implementation, should the arming method still be reported as AP_Arming::Method::RUDDER for consistency with the existing stick gesture logic, or would it be better to add a new method such as AP_Arming::Method::CSC for clearer logging?
For newer ArduPilot versions, would you recommend implementing this in the common RC layer, around RC_Channels::rudder_arm_disarm_check(), rather than in the Copter-specific arm_motors_check() path used in Copter 4.6.2?
Thanks again for the guidance. I want to keep the default behavior unchanged and make this optional, while staying consistent with the existing ArduPilot arming/disarming safety model.