Skip to content

AP_Scripting: VTOL-quicktune restrict tuning to QSTABILIZE/QHOVER/QLOITER - #33025

Open
rwoneill wants to merge 2 commits into
ArduPilot:masterfrom
rwoneill:quicktune-vtol-mode-gate
Open

AP_Scripting: VTOL-quicktune restrict tuning to QSTABILIZE/QHOVER/QLOITER#33025
rwoneill wants to merge 2 commits into
ArduPilot:masterfrom
rwoneill:quicktune-vtol-mode-gate

Conversation

@rwoneill

@rwoneill rwoneill commented May 11, 2026

Copy link
Copy Markdown

Summary

Refuse to tune in VTOL-quicktune.lua unless the quadplane is in QSTABILIZE / QHOVER / QLOITER, and add a note in the applet README pointing Plane users at the built-in AP_Quicktune library (shipping in Plane since 4.6.0).

Classification & Testing (check all that apply and add your own)

  • Checked by a human programmer
  • Non-functional change
  • No-binary change
  • Infrastructure change (e.g. unit tests, helper scripts)
  • Automated test(s) verify changes (e.g. unit test, autotest)
  • Tested manually, description below (e.g. SITL)
  • Tested on hardware
  • Logs attached
  • Logs available on request

SITL test plan run against this branch on arduplane --model quadplane, --speedup 20, scripting on, RC7_OPTION=300, QUIK_RC_FUNC=300, QUIK_DOUBLE_TIME=5. Test harness drives everything via pymavlink (mode set, force-arm, RC overrides, param polls).

  • FBWA + tune-switch high: blocked — Tuning: requires QSTABILIZE/QHOVER/QLOITER repeats, Q_A_RAT_RLL_D stays at baseline.
  • QRTL + tune-switch high: blocked — same gate message, gain unchanged. Script remains blocked even as the QRTL state machine progresses through VTOL airbrake → position1 → position2 → Land descend.
  • QLOITER + tune-switch high (happy path): tune proceeds normally — full RLL_D → RLL_P → PIT_D → PIT_P → YAW_D ramp/done sequence. Behavior identical to unpatched script in the supported mode.
  • Mid-tune mode change (QLOITER → FBWA): tune was in progress with gains elevated; switching to FBWA emitted Tuning: reverted and gains returned to baseline. Existing abort path fires correctly via the new not in_tunable_mode clause.
  • Multicopter LOITER tuning unchanged (untested — patch path is (not is_quadplane) → in_tunable_mode = true, so behavior is byte-identical for Copter; would still be good to confirm.)

Description

Bug

VTOL-quicktune.lua only gates on arming:is_armed() and vehicle:get_likely_flying(). Both are true during fixed-wing flight on a quadplane.

The "oscillation done" check uses AC_AttitudeControl:get_rpy_srate(). On a quadplane in fixed-wing flight, the VTOL attitude/rate controllers are not actively producing motor outputs, so the slew rate stays near zero. With srate < QUIK_OSC_SMAX always, the gain doubles every QUIK_DOUBLE_TIME seconds (default 10 s) without ever satisfying the "done" condition. QUIK_ANGLE_MAX (PR #28890) doesn't help either — same reason: the VTOL controller isn't running, so attitude error from its perspective stays at zero.

If the tune-position switch is bumped during a fixed-wing leg, Q_A_RAT_*_D ramps unbounded; on the transition back to VTOL the inflated gains drive the controller unstable.

Motivation

A pilot accidentally toggled the quicktune script during an RTL leg, which caused a progressive loss of control through the landing phase. The script ramped gains throughout the fixed-wing return; on the transition back to VTOL for landing, the inflated gains drove the aircraft unstable.

Fix (commit 1)

Restrict tuning to QSTABILIZE / QHOVER / QLOITER only — the pilot-controlled VTOL hover modes the applet's documentation was written for:

local in_tunable_mode = true
if is_quadplane then
   local m = vehicle:get_mode()
   in_tunable_mode = (m == 17 or m == 18 or m == 19)  -- QSTABILIZE/QHOVER/QLOITER
end
  • Quadplane: refuse to tune outside QSTABILIZE/QHOVER/QLOITER. Excludes fixed-wing modes (the bug above), auto-descent VTOL modes (QLAND, QRTL — pilot can't intervene cleanly), QAUTOTUNE (conflicts), and QACRO (rate-control intent collides with tune-induced motion). If the pilot transitions out of a tunable mode mid-tune, gains revert via the existing abort path (same behavior as disarming or moving the switch low).
  • Multicopter: unchanged. Rate controllers are always active in copter, so the existing slew-rate gate is sufficient and a mode restriction would be a regression.
  • The three mode IDs in the new gate match exactly the three modes that override Mode::supports_quicktune() to true in ArduPlane/mode.h — QSTABILIZE, QHOVER, QLOITER. Convergent evidence that this gate set is the right one.

Doc note (commit 2)

Adds a note to libraries/AP_Scripting/applets/VTOL-quicktune.md pointing Plane users at the built-in AP_Quicktune library, which has shipped in ArduPlane since 4.6.0 (May 2025). The Lua applet remains the only quicktune option for Copter (native quicktune is enabled only with HAL_QUADPLANE_ENABLED) and for users on older Plane firmware.

Suggested follow-up (separate PR to ardupilot_wiki)

The Plane wiki page https://ardupilot.org/plane/docs/quicktune.html documents the built-in version (parameters QWIK_*, aux function 181) but does not mention the Lua applet at all. A user with VTOL-quicktune.lua already on their SD card from a pre-4.6 setup has no easy way to tell that they're running a different code path (QUIK_* params, aux function 300). A short note on that wiki page calling out the distinction would close the loop. Happy to open a PR against ArduPilot/ardupilot_wiki if that's useful.

…ITER

VTOL-quicktune only gated on arming + vehicle:get_likely_flying(). On a
quadplane flying fixed-wing, the VTOL rate controllers are dormant, so
AC_AttitudeControl:get_rpy_srate() returns ~0 and the oscillation gate
never trips. If the tune-position switch is bumped during a fixed-wing
leg, Q_A_RAT_*_D ramps unbounded; on the transition back to VTOL the
inflated gains drive the controller unstable.

This patch refuses to tune unless the quadplane is in QSTABILIZE,
QHOVER, or QLOITER -- the pilot-controlled hover modes the applet's
documentation was written for. Auto-descent VTOL modes (QLAND/QRTL),
QAUTOTUNE, and QACRO are also excluded. If the pilot transitions out
of a tunable mode mid-tune, gains revert via the existing abort path.

The check is a no-op for multicopter, where rate controllers are
always active and the existing slew-rate gate is sufficient.

Signed-off-by: Roger O'Neill <rwoneill@users.noreply.github.com>
if is_quadplane then
local m = vehicle:get_mode()
-- QSTABILIZE=17, QHOVER=18, QLOITER=19
in_tunable_mode = (m == 17 or m == 18 or m == 19)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should allow GUIDED for quadplanes, but only if ground speed below 2m/s when tune starts
should also have a list of modes for copters
need to check the builtin C++ implementation to ensure it restricts modes

… Plane 4.6+

Adds a note at the top of the applet's README pointing Plane users at
the built-in AP_Quicktune library that has shipped since Plane 4.6.0
(May 2025). The Lua applet remains the only option for Copter and for
users on older Plane firmware.

Signed-off-by: Roger O'Neill <rwoneill@users.noreply.github.com>
@timtuxworth

timtuxworth commented May 13, 2026

Copy link
Copy Markdown
Contributor

I've found that the method get_mav_vtol_state() is useful to interpret what a VTOL is doing (fixed wing vs transition vs VTOL flight). If you add a binding for it to bindings.desc, you can use this in this Lua script which might be helpful.

MAV_VTOL_STATE Tailsitter_Transition::get_mav_vtol_state() const
{
    switch (transition_state) {
        case State::ANGLE_WAIT_VTOL:
            return MAV_VTOL_STATE_TRANSITION_TO_MC;

        case State::DONE:
            return MAV_VTOL_STATE_FW;

        case State::ANGLE_WAIT_FW: {
            if (quadplane.in_vtol_mode()) {
                return MAV_VTOL_STATE_MC;
            }
            return MAV_VTOL_STATE_TRANSITION_TO_FW;
        }
    }

    return MAV_VTOL_STATE_UNDEFINED;
}

You can add this line to bindings.desc to make this available in Lua:

singleton QuadPlane method get_mav_vtol_state uint16_t

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants