explainer
Bode plots and loop shaping: place gain and phase together
Read Bode plots and shape a position-control loop with a lead controller. Calculate crossover and phase margin, compare closed-loop tracking, and check what the model leaves out.
What you will learn
- Read magnitude in decibels and phase in degrees on a logarithmic frequency axis.
- Calculate the frequency response of a plant and lead controller.
- Find gain crossover and evaluate phase margin at that frequency.
- Explain why phase lead also changes magnitude and moves crossover.
- Distinguish loop gain from closed-loop tracking and identify model limits.
Before you start
Increasing a controller gain can improve tracking at one frequency while leaving less room for phase lag near crossover. A Bode plot makes that trade visible. A lead controller lets you change the shape as well as the overall gain.
This lesson follows one position-control model all the way from its equations to a working frequency-domain experiment. You will calculate the loop's gain crossover, inspect its phase there, and compare the loop with the closed-loop tracking response.
Read Bode plots for loop shaping
A Bode plot uses two aligned graphs: magnitude and phase versus frequency. Equal horizontal distances represent equal frequency ratios. Moving from 0.1 to 1 rad/s covers the same distance as moving from 1 to 10 rad/s: each is one decade.
For a dimensionless frequency response H(jω), magnitude in decibels is 20 log₁₀|H(jω)|. A magnitude of 1 gives 0 dB, 2 gives about 6.0206 dB, and 0.5 gives about −6.0206 dB. These are amplitude ratios; the logarithm does not make the underlying signals logarithmic.
Angular frequency ω uses rad/s. Frequency f in cycles per second uses Hz, with ω = 2πf. A point at 1 rad/s therefore represents about 0.159155 Hz.
Phase describes the shift between sinusoidal input and output. A phase of −90° corresponds to a quarter-cycle lag at that frequency. A phase angle alone does not imply a fixed time delay across every frequency.
Define the plant and lead controller
Let y be position in meters and u a commanded velocity in m/s. A simple velocity lag followed by position integration gives:
ÿ/wp + ẏ = u
G(s) = Y(s)/U(s) = 1/[s(1 + s/wp)]
The positive number wp is the velocity-response pole frequency in rad/s. The plant has a pole at zero from position integration and a pole at −wp from the lag. Its transfer-function units are seconds.
Use unity negative feedback, e = r − y, and a lead controller:
C(s) = K(1 + s/z)/(1 + s/p), with p ≥ z > 0
L(s) = C(s)G(s)
K has units of 1/s, so C maps a position error to a velocity command. The corner frequencies z and p use rad/s; the corresponding zero and pole are at −z and −p. L is dimensionless because the controller and plant units cancel.
The model is continuous, linear, and time invariant. Transfer functions use zero initial conditions; frequency responses describe sinusoidal behavior. The experiment includes no sampling delay, saturation, measurement filter, or structural resonance.
Add the magnitude and phase factors
Substitute s = jω, where j² = −1. A factor 1 + jω/a has magnitude √(1 + (ω/a)²) and phase arctan(ω/a). Multiplication combines magnitudes and adds phases; division subtracts the denominator's phase.
|L(jω)| = K √(1 + (ω/z)²)
/ [ω √(1 + (ω/wp)²) √(1 + (ω/p)²)]
The integrator contributes −90°. The two poles add lag, while the zero adds lead:
∠L(jω) = −90° − arctan(ω/wp) + arctan(ω/z) − arctan(ω/p)
Convert the arctangents to degrees before adding them to −90°. The lab uses this continuous, unwrapped phase expression, so its curve has no artificial jumps at an angle convention's boundary.
Far below both controller corners, C approaches K. Far above them, C approaches Kp/z. The gain-only comparison uses C = K at every frequency, with the same plant and low-frequency controller gain as the shaped loop.
Find crossover and phase margin
The gain crossover frequency ωc satisfies |L(jωc)| = 1, or 0 dB. At that frequency, the phase margin is PM = 180° + ∠L(jωc). These definitions match the MathWorks margin documentation.
This particular loop has exactly one positive gain crossover. To see why, differentiate its log magnitude with respect to log frequency:
d ln|L| / d lnω = −1 − ω²/(wp² + ω²)
- ω²/(z² + ω²) − ω²/(p² + ω²) < 0
The positive fraction is always less than one, so the entire expression is negative. Magnitude tends to infinity as ω approaches zero and to zero as ω grows without bound. Continuity and strict decrease give one crossing.
The lab solves for that crossing with bisection on the exact magnitude formula. It does not locate crossover by picking the nearest plotted sample. Other plants can have multiple crossings, for which the same one-number interpretation requires more care.
Place a lead zero and pole
For p greater than z, the controller contributes arctan(ω/z) − arctan(ω/p) of positive phase. Its maximum occurs at ωm = √(zp). That geometric mean lies halfway between the corners on a logarithmic frequency axis.
Writing a = p/z, the maximum phase lead is arcsin((a − 1)/(a + 1)). With z = 0.5 rad/s and p = 2 rad/s, a = 4, ωm = 1 rad/s, and the maximum lead is 36.869898°. If p = z, the factors cancel and C = K, with zero phase lead everywhere.
Placing this phase increase near the desired crossover is a useful design move. The Illinois ECE 486 lead-compensation notes explain the same geometric placement and its magnitude tradeoff.
Adding lead also raises loop magnitude and moves crossover. Evaluate the new phase margin at the new crossover, then adjust K and the corners again if needed. The controller's maximum phase lead is not the amount by which phase margin must improve.
Check one shaped loop by hand
Set K = 1 1/s, wp = 1 rad/s, z = 0.5 rad/s, and p = 2 rad/s. At ω = 1 rad/s:
C(j) = (1 + 2j)/(1 + 0.5j) = 1.6 + 1.2j
G(j) = 1/[j(1 + j)] = −0.5 − 0.5j
L(j) = −0.2 − 1.4j
Its magnitude is √2 = 1.414214, its magnitude in decibels is 3.010300 dB, and its phase is −98.130102°. Since the magnitude exceeds one, this inspection frequency is below crossover.
For this example, squaring the magnitude equation and setting x = ω² gives x³ + 5x² − 12x − 4 = 0. The positive solution is x = 2, so ωc = √2 = 1.414214 rad/s, or 0.225079 Hz. Evaluating the phase there gives −109.471221°, hence PM = 70.528779°.
With C = K alone, the crossover is 0.786151 rad/s and the phase margin is 51.827292°. The shaped loop improves this margin by about 18.701487°, even though the controller's maximum phase lead is about 36.87°. The two margins use different frequencies.
Separate loop gain from closed-loop tracking
For the unity feedback connection, the reference-to-output transfer function and sensitivity are:
T(s) = Y(s)/R(s) = L(s)/(1 + L(s))
S(s) = E(s)/R(s) = 1/(1 + L(s))
At the worked example's ω = 1 rad/s, T = (9 − 7j)/13. Its magnitude is √(10/13) = 0.877058, while |S| = √(5/13) = 0.620174. Complex T and S add to one; their magnitudes do not generally add to one.
The low-frequency limit of T is one for this position loop. A closed-loop half-power bandwidth would be measured where |T| reaches 1/√2 relative to that limit. Crossover instead uses |L| = 1, so it describes a different transfer function and threshold.
At crossover, |T| = 1/[2 sin(PM/2)] for this phase range. It equals 1/√2 when PM is 90°, but has other values at other margins. Continue with control bandwidth to connect a tracking frequency response to motion and command limits.
Check stability and physical limits
The characteristic equation 1 + L(s) = 0 becomes:
s³ + (wp + p)s² + wp p(1 + K/z)s + K wp p = 0
All coefficients are positive. The remaining cubic Routh stability condition is (wp + p)(1 + K/z) > K. It holds because p ≥ z and wp is positive, so this entire parameter family has an asymptotically stable ideal closed loop.
When p = z, the canceled controller factor corresponds to a stable pole; the reduced characteristic polynomial is s² + wp s + K wp. The stability argument is about this stated model. Phase margin alone does not certify a physical robot with delays, saturation, uncertain modes, or a different feedback connection.
Lead also changes noise-driven command effort. If additive measurement noise n enters yₘ = y + n, then U/N = −C/(1 + L) = −CS, while Y/N = −T. At high frequency, S tends to one and the noise-to-command gain tends to Kp/z in 1/s.
A larger pole-to-zero ratio can therefore demand more high-frequency velocity command from the same measured position noise. Actual command levels depend on the noise spectrum and units. Check derivative filtering, actuator limits, model uncertainty, and sampled implementation before choosing hardware settings.
Shape the loop in the lab
Start with Lead near crossover and confirm the worked values at 1 rad/s. Switch to Gain only, then Higher gain without lead. Increasing K moves crossover upward, where this plant contributes more lag.
Next compare Lead above crossover with the default. The same pole-to-zero ratio puts the same maximum phase lead at a different frequency, so its effect on crossover and margin changes. Wider lead range adds more maximum lead while also moving crossover; its phase margin need not exceed the default's.
Both plots use fixed axes across settings so comparisons preserve scale. The inspection control changes the selected-frequency readouts and dots; crossover readouts describe the entire loop. The green magnitude curve describes closed-loop tracking, and the blue curves describe loop gain.
Reproduce the calculations in Python
This standard-library example uses complex arithmetic to evaluate C, G, L, and T. It solves crossover independently of a plot and prints the same default values as the lab. It evaluates a frequency-domain model; it does not simulate a time trajectory.
import cmath
import math
K, wp, z, p = 1.0, 1.0, 0.5, 2.0
def loop(omega, lead=True):
s = complex(0.0, omega)
controller = K * (1 + s / z) / (1 + s / p) if lead else K
return controller / (s * (1 + s / wp))
def crossover(lead=True):
low, high = 0.01, 100.0
for _ in range(90):
middle = (low + high) / 2
if abs(loop(middle, lead)) > 1:
low = middle
else:
high = middle
return (low + high) / 2
value = loop(1.0)
wc = crossover()
pm = 180 + math.degrees(cmath.phase(loop(wc)))
baseline = crossover(False)
baseline_pm = 180 + math.degrees(cmath.phase(loop(baseline, False)))
print(f"Loop magnitude: {abs(value):.6f}")
print(f"Loop dB and phase: {20 * math.log10(abs(value)):.6f}, "
f"{math.degrees(cmath.phase(value)):.6f} deg")
print(f"Crossover: {wc:.6f} rad/s = {wc / (2 * math.pi):.6f} Hz")
print(f"Phase margin: {pm:.6f} deg")
print(f"Gain-only crossover and margin: {baseline:.6f}, {baseline_pm:.6f}")
print(f"Closed-loop magnitude: {abs(value / (1 + value)):.6f}")
print(f"Sensitivity magnitude: {abs(1 / (1 + value)):.6f}")
Expected output:
Loop magnitude: 1.414214
Loop dB and phase: 3.010300, -98.130102 deg
Crossover: 1.414214 rad/s = 0.225079 Hz
Phase margin: 70.528779 deg
Gain-only crossover and margin: 0.786151, 51.827292
Closed-loop magnitude: 0.877058
Sensitivity magnitude: 0.620174
Try it yourself
Exercise 1. A lead controller has K = 2 1/s, z = 1 rad/s, and p = 9 rad/s. Find its peak-lead frequency, maximum phase lead, and high-frequency gain. Can these values alone tell you the phase margin of a loop containing that controller?
Check the lead-controller calculation
The peak is at √(1 × 9) = 3 rad/s. The maximum lead is arcsin((9 − 1)/(9 + 1)) = arcsin(0.8) = 53.130102°. The high-frequency controller gain is Kp/z = 18 1/s.
You also need the plant and the resulting crossover frequency to calculate phase margin. The controller phase maximum may occur away from that crossover, and the plant contributes its own phase.
Exercise 2. At some frequency a loop has L = −0.5 − 0.5j. Calculate |L| in decibels, T = L/(1 + L), and |T|. Is this frequency a gain crossover or a closed-loop half-power point for a system with unit DC tracking gain?
Check the loop and closed-loop values
|L| = 1/√2, so its magnitude is −3.010300 dB. Dividing (−0.5 − 0.5j) by (0.5 − 0.5j) gives T = −j, with |T| = 1.
This frequency is neither point: gain crossover requires |L| = 1, while the closed-loop half-power point requires |T| = 1/√2. The −3 dB value belongs to L here, so it cannot be used as the bandwidth threshold for T.
Sources and further study
- MathWorks: gain margin, phase margin, and crossover frequencies defines the margin measurements and documents multiple-crossing and internal-stability qualifications.
- Illinois ECE 486: lead compensation and frequency-domain design, from the notes of Maxim Raginsky and Daniel Liberzon, develops lead compensation and its effects on crossover and phase.
- Illinois ECE 486: frequency-response design tradeoffs distinguishes design guidance from a complete stability test.
Continue with control bandwidth to evaluate how well a closed loop follows changing references. Then examine controller discretization to see what changes when the command updates at sampled times.