Chapter 11: Stability Analysis of Linear Systems

Lesson 2: Pole Locations and Stability Regions in the s-Plane

This lesson formalizes how the locations of poles in the complex \( s \)-plane determine qualitative and quantitative stability properties of continuous-time LTI systems. We connect the geometry of \( s=\sigma + j\omega \) to exponential mode behavior, derive stability regions (left-half plane, imaginary axis, right-half plane), and provide rigorous proofs for the classical pole-location stability conditions (with careful distinction between BIBO stability and zero-input/asymptotic behavior).

1. Prerequisites and Learning Outcomes

Prerequisites (from earlier chapters): complex numbers and the representation \( s=\sigma + j\omega \), Laplace transform and inverse transform, and the definition of poles as the roots of a transfer function denominator.

After this lesson, you will be able to:

  • Relate \( \Re(s) \) to exponential growth/decay and \( \Im(s) \) to oscillation.
  • Classify stability types from pole locations (stable/unstable/marginal) in the \( s \)-plane.
  • Prove the pole-location condition for BIBO stability of rational, causal LTI transfer functions.
  • Compute poles numerically and algorithmically in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica.

2. Geometry of the s-Plane and Exponential Modes

Consider the complex variable \( s=\sigma + j\omega \). A fundamental building block of linear dynamics is the exponential term \( e^{st} \). Using Euler’s identity:

\[ e^{(\sigma + j\omega)t} = e^{\sigma t}\left(\cos(\omega t) + j\sin(\omega t)\right). \]

The envelope \( e^{\sigma t} \) is controlled by \( \sigma=\Re(s) \):

  • If \( \sigma < 0 \), the mode decays exponentially.
  • If \( \sigma = 0 \), the mode has constant magnitude (pure oscillation).
  • If \( \sigma > 0 \), the mode grows exponentially.

Lemma (growth/decay rate from the real part). For \( t \ge 0 \):

\[ \left|e^{(\sigma + j\omega)t}\right| = \left|e^{\sigma t}\right|\cdot \left|\cos(\omega t)+j\sin(\omega t)\right| = e^{\sigma t}. \]

Proof. The complex sinusoid has unit magnitude: \( \left|\cos(\omega t)+j\sin(\omega t)\right|=\sqrt{\cos^2(\omega t)+\sin^2(\omega t)}=1 \), hence the magnitude is \( e^{\sigma t} \). If \( \sigma < 0 \), then \( e^{\sigma t} \to 0 \) as \( t \to \infty \); if \( \sigma > 0 \), it diverges. ■

flowchart LR
  S["s = sigma + j*omega"] --> R["sigma (real part)"]
  S --> I["omega (imag part)"]

  R --> LHP["sigma < 0  : decaying envelope e^(sigma t)"]
  R --> AX["sigma = 0  : constant envelope"]
  R --> RHP["sigma > 0  : growing envelope e^(sigma t)"]

  I --> OSC["omega != 0  : oscillation at frequency omega/(2*pi)"]
  I --> NOD["omega = 0  : non-oscillatory (real exponential)"]
        

3. Poles, Natural Response, and the Impulse Response Decomposition

For a causal, continuous-time LTI system described by a proper rational transfer function:

\[ G(s) = \frac{Y(s)}{U(s)} = \frac{N(s)}{D(s)}, \quad \deg(N) \le \deg(D), \quad D(s) \neq 0. \]

The system poles are the roots of \( D(s)=0 \). Assume for now that all poles are distinct (simple poles). Then a partial-fraction expansion gives:

\[ G(s) = \sum_{k=1}^{n}\frac{r_k}{s-p_k}, \quad D(p_k)=0, \]

where \( p_k \) are poles and \( r_k \) are residues. The impulse response \( h(t) \) is the inverse Laplace transform of \( G(s) \):

\[ h(t) = \mathcal{L}^{-1}\{G(s)\}(t) = \sum_{k=1}^{n} r_k e^{p_k t}\,u(t), \]

where \( u(t) \) is the unit step. Therefore, each pole contributes a mode \( e^{p_k t} \). By Section 2, the sign of \( \Re(p_k) \) determines whether that mode decays, persists, or grows.

Repeated poles. If \( p \) is a pole of multiplicity \( m \ge 2 \), terms appear as:

\[ \frac{a_1}{s-p} + \frac{a_2}{(s-p)^2} + \cdots + \frac{a_m}{(s-p)^m} \quad → \quad \left(a_1 + a_2 t + \cdots + a_m\frac{t^{m-1}}{(m-1)!}\right)e^{pt}u(t). \]

This polynomial-in-\( t \) factor is crucial for stability on the imaginary axis: even when \( \Re(p)=0 \), repeated poles introduce growth like \( t^{m-1} \).

4. Stability Regions in the s-Plane

We summarize pole-location regions for continuous-time systems:

  • Open left-half plane (LHP): \( \Re(s) < 0 \)
  • Imaginary axis: \( \Re(s) = 0 \)
  • Open right-half plane (RHP): \( \Re(s) > 0 \)

In this course, we emphasize two notions introduced in Lesson 1:

  • BIBO stability (input-output): bounded input produces bounded output.
  • Asymptotic stability (zero-input / natural decay): the natural modes decay to zero.

Key result (rational, causal LTI):

  • BIBO stable if and only if all poles satisfy \( \Re(p_k) < 0 \).
  • Unstable if any pole satisfies \( \Re(p_k) > 0 \), or if there is any repeated pole on the imaginary axis \( \Re(p_k)=0 \) with multiplicity \( \ge 2 \).
  • Marginal (non-asymptotic) behavior can occur when poles are in the LHP except for simple poles on the imaginary axis; the response can remain bounded but does not decay. (This does not satisfy BIBO stability for a causal rational transfer function, as shown in Section 5.)
flowchart TD
  A["Given poles p_k of D(s)=0"] --> B{"Any pole with Re(p_k) > 0 ?"}
  B -->|yes| U1["Unstable: \nexponential growth"]
  B -->|no| C{"Any pole with Re(p_k) = 0 ?"}
  C -->|no| S1["All Re(p_k) < 0 : \nBIBO stable and asymptotically stable"]
  C -->|yes| D{"Any imaginary-axis pole repeated? \n(mult > 1)"}
  D -->|yes| U2["Unstable: \npolynomial growth (t^(m-1))"]
  D -->|no| M1["Marginal: bounded oscillations \nmay occur; not asymptotic"]
        

5. Proof: BIBO Stability and Poles in the Open Left-Half Plane

The standard characterization of BIBO stability for continuous-time LTI systems is:

Theorem 1 (BIBO stability via impulse response).

A causal LTI system with impulse response \( h(t) \) is BIBO stable if and only if \( \int_{0}^{\infty} |h(t)|\,dt < \infty \).

Proof. For a causal LTI system, the output is the convolution:

\[ y(t) = (h*u)(t) = \int_{0}^{t} h(\tau)\,u(t-\tau)\,d\tau. \]

If the input is bounded, \( |u(t)| \le M \), then:

\[ |y(t)| \le \int_{0}^{t} |h(\tau)|\,|u(t-\tau)|\,d\tau \le M\int_{0}^{t} |h(\tau)|\,d\tau \le M\int_{0}^{\infty} |h(\tau)|\,d\tau. \]

Thus, if \( \int_{0}^{\infty}|h(\tau)|d\tau < \infty \), then \( y(t) \) is bounded for all bounded inputs (BIBO stable). Conversely, if the integral diverges, one can construct bounded inputs that align in sign with \( h(\tau) \) over successive intervals to make the convolution grow without bound. ■

Theorem 2 (pole-location condition for rational causal LTI).

Let \( G(s)=N(s)/D(s) \) be a proper rational transfer function with all poles strictly in the LHP: \( \Re(p_k) < 0 \). Then the corresponding causal LTI system is BIBO stable. If any pole satisfies \( \Re(p_k) \ge 0 \), the system is not BIBO stable.

Proof (sufficiency). Assume distinct poles for clarity. From Section 3:

\[ h(t) = \sum_{k=1}^{n} r_k e^{p_k t}u(t). \]

For \( t \ge 0 \) and \( \Re(p_k) = \sigma_k < 0 \), we have \( |e^{p_k t}| = e^{\sigma_k t} \). Hence:

\[ |h(t)| \le \sum_{k=1}^{n} |r_k|\,e^{\sigma_k t}. \]

Integrate both sides:

\[ \int_{0}^{\infty} |h(t)|\,dt \le \sum_{k=1}^{n}|r_k|\int_{0}^{\infty} e^{\sigma_k t}\,dt = \sum_{k=1}^{n}|r_k|\left(\frac{1}{-\sigma_k}\right) < \infty. \]

By Theorem 1, the system is BIBO stable. ■

Proof (necessity).

  • If a pole has \( \Re(p)=\sigma > 0 \), then \( h(t) \) contains a term proportional to \( e^{\sigma t} \), making \( \int_{0}^{\infty}|h(t)|dt \) diverge.
  • If a pole lies on the imaginary axis \( p=j\omega \), then \( |e^{j\omega t}|=1 \), so any nonzero sinusoidal component yields \( \int_{0}^{\infty}|h(t)|dt = \infty \).
  • If a pole on the imaginary axis is repeated, \( h(t) \) contains a factor \( t^{m-1} \), which also makes the integral diverge.

Therefore BIBO stability fails whenever any pole satisfies \( \Re(p) \ge 0 \). ■

6. Quantifying “How Stable”: A Pole-Based Stability Margin

Beyond “stable vs unstable,” pole locations quantify decay rates. Define the spectral abscissa (pole-based stability margin indicator):

\[ \alpha \triangleq \max_k \Re(p_k). \]

Interpretations:

  • If \( \alpha < 0 \), all modes decay; more negative \( \alpha \) implies faster worst-case decay.
  • If \( \alpha = 0 \), the system is on the stability boundary (imaginary-axis pole exists).
  • If \( \alpha > 0 \), at least one mode grows exponentially.

For a single mode \( e^{(\sigma + j\omega)t} \) with \( \sigma < 0 \), the envelope satisfies:

\[ e^{\sigma t} = e^{-|\sigma| t}. \]

A useful “time constant-like” quantity for that mode is \( T = 1/|\sigma| \), because \( e^{-t/T} \) decays to \( e^{-1} \) at \( t=T \).

7. Computational Implementations

Practical stability analysis begins by computing the poles (roots of \( D(s) \)). Below are consistent implementations that: (i) compute poles, (ii) classify stability region membership, and (iii) compute \( \alpha=\max \Re(p_k) \).

7.1 Python (SciPy / NumPy, optional: python-control)

Relevant libraries: numpy, scipy.signal, sympy, optionally control.


import numpy as np

def poles_from_den(den_coeffs):
    # den_coeffs: highest power first, e.g. s^2 + 3s + 2 => [1, 3, 2]
    return np.roots(np.array(den_coeffs, dtype=float))

def classify_poles(poles, eps=1e-9):
    # Returns (label, alpha)
    re_parts = np.real(poles)
    alpha = float(np.max(re_parts)) if len(poles) > 0 else float("-inf")

    any_rhp = np.any(re_parts > eps)
    any_axis = np.any(np.abs(re_parts) <= eps)

    if any_rhp:
        return "Unstable (RHP pole exists)", alpha

    if not any_axis:
        return "BIBO stable and asymptotically stable (all poles in LHP)", alpha

    # If we reach here: no RHP poles, but at least one on the axis (within eps).
    # Detect repeated/near-repeated axis poles by clustering.
    axis_poles = [p for p in poles if abs(np.real(p)) <= eps]
    repeated_axis = False
    for i in range(len(axis_poles)):
        for j in range(i+1, len(axis_poles)):
            if abs(axis_poles[i] - axis_poles[j]) < 1e-6:
                repeated_axis = True

    if repeated_axis:
        return "Unstable (repeated imaginary-axis pole)", alpha

    return "Marginal (simple imaginary-axis pole(s); not asymptotic; not BIBO)", alpha


# Example transfer function denominator: D(s)=s^3 + 2s^2 + 2s + 1
den = [1, 2, 2, 1]
p = poles_from_den(den)
label, alpha = classify_poles(p)

print("Poles:", p)
print("Classification:", label)
print("Pole-based stability margin alpha = max Re(p):", alpha)

# Optional: use scipy.signal for transfer function objects
from scipy import signal
num = [1]             # N(s)=1
sys = signal.TransferFunction(num, den)
print("SciPy poles:", sys.poles)
      

7.2 C++ (Companion Matrix + Eigen)

Relevant libraries: Eigen (linear algebra), optionally Boost for utilities. The idea: roots of \( D(s) \) are eigenvalues of the companion matrix. This uses only linear algebra (already covered in Chapter 2).


#include <iostream>
#include <vector>
#include <complex>
#include <Eigen/Dense>

using cd = std::complex<double>;
using Mat = Eigen::MatrixXd;

std::vector<cd> companion_roots(const std::vector<double>& den) {
    // den = [a0, a1, ..., an] for a0*s^n + a1*s^(n-1) + ... + an
    // Assume a0 != 0 and degree n >= 1
    const int n = (int)den.size() - 1;
    double a0 = den[0];

    // Build companion matrix C of size n x n
    Mat C = Mat::Zero(n, n);

    // Subdiagonal ones
    for (int i = 1; i < n; ++i) {
        C(i, i-1) = 1.0;
    }

    // Last column: -[a_n/a0, a_{n-1}/a0, ..., a_1/a0]^T
    // Note: indexing carefully: den[0]=a0, den[1]=a1, ..., den[n]=an
    for (int i = 0; i < n; ++i) {
        C(i, n-1) = -den[n - i] / a0; // maps to correct reversal
    }

    Eigen::EigenSolver<Mat> es(C);
    Eigen::VectorXcd eig = es.eigenvalues();

    std::vector<cd> roots;
    roots.reserve(n);
    for (int i = 0; i < n; ++i) roots.push_back(eig(i));
    return roots;
}

int main() {
    // Example: D(s)=s^3 + 2s^2 + 2s + 1
    std::vector<double> den = {1, 2, 2, 1};
    auto poles = companion_roots(den);

    double alpha = -1e300;
    bool any_rhp = false;
    bool any_axis = false;
    const double eps = 1e-9;

    std::cout << "Poles:" << std::endl;
    for (auto p : poles) {
        std::cout << p << std::endl;
        alpha = std::max(alpha, p.real());
        if (p.real() > eps) any_rhp = true;
        if (std::abs(p.real()) <= eps) any_axis = true;
    }

    std::cout << "alpha = max Re(p) = " << alpha << std::endl;
    if (any_rhp) {
        std::cout << "Classification: Unstable (RHP pole exists)" << std::endl;
    } else if (!any_axis) {
        std::cout << "Classification: BIBO stable (all poles in LHP)" << std::endl;
    } else {
        std::cout << "Classification: Boundary case (imag-axis pole detected)" << std::endl;
    }
    return 0;
}
      

7.3 Java (Apache Commons Math Polynomial Solver)

Relevant libraries: Apache Commons Math (complex numbers, polynomial solvers).


import org.apache.commons.math3.analysis.solvers.LaguerreSolver;
import org.apache.commons.math3.complex.Complex;

public class PoleStability {
    public static void main(String[] args) {
        // D(s) = s^3 + 2 s^2 + 2 s + 1  => coefficients low-to-high for Laguerre: [1,2,2,1]
        double[] coeffLowToHigh = new double[] {1.0, 2.0, 2.0, 1.0};

        LaguerreSolver solver = new LaguerreSolver();
        Complex[] roots = solver.solveAllComplex(coeffLowToHigh, 0.0);

        double eps = 1e-9;
        double alpha = -1e300;
        boolean anyRHP = false;
        boolean anyAxis = false;

        System.out.println("Poles:");
        for (Complex p : roots) {
            System.out.println(p);
            alpha = Math.max(alpha, p.getReal());
            if (p.getReal() > eps) anyRHP = true;
            if (Math.abs(p.getReal()) <= eps) anyAxis = true;
        }

        System.out.println("alpha = max Re(p) = " + alpha);

        if (anyRHP) {
            System.out.println("Classification: Unstable (RHP pole exists)");
        } else if (!anyAxis) {
            System.out.println("Classification: BIBO stable (all poles in LHP)");
        } else {
            System.out.println("Classification: Boundary case (imag-axis pole detected)");
        }
    }
}
      

7.4 MATLAB and Simulink

Relevant toolboxes: Control System Toolbox (for tf, pole), Simulink (block-diagram simulation).

MATLAB: Poles and Stability Classification


% Transfer function: G(s) = 1 / (s^3 + 2 s^2 + 2 s + 1)
num = 1;
den = [1 2 2 1];

p = roots(den);   % poles
alpha = max(real(p));

epsVal = 1e-9;
anyRHP = any(real(p) > epsVal);
anyAxis = any(abs(real(p)) <= epsVal);

disp('Poles:'); disp(p);
fprintf('alpha = max Re(p) = %.6g\n', alpha);

if anyRHP
    disp('Classification: Unstable (RHP pole exists)');
elseif ~anyAxis
    disp('Classification: BIBO stable (all poles in LHP)');
else
    disp('Classification: Boundary case (imag-axis pole detected)');
end

% Using Control System Toolbox
G = tf(num, den);
disp('Poles via pole(G):'); disp(pole(G));
      

Simulink: Programmatically Create a Simple Model and Observe Behavior

The script below creates a model with a Step input driving a Transfer Function block and a Scope. (Interpreting step responses was developed in Chapter 10; here we use it only as a qualitative check.)


modelName = 'SD_Ch11_L2_PolesStability';
new_system(modelName);
open_system(modelName);

add_block('simulink/Sources/Step', [modelName '/Step']);
add_block('simulink/Continuous/Transfer Fcn', [modelName '/G(s)']);
add_block('simulink/Sinks/Scope', [modelName '/Scope']);

set_param([modelName '/G(s)'], 'Numerator', '1', 'Denominator', '[1 2 2 1]');

add_line(modelName, 'Step/1', 'G(s)/1');
add_line(modelName, 'G(s)/1', 'Scope/1');

set_param(modelName, 'StopTime', '10');
save_system(modelName);

% Run simulation
sim(modelName);
      

7.5 Wolfram Mathematica

Relevant functionality: polynomial root finding, symbolic manipulation, transfer function modeling.


(* Transfer function: G(s) = 1/(s^3 + 2 s^2 + 2 s + 1) *)
den[s_] := s^3 + 2 s^2 + 2 s + 1;

poles = s /. NSolve[den[s] == 0, s];
alpha = Max[Re /@ poles];

Print["Poles: ", poles];
Print["alpha = max Re(p) = ", alpha];

eps = 10^-9;
anyRHP = AnyTrue[poles, Re[#] > eps &];
anyAxis = AnyTrue[poles, Abs[Re[#]] <= eps &];

If[anyRHP,
  Print["Classification: Unstable (RHP pole exists)"],
  If[!anyAxis,
    Print["Classification: BIBO stable (all poles in LHP)"],
    Print["Classification: Boundary case (imag-axis pole detected)"]
  ]
];

(* Optional: represent as a transfer function model *)
G = TransferFunctionModel[1/den[s], s];
Print["Poles (built-in): ", TransferFunctionPoles[G]];
      

8. Problems and Solutions

The following problems are designed to reinforce pole-location reasoning without using techniques not yet introduced (e.g., Routh–Hurwitz is deferred to Lesson 3).

Problem 1 (Classify by poles): Consider a system with poles \( p_1=-2 \), \( p_2=-1+j3 \), \( p_3=-1-j3 \). Classify BIBO and asymptotic stability.

Solution:

All poles satisfy \( \Re(p_k) < 0 \). Therefore the impulse response is a sum of decaying exponentials and decaying sinusoids: \( e^{-2t} \), \( e^{-t}\cos(3t) \), \( e^{-t}\sin(3t) \). Hence:

  • BIBO stable: yes (all poles in open LHP).
  • Asymptotically stable: yes (all natural modes decay).

Problem 2 (Right-half plane pole): Let \( G(s)=\frac{1}{(s-0.1)(s+2)} \). Is the system BIBO stable?

Solution:

One pole is \( p=0.1 \) with \( \Re(p)=0.1 > 0 \). The impulse response contains a term proportional to \( e^{0.1t} \), which grows without bound. Thus \( \int_{0}^{\infty}|h(t)|dt \) diverges and the system is not BIBO stable (unstable).

Problem 3 (Imaginary-axis simple pole): Consider \( G(s)=\frac{1}{s^2+1} \). Determine whether the system is BIBO stable.

Solution:

The poles are \( p=\pm j \), which satisfy \( \Re(p)=0 \). The impulse response is \( h(t)=\sin(t)\,u(t) \). Then:

\[ \int_{0}^{\infty} |h(t)|\,dt = \int_{0}^{\infty} |\sin(t)|\,dt = \infty, \]

because \( |\sin(t)| \) has nonzero average value over each period. Therefore, the system is not BIBO stable. (It exhibits sustained oscillations rather than decay.)

Problem 4 (Repeated imaginary-axis pole): Consider \( G(s)=\frac{1}{s^2} \). Determine stability and explain using the time-domain form.

Solution:

There is a repeated pole at \( s=0 \) with multiplicity 2. The inverse Laplace transform gives \( h(t)=t\,u(t) \). Then:

\[ \int_{0}^{\infty} |h(t)|\,dt = \int_{0}^{\infty} t\,dt = \infty, \]

so BIBO stability fails. Moreover, polynomial growth \( t \) indicates instability even without exponential growth.

Problem 5 (Second-order parameter range without Routh): Let \( D(s)=s^2 + a s + b \) with real parameters \( a,b \). Find conditions on \( a \) and \( b \) such that both poles satisfy \( \Re(p) < 0 \).

Solution:

The poles are given by the quadratic formula:

\[ p_{1,2} = \frac{-a \pm \sqrt{a^2 - 4b}}{2}. \]

We consider two cases:

  1. Real poles (\( a^2 - 4b \ge 0 \)): both poles are negative if and only if their sum and product are positive in the appropriate sense: \( p_1 + p_2 = -a \) and \( p_1 p_2 = b \). Requiring both poles in LHP for real poles is equivalent to: \( -a < 0 \) and \( b > 0 \), i.e., \( a > 0 \) and \( b > 0 \).
  2. Complex-conjugate poles (\( a^2 - 4b < 0 \)): then \( p_{1,2} = -\frac{a}{2} \pm j\omega \) for some \( \omega \neq 0 \). The real part is \( -\frac{a}{2} \), so \( \Re(p_{1,2}) < 0 \) holds iff \( a > 0 \). Also, since \( b = p_1 p_2 = \left(\frac{a}{2}\right)^2 + \omega^2 \), we necessarily have \( b > 0 \).

Combining both cases, the necessary and sufficient conditions are:

\[ a > 0 \quad \text{and} \quad b > 0. \]

These match the intuitive “LHP poles only” requirement for stability in second-order systems.

9. Summary

Pole locations in the \( s \)-plane determine modal behavior because each pole contributes a term proportional to \( e^{p t} \) (or \( t^{m-1}e^{p t} \) for repeated poles). The open left-half plane \( \Re(s) < 0 \) is the core stability region for causal rational LTI systems: it guarantees absolute integrability of the impulse response and therefore BIBO stability. Imaginary-axis poles place the system on the stability boundary, and repeated imaginary-axis poles introduce polynomial growth. Finally, the pole-based margin \( \alpha=\max\Re(p_k) \) provides a compact measure of “how stable” the system is.

10. References

  1. Hurwitz, A. (1895). Über die Bedingungen, unter welchen eine Gleichung nur Wurzeln mit negativen reellen Teilen besitzt. Mathematische Annalen, 46, 273–284.
  2. Routh, E.J. (1877). A Treatise on the Stability of a Given State of Motion. Macmillan. (Foundational stability analysis; connects characteristic roots to stability.)
  3. Nyquist, H. (1932). Regeneration theory. The Bell System Technical Journal, 11(1), 126–147. (Classic theoretical stability foundations; complements pole-based viewpoints.)
  4. Bode, H.W. (1945). Network Analysis and Feedback Amplifier Design. Van Nostrand. (Foundational theory linking complex-plane properties to stability and response.)
  5. Zadeh, L.A., & Desoer, C.A. (1963). Linear System Theory: The State Space Approach. McGraw-Hill. (Rigorous theory; includes stability concepts and analytic characterizations.)
  6. Sandberg, I.W. (1964). On the L1-boundedness of linear time-invariant systems. IEEE Transactions on Circuit Theory, 11(2), 220–221.