Chapter 15: Nyquist Criterion and Stability in the Frequency Domain
Lesson 1: Nyquist Contour and Mapping Principles
This lesson introduces the Nyquist contour in the complex \( s \)-plane and the mapping of this contour through transfer functions. We build the mathematical foundations (argument principle and contour mappings) that will be used in subsequent lessons to derive the Nyquist stability criterion for feedback systems.
1. Motivation and Closed-Loop Characteristic Function
Consider a standard unity-feedback single-input single-output (SISO) control loop with open-loop transfer function \( L(s) = G(s)C(s) \), where \( G(s) \) is the plant and \( C(s) \) is the controller. The closed-loop transfer function from reference to output is
\[ T(s) = \frac{L(s)}{1 + L(s)}. \]
The closed-loop poles are the roots of the characteristic equation
\[ 1 + L(s) = 0. \]
Define the characteristic function \( F(s) = 1 + L(s) \). Stability of the linear time-invariant (LTI) closed-loop system is determined by the locations of the zeros of \( F(s) \) in the complex plane (equivalently, the poles of \( T(s) \)).
Nyquist analysis is based on the following idea: instead of solving \( F(s) = 0 \) explicitly, we study how the complex function \( F(s) \) maps a special closed contour in the \( s \)-plane (the Nyquist contour) into the \( F(s) \)-plane. The number of encirclements of the origin by this image is related to the number of zeros and poles of \( F(s) \) inside the contour.
This viewpoint relies on basic complex function theory and the argument principle, which we summarize in the next sections in a control-oriented way (without assuming a full complex analysis course).
2. Definition of the Nyquist Contour
Let \( L(s) \) be a proper rational transfer function with no poles on the imaginary axis. We are interested in the closed-loop stability of the unity-feedback system. The Nyquist contour is a closed path in the \( s \)-plane that encloses the entire right half-plane (RHP), where potential unstable poles may lie.
For a sufficiently large radius \( R > 0 \), the standard Nyquist contour \( \Gamma_R \) consists of:
- The imaginary axis segment from \( s = -\mathrm{j}R \) to \( s = +\mathrm{j}R \), traversed upward.
- The right-half-plane semicircle \( s(\theta) = R e^{\mathrm{j}\theta} \) with \( \theta \) decreasing from \( +\frac{\pi}{2} \) to \( -\frac{\pi}{2} \), i.e., a clockwise arc closing the contour.
As \( R \to \infty \), the contour is denoted simply by \( \Gamma \). For strictly proper transfer functions, the contribution of the infinite semicircle typically collapses to the point \( L(\infty) = 0 \).
Formally, we can parameterize:
\[ \Gamma_R = \Gamma_1 \cup \Gamma_2, \]
\[ \Gamma_1:\; s(\omega) = \mathrm{j}\omega,\quad -R \le \omega \le R, \]
\[ \Gamma_2:\; s(\theta) = R e^{\mathrm{j}\theta},\quad \frac{\pi}{2} \ge \theta \ge -\frac{\pi}{2}. \]
The contour orientation is chosen such that the interior (the RHP) is always to the left of the direction of traversal. This orientation will be crucial when counting encirclements.
When \( L(s) \) has poles on the imaginary axis, one modifies the contour locally by introducing small semicircular detours of radius \( \varepsilon \) around those poles, but the global idea of enclosing the RHP remains intact. Those details will be important in later lessons.
3. Mapping of the Nyquist Contour and Argument Principle
Let \( F(s) \) be a complex-valued function that is meromorphic (rational) on and inside the Nyquist contour \( \Gamma \), with no zeros or poles on \( \Gamma \) itself. Denote by \( Z \) the number of zeros and \( P \) the number of poles of \( F(s) \) inside the contour (counted with multiplicity).
The argument principle states that the net change of the argument of \( F(s) \) when \( s \) traverses the contour once in the positive direction is related to \( Z \) and \( P \) by
\[ \Delta_{\Gamma} \arg F(s) = 2\pi (Z - P). \]
Geometrically, the net change in argument corresponds to the number of net encirclements of the origin by the curve \( F(\Gamma) \) in the complex plane:
\[ N = Z - P, \]
where \( N \) is the net number of clockwise encirclements of the origin (clockwise counted as positive by standard Nyquist convention; some texts use the opposite sign convention).
For closed-loop stability we are interested in \( F(s) = 1 + L(s) \). Then:
- Zeros of \( F(s) \) are the closed-loop poles (solutions of \( 1 + L(s) = 0 \)).
- Poles of \( F(s) \) are the open-loop poles of \( L(s) \).
Nyquist analysis uses the mapping of \( L(s) \) (or equivalently \( F(s) \)) of the Nyquist contour \( \Gamma \) to infer \( Z \) from the known \( P \), without directly solving the characteristic equation. The full stability criterion is developed in the next lesson; here our focus is the mapping concepts and the shape of the contour in the \( L(s) \)-plane.
flowchart TD
A["s-plane Nyquist contour Gamma"] --> B["Evaluate L(s) on Gamma"]
B --> C["L(Gamma) in complex plane"]
C --> D["Compute net encirclements of -1 point"]
D --> E["Relate encirclements to closed-loop poles via argument principle"]
4. Nyquist Plot as Image of the Imaginary Axis
For strictly proper rational transfer functions \( L(s) \), the contribution of the infinite semicircle of the contour often collapses to a single point \( L(\infty) = 0 \). In such cases, the essential part of the Nyquist plot comes from the mapping of the imaginary axis:
\[ L(\mathrm{j}\omega),\quad -\infty < \omega < +\infty. \]
Because \( L(s) \) is real-rational (its coefficients are real), we have the symmetry property
\[ L(-\mathrm{j}\omega) = \overline{L(\mathrm{j}\omega)}. \]
Therefore, the locus of \( L(\mathrm{j}\omega) \) for \( \omega \ge 0 \) determines the entire Nyquist plot (the negative frequencies give the complex conjugate reflection).
In practice, many software tools refer to the Nyquist plot as the parametric curve \( \omega \mapsto L(\mathrm{j}\omega) \) for \( \omega \ge 0 \), with the understanding that the full contour also includes the conjugate branch and the high-frequency limit.
For a robotic joint driven by a DC motor (single axis of a manipulator), a common linear model is
\[ G(s) = \frac{K}{Js^2 + Bs}, \]
where \( J \) is the equivalent inertia, \( B \) the viscous damping, and \( K \) a gain combining motor torque constant and gear ratio. For a proportional controller \( C(s) = K_p \), the loop transfer function is
\[ L(s) = \frac{K_p K}{Js^2 + Bs}. \]
Its Nyquist plot is the locus of \( L(\mathrm{j}\omega) \) as \( \omega \) varies, and it captures how the loop gain and phase change with frequency. This will be used in later lessons to judge stability and robustness of the robot joint controller.
5. Algorithmic Construction of a Nyquist Plot
Numerically, we approximate the image of the Nyquist contour by sampling a finite set of frequencies. The general procedure for a proper rational \( L(s) \) is:
- Choose a finite frequency grid \( \omega_k \), for example logarithmically spaced.
- Evaluate \( L(\mathrm{j}\omega_k) \) as complex numbers.
- Construct the conjugate branch \( L(-\mathrm{j}\omega_k) = \overline{L(\mathrm{j}\omega_k)} \).
- Include the limits as \( \omega \to 0 \) and \( \omega \to \infty \) if they exist.
- Connect the sampled points in correct orientation to approximate the continuous curve.
flowchart TD
S["Define transfer function L(s)"] --> G1["Select frequency grid {omega_k}"]
G1 --> G2["Compute points L(j*omega_k)"]
G2 --> G3["Build conjugate branch conj(L(j*omega_k))"]
G3 --> G4["Add low/high frequency limits (if applicable)"]
G4 --> G5["Plot complex points Re vs Im to approximate Nyquist curve"]
This discrete approximation underlies the numerical Nyquist plots in control libraries used for robotics and other applications.
6. Python Implementation (Nyquist Contour Sampling)
In Python, a common control-oriented stack for robotics and general
control includes
numpy, scipy, matplotlib, and the
python-control library (which also integrates with
roboticstoolbox-python for manipulator models). Below we
compute and plot a Nyquist curve for the robotic joint model
\( L(s) = \dfrac{K_p K}{Js^2 + Bs} \).
import numpy as np
import matplotlib.pyplot as plt
# Robot joint parameters (example)
J = 0.01 # inertia
B = 0.1 # viscous damping
K = 1.0 # motor/gear gain
Kp = 5.0 # proportional controller gain
def L_of_s(s):
return Kp * K / (J * s**2 + B * s)
# Frequency grid (rad/s)
w = np.logspace(-2, 3, 400) # 0.01 to 1000 rad/s
# Evaluate L(j w)
Ljw = L_of_s(1j * w)
# Build Nyquist points (positive and negative frequencies)
L_pos = Ljw
L_neg = np.conj(Ljw[::-1])
nyquist_points = np.concatenate([L_pos, L_neg])
plt.figure()
plt.plot(nyquist_points.real, nyquist_points.imag)
plt.axhline(0.0, linestyle="--")
plt.axvline(-1.0, linestyle="--") # reference for stability analysis
plt.xlabel("Re{L(j*omega)}")
plt.ylabel("Im{L(j*omega)}")
plt.title("Nyquist Curve for Robot Joint with P Control")
plt.grid(True)
plt.axis("equal")
plt.show()
Using python-control, the same can be done more compactly:
import control as ctrl
J = 0.01; B = 0.1; K = 1.0; Kp = 5.0
s = ctrl.TransferFunction.s
G = K / (J * s**2 + B * s)
C = Kp
L = C * G
# Nyquist plot (uses similar sampling internally)
ctrl.nyquist_plot(L)
In multi-axis robotic applications, each joint can often be approximated
by a SISO transfer function like G. Nyquist plots help tune
joint-level controllers before integrating them into a full manipulator
model.
7. C++ Implementation (Nyquist Sampling with Eigen / ROS Ecosystem)
In C++, numerical linear algebra is commonly handled with
Eigen, and robotics frameworks often rely on ROS (Robot
Operating System), ros_control, and kinematics libraries
such as Orocos KDL. Nyquist plots are usually generated offline (e.g.,
in a tuning tool) but can also be computed inside a C++ utility. Below,
we generate Nyquist samples for the same loop transfer function using
std::complex and std::vector.
#include <iostream>
#include <vector>
#include <complex>
#include <cmath>
int main() {
using std::complex;
using std::vector;
double J = 0.01;
double B = 0.1;
double K = 1.0;
double Kp = 5.0;
auto L_of_s = [&] (complex<double> s) {
return Kp * K / (J * s * s + B * s);
};
// Log-spaced frequency grid
int N = 400;
double w_min = 1e-2;
double w_max = 1e3;
vector<complex<double> nyquist_points;
nyquist_points.reserve(2 * N);
// Positive frequencies
for (int k = 0; k < N; ++k) {
double alpha = static_cast<double>(k) / (N - 1);
double w = w_min * std::pow(w_max / w_min, alpha);
complex<double> s(0.0, w);
nyquist_points.push_back(L_of_s(s));
}
// Negative frequencies (conjugate symmetry)
for (int k = N - 1; k >= 0; --k) {
nyquist_points.push_back(std::conj(nyquist_points[k]));
}
// At this point, nyquist_points can be exported to a file and plotted
// with gnuplot or a visualization tool integrated into a robotics tuning GUI.
for (const auto &z : nyquist_points) {
std::cout << z.real() << " " << z.imag() << "\n";
}
return 0;
}
In a ROS-based robotic system, such a computation could be packaged into
an offline tool that reads identified joint models and outputs Nyquist
data to guide controller tuning in ros_control.
8. Java Implementation (Nyquist Sampling with Apache Commons Math)
Java-based robotics platforms (for example in educational robotics or industrial monitoring front-ends) can leverage numerical libraries such as Apache Commons Math for complex arithmetic. Below is a simple Java method to compute Nyquist points; plotting would be done via a Java plotting library or exported to CSV for further processing.
import org.apache.commons.math3.complex.Complex;
import java.util.ArrayList;
import java.util.List;
public class NyquistExample {
static double J = 0.01;
static double B = 0.1;
static double K = 1.0;
static double Kp = 5.0;
static Complex L_of_s(Complex s) {
Complex numerator = new Complex(Kp * K, 0.0);
Complex denominator = s.multiply(s).multiply(J).add(s.multiply(B));
return numerator.divide(denominator);
}
public static void main(String[] args) {
int N = 400;
double wMin = 1e-2;
double wMax = 1e3;
List<Complex> nyquistPoints = new ArrayList<>(2 * N);
// Positive frequencies
for (int k = 0; k < N; ++k) {
double alpha = (double) k / (double) (N - 1);
double w = wMin * Math.pow(wMax / wMin, alpha);
Complex s = new Complex(0.0, w);
nyquistPoints.add(L_of_s(s));
}
// Conjugate branch
for (int k = N - 1; k >= 0; --k) {
nyquistPoints.add(nyquistPoints.get(k).conjugate());
}
// Export or plot results
for (Complex z : nyquistPoints) {
System.out.println(z.getReal() + "," + z.getImaginary());
}
}
}
In Java-based control systems for robotics (for example, some FRC robotics frameworks with Java APIs), such Nyquist computations can assist in tuning joint control loops or drive controllers by visualizing loop behavior.
9. MATLAB/Simulink Implementation (Control System Toolbox)
MATLAB and Simulink are standard tools in control and robotics. The
Control System Toolbox provides a direct nyquist command,
and the Robotics System Toolbox can be used to obtain robot dynamics
models that are then linearized around operating points and analyzed via
Nyquist plots.
% Robot joint model parameters
J = 0.01;
B = 0.1;
K = 1.0;
Kp = 5.0;
s = tf('s');
G = K / (J * s^2 + B * s);
C = Kp;
L = C * G;
figure;
nyquist(L);
grid on;
title('Nyquist Plot of Robot Joint with P Control');
% Example: obtaining a linearized joint model from a robotics toolbox model
% (pseudo-code; requires Robotics System Toolbox and a defined robot model)
% robot = loadrobot('kinovaGen3'); % example robot
% q0 = homeConfiguration(robot);
% linSys = linearize(robotModelToSimulink(robot), q0); % conceptual step
% nyquist(linSys);
In Simulink, the loop transfer function can be constructed using standard blocks (gain, transfer function) and analyzed with a Linear Analysis Tool to automatically generate Nyquist plots for closed-loop robot joint controllers.
10. Wolfram Mathematica Implementation
Wolfram Mathematica includes symbolic and numerical tools for control
analysis. The
TransferFunctionModel and
NyquistPlot functions directly implement the mapping from
the Nyquist contour to the complex plane.
J = 0.01;
B = 0.1;
K = 1.0;
Kp = 5.0;
s = ComplexExpand[I*w] /. w ->. w; (* symbolic placeholder *)
G = TransferFunctionModel[K/(J*s^2 + B*s), s];
C = Kp;
L = C*G;
NyquistPlot[L, {w, 0.01, 1000},
AxesLabel -> {"Re", "Im"},
PlotRange -> All,
GridLines -> Automatic,
PlotLegends -> {"Loop Transfer Function"}
]
Symbolic capabilities can be used to derive expressions for \( L(\mathrm{j}\omega) \) and study limiting behavior (e.g., \( \omega \to 0 \) and \( \omega \to \infty \)) analytically, complementing the numerical Nyquist plots.
11. Problems and Solutions
Problem 1 (Definition of the Nyquist Contour): Let \( L(s) \) be a proper rational transfer function with no poles on the imaginary axis. Give a precise definition of the Nyquist contour \( \Gamma_R \) that encloses the right half-plane, and show that as \( R \to \infty \), the contour encloses all possible right-half-plane poles of \( L(s) \).
Solution:
For any \( R > 0 \), define the contour
\[ \Gamma_R = \Gamma_1 \cup \Gamma_2 \]
\[ \Gamma_1:\; s(\omega) = \mathrm{j}\omega,\quad -R \le \omega \le R, \]
\[ \Gamma_2:\; s(\theta) = R e^{\mathrm{j}\theta},\quad \frac{\pi}{2} \ge \theta \ge -\frac{\pi}{2}. \]
The contour starts at \( s = -\mathrm{j}R \), moves upward along the imaginary axis to \( s = +\mathrm{j}R \), then follows the semicircle \( \Gamma_2 \) back to \( s = -\mathrm{j}R \). For any finite \( R \), the contour encloses the set \( \{s \in \mathbb{C} : \Re(s) > 0, |s| < R\} \). As \( R \to \infty \), the contour encloses the entire right half-plane \( \Re(s) > 0 \), hence all right-half-plane poles of \( L(s) \).
Problem 2 (Nyquist Locus for a First-Order System): Consider the loop transfer function \( L(s) = \dfrac{K}{s + a} \) with \( K > 0 \), \( a > 0 \). Derive a parametric expression for \( L(\mathrm{j}\omega) \) and sketch its path in the complex plane as \( \omega \) goes from \( 0 \) to \( \infty \).
Solution:
We have
\[ L(\mathrm{j}\omega) = \frac{K}{a + \mathrm{j}\omega} = \frac{K(a - \mathrm{j}\omega)}{a^2 + \omega^2} = \frac{Ka}{a^2 + \omega^2} - \mathrm{j}\frac{K\omega}{a^2 + \omega^2}. \]
Therefore the real and imaginary parts are
\[ x(\omega) = \Re\{L(\mathrm{j}\omega)\} = \frac{Ka}{a^2 + \omega^2},\quad y(\omega) = \Im\{L(\mathrm{j}\omega)\} = -\frac{K\omega}{a^2 + \omega^2}. \]
As \( \omega \to 0 \), we obtain \( x \to \frac{K}{a} \) and \( y \to 0 \). As \( \omega \to \infty \), both \( x \) and \( y \) tend to \( 0 \), with \( y(\omega) < 0 \) for \( \omega > 0 \). Thus the Nyquist locus for positive frequencies is a curve starting at \( \left(\frac{K}{a}, 0\right) \) and approaching the origin from below the real axis, remaining in the right half of the complex plane.
Problem 3 (Contribution of the Infinite Semicircle): Let \( L(s) \) be strictly proper of relative degree \( n_r \ge 2 \) (the degree of the denominator exceeds the degree of the numerator by at least 2). Show that \( L(s) \to 0 \) as \( |s| \to \infty \) along the semicircle \( s = R e^{\mathrm{j}\theta} \), and explain why the image of the infinite semicircle in the Nyquist plot collapses to the origin.
Solution:
A strictly proper rational transfer function can be written as
\[ L(s) = \frac{b_0 s^m + b_1 s^{m-1} + \cdots + b_m}{a_0 s^n + a_1 s^{n-1} + \cdots + a_n}, \]
with \( n > m \) and relative degree \( n_r = n - m \ge 2 \). For \( s = R e^{\mathrm{j}\theta} \) and \( R \to \infty \), we can factor out \( s^n \):
\[ L(s) = \frac{s^m (b_0 + b_1 s^{-1} + \cdots + b_m s^{-m})}{s^n (a_0 + a_1 s^{-1} + \cdots + a_n s^{-n})} = s^{-n_r} \frac{b_0 + \mathcal{O}(s^{-1})}{a_0 + \mathcal{O}(s^{-1})}. \]
Hence
\[ |L(s)| \approx \frac{|b_0|}{|a_0|} |s|^{-n_r} = \frac{|b_0|}{|a_0|} R^{-n_r}, \]
which tends to zero as \( R \to \infty \) since \( n_r \ge 2 \). Thus the image of the infinite semicircle \( \Gamma_2 \) under \( L(s) \) shrinks to the origin, and the Nyquist plot effectively connects the point \( L(\mathrm{j}R) \) to \( 0 \) and back to \( L(-\mathrm{j}R) \) as \( R \to \infty \).
Problem 4 (Robot Joint Example): For the robotic joint model \( L(s) = \dfrac{K_p K}{Js^2 + Bs} \) with \( J > 0, B > 0, K_p K > 0 \), determine the limits \( L(0^+) \) and \( L(\mathrm{j}\omega) \) as \( \omega \to \infty \), and describe how the Nyquist curve starts and ends in the complex plane.
Solution:
For \( s = \mathrm{j}\omega \), we have
\[ L(\mathrm{j}\omega) = \frac{K_p K}{-J\omega^2 + \mathrm{j}B\omega}. \]
As \( \omega \to 0^+ \), the denominator behaves like \( B\mathrm{j}\omega \), so
\[ L(\mathrm{j}\omega) \approx \frac{K_p K}{\mathrm{j}B\omega} = -\mathrm{j} \frac{K_p K}{B\omega}. \]
Therefore \( |L(\mathrm{j}\omega)| \to \infty \) and the phase tends to \( -\frac{\pi}{2} \); the Nyquist curve starts at infinity on the negative imaginary axis. As \( \omega \to \infty \), the denominator is dominated by \( -J\omega^2 \) and
\[ L(\mathrm{j}\omega) \approx -\frac{K_p K}{J\omega^2} \to 0^- \]
along the negative real axis. Hence, for positive frequencies, the Nyquist curve moves from infinity on the negative imaginary axis towards the origin, approaching it along the negative real axis. The negative-frequency branch is the complex conjugate, giving a symmetric curve.
12. Summary
In this lesson we introduced the Nyquist contour as a closed path surrounding the right half-plane, and we studied how a transfer function (in particular, the characteristic function \( F(s) = 1 + L(s) \)) maps this contour into the complex plane. Using the argument principle, we related the net encirclements of the origin by the image of the contour to the number of zeros and poles enclosed. We emphasized how, for strictly proper rational transfer functions, the contribution of the infinite semicircle collapses to the origin, so that the Nyquist plot can be constructed largely from the frequency response \( L(\mathrm{j}\omega) \).
We also illustrated, through a robotic joint example, how Nyquist plots arise in practice and provided implementations in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica that compute discrete approximations of the Nyquist contour mapping. In the next lesson, we will use these mapping principles to formulate and prove the Nyquist stability criterion for feedback systems.
13. References
- Nyquist, H. (1932). Regeneration theory. Bell System Technical Journal, 11(1), 126–147.
- Bode, H.W. (1945). Network Analysis and Feedback Amplifier Design. Van Nostrand, New York. (Classical frequency-domain foundations and Nyquist-related analysis.)
- Black, H.S. (1934). Stabilized feedback amplifiers. Electrical Engineering, 53(1), 114–120.
- Zames, G. (1966). On the input-output stability of time-varying nonlinear feedback systems Part I: Conditions derived using concepts of generalized gain. IEEE Transactions on Automatic Control, 11(2), 228–238.
- Truxal, J.G. (1955). Automatic Feedback Control System Synthesis. McGraw–Hill.
- MacColl, L.A. (1945). Fundamental theory of servomechanisms. Bell System Technical Journal, 24(3), 405–425.
- Desoer, C.A., & Kuh, E.S. (1969). Basic Circuit Theory. McGraw–Hill.
- Vidyasagar, M. (1985). Control System Synthesis: A Factorization Approach. MIT Press. (For a modern rigorous complex analysis perspective on feedback and stability.)
- 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.