dailymathdailymathMainPostsLogin
dailymath logo
dailymath
Login
Login
MainPosts

Curricula

RO M1UK A-LevelUK GCSEIB AAUS APUS SATUS HonorsFR SpéFR SecondeFR Expertes
AboutPostsPracticeSubmit a problemPrivacyTermsCookies

© 2026 dailymath

Back to posts
University / ProfessionalLessonControl theory

PID Controllers, Explained by Flying a Drone

A PID controller explained by flying a drone: why proportional control alone can't hold altitude, and what integral and derivative actually fix.

dailymath · July 17, 2026 · 9 min read

Set a thermostat to the crudest possible rule — heater full blast when the room is cold, off when it's warm — and the room never settles at your target temperature. It oscillates around it forever, in a slow triangle wave: too cold, blast, overshoot, too hot, off, drift back down, too cold again. This is bang-bang control, and it fails for a reason that generalizes far past thermostats. A refrigerator compressor short-cycling, a shower where the only two states are scalding and freezing, a cheap space heater that clicks on and off every ninety seconds — all of it is the same failure, because the controller treats "wrong" as one bit of information (too high or too low) instead of a number worth reasoning about.

Put the same instinct in the sky. A small drone is trying to hold one meter of altitude. Its onboard computer measures the gap between where it is and where it should be, and has to decide, dozens of times a second, how much thrust to send the motors. The bang-bang version says: too low, throttle to maximum; too high, cut the throttle. The drone doesn't hover — it porpoises, climbing hard, overshooting, falling, climbing hard again — because the rule only ever answers *which direction* to push, never *how hard*. It has no sense of scale, and no memory: every decision is made from scratch, using only the sign of the error, as if the previous decision never happened.

The fix sounds almost too simple: push harder the further away you are. That one sentence is the seed of the most widely deployed control algorithm on Earth — the PID controller, running in your cruise control, your 3D printer, your quadcopter, and a very large fraction of industrial control loops in existence. "PID" is just an acronym for its three ingredients — Proportional, Integral, Derivative — and each one exists to patch a specific failure the others leave behind. We'll build it term by term, using that hovering drone as the running example, until you know exactly what each of the three letters buys you, and what it costs.

Proportional: push harder the further you are

Replace "throttle to maximum" with something proportional. Define the error e(t)e(t)e(t) as the gap between where the drone should be (the setpoint) and where it actually is right now — positive when it's too low, negative when it's too high. The simplest sensible controller just scales its output by that error:
u(t)=Kp e(t)u(t) = K_p\, e(t)u(t)=Kp​e(t)
Here u(t)u(t)u(t) is the control signal — extra thrust — and KpK_pKp​ is a single tunable number called the proportional gain. Double the error, double the correction. This alone kills the porpoising: the drone eases off as it nears the target instead of slamming into it, because the push itself shrinks to zero as the error shrinks to zero. It's the same reason a spring feels gentle near its rest length and stiff when stretched far — the restoring force scales with displacement, not with a fixed on/off jolt.

And that's exactly the problem. Gravity does not go to zero. The drone's rotors have to fight a constant downward load just to hover, and u(t)=Kpe(t)u(t) = K_p e(t)u(t)=Kp​e(t) says the output *must* be zero when the error is zero. Zero output means zero thrust means the drone falls — so it can never actually reach zero error and stay there. It settles instead at whatever error produces just enough proportional output to balance the load. Work through the numbers behind Fig. 1: with a proportional gain of 8 and a load equivalent to 1.5 units of thrust, equilibrium requires Kpe=loadK_p e = \text{load}Kp​e=load, i.e. 8e=1.58e = 1.58e=1.5, which pins the resting error at e=0.1875e = 0.1875e=0.1875. The drone never reaches 1 meter. It hangs, forever, at 0.8125 meters — a fixed, visible gap below where you told it to go. This is steady-state error, and it isn't a tuning mistake; it's a structural property of pure proportional control under any sustained load. Any system that has to fight something constant — gravity holding a drone down, friction holding a motor back, an open door letting heat leak out of a room — will show this same gap under P-only control, no matter how carefully you pick KpK_pKp​. Crank the gain up and the gap shrinks, but it never closes to zero, and past some point a high gain starts to overshoot and ring instead of settling, because you're now reacting so hard to small errors that you overcorrect past them.

Fig. 1 · Step response — P vs PI vs PID

012345time (s)00.20.40.60.811.21.4altitude (m)
P only (steady-state error)
PI (error gone, overshoots)
PID (damped)
The dashed line is the target altitude. The P-only trace climbs fast, briefly pokes above the target, then settles visibly below it — the steady-state error worked out above. Add integral action (PI) and the gap closes completely, but the extra term overcorrects, carrying the drone past the target before it settles back down. Add derivative action (PID) and the response reaches the target with the overshoot damped out — the only one of the three that actually arrives and stays.

Integral: memory of every error you've ignored

Proportional control only ever looks at right now. It has no memory of how long it's been wrong, or by how much — a drone that's been 0.1875 meters low for one second and a drone that's been 0.1875 meters low for an hour get exactly the same correction. Integral control fixes that by keeping a running tally — literally an integral — of every bit of error accumulated since the loop started:
u(t)=Kp e(t)+Ki∫0te(τ) dτu(t) = K_p\, e(t) + K_i \int_0^t e(\tau)\,d\tauu(t)=Kp​e(t)+Ki​∫0t​e(τ)dτ
Think of ∫0te(τ) dτ\int_0^t e(\tau)\,d\tau∫0t​e(τ)dτ as debt. Every instant the drone hangs 0.1875 meters below target, that debt grows a little. The integral term multiplies the accumulated debt by a gain KiK_iKi​ and adds it straight into the thrust command — so even after the proportional term has settled into its comfortable, load-matching equilibrium, the integral term keeps quietly pushing, because the books haven't balanced yet. It only stops growing once the error itself hits zero, which makes exact setpoint-tracking the *only* stable resting point for a PI controller (proportional plus integral, no derivative yet). That's the PI trace in Fig. 1 finally touching the dashed line — the debt gets paid off completely, at the cost of the overshoot visible on the way there: by the time enough debt has piled up to counteract the load, there's usually more than enough, and the drone sails past 1 meter before the debt starts draining back down. Notice the trade the integral term makes: it buys you exact tracking, permanently, in exchange for a slower, wobblier path to get there. Nothing is free — you've just swapped one flaw (a fixed offset) for a different one (a temporary overshoot).

Integral windup

If the drone's motors are already at maximum thrust — saturated — a large setpoint change (say, a sudden jump from 1 meter to 10) makes the error, and the accumulated integral, keep growing even though more integral output can't produce more thrust; the actuator is already maxed out. When the drone finally starts closing the gap and the error shrinks, that oversized integral term takes a long time to unwind, driving a large, sluggish overshoot well past the new target. Real controllers guard against this by clamping the integrator — capping how much debt it's allowed to accumulate, or freezing it entirely while the actuator is saturated — so the accounting never runs further ahead than the hardware can pay back.

Derivative: braking before you arrive

P and I both look at where the error *is*. Neither looks at where it's *heading*. Watch the PI trace in Fig. 1 again: as the drone rockets toward the target, both the proportional and integral terms are still commanding full thrust right up until the moment it crosses 1 meter, because neither term has any notion of velocity — only of the current gap and the accumulated past. Derivative control adds a term proportional to the error's rate of change — how fast the gap is closing or widening right now — which lets the controller anticipate the overshoot and start braking before it happens. That gives the full PID law: proportional push, integral memory, derivative brake, summed into one control signal.
u(t)=Kp e(t)+Ki∫0te(τ) dτ+Kd dedtu(t) = K_p\, e(t) + K_i \int_0^t e(\tau)\,d\tau + K_d\, \frac{de}{dt}u(t)=Kp​e(t)+Ki​∫0t​e(τ)dτ+Kd​dtde​
The derivative term is friction against speed. When the drone is closing in on the target fast, dedt\frac{de}{dt}dtde​ is a large negative number — the error is shrinking quickly — and KddedtK_d \frac{de}{dt}Kd​dtde​ subtracts thrust exactly when the drone would otherwise keep accelerating into the target and blow past it. That's the difference between the PI trace and the PID trace in Fig. 1: the same integral action underneath, but the derivative term sees the approach coming and eases off early, so the drone arrives at 1 meter and stays there instead of overshooting and oscillating back down. It's the control-theory equivalent of tapping the brakes before a stop sign instead of flooring it the whole way and slamming them at the last second.

The catch is that derivative needs a *clean* signal to differentiate, and real sensors are never clean. Differentiating amplifies noise — a small, high-frequency jitter in an altitude reading becomes a large, violent spike once you divide by a tiny dtdtdt, and the controller reacts to that spike as if it were real motion, commanding a jerky correction to a wobble that was never actually there. This is why practitioners rarely feed the derivative term raw sensor data: they run it through a low-pass filter first, apply it to the measured output instead of the error (to avoid a sharp "derivative kick" whenever the setpoint itself jumps), or, in noisy or intrinsically slow-moving systems where a bit of overshoot is cheap and clean differentiation is expensive, skip the D term entirely and run PI alone. Plenty of production PID loops are really PI loops wearing the more famous name.

The whole machine on one diagram

Fig. 2 · The PID loop

PID controller block diagram
r(t)r(t)r(t)
Σ+−
e(t)e(t)e(t)
P
Kp e(t)K_p\,e(t)Kp​e(t)
I
Ki∫0te(τ) dτK_i \int_0^t e(\tau)\,d\tauKi​∫0t​e(τ)dτ
D
Kd de(t)dtK_d\,\frac{de(t)}{dt}Kd​dtde(t)​
Σ+++Process
y(t)y(t)y(t)
Trace the loop: the setpoint r(t)r(t)r(t) meets the measured output at a summing junction, producing the error e(t)e(t)e(t). That error feeds three parallel blocks — P, I, D — each computing its own correction from the same signal. Their outputs are summed into a single control signal, which drives the process (the drone and its rotors). The process's actual output y(t)y(t)y(t) is measured and fed back, negatively, into that first junction — closing the loop and producing the next error to correct. Each controller block wears the color of the Fig. 1 trace it unlocks: P purple, adding I blue, adding D orange.

Tuning: where the craft lives

Three numbers — KpK_pKp​, KiK_iKi​, KdK_dKd​ — and getting them right is most of the actual work of using a PID controller. A rough mental model: KpK_pKp​ is stiffness, how hard the system pushes back against a given error. KiK_iKi​ is patience, how insistently it corrects a persistent, small error over time. KdK_dKd​ is friction, how much it resists fast changes, damping the swings the other two terms create. Push any one too far and you get a specific, recognizable failure: too much KpK_pKp​ and the system turns twitchy, oscillating around the target even with no sustained load at all; too much KiK_iKi​ and small errors turn into slow, rolling overshoots as accumulated debt unwinds; too little KdK_dKd​ and there's nothing to damp the ringing left behind by the other two; too much KdK_dKd​ and the system gets sluggish and hesitant, flinching at every small sensor twitch as if it were a real, fast error to brake against.

There's no formula that hands you the right three numbers for an arbitrary system — the plant's mass, its damping, the delay between commanding thrust and the drone actually moving, all shift the ideal gains, and none of it is usually known precisely in advance. Tuning is empirical, iterative, and genuinely a craft. The closest thing to a standard starting recipe is Ziegler–Nichols: crank up KpK_pKp​ alone, with KiK_iKi​ and KdK_dKd​ at zero, until the output oscillates at a steady, unchanging amplitude; note that critical gain and the oscillation period; then plug both into a published set of ratios to get starting values for all three gains. It reliably gets you into the right neighborhood fast. It does not reliably get you a good controller — Ziegler–Nichols gains are famously aggressive and usually need hand-tuning down afterward, trading some of that speed for the damping the recipe leaves out. Treat it as a first draft, not a final answer.

Fig. 3 · Same plant, three tunings

012345time (s)00.511.5altitude (m)
Kp too high (oscillates)
over-damped (slow)
well-tuned
Same drone, same load, three different gain choices. Push KpK_pKp​ too high with no damping to match and the response oscillates around the target instead of settling. Lean too hard on damping relative to the other gains and the response crawls toward the target — technically stable, but sluggishly slow. Balance all three and you get the well-tuned trace: a fast approach that settles cleanly, with no overshoot and no lingering wobble.

Where you'll meet PID

PID is not a classroom abstraction — it's running, right now, in more machines than almost any other algorithm. Cruise control uses it to hold highway speed against hills and headwinds. 3D-printer hotends use it to hold nozzle temperature to within a degree. Quadcopter flight controllers run PID loops on each rotor's angular rate, hundreds of times a second, just to stay level. Chemical plants use it to hold a reactor's temperature or pressure inside a narrow safe band. Even a well-built espresso machine uses PID to hold brew temperature steady enough that your shot doesn't taste different every morning.
1

Check your intuition

Question 1 of 4

A P-only controller holds a drone below its target altitude forever. Why?

PID is calculus with a job — derivatives and integrals put to work holding something steady. If chasing that kind of intuition down to the arithmetic is your thing, solve a fresh math problem every morning with dailymath. One drop, one coffee, one win.

Try dailymath
Control theoryPIDEngineeringRoboticsLesson