Chapter 25: Limitations of State-Feedback Design

Lesson 4: Impact of Model Uncertainty on State-Feedback Designs (Qualitative)

This lesson explains why a state-feedback gain that is correct for a nominal model may behave poorly on the real plant. We study parametric uncertainty, actuator uncertainty, omitted dynamics, pole sensitivity, eigenvector conditioning, and Lyapunov stability margins. The goal is not yet full robust-control synthesis; the goal is to understand the mechanism by which modeling errors move the closed-loop poles and alter transient behavior.

1. Nominal State Feedback vs Real Plant

In previous lessons, state-feedback design was developed for a known LTI model \( \dot{x}=Ax+Bu \). For a full-state feedback law \( u=-Kx+r \), the nominal closed-loop matrix is

\[ A_c=A-BK. \]

The mathematical design problem appears simple: choose \( K \) so that the eigenvalues of \( A_c \) satisfy desired settling-time, damping, and stability requirements. The real plant, however, is rarely exactly \( (A,B) \). A more honest description is

\[ \dot{x}=(A+\Delta A)x+(B+\Delta B)u, \quad u=-Kx+r. \]

Therefore, the implemented closed-loop matrix is

\[ A_{c,true}=A_c+\Delta A_c, \qquad \Delta A_c=\Delta A-\Delta B K. \]

This expression is the central qualitative fact of the lesson: uncertainty in \( B \) is multiplied by the feedback gain \( K \). Thus aggressive feedback can increase the influence of actuator-model errors even when the nominal poles look very attractive.

flowchart TD
  M["Nominal model: A, B"] --> D["Choose state-feedback gain K"]
  D --> N["Nominal closed loop: Ac = A - B K"]
  R["Real plant: A + dA, B + dB"] --> I["Implemented closed loop"]
  D --> I
  I --> T["Ac_true = Ac + dA - dB K"]
  T --> P["Pole movement and changed transients"]
  T --> E["Possible instability if margin is small"]
        

2. Types of Model Uncertainty in State-Space Design

Model uncertainty is not a single phenomenon. It enters state-feedback design through several channels:

  • Parametric uncertainty: entries of \( A \) and \( B \) depend on masses, inertias, damping coefficients, gains, or time constants that are only approximately known.
  • Linearization uncertainty: a linear model is valid near an operating point, but the true nonlinear plant changes as the state moves away from that point.
  • Actuator uncertainty: the command channel may contain uncertain gain, saturation, delay, rate limits, or dead zones.
  • Sensor and state-estimation uncertainty: even if this chapter assumes state availability, the measured state can be scaled, biased, noisy, or reconstructed imperfectly.
  • Unmodeled high-frequency dynamics: flexible modes, neglected actuator dynamics, sampling effects, and parasitic dynamics may not appear in the nominal low-order model.

In compact notation, a family of possible plants may be written as \( \mathcal{P}=\{(A(\theta),B(\theta)): \theta\in\Theta\} \), where \( \theta \) is an uncertain parameter vector. The nominal design uses a single point \( \theta_0 \), but the real plant uses some unknown \( \theta \) inside the admissible set.

\[ A(\theta)=A(\theta_0)+\Delta A(\theta), \qquad B(\theta)=B(\theta_0)+\Delta B(\theta). \]

3. First-Order Closed-Loop Pole Sensitivity

Let \( \lambda_i \) be a simple eigenvalue of \( A_c \), with right and left eigenvectors \( v_i \) and \( w_i \):

\[ A_c v_i=\lambda_i v_i, \qquad w_i^*A_c=\lambda_i w_i^*, \qquad w_i^*v_i=1. \]

Under a small perturbation \( \Delta A_c \), the first-order eigenvalue shift is

\[ \delta\lambda_i \approx w_i^*\Delta A_c v_i =w_i^*(\Delta A-\Delta B K)v_i. \]

Hence the pole movement depends not only on the size of the modeling error, but also on how the modeling error is aligned with the left and right eigenvectors of the closed-loop matrix.

Proof sketch. Write the perturbed eigenvalue equation:

\[ (A_c+\Delta A_c)(v_i+\delta v_i)=(\lambda_i+\delta\lambda_i) (v_i+\delta v_i). \]

Removing second-order terms gives

\[ A_c\delta v_i+\Delta A_c v_i=\lambda_i\delta v_i+ \delta\lambda_i v_i. \]

Premultiply by \( w_i^* \). Since \( w_i^*A_c=\lambda_i w_i^* \), the terms containing \( \delta v_i \) cancel and, using \( w_i^*v_i=1 \), we obtain \( \delta\lambda_i=w_i^*\Delta A_c v_i \).

If the eigenvectors are poorly conditioned, a small matrix perturbation can cause large pole movement. A useful qualitative measure is

\[ \kappa_i=\frac{\|w_i\|_2\|v_i\|_2}{|w_i^*v_i|}, \qquad |\delta\lambda_i|\le \kappa_i\|\Delta A_c\|_2. \]

Large \( \kappa_i \) indicates a sensitive pole. In pole placement, this often occurs when closed-loop eigenvectors are nearly linearly dependent or when extremely fast poles are forced using high feedback gains.

4. Eigenvector Conditioning and Bauer-Fike Interpretation

Suppose \( A_c \) is diagonalizable:

\[ A_c=V\Lambda V^{-1}. \]

If \( \mu \) is an eigenvalue of \( A_c+\Delta A_c \), the Bauer-Fike theorem implies

\[ \min_i |\mu-\lambda_i|\le \kappa_2(V)\|\Delta A_c\|_2, \qquad \kappa_2(V)=\|V\|_2\|V^{-1}\|_2. \]

Therefore, robust-looking pole locations are not determined only by the distances of the nominal poles from the imaginary axis. They also depend on the conditioning of the closed-loop eigenvector matrix. A controller with poles at \( -5,-6,-7 \) can be less robust than a controller with poles at \( -2,-3,-4 \) if the first design produces a highly nonnormal closed-loop matrix.

\[ \text{Large }\kappa_2(V) \quad \Longrightarrow \quad \text{large possible pole movement for the same }\|\Delta A_c\|_2. \]

5. A Lyapunov View of Robust Stability Margins

Assume the nominal closed-loop matrix \( A_c \) is Hurwitz, meaning all closed-loop poles satisfy \( \operatorname{Re}(\lambda_i(A_c))<0 \). Choose \( Q=Q^T\succ 0 \) and solve the Lyapunov equation

\[ A_c^T P+P A_c=-Q, \qquad P=P^T\succ 0. \]

For the perturbed system \( \dot{x}=(A_c+\Delta A_c)x \) and Lyapunov function \( V(x)=x^TPx \), we obtain

\[ \dot{V}=x^T\left((A_c+\Delta A_c)^TP+P(A_c+\Delta A_c)\right)x. \]

Substituting the nominal Lyapunov equation gives

\[ \dot{V}=-x^TQx+x^T(\Delta A_c^TP+P\Delta A_c)x. \]

Using spectral-norm bounds,

\[ \dot{V}\le -\lambda_{\min}(Q)\|x\|_2^2 +2\|P\|_2\|\Delta A_c\|_2\|x\|_2^2. \]

Therefore, a sufficient condition for robust asymptotic stability is

\[ 2\|P\|_2\|\Delta A_c\|_2 < \lambda_{\min}(Q). \]

This condition is conservative, but it teaches an important engineering lesson: a nominally stable design is safer when it has a large Lyapunov decay margin and a moderate \( \|P\|_2 \). When \( P \) is large, the closed-loop system stores energy in directions that decay slowly or transiently amplify before decaying.

6. Why Aggressive Pole Placement Can Reduce Robustness

Moving poles farther left normally improves nominal speed, but it often requires a larger feedback gain. With actuator-gain uncertainty \( B_{true}=B(I+E) \), the real closed-loop matrix is

\[ A_{c,true}=A-B(I+E)K=A_c-BEK. \]

Hence the uncertainty-induced perturbation satisfies

\[ \|\Delta A_c\|_2=\|BEK\|_2\le \|B\|_2\|E\|_2\|K\|_2. \]

The same gain that accelerates nominal poles also magnifies uncertainty in the input channel. This is one reason Chapter 25 treats pole placement as a constrained engineering problem rather than a purely algebraic one.

flowchart TD
  A["Move nominal poles farther left"] --> B["Need larger feedback gain K"]
  B --> C["Higher control effort"]
  B --> D["Input uncertainty multiplied by K"]
  D --> E["Larger closed-loop perturbation"]
  C --> F["Saturation and actuator stress"]
  E --> G["Pole movement and robustness loss"]
  F --> G
        

7. Qualitative Design Guidelines

Before introducing formal robust-control design, a state-feedback designer can already use several practical checks:

  1. Do not place poles faster than needed. Excessively fast poles usually increase \( \|K\| \), control effort, and sensitivity to \( \Delta B \).
  2. Check eigenvector conditioning. A closed-loop matrix with poorly conditioned eigenvectors may have fragile eigenvalues and large transient amplification.
  3. Perform uncertainty sweeps. Vary physical parameters over plausible ranges and evaluate closed-loop poles, settling time, overshoot, and actuator effort.
  4. Separate model errors by channel. Errors in \( A \) and \( B \) have different effects because \( \Delta B \) is multiplied by \( K \).
  5. Keep robustness margins visible. Use Lyapunov margin, pole displacement, and Monte Carlo samples as diagnostic tools.

These checks do not replace robust synthesis, but they often reveal why a controller that is perfect in nominal simulation fails on real hardware or on a higher-fidelity simulation model.

8. Python Implementation — Monte Carlo Pole Movement

Chapter25_Lesson4.py

"""
Chapter25_Lesson4.py
Impact of Model Uncertainty on State-Feedback Designs

Monte Carlo study for a second-order state-feedback controller under
parametric uncertainty in A and actuator-gain uncertainty in B.

Dependencies:
    pip install numpy scipy matplotlib
"""

import numpy as np
from scipy.signal import place_poles
from scipy.linalg import solve_continuous_lyapunov
import matplotlib.pyplot as plt

np.random.seed(25)

# Nominal plant: x_dot = A x + B u
A = np.array([[0.0, 1.0],
              [-2.0, -0.5]])
B = np.array([[0.0],
              [1.0]])

# Desired nominal closed-loop poles
poles = np.array([-2.0, -3.0])
K = place_poles(A, B, poles).gain_matrix
Acl = A - B @ K

print("Nominal K =", K)
print("Nominal closed-loop eigenvalues =", np.linalg.eigvals(Acl))

# Lyapunov margin around the nominal closed loop.
# Acl.T P + P Acl = -Q, with Q = I.
Q = np.eye(2)
P = solve_continuous_lyapunov(Acl.T, -Q)
margin_bound = np.min(np.linalg.eigvals(Q).real) / (2.0 * np.linalg.norm(P, 2))
print("Sufficient perturbation bound ||DeltaAcl||_2 <", margin_bound)

# Monte Carlo uncertainty model:
# A_true = A + dA, B_true = B * (1 + rho), so Acl_true = A + dA - B_true K
N = 5000
sigma_A = 0.05
rho_max = 0.25
worst_real_part = []
unstable_count = 0
stable_examples = []

for _ in range(N):
    dA = sigma_A * np.random.randn(2, 2)
    rho = np.random.uniform(-rho_max, rho_max)
    A_true = A + dA
    B_true = B * (1.0 + rho)
    Acl_true = A_true - B_true @ K
    eigs = np.linalg.eigvals(Acl_true)
    mr = np.max(eigs.real)
    worst_real_part.append(mr)
    if mr >= 0.0:
        unstable_count += 1
    else:
        stable_examples.append(eigs)

worst_real_part = np.array(worst_real_part)
print("Unstable samples:", unstable_count, "out of", N)
print("Worst observed max real part:", np.max(worst_real_part))
print("95th percentile max real part:", np.percentile(worst_real_part, 95))

plt.figure(figsize=(8, 4.5))
plt.hist(worst_real_part, bins=50)
plt.axvline(0.0, linestyle="--")
plt.xlabel("max real part of closed-loop eigenvalues")
plt.ylabel("sample count")
plt.title("Closed-loop pole movement under model uncertainty")
plt.tight_layout()
plt.show()

9. C++ Implementation — Ackermann Design and Random Perturbations

Chapter25_Lesson4.cpp

/*
Chapter25_Lesson4.cpp
Impact of Model Uncertainty on State-Feedback Designs

Compile example with Eigen installed:
    g++ Chapter25_Lesson4.cpp -std=c++17 -O2 -I /path/to/eigen -o Chapter25_Lesson4

This example uses a 2x2 SISO plant and Ackermann's formula from scratch.
*/

#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <iostream>
#include <random>

using Matrix2 = Eigen::Matrix2d;
using Vector2 = Eigen::Vector2d;
using Row2 = Eigen::RowVector2d;

Row2 ackermann2(const Matrix2& A, const Vector2& B, double p1, double p2) {
    Eigen::Matrix2d C;
    C.col(0) = B;
    C.col(1) = A * B;

    if (std::abs(C.determinant()) < 1e-12) {
        throw std::runtime_error("System is not controllable or is ill-conditioned.");
    }

    // Desired characteristic polynomial: s^2 + a1 s + a0
    double a1 = -(p1 + p2);
    double a0 = p1 * p2;
    Matrix2 phiA = A * A + a1 * A + a0 * Matrix2::Identity();

    Row2 en;
    en << 0.0, 1.0;
    return en * C.inverse() * phiA;
}

int main() {
    Matrix2 A;
    A << 0.0, 1.0,
        -2.0, -0.5;
    Vector2 B;
    B << 0.0, 1.0;

    Row2 K = ackermann2(A, B, -2.0, -3.0);
    Matrix2 Acl = A - B * K;

    std::cout << "K = " << K << "\n";
    std::cout << "Nominal closed-loop eigenvalues:\n"
              << Eigen::EigenSolver<Matrix2>(Acl).eigenvalues() << "\n\n";

    std::mt19937 gen(25);
    std::normal_distribution<double> normal(0.0, 0.05);
    std::uniform_real_distribution<double> uniform(-0.25, 0.25);

    int N = 5000;
    int unstable = 0;
    double worst = -1e9;

    for (int i = 0; i < N; ++i) {
        Matrix2 dA;
        dA << normal(gen), normal(gen), normal(gen), normal(gen);
        double rho = uniform(gen);
        Vector2 Btrue = (1.0 + rho) * B;
        Matrix2 Atrue = A + dA;
        Matrix2 Acl_true = Atrue - Btrue * K;
        auto eigs = Eigen::EigenSolver<Matrix2>(Acl_true).eigenvalues();
        double maxReal = std::max(eigs(0).real(), eigs(1).real());
        worst = std::max(worst, maxReal);
        if (maxReal >= 0.0) unstable++;
    }

    std::cout << "Unstable samples = " << unstable << " out of " << N << "\n";
    std::cout << "Worst observed max real part = " << worst << "\n";
    return 0;
}

10. Java Implementation — From-Scratch 2x2 Robustness Check

Chapter25_Lesson4.java

/*
Chapter25_Lesson4.java
Impact of Model Uncertainty on State-Feedback Designs

Compile and run:
    javac Chapter25_Lesson4.java
    java Chapter25_Lesson4

This file implements the 2x2 calculations from scratch.
*/

import java.util.Random;

public class Chapter25_Lesson4 {
    static double[][] matMul(double[][] A, double[][] B) {
        double[][] C = new double[A.length][B[0].length];
        for (int i = 0; i < A.length; i++)
            for (int j = 0; j < B[0].length; j++)
                for (int k = 0; k < B.length; k++)
                    C[i][j] += A[i][k] * B[k][j];
        return C;
    }

    static double[][] matAdd(double[][] A, double[][] B) {
        double[][] C = new double[A.length][A[0].length];
        for (int i = 0; i < A.length; i++)
            for (int j = 0; j < A[0].length; j++)
                C[i][j] = A[i][j] + B[i][j];
        return C;
    }

    static double[][] scalarMul(double a, double[][] A) {
        double[][] C = new double[A.length][A[0].length];
        for (int i = 0; i < A.length; i++)
            for (int j = 0; j < A[0].length; j++)
                C[i][j] = a * A[i][j];
        return C;
    }

    static double[][] inverse2(double[][] M) {
        double det = M[0][0] * M[1][1] - M[0][1] * M[1][0];
        if (Math.abs(det) < 1e-12) throw new RuntimeException("Singular 2x2 matrix.");
        return new double[][]{ { M[1][1]/det, -M[0][1]/det }, { -M[1][0]/det, M[0][0]/det } };
    }

    static double[] rowTimesMatrix(double[] r, double[][] M) {
        return new double[]{r[0]*M[0][0] + r[1]*M[1][0], r[0]*M[0][1] + r[1]*M[1][1]};
    }

    static double[] rowTimesMatrix2(double[] r, double[][] M1, double[][] M2) {
        return rowTimesMatrix(rowTimesMatrix(r, M1), M2);
    }

    static double[] ackermann2(double[][] A, double[][] Bcol, double p1, double p2) {
        double[][] AB = matMul(A, Bcol);
        double[][] C = { {Bcol[0][0], AB[0][0]}, {Bcol[1][0], AB[1][0]} };
        double[][] Cinv = inverse2(C);

        double a1 = -(p1 + p2);
        double a0 = p1 * p2;
        double[][] A2 = matMul(A, A);
        double[][] phiA = matAdd(matAdd(A2, scalarMul(a1, A)), scalarMul(a0, new double[][]{ {1,0},{0,1} }));
        return rowTimesMatrix2(new double[]{0.0, 1.0}, Cinv, phiA);
    }

    static double[] eigRealParts2(double[][] M) {
        double tr = M[0][0] + M[1][1];
        double det = M[0][0]*M[1][1] - M[0][1]*M[1][0];
        double disc = tr*tr - 4.0*det;
        if (disc >= 0.0) {
            double root = Math.sqrt(disc);
            return new double[]{(tr + root)/2.0, (tr - root)/2.0};
        }
        return new double[]{tr/2.0, tr/2.0};
    }

    public static void main(String[] args) {
        double[][] A = { {0.0, 1.0}, {-2.0, -0.5} };
        double[][] B = { {0.0}, {1.0} };
        double[] K = ackermann2(A, B, -2.0, -3.0);
        System.out.printf("K = [%.6f %.6f]%n", K[0], K[1]);

        Random rng = new Random(25);
        int N = 5000;
        int unstable = 0;
        double worst = -1e9;

        for (int s = 0; s < N; s++) {
            double[][] dA = new double[2][2];
            for (int i = 0; i < 2; i++)
                for (int j = 0; j < 2; j++)
                    dA[i][j] = 0.05 * rng.nextGaussian();

            double rho = -0.25 + 0.5 * rng.nextDouble();
            double[][] Atrue = matAdd(A, dA);
            double[][] BK = { {B[0][0]*(1+rho)*K[0], B[0][0]*(1+rho)*K[1]},
                             {B[1][0]*(1+rho)*K[0], B[1][0]*(1+rho)*K[1]} };
            double[][] Acl = matAdd(Atrue, scalarMul(-1.0, BK));
            double[] rp = eigRealParts2(Acl);
            double maxReal = Math.max(rp[0], rp[1]);
            worst = Math.max(worst, maxReal);
            if (maxReal >= 0.0) unstable++;
        }

        System.out.println("Unstable samples = " + unstable + " out of " + N);
        System.out.println("Worst observed max real part = " + worst);
    }
}

11. MATLAB/Simulink Implementation — Uncertainty Sweep

Chapter25_Lesson4.m

% Chapter25_Lesson4.m
% Impact of Model Uncertainty on State-Feedback Designs
% Requires Control System Toolbox for place(). Simulink section is optional.

clear; clc; close all;
rng(25);

A = [0 1; -2 -0.5];
B = [0; 1];
C = [1 0];
D = 0;

poles = [-2 -3];
K = place(A, B, poles);
Acl = A - B*K;

disp('Nominal K ='); disp(K);
disp('Nominal closed-loop eigenvalues ='); disp(eig(Acl));

% Lyapunov sufficient perturbation bound
Q = eye(2);
P = lyap(Acl', Q);  % solves Acl'*P + P*Acl = -Q
bound = min(eig(Q))/(2*norm(P,2));
fprintf('Sufficient perturbation bound ||DeltaAcl||_2 < %.6f\n', bound);

N = 5000;
sigmaA = 0.05;
rhoMax = 0.25;
maxReal = zeros(N,1);

for k = 1:N
    dA = sigmaA*randn(2,2);
    rho = -rhoMax + 2*rhoMax*rand;
    Atrue = A + dA;
    Btrue = B*(1 + rho);
    Acl_true = Atrue - Btrue*K;
    maxReal(k) = max(real(eig(Acl_true)));
end

fprintf('Unstable samples: %d out of %d\n', sum(maxReal >= 0), N);
fprintf('Worst observed max real part: %.6f\n', max(maxReal));
fprintf('95th percentile max real part: %.6f\n', prctile(maxReal,95));

figure;
histogram(maxReal, 50);
xline(0, '--');
xlabel('max real part of closed-loop eigenvalues');
ylabel('sample count');
title('Closed-loop pole movement under model uncertainty');
grid on;

% Optional Simulink construction: nominal and perturbed state-space blocks.
% This creates a minimal model if Simulink is installed.
try
    mdl = 'Chapter25_Lesson4_Simulink';
    if bdIsLoaded(mdl), close_system(mdl, 0); end
    new_system(mdl); open_system(mdl);
    add_block('simulink/Sources/Step', [mdl '/Step'], 'Position', [50 80 80 110]);
    add_block('simulink/Continuous/State-Space', [mdl '/Nominal Closed Loop'], ...
        'A', 'Acl', 'B', 'B', 'C', 'C', 'D', 'D', 'Position', [160 55 320 135]);
    add_block('simulink/Sinks/Scope', [mdl '/Scope'], 'Position', [390 75 420 115]);
    add_line(mdl, 'Step/1', 'Nominal Closed Loop/1');
    add_line(mdl, 'Nominal Closed Loop/1', 'Scope/1');
    save_system(mdl);
    disp(['Created optional Simulink model: ' mdl '.slx']);
catch ME
    disp('Simulink model was not created. Reason:');
    disp(ME.message);
end

12. Wolfram Mathematica Implementation — Symbolic and Sampled Uncertainty

Chapter25_Lesson4.nb

A = { {0, 1}, {-2, -0.5} };
B = { {0}, {1} };
K = { {4, 4.5} };
Acl = A - B.K;
Eigenvalues[Acl]

SeedRandom[25];
samples = Table[
   Module[{dA, rho, Atrue, Btrue, eig},
    dA = 0.05 RandomVariate[NormalDistribution[0, 1], {2, 2}];
    rho = RandomReal[{-0.25, 0.25}];
    Atrue = A + dA;
    Btrue = B (1 + rho);
    eig = Eigenvalues[Atrue - Btrue.K];
    Max[Re[eig]]
    ],
   {5000}
   ];

Count[samples, x_ /; x >= 0]
Max[samples]
Histogram[samples, 50, PlotLabel -> "Closed-loop pole movement under uncertainty"]

13. Problems and Solutions

Problem 1 (Closed-loop perturbation): A nominal plant is \( \dot{x}=Ax+Bu \) and the implemented plant is \( \dot{x}=(A+\Delta A)x+(B+\Delta B)u \). With \( u=-Kx \), derive the implemented closed-loop matrix and identify the perturbation relative to \( A_c=A-BK \).

Solution:

\[ \dot{x}=\left(A+\Delta A-(B+\Delta B)K\right)x. \]

Therefore,

\[ A_{c,true}=A-BK+\Delta A-\Delta B K=A_c+\Delta A_c, \qquad \Delta A_c=\Delta A-\Delta B K. \]

The input-channel uncertainty is multiplied by the feedback gain. This is why large \( K \) can reduce robustness.

Problem 2 (First-order pole shift): Let \( A_c v=\lambda v \), \( w^*A_c=\lambda w^* \), and \( w^*v=1 \). Show that the first-order eigenvalue shift under \( \Delta A_c \) is \( \delta\lambda=w^*\Delta A_c v \).

Solution: Substitute the perturbed eigenpair:

\[ (A_c+\Delta A_c)(v+\delta v)=(\lambda+\delta\lambda)(v+\delta v). \]

Ignoring second-order terms yields

\[ A_c\delta v+\Delta A_c v=\lambda\delta v+\delta\lambda v. \]

Premultiplication by \( w^* \) cancels the \( \delta v \) terms, giving \( \delta\lambda=w^*\Delta A_c v \).

Problem 3 (Lyapunov robustness condition): Suppose \( A_c^TP+PA_c=-Q \), where \( P=P^T\succ0 \) and \( Q=Q^T\succ0 \). Derive a sufficient condition on \( \|\Delta A_c\|_2 \) for stability of \( A_c+\Delta A_c \).

Solution: For \( V=x^TPx \),

\[ \dot{V}=-x^TQx+x^T(\Delta A_c^TP+P\Delta A_c)x. \]

Using norm bounds,

\[ \dot{V}\le -\left(\lambda_{\min}(Q)-2\|P\|_2\|\Delta A_c\|_2\right) \|x\|_2^2. \]

Thus a sufficient condition is

\[ 2\|P\|_2\|\Delta A_c\|_2 < \lambda_{\min}(Q). \]

Problem 4 (Input gain uncertainty): If \( B_{true}=B(I+E) \), show how the perturbation scales with \( K \).

Solution:

\[ A_{c,true}=A-B(I+E)K=A_c-BEK. \]

Therefore,

\[ \|\Delta A_c\|_2=\|BEK\|_2\le \|B\|_2\|E\|_2\|K\|_2. \]

Larger gains increase the possible effect of input-channel uncertainty.

Problem 5 (Qualitative design decision): Two controllers stabilize the same nominal plant. Controller 1 has slower poles but a small gain and well-conditioned eigenvectors. Controller 2 has very fast poles but a large gain and a poorly conditioned eigenvector matrix. Which design is more likely to be robust to moderate model uncertainty?

Solution: Controller 1 is usually more robust. Its smaller gain reduces amplification of \( \Delta B \), and its better eigenvector conditioning reduces sensitivity predicted by \( \kappa_2(V)\|\Delta A_c\|_2 \). Controller 2 may have excellent nominal settling time, but it is more likely to suffer pole migration, actuator stress, and transient amplification.

14. Summary

State-feedback design is model-dependent. If the implemented plant is \( (A+\Delta A,B+\Delta B) \), then the real closed-loop matrix is \( A_c+\Delta A-\Delta B K \). Pole movement is governed by eigenvalue sensitivity, eigenvector conditioning, and Lyapunov decay margins. Aggressive pole placement can improve nominal speed but can also magnify actuator uncertainty and control effort. A good state-feedback design therefore balances speed, effort, numerical conditioning, and robustness margin.

15. References

  1. Kautsky, J., Nichols, N.K., & Van Dooren, P. (1985). Robust pole assignment in linear state feedback. International Journal of Control, 41(5), 1129–1155.
  2. Doyle, J.C., & Stein, G. (1981). Multivariable feedback design: Concepts for a classical/modern synthesis. IEEE Transactions on Automatic Control, 26(1), 4–16.
  3. Hinrichsen, D., & Pritchard, A.J. (1986). Stability radii of linear systems. Systems & Control Letters, 7(1), 1–10.
  4. Barmish, B.R. (1985). Necessary and sufficient conditions for quadratic stabilizability of an uncertain system. Journal of Optimization Theory and Applications, 46, 399–408.
  5. Byers, R., & Nash, S.G. (1989). Approaches to robust pole assignment. International Journal of Control, 49(1), 97–117.
  6. Tits, A.L., & Yang, Y. (1996). Globally convergent algorithms for robust pole assignment by state feedback. IEEE Transactions on Automatic Control, 41(10), 1432–1452.
  7. Gahinet, P., & Apkarian, P. (1994). A linear matrix inequality approach to H-infinity control. International Journal of Robust and Nonlinear Control, 4(4), 421–448.