ADRC quickstart guide
Setting up and tuning active disturbance rejection control as an alternative to PID control.
This is an experimental feature. It replaces the PID loop with a fundamentally different control algorithm.
TL;DR: I just want to get flying
- ADRC has three parameters: nominal control gain (
b0), observer bandwidth (wo) and control bandwidth (wc). Theb0parameter is hardware dependent. The ratio between observer and controller bandwidth represents a trade-off between disturbance rejection and control responsiveness. - Perform a flight using PID controls, note the % throttle needed to hover, execute a chirp command on each axis or just fly around and make sure there are a fair number of oscillations on each axis.
- Switch to ADRC and set the hover throttle % using the Betaflight CLI:
set adrc_hover_throttle = [Your actual hover throttle] set PID_TYPE = ADRC save - Disable all PID filters except for motor RPM.
- Use the plant fitting tool to obtain
b0values, with Proposed wc set to 80. Make sure the ctrl-free and eRPM values are reasonably close to one another, then use them directly as theadrc_b0parameters for each axis. Use the fitted motor lag asadrc_motor_tau_ms. Set thewcparameters for each axis to 80. Set thewoparameters for each axis to 90. Set the following parameters in the Betaflight CLI:set adrc_b0_roll = <calculated_roll_b0> set adrc_b0_pitch = <calculated_pitch_b0> set adrc_b0_yaw = <calculated_yaw_b0> set adrc_wc_roll = 80 set adrc_wc_pitch = 80 set adrc_wc_yaw = 80 set adrc_wo_roll = 90 set adrc_wo_pitch = 90 set adrc_wo_yaw = 90 set adrc_motor_tau_ms = <fitted_motor_lag> save - If flying with
pid_at_min_throttle = ON(Betaflight default), the first time you arm your drone, physically tap on the drone a few times using a stick. If it starts hopping, lifting, or tries to fly away, immediately disarm and reduceadrc_ground_wcto a lower value (the default is 10) using the Betaflight CLI:set adrc_ground_wc = <lower_value>Repeat the tap test, and keep reducing this value until the drone no longer hops or lifts. DO NOT set it to 0 if the drone bounces on the ground, as that disables the oscillation prevention entirely.
1. What is ADRC, and why use it?
ADRC is an experimental, optional, complete replacement for PID. Instead of relying on static parameters or complicated aerodynamic models, it continuously estimates everything that is pushing on your quad and cancels it out in real time. External forces include things like wind, drag, and prop wash, while internal dynamics include things like frame flex, battery voltage sag, a shifting center of gravity, and unexpected propeller damage. ADRC lumps all of these into a single fictitious force called “disturbance” rather than trying to model each one separately. Because the controller is always adjusting for these forces, there are a few practical benefits:
- Fewer re-tunes. With PID, changes like mounting a heavy camera on top, carrying an unbalanced load, or swapping propellers usually means retuning. With ADRC, the drone handles the same way as long as your motors have enough power to make up the difference. Once it is tuned, it generally never needs re-tuning unless you make a very major hardware change.
- Better resistance to being knocked off course. A sudden gust or a bump is corrected automatically, so the pilot never has to respond. There are limits: the motors still need enough power, and a tiny whoop can’t fly in a hurricane. It will just be noticeably harder to push around. This is probably most useful for something like a cinematic drone, where smooth flight matters most.
- Forgiveness when things go wrong. ADRC compensates for basically anything that makes the drone behave differently than expected. A crash that snaps off part of a propeller blade can still fly normally. This has happened a couple of times in testing, and the damage wasn’t noticed until the drone was close enough to hear.
Simpler tuning. The tuning parameters are also a little easier to understand than PID’s. The main one is a physical value specific to your drone, essentially its acceleration on each axis. The other two simply control how fast you want the drone to respond.
Early ADRC research describes it as an extension of PID, and you can think of it as a PID controller that constantly re-tunes itself. That is a simplification, but it is a somewhat reasonable way to think about how ADRC works.
A note on filters. ADRC can interact in unexpected ways with some of the default filters. It is recommended to disable any filters that are not directly related to something physical on the drone: disable everything in the filters setting tab other than the gyro RPM filter and any notch filters that have been previously set to account for a frame resonance.
2. The control parameters
b0 — nominal control gain
Set per axis.
This is the most important parameter, as it gives the controller an estimate of how each
axis responds for a given input. Think of this as how much the controller expects the drone
to accelerate for a given amount of motor power. A drone with a high thrust-to-weight ratio
will have a higher b0 than one with a low thrust-to-weight ratio.
This parameter only needs to be a reasonably close ballpark estimate, as a gap between the
drone's actual gain (b) and the control gain is lumped into the disturbance
estimate. However, if b0 is too far off the actual b, the mismatch can
exceed what the controller is able to correct, and result in motor oscillations, tracking
lag, and instability. This value can be determined using the included code that fits a
blackbox log.
wo — observer bandwidth
Set per axis. Units: rad/s.
This governs how fast the observer is able to detect and estimate disturbances. This is limited by gyro noise and frame vibrations; setting this too high will eventually cause the observer to pick up sensor noise and normal drone vibrations. This leads to excessive erroneous corrections, resulting in wasted battery, motor heating, and oscillations. If this is too low the drone will respond slowly to disturbances. As a rule of thumb, this parameter should be set as high as the drone's noise floor allows.
wc — controller bandwidth
Set per axis. Units: rad/s.
This governs how fast the controller attempts to adjust the drone. If this is too low, the drone will be sluggish and respond slowly to inputs. If this is too high the drone will feel twitchy and can overshoot commanded movements. This is similar but not exactly the same as the P gain in a PID controller. This must always be lower than the observer bandwidth, or the controller will attempt adjustments before it can see disturbances and create instabilities.
adrc_b0_law — scaling for b0
Accepted values: QUADRATIC, LINEAR, SQRT,
FIXED. Default: SQRT.
This scales the nominal control gain (b0) based on the throttle. Because thrust
is slightly nonlinear with throttle, the drone's actual gain varies based on throttle
position. The optimal scaling law varies depending on the specific hardware configuration.
For most tested hardware configurations, either SQRT or LINEAR
perform well. FIXED disables this function.
adrc_hover_throttle — throttle % at which the drone hovers
Default: 35%. This is the throttle % at which the b0 scaling law kicks in. Does
nothing if adrc_b0_law is FIXED.
The wc/wo ratio represents a trade-off between disturbance rejection and responsiveness.
Setting wc much lower than wo (around 30–50%) will result in
a slower response to control inputs, but will better reject disturbances. A higher
wc/wo ratio (around 90%) will result in a faster response, but it will reject
disturbances slower and may overshoot more. A wc/wo ratio of 0.9 (low disturbance rejection) on a 5″ drone
is still able to fly with missing propeller blades.
3. Quick start tuning procedure
Because the gain of a particular drone is specific to the hardware configuration (mostly the motors and propellers) there is not a universal setting that works reasonably well across all hardware configurations, unlike the stock PID settings. The easiest way to determine these values is from a blackbox log recorded during a test flight while using the stock PID settings.
Record baseline PID flight & gather data
Fly the drone using standard PID controls. Note the throttle percentage required to maintain a hover. During the flight execute a chirp command used for the PID auto tune on each axis, or fly around with a fair number of movements on each axis. The baseline flight should basically be a hover with some wobbles commanded on each axis.
Calculate b0 values from the recorded baseline flight
Run the recorded blackbox log through the plant-fitting script to determine the nominal control gain (b0).
Before dropping in the log, set Proposed wc to the controller bandwidth
you plan to fly (80 if you’re following this guide). The output of the fitting script includes several plots that
show the points used for the fit along with the fit. Shown below is an example of a fit
performed on the baseline flight from a 5″ drone.
Make sure that the fit output looks reasonable (the fit curves should overlap reasonably with
the points used for the fit). Also check that the calculated ctrl-free and
eRPM values are reasonably close to each other. If the fits on the plot do not line
up well, or the ctrl-free and eRPM values are very far apart, redo the baseline PID flight
with more movement on each axis. The fitter reports b0 matched to the
wc you entered, so the output values can be used directly as your initial
b0 values with no further adjustment. If you later change wc,
rerun the fit with the new value to get a matching b0.
The fitter also outputs a motor lag value. Set this as adrc_motor_tau_ms in
the CLI.
Occasionally there will be an output warning that says something like:
[WARNING: yaw] 2nd pole above the excited band
This most frequently occurs with the yaw axis. It means that the axis was not excited
enough for a proper fit — in the example plots, the controller-free and eRPM fits
diverge slightly at lower frequency. This may be corrected by adjusting the chirp
parameters or including more yaw movements in the test flight. Because b0
does not need to be exact, in most cases this parameter can be used and the baseline
flight does not need to be repeated. This has not been found to matter so far in
testing.
Disable unnecessary filters (optional)
Filters used by PID control can interact in unexpected ways, because they introduce a slight delay to what the observer sees and can cause the controller to attempt to correct for disturbances too slowly. Navigate to the PID Tuning > Filter Settings tab in Betaflight and disable all PID filters (lowpass filters, dynamic notch, D-term filters). Keep only physical hardware-related filters enabled, such as the motor / gyro RPM filter and any manual notch filters tuned for known structural frame resonances.
Switch controller and apply parameters
Open the Betaflight CLI and run the following commands. Substitute in your calculated
b0 values, fitted motor lag, and measured hover throttle:
Betaflight CLI
set PID_TYPE = ADRC
set adrc_hover_throttle = <your_hover_throttle_value>
set adrc_b0_roll = <calculated_roll_b0>
set adrc_b0_pitch = <calculated_pitch_b0>
set adrc_b0_yaw = <calculated_yaw_b0>
set adrc_wc_roll = 80
set adrc_wc_pitch = 80
set adrc_wc_yaw = 80
set adrc_wo_roll = 90
set adrc_wo_pitch = 90
set adrc_wo_yaw = 90
set adrc_motor_tau_ms = <fitted_motor_lag>
save
The wc/wo values of 80/90 provide fairly responsive controls and are a good starting place for further tuning if desired.
Perform ground arm tap test
This is only necessary if the control loop is active on the ground (Betaflight default). If
pid_at_min_throttle = OFF this process is not necessary.
If the control loop is active on the ground, the drone can lift or hop by itself right after
arming in airmode. This mostly occurs on smaller drones. It shows up as the drone bouncing
or hopping on the ground and then abruptly flying away when no throttle is commanded. The
parameter adrc_ground_wc sets the controller bandwidth to a low value while on
the ground. It prevents unintended lifting or hopping on arm in airmode, which can lead to
a flyaway while the control loop is still closed through ground contact. By default
adrc_ground_wc = 10, which should prevent this from occurring.
To ensure this is not possible on your drone, arm the drone and, when no throttle is
commanded, physically tap on the drone a couple of times using a stick. Lifting the back of the
drone slightly and letting it drop down also works. If the drone starts bouncing on the
ground during this test, reduce the adrc_ground_wc value until it stops
occurring.
Setting adrc_ground_wc to 0 disables this protection.
Do not set this value to 0 if the drone bounces on the ground during this
test, as this will cause it to unpredictably fly away when armed.
Initial ADRC setup is now complete.
4. Parameter tuning table
| Setting | What it does | If it's too high | If it's too low | Rule of thumb |
|---|---|---|---|---|
Observer bandwidth (wo) |
How quickly the drone notices things like wind gusts or extra weight. | The drone overreacts to tiny vibrations. The motors buzz and twitch, run hot, and drain the battery faster. | The drone is slow to notice wind or changes, so it drifts and wobbles before correcting. | Increase it until the motors start sounding rough, then turn it back down a bit. |
Controller bandwidth (wc) |
How quickly and firmly the drone responds to commands and corrections. | The drone is twitchy and overshoots its target. It can start oscillating and potentially lose stability. | The drone feels sluggish to respond to commanded movements and hold position. | Start low and increase gradually until the drone feels crisp but not twitchy. |
Nominal control gain (b0) |
The controller's guess of how strongly the drone responds to motor changes. | The controller doesn't request motor power quickly enough, so the drone feels sluggish and soft. | The controller requests motor power too quickly, so the drone overshoots or oscillates. This causes instability. | If unsure, guess a little high. Sluggish and stable is safer than twitchy and unstable. |
Bandwidth ratio
| State / range | Ratio value (wc / wo) | Flight behavior & primary effect | Potential risks / downsides |
|---|---|---|---|
| Too low | < 0.30 | Highly damped and sluggish stick response; observer runs much faster than control action. | The drone feels unresponsive and delayed on stick inputs. |
| High rejection (conservative) | ≈ 0.30 – 0.50 | Prioritizes rejecting external forces, wind, prop wash, and frame anomalies. | Slower response to pilot control inputs. |
| High responsiveness (aggressive) | ≈ 0.80 – 0.90 | Fast tracking to stick inputs with minimal lag. | Slower disturbance rejection (though a 0.9 ratio on a 5″ drone can still fly with damaged or missing prop blades). |
| Too high (marginal) | > 0.90 – 0.95 | Extremely reactive, twitchy feel; can feel over-sensitive to stick inputs. | Prone to overshoot on aggressive maneuvers; disturbance rejection becomes sluggish. |
| Critical limit / instability | ≥ 1.0 (wc ≥ wo) | Controller attempts to make physical adjustments before the observer can detect and estimate disturbances. | Control instability, potential for rapid self-excited oscillations. |
The interactive tuning sandbox lets you drag
wc, wo and b0 on a simulated rate loop and watch the
step response and disturbance recovery change.