
How to Tune ArduPilot PID Controllers on a Quadcopter
Key Takeaway
ArduPilot Copter PID tuning uses ATC_RAT_RLL_P/I/D for the rate loop, ATC_ANG_RLL_P for the angle loop (default 4.5, typical post-tune 6-10), and ATC_ACCEL_R_MAX for the output limit. AutoTune is the fastest path; RATE.RDes vs RATE.R divergence is the cleanest log signature of a tune that isn't tracking. AutoTune results below 4.5 indicate the run failed.
TL;DR: ArduPilot Copter PID tuning lives in three parameter families per axis: ATC_RAT_RLL_P/I/D (rate loop), ATC_ANG_RLL_P (angle loop), and ATC_ACCEL_R_MAX (output limit). The fastest path to a usable tune on a new airframe is AutoTune (AUTOTUNE mode, with AUTOTUNE_AXES set per-axis); the cleanest way to confirm a tune is to plot RATE.RDes against RATE.R and check that the achieved rate follows the desired rate within roughly 10% with no sustained oscillation. The 4.5-default, ~6 tight, ~10 aggressive convention for ATC_ANG_RLL_P is your sanity check — AutoTune results under 4.5 mean the run failed and the airframe needs more attention.
What you're actually tuning
ArduPilot Copter runs a cascaded controller: angle in, rate out, motor in. Each loop has its own gains:
- Angle loop —
ATC_ANG_RLL_P,ATC_ANG_PIT_P,ATC_ANG_YAW_P. Converts a desired angle (from your stick or from a position controller) into a desired rate. Default 4.5. - Rate loop —
ATC_RAT_RLL_P,ATC_RAT_RLL_I,ATC_RAT_RLL_D(and the pitch / yaw equivalents). Converts a desired rate into a motor mix output. The D term is the term most likely to need careful adjustment. - Output limits —
ATC_ACCEL_R_MAXcaps the maximum rotational acceleration the controller will command, in centidegrees per second squared.
You almost never need to touch all three loops on a new airframe. Get the rate-loop gains right with AutoTune and the angle-loop gain follows.
The AutoTune workflow
Run AutoTune on a calm day in a large open area, with the airframe in good mechanical condition (balanced props, low VIBE):
- Set up the flight.
AUTOTUNE_AXES = 1tunes roll, 2 pitch, 4 yaw.= 7tunes all three. Start with one axis at a time on a new airframe so you can revert if anything goes wrong. - Pick aggressiveness.
AUTOTUNE_AGGR = 0.1is the default (the looser end).0.075is medium-tight;0.05is aggressive. Start with 0.1. - Take off in AltHold. Climb to a safe altitude. Face the vehicle so the wind blows from the side of the axis you're tuning — pointing into the wind biases the tune.
- Switch to AUTOTUNE mode. The vehicle will twitch ~20 degrees in each direction on the axis being tuned. It will spend several minutes per axis.
- Land without disarming. Switch out of AUTOTUNE and back in to test the new gains. If the airframe feels right, land and disarm with the AUTOTUNE switch high — the gains save permanently. Disarm with the switch low and the autopilot reverts to the original gains.
Reading the tune in the log
The RATE message is your verdict. It records both the desired and achieved rate per axis:
RATE TimeUS RDes R ROut PDes P POut YDes Y YOut ADes A AOut AOutSlew
What to plot in Mission Planner:
RATE.RDesandRATE.Ron the same axis — a healthy tune has the achieved rate tracking the desired rate with under ~50 ms lag and no overshoot.RATE.ROut— the normalised motor output for the roll axis. Saturation at ±1.0 for sustained periods means the controller is asking for more than the motors can deliver.
In MAVExplorer:
MAV> graph RATE.RDes RATE.R
MAV> graph RATE.PDes RATE.P
MAV> graph RATE.ROut RATE.POut
Telling a good AutoTune from a bad one
The MethodicConfigurator project documents the practical sanity checks for an AutoTune result:
- AutoTune is considered failed if
ATC_ANG_RLL_Pends below 4.5. That's the default; tuning is supposed to raise it. - It's also considered failed if
ATC_RAT_RLL_Dends atAUTOTUNE_MIN_D— the algorithm bottomed out the D term, usually because mechanical noise was too high. - Higher
ATC_ANG_RLL_Pimplies a tighter response. Most well-tuned multirotors land between 6 and 10. Above 12 the response can become twitchy in manual modes; check stability in Stabilise before committing.
If AutoTune fails, the cause is usually vibration (VIBE.VibeZ above 30 m/s² corrupts the algorithm's measurements), a motor imbalance, or a frame structural problem. Fix those before retrying.
Manual tuning when AutoTune won't converge
When AutoTune fails on a difficult airframe, the manual sequence is roll first, then pitch, then yaw, then the D-yaw refinement:
- Start with
ATC_RAT_RLL_D = 0.001, raise it in small steps. Stop just before the motors start to whine in hover — that's the D-onset of high-frequency noise. - Raise
ATC_RAT_RLL_Puntil small stick inputs become responsive but you don't see oscillation. Typical landing: 0.1–0.2 for small frames, 0.05–0.1 for heavy frames. ATC_RAT_RLL_Ifollows P proportionally (the convention is I = P).- Raise
ATC_ANG_RLL_Puntil the angle response feels right. - Repeat for pitch (typically the same gains as roll on a symmetric quad).
This is slower than AutoTune and only useful when AutoTune can't run. For the official procedure, follow ArduPilot's AutoTune documentation or the MethodicConfigurator tuning guide.
When the tune doesn't fix the problem
If you've run AutoTune and the airframe still oscillates, the cause is usually downstream of the PID gains:
- Harmonic notch not configured. Motor noise above the gyro bandwidth aliases into the rate loop and AutoTune can't tune through it.
INS_HNTCH_*needs to be set before tuning on most modern airframes. - Mechanical vibration. See our VIBE message guide; AutoTune assumes the IMU signal is trustworthy.
- Wrong frame configuration.
FRAME_CLASSorFRAME_TYPEset incorrectly produces mixed-up motor outputs that no PID can fix. See our takeoff-flip post. - Battery sag during tune. AutoTune samples a single flight envelope; if the pack is on its way down during the run, the gains may not transfer cleanly. Use
MOT_BAT_VOLT_MIN/MOT_BAT_VOLT_MAXscaling.
When LogHat helps — and when it doesn't
Upload the tuning flight log and LogHat plots RATE.RDes versus RATE.R with overshoot and lag metrics already computed, flags any axis where the achieved rate is saturating RATE.ROut, and shows the parameter snapshot at takeoff so you can confirm the post-AutoTune gains are the ones flying. What we can't tell you is whether a heavier payload tomorrow will need a different tune — that needs you to fly another envelope and re-evaluate.
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