Guidance, Navigation and Control · Theory · M3
M3-T3 — Frequency Response and Bode Plots
Feed a linear system a sine wave and a sine wave of the same frequency comes out, scaled and delayed. Drawing the scale and the delay against frequency is the most useful picture in control.
A control loop has to work at many frequencies at once: it must follow slow commands, reject mid-frequency gusts and ignore fast noise. The frequency response shows how it treats each, in two curves. A sine wave goes in, a sine wave of the same frequency comes out with a different amplitude and a shifted phase, and those two numbers as functions of the frequency are the Bode plot. This lesson shows where the plot comes from, how to draw it from the poles and zeros with a pencil, and how to read the two numbers that matter, the crossover frequency and the phase there.
Learning objectives
After this lesson, you should be able to:
- Explain why a linear system turns a sine wave into a sine wave of the same frequency.
- Draw the asymptotic Bode magnitude of a transfer function from its poles and zeros.
- Read a loop's crossover frequency, low-frequency gain and roll-off from a Bode plot.
- Verify a frequency response by simulating a sinusoid through the system.
The intuition
The last two lessons used transfer functions as algebra in . This lesson uses the same function at one special set of points, , the imaginary axis. There the transfer function is a complex number whose magnitude and angle have a physical meaning.
Sine in, sine out
Feed a stable linear system a sinusoid . After the start-up transient has died, the output is another sinusoid of exactly the same frequency. Only two things have changed.
- The amplitude is multiplied by , the gain at that frequency.
- The phase is shifted by , usually a lag (a negative angle): the output is late.
This is a property of linear systems with constant coefficients and nothing else. It is why frequency is the natural language of control: any signal is a sum of sinusoids, and the system treats each one separately.
The Bode plot
A Bode plot draws the two numbers against frequency, with the frequency axis logarithmic and the gain in decibels (). The logarithms are the point. The transfer function of a loop is a product of simple factors, one per pole or zero, and the logarithm of a product is a sum. So the Bode plot of a loop is the sum of the plots of its factors, and each factor has a plot simple enough to draw by hand.
- A pole at , the factor , is flat at 0 dB below the corner and falls at 20 dB per decade (a factor of 10 in frequency) above it. The true curve is 3 dB below the asymptotes at the corner. Its phase goes from 0° to −90°, passing through −45° at the corner.
- A zero at does the opposite: the gain rises 20 dB per decade above the corner and the phase rises by up to 90°.
- An integrator is a straight line of slope −20 dB per decade and a constant phase of −90°.
What to read from it
Four features of a loop's Bode plot say most of what you need.
- The low-frequency gain. How large is for slow signals. It sets how well the loop rejects slow disturbances (the lesson before: ).
- The crossover frequency , where crosses 0 dB. It is the loop's bandwidth, roughly: the speed of the closed loop.
- The slope near crossover. A slope of −20 dB/decade is comfortable. A slope of −40 dB/decade there means two lags accumulate and the phase is near −180°.
- The phase at crossover. The distance of the phase from −180° at is the phase margin, the subject of the next lesson. In the figure it is 55.5°.
A Bode plot is a sum of simple pieces, and the two numbers that matter most, the crossover frequency and the phase at it, can be read off without solving anything.
Definitions
- Frequency response
- The transfer function evaluated on the imaginary axis, , with the angular frequency in rad/s. A complex number for each .
- Gain and phase
- The magnitude and the angle of that number. The gain in decibels is .
- Corner frequency
- The frequency of a pole or a zero, where the asymptotes of its factor meet.
- Decade
- A factor of 10 in frequency.
- Crossover frequency
- The frequency at which the loop gain equals 1 (0 dB).
The statement about sinusoids is that the steady-state response to is another sinusoid:
A transfer function that is a product of factors has a gain that is the product of the factors' gains and a phase that is the sum of their phases:
A single pole at has:
Hopper's pitch loop with the servo is the product of a PD controller, the unstable pitch plant and the servo lag:
Derivation: why a sine comes out as a sine, and why Bode plots add
The claim at the heart of the lesson takes four lines, using the exponential result of M3-T1: Transfer Functions, Poles and Zeros.
A linear system with constant coefficients answers the exponential with , as derived for the transfer function. Take the exponent on the imaginary axis, .
Write the complex number in polar form. Its magnitude scales the exponential and its angle shifts the phase.
A sine is the imaginary part of the complex exponential, and the system is real and linear, so the output for the sine is the imaginary part of the output for the exponential.
The full response also contains the natural modes , which decay if every pole has a negative real part. After that only the sinusoid remains. For an unstable system the transient grows, and the frequency response describes only the part driven by the input.
Why the plot is built from pieces
The magnitude of a product of complex numbers is the product of their magnitudes, and the logarithm turns a product into a sum.
The angle of a product is the sum of the angles, with no logarithm needed.
A pole has two asymptotes: a flat one below the corner and a line of slope −1 (−20 dB per decade) above it. The curve is 3.01 dB below their intersection.
The frequency response is the transfer function walked along the imaginary axis. Because a loop is a product of simple factors, its Bode plot is the sum of simple pieces, and its crossover and phase can be read off by eye.
A worked example
Draw and check the Bode plot of Hopper's pitch loop with the servo, and then confirm the central claim of the lesson by simulation.
- One factor. The servo has its corner at 40 rad/s. At 4 rad/s its gain is −0.04 dB and its phase −5.7°, essentially nothing. At 40 rad/s the gain is −3.01 dB and the phase −45.0°. Beyond that it follows its asymptote: −6.99 dB at 80 rad/s (asymptote −6.02) and −20.04 dB at 400 rad/s (asymptote −20.00).
- The whole loop. Evaluate at six frequencies. The gain falls from 30.4 dB at 0.1 rad/s to −33.6 dB at 100 rad/s, crossing 0 dB at 6.07 rad/s. The phase is −178° at 0.1 rad/s (the plant), rises to −120.5° at 12 rad/s (the zero of the PD controller) and falls back to −160° by 100 rad/s (the servo).
- Read it. At the crossover the phase is −124.5°, so there are 55.5° between the loop and −180°: the margin of the next lesson. The slope at the crossover is about −20 dB per decade, comfortable.
- Check the central claim. Feed into the closed loop for 40 s, discard the transient and fit a sine to the last four periods. The simulation gives a gain of 1.3406 and a phase of −36.36°; the transfer function at gives 1.3404 and −36.36°. The two agree because the claim is a theorem.
- Convert the phase to time. A phase lag of 36.36° at 4 rad/s is a delay of s: the output is late by about a sixth of a second.
import cmath, math
import gnckit as g
b, lam, wn, zeta = 19.62, 0.7, 4.0, 0.7
Kd, Kp = 2 * zeta * wn / b, (wn ** 2 + lam ** 2) / b
L = g.TF([b * Kd, b * Kp], g.poly_mul([1, 0, -lam ** 2], [1 / 40, 1])) # pitch loop including the 40 rad/s gimbal servo
print('one factor, the servo 1/(1 + s/40): exact against its asymptote')
servo = g.TF([1], [1 / 40, 1])
for w in (4, 20, 40, 80, 400):
db = 20 * math.log10(abs(servo.freq(w)))
asym = 0.0 if w <= 40 else -20 * math.log10(w / 40)
print(f' w = {w:3d}: {db:6.2f} dB (asymptote {asym:6.2f}), phase {math.degrees(cmath.phase(servo.freq(w))):6.1f} deg')
print('the whole loop (the factors add in dB and in degrees):')
mag, ph = g.bode(L, [0.1, 1, 4, 12, 40, 100])
for w, a, p in zip([0.1, 1, 4, 12, 40, 100], mag, ph):
print(f' w = {w:5.1f}: {a:6.2f} dB, {p:7.1f} deg')
# a sinusoid through the closed loop: measure the gain and delay, and compare with T(jw)
Tcl = g.TF(L.num, g.poly_add(L.den, L.num))
A, B, C, D = Tcl.ss()
w, dt = 4.0, 0.001
f = lambda t, x: [r + B[i] * math.sin(w * t) for i, r in enumerate(g.mat_vec(A, x))]
ts, xs = g.integrate(f, [0.0] * len(A), 40.0, dt)
y = [sum(c * v for c, v in zip(C, x)) for x in xs]
n0 = int((40.0 - 4 * 2 * math.pi / w) / dt) # keep the last four periods, after the transient has died
a = sum(y[i] * math.sin(w * ts[i]) for i in range(n0, len(ts))) / sum(math.sin(w * ts[i]) ** 2 for i in range(n0, len(ts)))
c = sum(y[i] * math.cos(w * ts[i]) for i in range(n0, len(ts))) / sum(math.cos(w * ts[i]) ** 2 for i in range(n0, len(ts)))
print(f'measured: gain {math.hypot(a, c):.4f}, phase {math.degrees(math.atan2(c, a)):.2f} deg')
print(f'T(j{w:g}): gain {abs(Tcl.freq(w)):.4f}, phase {math.degrees(cmath.phase(Tcl.freq(w))):.2f} deg')one factor, the servo 1/(1 + s/40): exact against its asymptote w = 4: -0.04 dB (asymptote 0.00), phase -5.7 deg w = 20: -0.97 dB (asymptote 0.00), phase -26.6 deg w = 40: -3.01 dB (asymptote 0.00), phase -45.0 deg w = 80: -6.99 dB (asymptote -6.02), phase -63.4 deg w = 400: -20.04 dB (asymptote -20.00), phase -84.3 deg the whole loop (the factors add in dB and in degrees): w = 0.1: 30.37 dB, -178.2 deg w = 1.0: 21.35 dB, -162.7 deg w = 4.0: 4.50 dB, -132.1 deg w = 12.0: -6.77 dB, -120.5 deg w = 40.0: -20.07 dB, -139.2 deg w = 100.0: -33.64 dB, -159.9 deg measured: gain 1.3406, phase -36.36 deg T(j4): gain 1.3404, phase -36.36 deg
In robotics
Frequency response is how loops are specified, measured and debugged in practice.
- Measuring it. The frequency response of a real vehicle or actuator is measured by exciting it with sinusoids or with a sweep (a chirp) and fitting gain and phase at each frequency. Flight-test teams identify an aircraft's dynamics this way, and a servo's bandwidth and delay are read from its response to a sweep. This is the practical form of the system identification of Robot Learning M7-T2.
- Structural modes. A rocket or a flexible aircraft has bending modes that appear as sharp peaks in the response at tens of rad/s. A loop whose gain is above 0 dB at a peak can be destabilized by it, and the cure is a notch filter or a lower bandwidth (lesson 7).
- Requirements. A specification such as "bandwidth 4 rad/s, rolling off at 20 dB per decade above 10 rad/s, 45° of margin" is a statement about a Bode plot, and a design review is a review of the plot.
- Tools. The frequency response of a model is computed in one line (
bodein python-control and ingnckit), which is how the numbers here were produced. The same function applied to measured data tells you whether the model describes the vehicle. - Digital loops. A sampled controller adds a delay of half a sample, a phase lag that shows on the Bode plot as extra phase falling with frequency (lesson 7).
The linear model of M2-T4: Trim and Linearization is the starting point, and its poles are what the corner frequencies of the plot are made of. The next lesson uses the phase at crossover for the quantity that decides whether the loop is safe: the phase margin.
Common misconceptions
“A frequency response exists for every system.”
It describes the steady response of a stable system to sinusoids. An unstable system's free motion grows without bound, and the frequency response of its open loop is still a useful function of frequency, but it does not describe what the system does when left alone. Hopper's pitch plant is the example: its response is defined, but its outputs diverge.
“The Bode plot approximation is exact at the corners.”
The asymptotes are exact only far from the corners. At a corner the true gain is 3 dB below the intersection of the asymptotes, and the phase is exactly halfway (−45° for one pole). The asymptotic plot is a sketch to understand the shape, not a calculation.
“Phase lag is a delay of the same size at every frequency.”
A phase lag of at frequency corresponds to a time delay , which differs from frequency to frequency. A pure time delay has a phase that grows linearly with frequency, , which is why delays hurt fast loops more.
“The crossover frequency is the bandwidth of the closed loop.”
It is close to it, within a factor of about 2. Hopper's loop crosses at 6.07 rad/s, and the closed-loop |T| falls to 0.707 of its low-frequency value at a similar frequency. The precise bandwidth depends on the phase margin, which is why the two are not interchanged.
“Gain in decibels is a different quantity from gain.”
It is the same number on a logarithmic scale: 20 dB is a factor of 10, 6 dB a factor of 2, 0 dB a factor of 1, −20 dB a factor of 0.1. The scale makes products into sums and shows many decades of gain on one plot.
Key takeaways
- A stable linear system turns a sine wave into a sine wave of the same frequency, scaled by and shifted by .
- A Bode plot draws gain in decibels and phase in degrees against a logarithmic frequency axis. A loop's plot is the sum of the plots of its factors.
- A pole at is flat below it and falls 20 dB per decade above; its phase goes from 0° to −90°, with −45° and −3.01 dB at the corner.
- Read four things from a loop's plot: the low-frequency gain, the crossover frequency, the slope there, and the phase there.
- Hopper's pitch loop crosses 0 dB at 6.07 rad/s with a phase of −124.5°, leaving 55.5° of margin.
- A phase lag of at is a delay of ; a pure delay's phase grows linearly with frequency.
References and further reading
Each source is marked free or paid. Free to read does not mean free to reuse: the course resources page lists every source with its licence.
- K. J. Åström and R. M. Murray, Feedback Systems, 2nd edition, Princeton University Press, 2021 , the chapter on frequency domain analysis. Free to read as the authors' PDF; the book is copyrighted.
- B. Douglas, “Bode Plots” (video series) . A patient walk through drawing and reading Bode plots. Free to watch.
- J. How and E. Frazzoli, MIT 16.30 Feedback Control Systems (OpenCourseWare) , the lectures on frequency response and Bode plots. Free; licence CC BY-NC-SA 4.0.
- Python Control Systems Library documentation , the section on frequency response. Free; BSD licence.
Knowledge check
Three questions. Write an answer, then reveal the explanation. Your answers stay in your browser.
Question 1
A first-order servo with a corner at 40 rad/s is driven at 100 rad/s. What are its gain in decibels and its phase lag?
Explanation
The gain is 1/√(1 + (100/40)²) = 1/√7.25 = 0.371, which is 20 log₁₀ 0.371 = −8.6 dB. The phase is −arctan(100/40) = −68.2°. The asymptote would give −7.96 dB, so the true value is 0.6 dB lower there. At 100 rad/s the servo is already attenuating by more than a factor of 2.5 and the output is late by 68°, about 12 ms.
Question 2
A double integrator 1/s² has what slope on a Bode magnitude plot, and by how many decibels does its gain drop between 1 and 10 rad/s? What is its phase?
Explanation
Each integrator has a slope of −20 dB per decade, so the double integrator has −40 dB per decade and its gain falls by 40 dB between 1 and 10 rad/s, a factor of 100. Its phase is constant at −180°. A loop that crosses 0 dB on such a slope sits at −180° (before any controller or servo lag), which is why a double-integrator plant such as a multirotor attitude axis needs phase lead from a derivative term to be stabilized.
Question 3
In the simulation of the example the closed loop gives a phase of −36.36° at 4 rad/s. What delay is that, and would the same delay produce the same phase at 8 rad/s?
Explanation
The delay is the phase in radians over the frequency: 36.36° = 0.6346 rad, divided by 4 rad/s gives 0.159 s. A pure time delay of 0.159 s would have a phase of −ωτ, so at 8 rad/s it would be −72.7°, twice as much. The closed loop is not a pure delay, so its actual phase at 8 rad/s is different (it has a different shape), but the comparison shows why a phase lag measured at one frequency cannot be assumed at another, and why delays are damaging at high frequency.
What’s next
Related content
Nothing below is required to finish this lesson.
- BeforeM3-T2: What Feedback Buys and What It Costs
Derive the sensitivity and complementary sensitivity functions, and explain the trade between disturbance rejection, noise transmission and control effort.
- LabM3-L1: Rescue the Phase Margin
Hopper's pitch loop rings after a heavier engine was fitted. Measure the margins from the open-loop response and add a lead compensator that restores 45 degrees and 6 dB.
Other courses on this site treat neighbouring topics from their own angle:
- Lab: Tune a PID Controller
- Lab: Fix the Oscillating Robot
- UAV M5-T6: PID controllers
- UAV M7-T6: End-to-end latency
This course leaves the following to the pages that already teach them:
Get notified when the next lesson and new labs are released.
One email per new lesson or lab.