How to Tune ArduPilot PID Controllers on a Quadcopter
ardupilotpid-tuningautotunelog-analysisquadcopter

How to Tune ArduPilot PID Controllers on a Quadcopter

LogHat Engineering TeamMarch 27, 20265 min read

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 loopATC_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 loopATC_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 limitsATC_ACCEL_R_MAX caps 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):

  1. Set up the flight. AUTOTUNE_AXES = 1 tunes roll, 2 pitch, 4 yaw. = 7 tunes all three. Start with one axis at a time on a new airframe so you can revert if anything goes wrong.
  2. Pick aggressiveness. AUTOTUNE_AGGR = 0.1 is the default (the looser end). 0.075 is medium-tight; 0.05 is aggressive. Start with 0.1.
  3. 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.
  4. 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.
  5. 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.RDes and RATE.R on 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_P ends below 4.5. That's the default; tuning is supposed to raise it.
  • It's also considered failed if ATC_RAT_RLL_D ends at AUTOTUNE_MIN_D — the algorithm bottomed out the D term, usually because mechanical noise was too high.
  • Higher ATC_ANG_RLL_P implies 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:

  1. 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.
  2. Raise ATC_RAT_RLL_P until 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.
  3. ATC_RAT_RLL_I follows P proportionally (the convention is I = P).
  4. Raise ATC_ANG_RLL_P until the angle response feels right.
  5. 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_CLASS or FRAME_TYPE set 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_MAX scaling.

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

LE

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

ardupilotpid-tuningautotunelog-analysisquadcopter

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