Chapter 18: Frequency-Domain Performance Specifications
Lesson 1: Low-Frequency Gain and Tracking Performance
This lesson establishes a precise relationship between the low-frequency magnitude of the loop transfer function and the tracking performance of a feedback system. Building on Bode and Nyquist analysis from previous chapters, we derive closed-loop frequency-domain expressions for the tracking error, connect them to static error constants and system type, and show how to convert tracking specifications into inequalities on the open-loop gain. Numerical examples are illustrated in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica with a focus on servo and robotic applications.
1. Conceptual Overview
In earlier chapters you learned how to use frequency response (Bode, Nyquist, Nichols) to assess stability and stability margins. In this lesson we use the same tools to study tracking performance: how well the output \( y(t) \) follows the reference \( r(t) \) for low-frequency commands (slowly varying steps, ramps, or low-frequency sinusoids).
We consider the standard unity-feedback configuration with controller \( C(s) \), plant \( P(s) \), loop transfer function \( L(s) = C(s)P(s) \), and error \( e(t) = r(t) - y(t) \). The structure is:
flowchart LR
R["r(t)"] --> E["e(t) = r(t) - y(t)"]
Y["y(t)"] -- "feedback" --> E
E --> C["C(s)"]
C --> P["P(s)"]
P --> Y
Intuitively, good low-frequency tracking means that for all reference frequencies \( \omega \) in some band \( 0 \le \omega \le \omega_r \) (the tracking band), the closed-loop behaves almost like an ideal system with transfer function \( 1 \) from reference to output:
\[ \frac{Y(j\omega)}{R(j\omega)} \approx 1 \quad \text{for} \quad 0 \le \omega \le \omega_r. \]
We will show that this is achieved when the magnitude of the loop transfer function \( L(j\omega) \) is sufficiently large at low frequencies. This is the frequency-domain counterpart of the time-domain static error constants from Chapter 8.
2. Closed-Loop Frequency-Domain Tracking Relations
For the unity-feedback loop with \( L(s) = C(s)P(s) \) we can derive the closed-loop transfer functions between reference, output, and error using algebra in the Laplace domain. From the block diagram,
\( E(s) = R(s) - Y(s) \), \( Y(s) = L(s)E(s) \).
Eliminating \( E(s) \) gives
\[ Y(s) = L(s)\bigl(R(s) - Y(s)\bigr) \quad \Rightarrow \quad \bigl(1 + L(s)\bigr)Y(s) = L(s)R(s). \]
Hence the reference–output and reference–error transfer functions are
\[ \frac{Y(s)}{R(s)} = \frac{L(s)}{1 + L(s)}, \qquad \frac{E(s)}{R(s)} = \frac{1}{1 + L(s)}. \]
For sinusoidal steady state we evaluate these at \( s = j\omega \). The magnitude relations become
\[ \left|\frac{Y(j\omega)}{R(j\omega)}\right| = \left|\frac{L(j\omega)}{1 + L(j\omega)}\right|, \qquad \left|\frac{E(j\omega)}{R(j\omega)}\right| = \left|\frac{1}{1 + L(j\omega)}\right|. \]
Thus, the tracking error amplification at frequency \( \omega \) is completely determined by \( L(j\omega) \). When the loop gain magnitude \( |L(j\omega)| \) is large, the error amplification is small.
It is also useful to write the closed-loop reference–output transfer function as
\[ \frac{Y(j\omega)}{R(j\omega)} = 1 - \frac{1}{1 + L(j\omega)} = 1 - \frac{E(j\omega)}{R(j\omega)}. \]
Hence the deviation of \( Y(j\omega)/R(j\omega) \) from unity is \( -E(j\omega)/R(j\omega) \). Bounding the error transfer function \( 1/(1 + L(j\omega)) \) simultaneously bounds the tracking quality.
3. Low-Frequency Gain, System Type, and Static Error Constants
In Chapter 8 you defined static error constants and system type using time-domain methods. Here we reinterpret them in the frequency domain using the low-frequency behavior of \( L(s) \).
For a unity-feedback system with step input \( r(t) = 1 \), the Laplace transform is \( R(s) = 1/s \). The steady-state error can be obtained via the final value theorem:
\[ e_{\text{ss}} = \lim_{t \to \infty} e(t) = \lim_{s \to 0} sE(s) = \lim_{s \to 0} \frac{sR(s)}{1 + L(s)} = \lim_{s \to 0} \frac{1}{1 + L(s)}. \]
This suggests defining the position error constant \( K_p \) in terms of the loop transfer function:
\[ K_p := \lim_{s \to 0} L(s). \]
When \( K_p \) is finite (type 0), the steady-state step error is
\[ e_{\text{ss}} = \frac{1}{1 + K_p}. \]
In frequency-domain terms, for a type 0 system \( K_p = \lim_{\omega \to 0} L(j\omega) \), so controlling the zero-frequency loop gain directly controls the step tracking accuracy.
For systems with integrators (type 1, type 2, …) we can factor the loop transfer function as
\[ L(s) = \frac{K \displaystyle\prod_{i=1}^{z} \left(1 + \frac{s}{z_i}\right)} {s^{n} \displaystyle\prod_{k=1}^{p} \left(1 + \frac{s}{p_k}\right)}, \quad n = \text{number of integrators (system type)}. \]
For frequencies much smaller than all finite poles and zeros, i.e. \( 0 \le \omega \ll \min\{|p_k|, |z_i|\} \), we have the low-frequency approximation
\[ |L(j\omega)| \approx \frac{K}{\omega^{n}}. \]
Thus, higher system type corresponds to a steeper low-frequency magnitude slope (about \( -20n \) dB per decade) and an unbounded DC gain. This is precisely why type 1 systems achieve zero steady-state error for steps and type 2 systems achieve zero steady-state error for ramps.
In summary, low-frequency gain of \( L(j\omega) \) and system type are the frequency-domain mechanisms that enforce small tracking error for slowly varying commands.
4. Quantitative Bounds – From Error Specs to Gain Specs
Suppose a tracking specification is stated as:
“For all reference signals whose dominant frequencies satisfy \( 0 \le \omega \le \omega_r \), the amplitude of the tracking error must be at most a fraction \( \delta \) of the reference amplitude.”
In sinusoidal steady state this becomes the inequality
\[ \left|\frac{E(j\omega)}{R(j\omega)}\right| = \left|\frac{1}{1 + L(j\omega)}\right| \le \delta, \quad 0 \le \omega \le \omega_r. \]
We can relate this requirement to a constraint on the loop magnitude by using the reverse triangle inequality for complex numbers:
\[ |1 + L(j\omega)| \ge \bigl||L(j\omega)| - 1\bigr|. \]
Therefore
\[ \left|\frac{1}{1 + L(j\omega)}\right| \le \frac{1}{\bigl||L(j\omega)| - 1\bigr|}. \]
If we enforce a conservative bound \( |L(j\omega)| \ge M \ge 1 \) for \( 0 \le \omega \le \omega_r \), then
\[ \left|\frac{E(j\omega)}{R(j\omega)}\right| \le \frac{1}{M - 1}, \quad 0 \le \omega \le \omega_r. \]
For large \( M \), this is approximately \( 1/M \). Thus, a simple design rule emerges:
To achieve an error amplitude fraction roughly no larger than \( \delta \), choose the low-frequency loop gain such that \( |L(j\omega)| \gtrsim 1/\delta \) in the desired tracking band.
In decibels this reads
\[ 20\log_{10}|L(j\omega)| \gtrsim -20\log_{10}(\delta), \quad 0 \le \omega \le \omega_r. \]
For example, if you want \( \delta = 0.02 \) (2% amplitude error) up to \( \omega_r \), then you need approximately \( |L(j\omega)| \gtrsim 50 \) or \( 20\log_{10}|L(j\omega)| \gtrsim 34 \) dB in that band.
flowchart TD
SPEC["Specify tracking band 0 <= w <= w_r and max error delta"]
SPEC --> BOUND["Translate to bound on |E/R| = |1/(1 + L(jw))|"]
BOUND --> LFGAIN["Impose lower bound on |L(jw)| in low-frequency band"]
LFGAIN --> DESIGN["Adjust controller C(s) to meet gain and stability margins"]
DESIGN --> VERIFY["Verify with Bode plots and time-domain simulations"]
In practice, this low-frequency gain requirement must be combined with stability-margin constraints from Chapter 17; increasing low-frequency gain generally improves tracking but reduces gain margin and may cause excessive overshoot in the time domain.
5. Python Example – Bode-Based Tracking for a Robot Joint Servo
Consider a simplified rotary joint of a robot arm modeled as a type 1 plant \( P(s) = 1/(s(s + 1)) \). A proportional controller \( C(s) = K \) gives the loop transfer function
\[ L(s) = \frac{K}{s(s + 1)}. \]
We choose \( K \) such that the tracking error for
sinusoidal position commands up to
\( \omega_r = 1 \) rad/s is within about 2%. The Python
code below evaluates
\( |E(j\omega)/R(j\omega)| \) numerically and plots the
result. The python-control package is commonly used in
robotics for such linear analyses, often together with ROS-based motion
stacks.
import numpy as np
import matplotlib.pyplot as plt
# Loop transfer function L(s) = K / (s (s + 1))
def loop_L(jw, K):
s = 1j * jw
P = 1.0 / (s * (s + 1.0))
C = K
return C * P
def G_ref(jw, K):
"""Closed-loop transfer from reference to output: Y/R = L/(1+L)."""
L = loop_L(jw, K)
return L / (1.0 + L)
def G_err(jw, K):
"""Closed-loop transfer from reference to error: E/R = 1/(1+L)."""
L = loop_L(jw, K)
return 1.0 / (1.0 + L)
# Design parameter: try a few candidate gains
K = 50.0
w_vals = np.logspace(-2, 2, 400) # 0.01 to 100 rad/s
err_mag = np.array([np.abs(G_err(w, K)) for w in w_vals])
ref_mag = np.array([np.abs(G_ref(w, K)) for w in w_vals])
print("Approx. error magnitude at w = 1 rad/s:",
np.abs(G_err(1.0, K)))
# Plot magnitude of error and tracking transfer functions
plt.figure()
plt.loglog(w_vals, err_mag, label="|E(jw)/R(jw)|")
plt.loglog(w_vals, np.abs(1.0 - ref_mag), linestyle="--",
label="|1 - Y(jw)/R(jw)|")
plt.axvline(1.0, linestyle=":", label="w_r = 1 rad/s")
plt.axhline(0.02, linestyle=":", label="delta = 0.02")
plt.xlabel("Frequency w [rad/s]")
plt.ylabel("Amplitude ratio")
plt.legend()
plt.grid(True, which="both")
plt.title("Low-frequency tracking error vs loop gain K")
plt.show()
In a robotics context, the same analysis could be applied to a more
detailed joint model obtained from the robot's rigid-body dynamics
(e.g., using roboticstoolbox-python) while still using
python-control to compute
\( L(j\omega) \) and the associated tracking error
curves.
6. C++ Example – Computing Low-Frequency Error Gain
In embedded robotic controllers written in C++ (for example, within ROS control loops), one often needs to reason about tracking quality for a few key frequencies. The following C++ snippet computes \( |E(j\omega)/R(j\omega)| \) for the same plant \( P(s) = 1/(s(s + 1)) \) and proportional gain \( K \) at a single frequency \( \omega_0 \).
#include <iostream>
#include <complex>
int main() {
double K = 50.0;
double w0 = 1.0; // rad/s
std::complex<double> s(0.0, w0);
std::complex<double> P = 1.0 / (s * (s + 1.0));
std::complex<double> C = K;
std::complex<double> L = C * P;
std::complex<double> G_ref = L / (1.0 + L); // Y/R
std::complex<double> G_err = 1.0 / (1.0 + L); // E/R
std::cout << "At w = " << w0 << " rad/s\n";
std::cout << " |Y/R| = " << std::abs(G_ref) << "\n";
std::cout << " |E/R| = " << std::abs(G_err) << std::endl;
return 0;
}
In a robotics stack, this type of computation can be integrated with
libraries such as
Eigen for linear algebra and the ROS
ros_control framework to tune the low-frequency gain of
joint controllers so that position commands are accurately tracked up to
the desired bandwidth.
7. Java Example – Evaluating Tracking Gain Across Frequencies
Java is used in some robotic platforms (for example, educational robots and industrial automation controllers). The following minimal example computes \( |E(j\omega)/R(j\omega)| \) for a chosen frequency without requiring external control libraries.
public class TrackingErrorExample {
public static void main(String[] args) {
double K = 50.0;
double w0 = 1.0; // rad/s
// s = j w0
double sr = 0.0;
double si = w0;
// P(s) = 1 / (s (s + 1))
Complex s = new Complex(sr, si);
Complex P = Complex.one().divide(s.multiply(s.add(Complex.one())));
Complex C = new Complex(K, 0.0);
Complex L = C.multiply(P);
Complex Gref = L.divide(Complex.one().add(L)); // Y/R
Complex Gerr = Complex.one().divide(Complex.one().add(L)); // E/R
System.out.println("At w = " + w0 + " rad/s");
System.out.println(" |Y/R| = " + Gref.abs());
System.out.println(" |E/R| = " + Gerr.abs());
}
// Minimal complex helper (in practice use Apache Commons Math or similar)
static class Complex {
final double re, im;
Complex(double r, double i) { re = r; im = i; }
static Complex one() { return new Complex(1.0, 0.0); }
Complex add(Complex z) { return new Complex(re + z.re, im + z.im); }
Complex multiply(Complex z) {
return new Complex(re * z.re - im * z.im, re * z.im + im * z.re);
}
Complex divide(Complex z) {
double d = z.re * z.re + z.im * z.im;
return new Complex((re * z.re + im * z.im) / d,
(im * z.re - re * z.im) / d);
}
double abs() { return Math.hypot(re, im); }
}
}
For robotics applications (for instance, in FIRST robotics with WPILib), one would typically wrap such computations inside higher-level control APIs but the underlying low-frequency gain reasoning remains the same.
8. MATLAB/Simulink Example – Loop Shaping for Tracking
MATLAB and Simulink are standard tools in control and robotics. The code below defines the loop transfer function, computes the closed-loop reference–output and reference–error transfer functions, and visualizes them with Bode plots. The same models can be used directly in Simulink for time-domain simulation of robot joint tracking.
s = tf('s');
% Plant and controller
P = 1 / (s * (s + 1)); % robot joint approximation
K = 50;
C = K;
% Loop and closed-loop transfer functions
L = C * P; % loop transfer L(s)
Tref = L / (1 + L); % Y/R = L/(1+L)
Terr = 1 / (1 + L); % E/R = 1/(1+L)
% Bode plots of loop and error transfer
w = logspace(-2, 2, 400);
figure;
bode(L, w), grid on;
title('Loop transfer L(s)');
figure;
bode(Terr, w), grid on;
title('Error transfer E/R = 1 / (1 + L)');
% Evaluate error magnitude at w = 1 rad/s
[Terr_mag, Terr_phase] = bode(Terr, 1);
fprintf('Error amplitude ratio at w = 1 rad/s: %g\n', Terr_mag);
In Simulink, a corresponding block diagram would contain
transfer-function blocks for C(s) and P(s), a
unity feedback block, and a source generating step or sinusoidal
references. By varying K, the Bode plot of
L(s) can be shaped so that its low-frequency magnitude
satisfies the tracking specifications while stability margins remain
acceptable.
9. Wolfram Mathematica Example – Symbolic and Numeric Analysis
Mathematica is well suited for symbolic manipulation of transfer functions and for generating analytical expressions for low-frequency approximations of \( L(j\omega) \) and the error transfer function.
(* Define symbolic variables *)
K = 50.0;
s = I*ω;
P[ω_] := 1/(s*(s + 1)); (* P(s) = 1 / (s (s + 1)) *)
C[ω_] := K; (* Proportional controller *)
L[ω_] := C[ω]*P[ω];
Gref[ω_] := L[ω]/(1 + L[ω]); (* Y/R *)
Gerr[ω_] := 1/(1 + L[ω]); (* E/R *)
(* Low-frequency series expansion of error transfer *)
Series[Gerr[ω], {ω, 0, 2}]
(* Numerical Bode-like magnitude plot for error transfer *)
Plot[Abs[Gerr[ω]], {ω, 0.01, 10},
ScalingFunctions -> {"Log", "Log"},
AxesLabel -> {"w [rad/s]", "|E(j w)/R(j w)|"}]
Symbolic series expansions provide insight into how \( |E(j\omega)/R(j\omega)| \) behaves as \( \omega \to 0 \), reinforcing the link between low-frequency gain and steady-state tracking performance.
10. Problems and Solutions
Problem 1 (Error bound via loop magnitude). Consider a unity-feedback system with loop transfer function \( L(s) \). Show that for every frequency \( \omega \),
\[ \left|\frac{E(j\omega)}{R(j\omega)}\right| = \left|\frac{1}{1 + L(j\omega)}\right| \le \frac{1}{\bigl||L(j\omega)| - 1\bigr|}. \]
Solution: The starting point is the reverse triangle inequality:
\[ |a + b| \ge \bigl||a| - |b|\bigr| \quad \text{for all complex } a,b. \]
Take \( a = 1 \) and \( b = L(j\omega) \). Then
\[ |1 + L(j\omega)| \ge \bigl||1| - |L(j\omega)|\bigr| = \bigl||L(j\omega)| - 1\bigr|. \]
Since \( E(j\omega)/R(j\omega) = 1/(1 + L(j\omega)) \), taking reciprocals of both sides (and noting that magnitudes are positive) gives
\[ \left|\frac{1}{1 + L(j\omega)}\right| \le \frac{1}{\bigl||L(j\omega)| - 1\bigr|}, \]
which is the desired bound.
Problem 2 (From error specification to loop gain). A unity-feedback controller must track sinusoidal references with frequencies \( 0 \le \omega \le 0.5 \) rad/s such that the ratio of error amplitude to reference amplitude is at most 5%. Find a simple sufficient condition on \( |L(j\omega)| \) in that frequency band.
Solution: The specification is \( |E(j\omega)/R(j\omega)| \le 0.05 \) for \( 0 \le \omega \le 0.5 \). Using the bound from Problem 1, if we enforce
\[ |L(j\omega)| \ge M \quad \text{for } 0 \le \omega \le 0.5, \]
then
\[ \left|\frac{E(j\omega)}{R(j\omega)}\right| \le \frac{1}{M - 1}. \]
We need \( 1/(M - 1) \le 0.05 \), so \( M - 1 \ge 20 \) and hence \( M \ge 21 \). Thus a sufficient condition is
\[ |L(j\omega)| \ge 21 \quad \text{for } 0 \le \omega \le 0.5. \]
In decibels this corresponds to \( 20\log_{10}21 \approx 26.4 \) dB of loop gain in the tracking band.
Problem 3 (Low-frequency gain and step error for a type 0 system). Consider \( P(s) = 1/(s + 2) \) and \( C(s) = K \), so that \( L(s) = K/(s + 2) \). The system is type 0. Determine the steady-state step error \( e_{\text{ss}} \) as a function of \( K \), and find the minimum \( K \) such that \( e_{\text{ss}} \le 0.05 \).
Solution: For a step input in unity feedback,
\[ e_{\text{ss}} = \lim_{s \to 0} \frac{1}{1 + L(s)}. \]
Here \( L(s) = K/(s + 2) \), so
\[ K_p = \lim_{s \to 0} L(s) = \frac{K}{2}. \]
Hence
\[ e_{\text{ss}} = \frac{1}{1 + K_p} = \frac{1}{1 + K/2}. \]
The requirement \( e_{\text{ss}} \le 0.05 \) implies \( 1/(1 + K/2) \le 0.05 \), or
\[ 1 + \frac{K}{2} \ge 20 \quad \Rightarrow \quad \frac{K}{2} \ge 19 \quad \Rightarrow \quad K \ge 38. \]
Thus, any \( K \ge 38 \) yields a steady-state step error not exceeding 5%. In the frequency domain this corresponds to a DC loop gain \( |L(0)| = K/2 \ge 19 \), consistent with the low-frequency gain interpretation.
Problem 4 (Relationship between low-frequency slope and system type). Let the loop transfer function be
\[ L(s) = \frac{K}{s^{n}} \prod_{k=1}^{p} \frac{1}{1 + \frac{s}{p_k}}, \]
where all \( p_k \) have positive real parts and \( n \) is a positive integer. Show that for small \( \omega \) (compared with the finite pole locations) the Bode magnitude of \( L(j\omega) \) has asymptotic slope \( -20n \) dB per decade.
Solution: For small \( \omega \), each factor satisfies
\[ \left|1 + \frac{j\omega}{p_k}\right| \approx 1, \]
so the magnitude is approximately
\[ |L(j\omega)| \approx \frac{K}{\omega^{n}}. \]
Taking logarithms in base 10 and multiplying by 20 yields the magnitude in decibels:
\[ 20\log_{10}|L(j\omega)| \approx 20\log_{10}K - 20n\log_{10}\omega. \]
If \( \omega \) is increased by one decade (i.e. \( \omega \) multiplied by 10), then \( \log_{10}\omega \) increases by 1, and the magnitude in decibels decreases by \( 20n \). Therefore the low-frequency asymptotic slope is \( -20n \) dB per decade, and \( n \) coincides with the system type defined by the number of integrators.
11. Summary
In this lesson we derived closed-loop frequency-domain expressions for reference tracking and error in a unity-feedback system, showing that \( Y(j\omega)/R(j\omega) = L(j\omega)/(1 + L(j\omega)) \) and \( E(j\omega)/R(j\omega) = 1/(1 + L(j\omega)) \). These formulas explicitly connect tracking performance to the loop transfer function \( L(s) \).
We reinterpreted system type and static error constants via the low-frequency behavior of \( L(s) \), leading to simple design rules: large low-frequency loop gain and higher system type yield smaller steady-state error for low-frequency references. Using the reverse triangle inequality, we obtained quantitative bounds that translate tracking specifications on \( |E(j\omega)/R(j\omega)| \) into inequalities on \( |L(j\omega)| \) in the tracking band.
Computational examples in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica illustrated how to evaluate these quantities for a simple robot joint model. In subsequent lessons, disturbance rejection, noise attenuation, and performance trade-offs will extend these ideas to the full frequency spectrum of the closed-loop system.
12. References
- Bode, H. W. (1945). Network Analysis and Feedback Amplifier Design. Van Nostrand.
- Nyquist, H. (1932). Regeneration theory. Bell System Technical Journal, 11(1), 126–147.
- Black, H. S. (1934). Stabilized feed-back amplifiers. Bell System Technical Journal, 13(1), 1–18.
- Freudenberg, J. S., & Looze, D. P. (1985). Right half plane poles and zeros and design tradeoffs in feedback systems. IEEE Transactions on Automatic Control, 30(6), 555–565.
- Zames, G. (1966). On the input–output stability of time-varying nonlinear feedback systems, Part I. IEEE Transactions on Automatic Control, 11(2), 228–238.
- Middleton, R. H., & Goodwin, G. C. (1988). Improved finite word length characteristics in digital control using delta operators. IEEE Transactions on Automatic Control, 33(1), 97–103.
- Doyle, J. C., Francis, B. A., & Tannenbaum, A. R. (1992). Feedback Control Theory. Macmillan.
- Åström, K. J., & Hägglund, T. (1995). PID Controllers: Theory, Design, and Tuning (2nd ed.). Instrument Society of America.
- Skogestad, S., & Postlethwaite, I. (2005). Multivariable Feedback Control: Analysis and Design (2nd ed.). Wiley.
- Franklin, G. F., Powell, J. D., & Emami-Naeini, A. (2015). Feedback Control of Dynamic Systems (7th ed.). Pearson.