
Diagnosing Altitude Hold Failures in ArduPilot with BARO and CTUN Logs
Key Takeaway
Altitude hold failures show as CTUN.Alt diverging from CTUN.DAlt. Diagnose by comparing BARO.Alt (raw baro) against CTUN.Alt (EKF fused) and CTUN.ThO against CTUN.ThH (controller authority). Five common causes: baro glitch, vibration, ground effect, authority saturation, EKF source disagreement. Tunes live in EK3_ALT_M_NSE, EK3_HGT_I_GATE, EK3_SRC1_POSZ, and GROUND_EFFECT_COMP.
TL;DR: Altitude hold failures in ArduPilot show up as CTUN.Alt diverging from CTUN.DAlt, with the cause usually upstream in the barometer or EKF rather than in the altitude controller itself. Plot BARO.Alt versus CTUN.Alt versus POS.Alt to separate baro drift from EKF disagreement from controller saturation, and watch CTUN.ThO against CTUN.ThH to confirm the autopilot wasn’t simply out of authority. Most fixes are in the sensor and EKF parameter families (EK3_ALT_M_NSE, EK3_SRC1_POSZ) and the ground-effect compensation knob.
What altitude hold actually depends on
AltHold, Loiter, and every other altitude-controlled mode trust the autopilot’s fused altitude estimate. That estimate is built from three sources by the EKF:
- Barometer (
BARO) — primary in default builds. - GPS (
POS.Alt) — available when GPS reports a 3D fix. - Rangefinder (
RFND) — near ground if fitted and configured.
The EKF blends them via configurable weights and gates. If any input drifts, the fused estimate drifts. EK3_SRC1_POSZ selects which sources feed the altitude estimate; the default uses baro plus accelerometer integration.
The CTUN fields that diagnose altitude hold
CTUN TimeUS ThI ABst ThO ThH DAlt Alt BAlt DSAlt SAlt TAlt DCRt CRt
DAlt— desired altitude (what the controller is trying to hold).Alt— achieved altitude (the EKF’s fused estimate).BAlt— raw barometric altitude.DSAlt— desired rangefinder altitude near ground.SAlt— achieved rangefinder altitude.TAlt— terrain altitude.DCRt/CRt— desired and achieved climb rate.ThO/ThH— throttle output versus calculated hover throttle.
Reading the failure in Mission Planner
Plot CTUN.DAlt, CTUN.Alt, and BARO.Alt on one chart:
- If
BARO.Altjumped andCTUN.Altfollowed, the baro lied to the EKF and the controller tracked the lie. Baro problem. - If
BARO.Altis clean butCTUN.Altdrifts away from it, the EKF stopped trusting baro — checkXKF4.SHfor height-rejection ratios. EKF problem. - If
CTUN.AltmatchesCTUN.DAltclosely but the actual physical altitude differs, the autopilot is correctly holding a wrong reference — ground-effect or sensor calibration is the cause. - If
CTUN.ThOsits at its maximum whileCTUN.CRtcan’t reachCTUN.DCRt, the autopilot is out of authority — payload too heavy or pack too weak.
Confirming it in MAVExplorer
MAV> graph CTUN.DAlt CTUN.Alt BARO.Alt
MAV> graph CTUN.ThO CTUN.ThH
MAV> graph XKF4.SH
The XKF4.SH trace tells you whether the EKF was rejecting baro measurements. Values above 1 mean rejection; sustained values above 0.5 mean the EKF is de-weighting baro and altitude estimate confidence is degrading.
The five common altitude hold failure modes
- Baro glitch from sun or prop wash. See our BARO glitch post for the full diagnostic chain.
- Vibration corrupting altitude estimate.
VIBE.VibeZabove 30 m/s² degrades the accelerometer integration the EKF uses between baro updates. See our VIBE message guide. - Ground effect at low altitude. The barometric reading shifts in the final metre due to air compression under the rotors. Enable
GROUND_EFFECT_COMP = 1or fit a rangefinder withWPNAV_RFND_USE = 1. - Authority saturation. Payload too heavy for the airframe;
CTUN.ThOsaturates at maximum and the autopilot physically can’t climb. Reduce payload or upsize motors. - EKF disagreement between altitude sources. Baro says one altitude, GPS says another; the EKF rejects whichever source has the larger innovation.
XKF4.SHclimbs in either case. Fix the disagreeing sensor.
Tuning altitude hold without breaking it
EK3_ALT_M_NSE— barometer noise estimate. Default 1.0; raise to 3–5 in genuinely noisy environments to de-weight baro.EK3_HGT_I_GATE— height innovation gate. Default 500 (5.0 sigma). Raising it tolerates more baro disagreement but lets bad measurements through.EK3_SRC1_POSZ— primary vertical position source. 0 = none, 1 = baro, 2 = rangefinder, 3 = GPS, 4 = beacon. Default 1 (baro).PSC_VELZ_P/PSC_ACCZ_P— vertical velocity and acceleration P gains for the position controller. Default values are conservative; raise carefully if the response is sluggish on heavy payloads.GROUND_EFFECT_COMP— 1 enables baro compensation for ground-effect pressure shifts during the last metre.
When this isn’t actually an altitude hold problem
- Pilot input not understood. Stick deadband (
RCx_DZ) below the pilot’s offset produces a constant climb or descent command. CheckRCIN.C3versus expected centre. - Mode misinterpretation. Some altitude-controlled modes (Loiter) drift down if pilot input is exactly neutral but the descent rate isn’t. AltHold should hold; if you switched to a different mode mid-flight, behaviour changes.
- Battery sag triggering failsafe. A voltage dip forced the autopilot into LAND mode mid-hover; what looked like altitude failure was actually correct failsafe behaviour. Check
MODE.Rsn=4and our power module post.
When LogHat helps — and when it doesn’t
LogHat plots the altitude-hold diagnostic suite (CTUN.DAlt, CTUN.Alt, BARO.Alt, XKF4.SH, CTUN.ThO) on one panel and flags which of the five failure modes the log signature points at. What we can’t do is tell you whether the operator added an unexpected payload — that needs flight-record context the autopilot doesn’t capture.
About the author
LogHat Engineering Team
The LogHat engineering team — drone-systems engineers who build and operate the LogHat flight analytics platform. Posts in this byline are written and reviewed by team members working on the parsers, analysis engine, and Vector AI that the post describes.
Tagged
Try LogHat
Analyze your flight logs in seconds
Upload a .bin, .tlog, .log, or .ulg file. Get AI crash analysis, 3D replay, and forensic PDF reports instantly.
Try LogHat Free