Failsafes
This page gives what the aircraft does when it loses the RC link, the ground control station
(GCS) link or battery voltage. The values are from params/terrahawk-common.parm. The
behaviour is from the ArduPlane source at commit 4c98c92 (ArduPlane/events.cpp and
ArduPlane/system.cpp). The checks that prove it on the aircraft are in the first-flight card.
Triggers
Section titled “Triggers”| Failsafe | Trigger | Time before action | Parameters |
|---|---|---|---|
| RC short | No valid RC data | 1 s | RC_FS_TIMEOUT 1, FS_SHORT_ACTN 0 |
| RC long | No valid RC data | 5 s | FS_LONG_TIMEOUT 5, FS_LONG_ACTN 0 |
| GCS | No heartbeat from the GCS, after at least one heartbeat was received | 5 s | FS_GCS_ENABL 1, FS_LONG_TIMEOUT 5, MAV_GCS_SYSID 255 (default) |
| Battery low | 4500 mAh left (45 % of the P50B), or the sag-compensated voltage below 21.6 V (45 % at rest) | None for the capacity, 10 s for the voltage | BATT_LOW_MAH 4500, BATT_LOW_VOLT 21.6, BATT_FS_LOW_ACT 1, BATT_LOW_TIMER 10 (default) |
| Battery critical | 3000 mAh left (30 %), or the sag-compensated voltage below 20.4 V (30 % at rest) | None for the capacity, 10 s for the voltage | BATT_CRT_MAH 3000, BATT_CRT_VOLT 20.4, BATT_FS_CRT_ACT 4, BATT_LOW_TIMER 10 (default) |
THR_FAILSAFE 1 also stops the aircraft from arming without an RC source, and a throttle
input below THR_FS_VALUE (950 µs, default) counts as RC loss. The values are for the flight pack,
the 6S2P Molicel P50B, 10 Ah. The capacity triggers normally act first, and they act immediately: BATT_LOW_TIMER applies only to the voltage triggers. After the landing, the pre-arm message names the trigger (“low capacity failsafe” or “low voltage failsafe”). The voltage triggers use the
sag-compensated voltage (BATT_FS_VOLTSRC 1): a 27 A hover reads 1.2 V lower than the rest voltage,
and a raw trigger would act much too early. For the Tattu LiPo, load params/pack-lipo-4500.parm, and fly it only within 500 m of home.
Actions by flight mode
Section titled “Actions by flight mode”| Flight mode when the failsafe starts | RC short (1 s) | RC long (5 s) and GCS | Battery low | Battery critical |
|---|---|---|---|---|
QSTABILIZE, QHOVER, QLOITER, QACRO, QAUTOTUNE |
QRTL |
QRTL |
RTL |
QLAND |
FBWA, FBWB, MANUAL, STABILIZE, ACRO, CRUISE, TRAINING, AUTOTUNE |
CIRCLE |
RTL |
RTL |
QLAND |
CIRCLE, LOITER, THERMAL |
No change (LOITER, THERMAL); none for CIRCLE |
RTL |
RTL |
QLAND |
AUTO, GUIDED |
No change | No change | RTL |
QLAND |
AUTO in a VTOL takeoff |
No change | QLAND |
RTL |
QLAND |
RTL |
No change | No change | No change | QLAND |
QRTL, QLAND |
No change | No change | No change | No change in QLAND; QLAND from QRTL |
Notes for the table:
QRTLin the Q modes comes fromQ_OPTIONSbit 5. Bit 20, which selectsRTL, is not set.RTLflies home as a plane and changes toQRTLnear home (Q_RTL_MODE1).- With
Q_OPTIONSbit 16,QRTLhovers home from any distance. It does not fly the fixed-wing approach. AQRTLfar from home is slow and uses much energy. - In
FBWA, the RC short failsafe changes toCIRCLEat 1 s. The RC long failsafe then changes toRTLat 5 s. - After an RC short failsafe in a Q mode, the aircraft is in
QRTL. The RC long failsafe makes no more change.
Pilot action at a battery failsafe
Section titled “Pilot action at a battery failsafe”In FBWA, do not reduce the throttle when the battery failsafe warns. On the capacity trigger the
low-battery RTL starts immediately; on the voltage trigger it starts after BATT_LOW_TIMER (10 s). In
SITL at mid throttle from cruise, the aircraft sank 3.3 m/s and
lost 32 m in 10 s (th-testpilot XF-sink, 2026-09-30). Below Q_ASSIST_ALT (30 m) the lift motors
start, and they use the energy that the low pack does not have. Keep the cruise throttle, or select
RTL at once. In the landing, the throttle stick does not change the descent.
After the critical battery failsafe, do not select a fixed-wing mode (FBWA, CRUISE, RTL or
AUTO), and do not abort the landing with a forward transition. Land in a VTOL mode. If the landing
point is not safe, move the aircraft in QLOITER and land near it. On a 31 % pack in SITL, a
forward transition stalled at 15 to 16 m/s with the pack at 17 V and 48 to 64 A (th-simulator,
2026-10-01, on both pusher models). The flight script will refuse this mode change (not written
yet).
Conditions that stop a failsafe action
Section titled “Conditions that stop a failsafe action”| Condition | Effect |
|---|---|
| Flight stage is landing | The RC short and RC long failsafes do not start |
AUTO in a landing sequence |
The RC failsafes make no mode change |
Aircraft already in QLAND or a VTOL landing |
The battery failsafes do not start a return |
| No GCS heartbeat received since boot | The GCS failsafe does not start |
Recovery
Section titled “Recovery”| Event | Result |
|---|---|
| RC data returns after an RC short failsafe | The aircraft goes back to the flight mode it had before, if the current mode is still the one the failsafe set |
| RC data returns after an RC long failsafe | The failsafe state clears. The pilot selects the flight mode again |
| GCS heartbeat returns | The GCS failsafe state clears. The pilot selects the flight mode again |
Ground test
Section titled “Ground test”WARNING: Remove all propellers before a failsafe test on the ground. QRTL can start on the
ground and can command the lift motors to climb to Q_RTL_ALT.
- Do the tests in this order: RC short, GCS, battery low.
- Do the RC test with the aircraft armed in
QSTABILIZE. Switch off the transmitter. - Make sure that the GCS and the log show
QRTLafter 1 s. - Disarm the aircraft immediately after the check.
- Before the GCS test, make sure that the flight controller received a GCS heartbeat. The GCS failsafe does not start without it.
- For the battery test, set
BATT_LOW_VOLTabove the pack voltage. Make sure that the aircraft changes toRTLafter 10 s. Then setBATT_LOW_VOLTback to 21.6 (21.0 on the Tattu). - After the tests, save the board’s parameters and compare them with
tools/check_params.py --loaded(params/README.md).
Pre-arm: telemetry radio
Section titled “Pre-arm: telemetry radio”th_prearm.lua v0.4 (adopted 2026-10-15, th-testpilot 7d391419) refuses arming until the flight controller sees
the mLRS telemetry radio on TELEM2 (system 51, component 68). It needs all of these, without a gap, for 12 s: a
RADIO_STATUS less than 3 s old, the radio’s RSSI_A, RSSI_B and LQ values less than 3 s old, and no
“LoRa radio fault” text. The radio sends the three values after each RADIO_STATUS, once a second. On a radio with
one LoRa chip, RSSI_B is always -127: that value means “no antenna B”, not a weak signal. The 12 s holds two of the
radio’s 5 s fault-text repeats, so a fault from power-up is seen before the check can pass.
| Pre-arm text | Cause |
|---|---|
no telemetry radio on TELEM2 |
No RADIO_STATUS from the radio in 3 s: the radio is off, not connected or not on TELEM2 |
radio: no values (signing key?) |
RADIO_STATUS comes, but the values do not. With MAVLink signing, this is a key mismatch: the flight controller drops the frames signed with the wrong key, and the radio then sends only an unsigned RADIO_STATUS. The radio also sends only RADIO_STATUS for a few seconds after power-up, until it sees the flight controller |
radio: settling, 12 s |
The radio is seen; wait |
LoRa radio fault |
The radio reported a missing LoRa chip. This stays until the next power-up |
TH_RAD_REQ (in airframe.parm, 1) switches the check on. Set it to 0 only on a bench without the radio. SITL sets 0
in its harness, because SITL has no mLRS radio.
Dock and GCS system ids
Section titled “Dock and GCS system ids”Only heartbeats from system id 255 (MAV_GCS_SYSID) count for the GCS failsafe. The dock sends
SITE_CLR from its own system id, so the dock is not a GCS for the failsafe. A launch from the
dock with no GCS connected has no GCS failsafe, because the flight controller received no GCS heartbeat.
RC overrides (RC_CHANNELS_OVERRIDE) and MANUAL_CONTROL messages from system id 255 also count as
heartbeats. While a GCS sends them, the GCS failsafe does not start (GCS_Common.cpp at 4c98c92).
Not yet in the parameters
Section titled “Not yet in the parameters”9e1e451, no wind. How it was flown, and the other films. Soundtrack, off until you unmute the player: Wagner, Ride of the Valkyries (American Symphony Orchestra, Edison 1921; public domain), from Wikimedia Commons. Flown by ArduPilot; the logo on the title card is the project's own, used under CC BY-SA 3.0.| Item | Status |
|---|---|
| RC loss far from home in fixed-wing flight | far_return.lua and spdweight_band.lua give a safe return in SITL. They go in the combined flight script, which is not written yet. Do not do RC-loss tests in fixed-wing flight before that script is loaded |
| Battery values for the P50B Li-ion pack | Set from Molicel’s data and SITL (2026-10-01) and provisional. The battery-reserve flight sets the final values for each pack |
| GPS loss in VTOL flight | ArduPlane’s EKF failsafe does not act on a GPS loss. It acts on high innovation variances, and a GPS that stops sending gives none (th-testpilot F8, 2026-09-30). About 7 s after the loss, the AHRS changes to DCM, and DCM keeps the last GPS velocity. Every mode that holds a position then flies on that wrong velocity: QRTL moved 322 m with five ground strikes on ArduPlane master, and QLAND leaned into it and ran 136 to 366 m at up to 17 m/s from the dock approach. QHOVER uses no position, so it stays level. gps_loss_guard.lua v2.5.1 goes in the flight script (adopted 2026-10-15, th-testpilot efe943bf for v2.4e, 3e01554f for v2.4f and ea0d7da0 for v2.5). A good GPS sample is a 3D fix with 6 or more satellites. The script examines each receiver: the Q43 (GPS1) and the M10 (GPS2). A GPS loss is a loss of the two receivers. If the Q43 is lost for 2 s and the M10 is good for 3 s, the script sets GPS2 as the primary and stops the automatic switch (GPS_PRIMARY 1, GPS_AUTO_SWITCH 0, not saved) and shows “gpsguard: GPS1 fault, flying on GPS2”. The aircraft then flies on the M10’s L1 position, without RTK. When the Q43 is good for 10 s, or at the disarm, the script sets the two parameters back and shows “gpsguard: GPS1 back, primary restored” (not at the disarm). Without this pin, the automatic switch gave the primary back to a jammed Q43 at each short lock, and the script landed the aircraft in 3 of 3 flights (SITL J11). With v2.5 the aircraft held its position for 90 s in 3 of 3 flights. A receiver that sends no message for 0.5 s is bad at once (v2.5.1, adopted 2026-10-15, th-testpilot 887c84f7): if the two receivers stop at the same time (a cable cut), the script shows the loss text, not the GPS1 fault text, 3.4 to 3.6 s sooner than v2.5. After 2 s without one the loss is declared, and only 10 s of good samples end it, so a jammed GPS’s short “locks” cannot. For the loss the EKF stops using the GPS (source set 2: barometer height, compass yaw, no GPS position or velocity; EK3_SRC2_YAW 1) and the AHRS is kept on the EKF (AHRS_OPTIONS bit 1, set in flight only and put back at the fix or the disarm). Each time a mode that needs a position is selected (QLAND included), it selects QHOVER. With a pilot (RC valid and channel 12 above 1700 µs), the pilot lands and disarms by hand. With no pilot, the script lands the aircraft: full down above 10 m over home on the barometer, then about 0.7 m/s to the ground, and it disarms after its own touchdown check. With no RC at all, QHOVER descends at 0.5 m/s, and the same disarm applies. On the TerraHawk model (th-testpilot, 2026-10-12, 31 flights): touchdown 0.46 to 0.82 m/s, disarm 3.9 to 4.2 s after touchdown, 0.7 to 90 m from the pad in calm air; in 8 m/s gusts from 50 m it drifts 387 to 468 m downwind. A pilot who raises channel 12 has the throttle within 0.5 s. A handset pilot sets channel 12 to +100 %; a handset that leaves it centred reads as no pilot. QHOVER does not disarm by itself: after a GPS-loss landing in QHOVER, disarm by hand. Until the flight script is loaded, if the GCS shows a GPS loss in a hover, select QHOVER and fly the aircraft by hand. A jammed GPS (SITL SIM_GPS1_JAM, th-testpilot efe943bf): 32 of 32 no-pilot flights land, touchdown 0.64 to 0.70 m/s, disarmed 3.0 to 3.3 s after and still down 20 s later, roll 2.5° or less, no climb, drift 9 to 16 m in calm air and 202 to 269 m in 8 m/s gusts. If the fix comes back during a no-pilot descent, the landing continues. With a pilot it says “fly and land by hand” and the pilot lands in QHOVER (1.0 m/s). The v2.3 it replaces failed every jam row: its descent ended at the first lock, and with or without a pilot QHOVER climbed 85 to 1,263 m on the jammed vertical velocity. With a good fix that the EKF rejects (SITL J7: a 20 m/s velocity error), ArduPlane’s EKF failsafe selects QHOVER, and with no pilot v2.4f lands it (“gpsguard: GPS lost, EKF failsafe: landing here”; 0.67 m/s, 6.8 m drift). It reads the failsafe’s own mode reason, so the failsafe’s 1 s up/down counter does the debouncing. In AUTO the failsafe first selects QLAND, then QHOVER when it fires again in QLAND, and v2.4f lands that QHOVER (J8: 0.99 m/s, disarmed). With a pilot on channel 12 it does not take over. A steady 5 m/s vertical velocity error does not trip the failsafe: the EKF holds height on the barometer. v2.4e, the first adopted version, never fired on this path and left the aircraft hovering. If a GPS-loss message comes and the aircraft does not land or climbs, select QSTABILIZE and land by hand on the throttle, which sets the motor power directly (J6: level, 0.70 m/s) |
| Tip-over on the ground in a Q mode | ArduPlane’s crash detection (CRASH_DETECT) runs in AUTO only and is built for fixed-wing landings, so nothing stock disarms a quadplane that tips over in a Q mode: it lies armed and the motors drive against the ground. A GPS-loss landing in wind is the likely case (th-aeronautics, estimate: a sole that catches on turf tips it at about 2.5 m/s across). tip_guard.lua goes in the flight script: armed in VTOL flight, not QACRO, roll or pitch over 60° for 1 s with the barometer height steady within 0.5 m, it disarms and sends tipguard: tipped over; disarmed. The first adopted version (b6010ac) never ran: it called ahrs:get_roll() and get_pitch(), which raise a Lua error in our ArduPilot tree, and the dead script then failed the Scripting pre-arm, so a second arming was refused until a reboot. Its 23-flight SITL result is withdrawn. 3482dc7 uses get_roll_rad() and get_pitch_rad() and sends tipguard: armed once at each arming, so a script that is not running can be seen. If that text does not appear after arming in a VTOL mode, the guard is not running. The SITL flights that show it never fires in the air are to be flown again. SITL cannot lie the aircraft on its side, so the positive proof is a bench test: props off, armed in QHOVER, tilt past 60° and hold; it disarms within about 1 s. Until the flight script is loaded, disarm a tipped aircraft from the GCS |
Q_OPTIONS bit 15 |
Cleared: 196640, not 229408 (2026-09-30), in the parameter files and in SITL. With bit 15, a throttle stick above 70 % makes every RTL, QRTL or battery-failsafe landing climb (th-testpilot F6: 61 to 640 m, then impact). With 196640 the same flight landed 0.1 m from home. In an automatic landing the throttle stick does not change the descent; to stop a descent, select QLOITER or QHOVER. Do not fly the real aircraft with 229408 |
| Geofence | Not enabled. FENCE_OPTIONS 0 is set in the common file now (2026-10-01), so it is already correct when the fence is enabled. Plane’s default refuses every mode change during fence recovery except a landing sequence, so the critical-battery QLAND is refused. In SITL with the default, a breach at critical kept the aircraft in RTL for 15 s and it climbed from 15 to 82 m (th-testpilot F14) |
| Airspeed sensor rejected after a sudden wind change | ARSPD_OPTIONS is 9 since 2026-10-19 (it was the default, 11): the pitot is disabled when it disagrees with GPS speed minus the EKF wind (bit 0) or with the EKF (bit 3), and ArduPilot does not enable it again in flight (bit 1 off). With bit 1 the EKF could learn a wind that explains a stuck reading, and the health check then enabled the stuck pitot again: in SITL that gave TECS the stuck value about 45 s after the disable, and the aircraft lost 8.8 to 11.2 m before arspd_stuck_guard.lua caught it a second time. At 9 the worst case was 3.1 m (th-testpilot 4fa36c21, 184610e8). The cost: a good pitot that a sudden wind change rejects stays off for the rest of the flight. The EKF wind changes slowly, so after a gust front a good pitot can disagree by several m/s; the health value then falls by 10 % every 200 ms and the pitot is disabled in about 4 s (AP_Airspeed_Health.cpp at 4c98c92). On Fuselage C, wind steps of 10 to 14 m/s did not cause a rejection in SITL (th-simulator, 2026-10-19), so a rejection is more likely a real fault (a blocked, leaking or stuck line). The aircraft then flies on synthetic airspeed, which carries the EKF’s wind error. Speed assist does not run on it (Q_OPTIONS bit 12, since 2026-10-19): without bit 12, assisted flight stopped the EKF’s wind states, the estimate fell to DCM’s synthetic airspeed (about 13 m/s at a true 21) and the assist started again every 5 s with the lift motors on (th-testpilot 83567e78). Height and angle assist still run (cc6d5d92). The other direction (synthetic airspeed high while the aircraft is slow) was tested in SITL with the EKF wind converged first (th-simulator, 2026-10-01): an 8 m/s headwind that stopped in one step, and an 8 m/s tailwind that started in one step, gave a true low of 16.8 and 15.9 m/s in about 2 s, the pitot stayed in use because the loss ended before the 4 s rejection, the assist started at the true low airspeed, and the aircraft lost 10 m of height or less. Not yet tested: the real pitot’s lag and noise. The GPS-loss fall-back, which enables a rejected pitot again when GPS loses its 3D fix (AP_Airspeed_Health.cpp:44-50), does not depend on bit 1. If the GCS shows “Airspeed sensor 1 failure. Disabling”, the pitot does not come back in this flight: watch the ground speed, keep the speed up, fly one full circle of 60 s or more at 50 m or more before any slowdown, approach or transition back, and land. Until that circle, the airspeed estimate is about the ground speed: in SITL with no airspeed the motor-out row latched 0 of 6 without it and 6 of 6 with it (th-testpilot cc6d5d92) |
| Airspeed sensor rejected and the EKF wind stuck | Without airspeed, straight flight does not show the EKF the along-track wind, so after a rejection on a straight leg the estimate stays wrong until the aircraft turns. In SITL before 2026-10-19 (ARSPD_OPTIONS 11, no Q_OPTIONS bit 12) ArduPilot enabled the pitot again on a timer (about 43 s), the wrong wind rejected it again about 6.5 s later, and the aircraft flew the rest of the flight without airspeed at about 28 m/s; the return used up to 1462 of the 1500 mAh between the low and critical triggers (th-testpilot and th-simulator, 2026-10-01). With ARSPD_OPTIONS 9 the pitot is not enabled again, so the turns must teach the EKF the wind. With Q_OPTIONS bit 12 they do: in SITL with no airspeed, the EKF wind reached 8.4 to 8.8 m/s against a true 8 in the survey’s turns, while it stayed at 0.1 to 0.5 m/s for 20 s of straight flight (th-testpilot 83567e78). The 2026-10-04 result that a circle with the pitot disabled taught only about 1 m/s came before bit 12. Assisted flight stops the EKF’s wind states, so the assist loop may explain it, but that is not checked. arspd_orbit.lua v5 (adopted in the SITL test set) goes in the flight script: in AUTO, or in RTL more than 1 km from home, it flies LOITER circles (two at most) when the pitot is disabled, then continues the mission with a warning, because at 9 the pitot does not come back (th-testpilot 184610e8). Its wait for the EKF to fuse an enabled pitot (test ratio under 0.7 for 10 s) now matters only for the GPS-loss fall-back. Until the flight script is loaded, and in a pilot mode: if the GCS shows “Airspeed sensor 1 failure. Disabling”, fly a full circle before any slowdown, as the row above says. A larger EK3_WIND_P_NSE slows the rejection of a pitot that reads high, which can cause a stall, so it stays at the Plane default, 0.1 |
| Pitot that reads high (stuck or blocking) | A pitot that reads high makes TECS give the real airspeed away. ArduPilot rejects it only 9 to 86 s later; in SITL that was after the stall (about +12 s) every time, from 106 m lost to a crash (th-simulator, 2026-10-01). No parameter caught it in time: ARSPD_WIND_MAX did not trip first, and a larger EK3_WIND_P_NSE made it slower. arspd_stuck_guard.lua (v7, feb3540; v7.1 2026-10-19, th-testpilot c7a04479) goes in the flight script. It compares the rate of change of the pitot’s airspeed with the aircraft’s acceleration along its air path. When they disagree by more than 0.4 m/s² on a 3 s average, and the pitot reads more than 3 m/s over the airspeed from GPS and the EKF wind, both for 2 s, it sets ARSPD_USE 0 (not saved). TECS then flies without airspeed. In SITL it caught a stuck pitot from 80 and 116 m, a slow drift and a fault in a climb at +3.2 to +5.9 s, with 4 m or less lost. It stayed silent in ten gusty surveys, an 8 m/s headwind and tailwind step and an RTL descent. The margin against real pitot noise and vibration is not known. So on the real aircraft it runs monitor-only (ACT false: it reports “WOULD FIRE” and does nothing) until the first flights’ logs pass sim/pitot_kinematics.py --lua-equivalent. Since v7.1 the script decides this itself: it acts only where SITL’s SIM_ parameters exist, so the card’s unchanged copy runs monitor-only on the board, and its load text ends “monitor only” (v7 set it with a constant, true for SITL). A larger error is the EKF’s: it stops using a pitot that reads more than about 7 m/s high within 3.1 to 3.4 s, and in SITL the guard or the EKF acted within 3.4 s for every stuck reading from 25.7 to 37.3 m/s, with 4.4 m or less lost. AHRS_OPTIONS 0 keeps that EKF check on (bit 2 would turn it off). The guard stays silent beside a deliberate deceleration to the stall break and beside sharp pitch and roll doublets (th-testpilot, T1 and H5 rows flown with and without the scripts, 2026-10-05), so the stall test and the doublets fly with the flight script loaded. A pitot that reads low is not dangerous: the lift motors assist and the aircraft stays fast. Check the pitot before every flight |
| Lift motor out | ArduPilot cannot hover the quad-X on three lift motors. In SITL every VTOL demand with a dead lift motor (QRTL, the approach’s QLOITER, Q-assist) rolled the aircraft past 30° in 1.1 to 1.3 s, before ArduPilot’s own thrust-loss message (th-testpilot F11, 2026-10-04). On the 3-blade props the RTL turn after a failure sank to 29 m, the height assist started three motors, and the aircraft hit the ground 8 s after the failure (th-testpilot F11-rtl, 2026-10-08). In cruise the lift motors are stopped, so a dead motor is not seen until VTOL is necessary. lift_check.lua v1.6.9 (Ryan approved the design on 2026-10-08 and v1.6.1 on 2026-10-12; v1.6.3 to v1.6.5 adopted 2026-10-18, th-testpilot 5f21a1f0, 12f52429 and 1d51b2d9; v1.6.7 on dd6577cd; v1.6.9 on b8bd26d6) checks the motors before VTOL is necessary. On the ground it disarms if a lift motor does not turn at Q_M_SPIN_ARM (ESC telemetry RPM). On the wing it turns all four lift motors at 20 % for 0.7 s every 50 s, and at once when RTL or GUIDED starts or an AUTO VTOL landing starts, in turns up to 45° of bank and down to 15 m. It also checks, at most every 10 s, when the airspeed is less than Q_ASSIST_SPEED + 1.5 m/s or the height is less than Q_ASSIST_ALT + 10 m, because Q-assist starts there (v1.6.3; until v1.6.1 it used AIRSPEED_MIN, which was equal to Q_ASSIST_SPEED). In assisted flight the script cannot spin the motors, so it judges the rpm that assist already gives them: with every lift output at or above the check’s spin output, a good rpm counts as a passed check (v1.6.4). Before, the axis approach’s brake could wait for a check that could not run and brake past the axis point toward the dock. A check is allowed down to 2 m/s under Q_ASSIST_SPEED (v1.6.5; it was AIRSPEED_MIN), so the re-check after a first failed check also runs when the pilot slows the aircraft. The dock approach (axis_approach_brake.lua v3.2.4) asks for a check about 3 s before its brake point and brakes only after that check passes. After that check passes, the lift motors stay at the check speed and their RPM is read every 50 ms until the VTOL starts, so a motor that stops in the last seconds locks out VTOL within 0.2 s. This also applies when the request comes while a check is already running (v1.6.7). After a late script cycle (150 ms or more) the hold waits for 300 ms of normal cycles before it judges again, because a late cycle had let the outputs fall to idle and the next cycle read stopped motors as a failure: 2 false lock-outs in 46 SITL dock approaches before v1.6.9, none in 215 after it (th-testpilot b8bd26d6). Before, that check passed with no hold after it, and in SITL a motor that stopped 1.1 s later was not seen before the brake. An AUTO VTOL landing gets a second check when the aircraft comes within its stopping distance plus 4 s of the landing point. Q-assist is enabled in fixed-wing flight only for 60 s after a check passes, and a failed check disables it immediately. Two failed checks lock out VTOL. From the first failed check, and after a lock-out, while the airspeed is less than AIRSPEED_MIN + 4 m/s on the wing, the script limits the pitch-up to 5° in every mode (to PTCH_TRIM_DEG + 3° if that is higher, v1.6.6, because ArduPilot adds the trim to the limit) and the pitch-up rate to 15°/s, so neither the pilot nor RTL can pull the slow wing into a stall; a stalled wing with the nose more than 20° down has the elevons’ pitch part held at trim, with the roll passed through, until it recovers (v1.6; in SITL a pilot slowing with a dead motor stalled and hit the ground at 27 m/s on v1.5.1, and v1.6.1 recovered 3 of 3 with no false lock-out in 47 normal flights; the elevon unload has not yet run in SITL). Then the script disables Q-assist, keeps RTL fixed-wing, changes the battery failsafe QLAND actions to RTL, and changes each VTOL mode to RTL through MANUAL. The aircraft circles home for 120 s, and the pilot can take control in a fixed-wing mode. Then it lands fixed-wing on the keels on the mission’s landing lane, with the elevons at trim after touchdown. On an RC loss or a battery failsafe it lands at once. The lane is a JUMP_TAG 900, two approach waypoints in line and a NAV_LAND, after the mission’s RTL item; one approach waypoint gave a turn onto a short, steep final in SITL. Without a lane the aircraft cannot arm. After a lock-out it cannot arm until the next reboot. In SITL (2026-10-08) the F11-rtl case locked out VTOL 2.9 s after RTL started, at 37 m in a 36° bank, and the aircraft landed on the lane. The lane landing keeps PTCH2SRV_TCONST 0.5 and LAND_FLARE_SEC 2: it touches down at about 1.9 m/s and 19 to 20 m/s and stops 38 to 56 m past the landing point (th-testpilot, 2026-10-10). A PTCH2SRV_TCONST of 0.3 on the lane gave 1.6 to 1.7 m/s in calm air, but in 5 m/s gusts one of nine landings went into a pitch oscillation and dived into the ground, so it is not used. th-aeronautics asks for 1.2 m/s or less on firm ground, so the lane stays on soft grass until the real aircraft’s pitch tune is known. It goes in the combined flight script, which is not written yet. The ground check needs bidirectional DShot RPM on the bench first. |
Source: docs/failsafes.md in the repo. Edit it there; this page is generated.
Comments
Comment on the whole page here, or on one section or step with the button beside it.