Control Systems
Build an autopilot for a drone with a late, noisy sensor
This guide builds a drone altitude hold that works with a realistic height sensor: one that reports 200 ms late, jitters by ±0.3 m, and feeds a controller whose thrust tops out at 30. The controller is a PID with two additions. Each of its four parts fixes one problem: feedforward carries the weight, P pulls towards the target, a filtered D damps the swing without amplifying the noise, and a clamped I trims what's left without winding up.
The mission
- Climb from the ground to 40 m and hold, never passing 43 m
- Keep the thrust calm on the noisy sensor
- At 15 s a gust knocks the drone down; climb back to within half a metre and hold
Thrust is in units where 9.8 exactly hovers, and the controller runs every 10 ms.
1. Feed the hover thrust forward
Start every thrust at 9.8. Then P and D only have to supply corrections, not the drone's whole weight. Without it, P alone would need 2 × error = 9.8 to hover, so the drone would hang 4.9 m low.
2. P and a filtered D
Kp 2 pulls towards the target. Kd 2 brakes on the rate the error is changing, which matters behind a 200 ms lag. But the raw derivative turns ±0.3 m of noise into thrust kicks of over a hundred units, so filter it at alpha 0.05.
3. An optional, clamped I
Ki 0.5 with the integral held between −1 and +1. On the long climb the thrust sits pinned at 30 for seconds; an unclamped integral would store that whole climb and pay it back as overshoot.
float error = target - height;
float d = (error - prev) / 0.01;
prev = error;
dfilt = dfilt + 0.05 * (d - dfilt);
integral = integral + error * 0.01;
integral = constrain(integral, -1.0, 1.0);
thrust = 9.8 + 2.0 * error + 2.0 * dfilt + 0.5 * integral;
Live experiment
Fly the autopilot first
A drone climbs to 40 m on a sensor 200 ms late with ±0.3 m of noise, thrust limited to 30, and a gust at 15 s. Switch the hover feedforward on or off, the D term raw or filtered, and the integral out, unclamped or clamped to ±1, and find a build that passes all three checks.
“Project: Autopilot” is the project that ends Lag Lagoon, Control Systems World 2. Free with an account. Lessons unlock in order, so you’ll do the 13 before it first.
What each mistake looks like
| Left out or wrong | Symptom |
|---|---|
| Raw D, no filter | Jittery thrust that never holds |
| Integral unclamped | Overshoots 43 m after the climb |
| No feedforward | Hangs low: drooping |
The gust
A gust is a disturbance the controller never saw coming, and it doesn't need to. The drop shows up as error and as a rate, and the P and D terms correct it exactly as they corrected the climb. Feedback catches whatever the feedforward didn't know about.
Free lesson
Now build it yourself
Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.
“Project: Autopilot” is the project that ends Lag Lagoon, Control Systems World 2. Free with an account. Lessons unlock in order, so you’ll do the 13 before it first.
Or start from the very first lesson, no account neededPractice questions
Three quick questions from the lessons. Pick an answer to check it.
Show the answer
Answer: Clamped, or left out: unclamped it winds up and the drone overshoots. Feedforward already carries the load, so the I term has little to do. Clamp it to ±1 or leave it out.
- Why not “Unclamped”? Unclamped, it keeps adding error while the thrust is pinned, then carries the drone past 40 m.
- Why not “Large”? A large integral is the problem: it stores the climb's error and pays it back as overshoot.
- Why not “Negative”? The sign isn't the issue. Any big stored value comes back as overshoot, so it must stay small.
Show the answer
Answer: 1 unit of thrust, times Ki. Ki × 1. Enough to trim a steady error, never enough to launch the drone past the target.
- Why not “600”? The clamp holds the integral between −1 and 1, so the most it can add is Ki × 1.
- Why not “30”? 30 is the thrust limit, not the integral's. Clamped to ±1, its share is Ki × 1.
- Why not “Nothing”? A clamp of ±1 still leaves the integral room to trim a small steady error.
Show the answer
Answer: 10 m: the climb arrives fast and nothing damps it. Anti-windup fixes the integral. The approach itself still needs damping: the D term.
- Why not “50 m”? About 50 m is the unclamped integral's overshoot. Clamped, the overshoot comes only from the missing damping.
- Why not “0”? Clamping stops windup, but nothing damps the approach, so a fast climb still overshoots.
- Why not “1 m”? With the D term added the overshoot shrinks to well under a metre. Without it, it's about 10 m.
“Project: Autopilot” is the project that ends Lag Lagoon, Control Systems World 2. Free with an account. Lessons unlock in order, so you’ll do the 13 before it first.
Questions people ask
What PID gains should I start with for a drone's altitude hold?
It depends on the drone and the sensor. Here, with thrust measured so that 9.8 hovers, Kp 2 and Kd 2 with the D filtered at alpha 0.05 work behind a 200 ms lag. On a real drone, start with a small Kp, add Kd until the swing dies in one overshoot, then raise both together.
Does an altitude hold need an integral term?
Not always. If the hover thrust is fed forward, P and D can hold height on their own. A small, clamped I term then trims what's left, such as a battery sagging or a payload. Without feedforward, the I term has to do the lifting and is far more likely to wind up.
Why do drones use a barometer for altitude if it's so noisy?
It works at any height and costs almost nothing. Its noise and lag are handled exactly as here: filter the D term, keep the gains modest, and blend in an accelerometer or rangefinder where one is available.
Related topics
- PID control explainedWhat the P, I and D terms each do, shown on a drone climbing to 10 m.
- What is feedforward control?Put in what you already know the system needs, and let feedback fix the rest.
- What is integral windup, and how do you stop it?When the motors max out, the I term keeps counting, and pays it back as overshoot.
- How to filter the derivative term in a PID controllerThe D term turns half a metre of sensor noise into a hundred units of thrust. One line of code calms it.