Chapter 25: Limitations of State-Feedback Design
Lesson 1: Uncontrollable Modes and Unassignable Poles
This lesson explains the exact mathematical reason why state feedback cannot arbitrarily relocate every pole of a non-controllable realization. We prove that uncontrollable modes are invariant under full-state feedback, connect the result to the Kalman and PBH controllability tests, and distinguish between full pole assignment, partial pole assignment, and stabilizing feedback when uncontrollable modes are already stable.
1. Conceptual Overview
In previous chapters, state feedback was introduced as a direct way of modifying the internal dynamics of a linear time-invariant system. For the continuous-time plant \( \dot{\mathbf{x} }=\mathbf{A}\mathbf{x}+\mathbf{B}\mathbf{u} \), the full-state feedback law \( \mathbf{u}=-\mathbf{K}\mathbf{x}+\mathbf{r} \) gives the closed-loop matrix
\[ \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K}. \]
If \( (\mathbf{A},\mathbf{B}) \) is controllable, then the eigenvalues of \( \mathbf{A}-\mathbf{B}\mathbf{K} \) can be assigned to any desired self-conjugate set of complex numbers. The limitation studied here appears when the actuator matrix \( \mathbf{B} \) cannot influence some internal modes. Those modes are called uncontrollable modes, and their corresponding poles are unassignable poles.
\[ \boxed{\text{uncontrollable mode} \quad \Rightarrow \quad \text{closed-loop pole fixed for every admissible }\mathbf{K} } \]
This is not a numerical artifact of a particular pole-placement algorithm. It is a structural obstruction caused by the pair \( (\mathbf{A},\mathbf{B}) \). If a mode is outside the reachable subspace, state feedback can at most change how the controllable part is driven; it cannot create actuator authority over a direction that the input channel never reaches.
flowchart TD
A["Plant: xdot = A x + B u"] --> B["Choose feedback: u = -K x + r"]
B --> C["Closed-loop matrix: Acl = A - B K"]
C --> D["Check controllability of (A,B)"]
D -->|"rank controllability matrix = n"| E["All poles assignable"]
D -->|"rank controllability matrix less than n"| F["Only reachable modes assignable"]
F --> G["Unreachable modes remain fixed"]
G --> H["If fixed unstable modes exist, \nstabilization is impossible"]
2. Reachable Subspace and Kalman Rank Test
For an \( n \)-state, \( m \)-input LTI system, the Kalman controllability matrix is
\[ \mathcal{C}(\mathbf{A},\mathbf{B})= \begin{bmatrix}\mathbf{B} & \mathbf{A}\mathbf{B} & \mathbf{A}^2\mathbf{B} & \cdots & \mathbf{A}^{n-1}\mathbf{B} \end{bmatrix}. \]
The reachable subspace is the image of this matrix:
\[ \mathcal{R}=\operatorname{im}\mathcal{C}(\mathbf{A},\mathbf{B}), \qquad r=\dim(\mathcal{R})=\operatorname{rank}\mathcal{C}(\mathbf{A},\mathbf{B}). \]
The pair is controllable exactly when \( r=n \). If \( r<n \), then the state space contains directions that cannot be reached from the origin by any finite-energy input. These directions generate the unassignable part of the closed-loop spectrum.
Key invariance property. The reachable subspace is invariant under \( \mathbf{A} \):
\[ \mathbf{A}\mathcal{R}\subseteq \mathcal{R}. \]
Indeed, each generator \( \mathbf{A}^k\mathbf{B} \) is mapped to \( \mathbf{A}^{k+1}\mathbf{B} \). For \( k=0,\dots,n-2 \), this vector is explicitly in the controllability matrix. For \( k=n-1 \), the Cayley-Hamilton theorem expresses \( \mathbf{A}^n\mathbf{B} \) as a linear combination of \( \mathbf{B},\mathbf{A}\mathbf{B},\dots,\mathbf{A}^{n-1}\mathbf{B} \).
3. Kalman Decomposition and Proof of Unassignable Poles
Choose a nonsingular transformation matrix \( \mathbf{T}=\begin{bmatrix}\mathbf{T}_r & \mathbf{T}_u\end{bmatrix} \), where the columns of \( \mathbf{T}_r \) span the reachable subspace \( \mathcal{R} \). In the new coordinates \( \mathbf{x}=\mathbf{T}\bar{\mathbf{x} } \), the pair takes the block form
\[ \bar{\mathbf{A} }=\mathbf{T}^{-1}\mathbf{A}\mathbf{T}= \begin{bmatrix} \mathbf{A}_r & \mathbf{A}_{12}\\ \mathbf{0} & \mathbf{A}_u \end{bmatrix}, \qquad \bar{\mathbf{B} }=\mathbf{T}^{-1}\mathbf{B}= \begin{bmatrix} \mathbf{B}_r\\ \mathbf{0} \end{bmatrix}. \]
Partition the transformed feedback gain as \( \bar{\mathbf{K} }=\mathbf{K}\mathbf{T}= \begin{bmatrix}\mathbf{K}_r & \mathbf{K}_u\end{bmatrix} \). Then
\[ \bar{\mathbf{A} }-\bar{\mathbf{B} }\bar{\mathbf{K} }= \begin{bmatrix} \mathbf{A}_r-\mathbf{B}_r\mathbf{K}_r & \mathbf{A}_{12}-\mathbf{B}_r\mathbf{K}_u\\ \mathbf{0} & \mathbf{A}_u \end{bmatrix}. \]
Because this matrix is block upper triangular, its characteristic polynomial factors as
\[ \det\left(s\mathbf{I}-\bar{\mathbf{A} }+ \bar{\mathbf{B} }\bar{\mathbf{K} }\right)= \det\left(s\mathbf{I}-\mathbf{A}_r+ \mathbf{B}_r\mathbf{K}_r\right) \det\left(s\mathbf{I}-\mathbf{A}_u\right). \]
Therefore the eigenvalues of \( \mathbf{A}_u \) are present in the closed-loop spectrum for every feedback matrix \( \mathbf{K} \). They are exactly the unassignable poles.
flowchart TD
X["Original coordinates"] --> T["Change basis T"]
T --> R["Reachable block: Ar, Br"]
T --> U["Unreachable block: Au, zero input"]
R --> RF["Feedback changes Ar - Br Kr"]
U --> UF["Feedback cannot change Au"]
RF --> P1["Assignable poles"]
UF --> P2["Unassignable poles"]
4. PBH Test and Modal Interpretation
The PBH test gives an eigenvalue-level diagnosis. The pair \( (\mathbf{A},\mathbf{B}) \) is controllable if and only if
\[ \operatorname{rank}\begin{bmatrix}\lambda\mathbf{I}- \mathbf{A} & \mathbf{B}\end{bmatrix}=n \quad \text{for every }\lambda\in\sigma(\mathbf{A}). \]
A particular eigenvalue \( \lambda \) is an uncontrollable mode when
\[ \operatorname{rank}\begin{bmatrix}\lambda\mathbf{I}- \mathbf{A} & \mathbf{B}\end{bmatrix}<n. \]
Equivalently, there exists a nonzero left eigenvector \( \mathbf{q}^* \) such that
\[ \mathbf{q}^*\mathbf{A}=\lambda\mathbf{q}^*, \qquad \mathbf{q}^*\mathbf{B}=\mathbf{0}. \]
The invariance under feedback follows immediately:
\[ \mathbf{q}^*(\mathbf{A}-\mathbf{B}\mathbf{K})= \mathbf{q}^*\mathbf{A}-\mathbf{q}^*\mathbf{B}\mathbf{K}= \lambda\mathbf{q}^*. \]
Thus the same left eigenvector certifies that \( \lambda \) remains a closed-loop eigenvalue of \( \mathbf{A}-\mathbf{B}\mathbf{K} \) for all feedback gains. This proof is often the shortest way to identify unassignable poles in symbolic examples.
5. Stabilizability and Design Consequences
Complete pole placement requires controllability. Stabilization requires less: the uncontrollable modes only need to be already stable. For continuous-time systems, the pair \( (\mathbf{A},\mathbf{B}) \) is stabilizable if every uncontrollable eigenvalue lies in the open left half-plane:
\[ \lambda\in\sigma(\mathbf{A}_u) \quad\Rightarrow\quad \operatorname{Re}(\lambda)<0. \]
Equivalently, the PBH rank condition only has to be checked for unstable or marginal eigenvalues:
\[ \operatorname{rank}\begin{bmatrix}\lambda\mathbf{I}- \mathbf{A} & \mathbf{B}\end{bmatrix}=n \quad \text{for every }\lambda\in\sigma(\mathbf{A}) \text{ with }\operatorname{Re}(\lambda)\ge 0. \]
This condition separates two different design failures. If an uncontrollable pole is stable, arbitrary pole assignment is impossible, but stabilization may still be possible by moving the controllable poles. If an uncontrollable pole is unstable, no state-feedback gain can make the full closed-loop system asymptotically stable.
\[ \boxed{\text{unstable uncontrollable pole} \quad \Rightarrow \quad \nexists\,\mathbf{K}\;\text{such that }\mathbf{A}- \mathbf{B}\mathbf{K}\text{ is Hurwitz} } \]
6. Worked Example: A Fixed Unstable Pole
Consider
\[ \mathbf{A}=\begin{bmatrix}0&0\\0&2\end{bmatrix}, \qquad \mathbf{B}=\begin{bmatrix}1\\0\end{bmatrix}. \]
The controllability matrix is
\[ \mathcal{C}=\begin{bmatrix}\mathbf{B}&\mathbf{A}\mathbf{B}\end{bmatrix} =\begin{bmatrix}1&0\\0&0\end{bmatrix}, \qquad \operatorname{rank}(\mathcal{C})=1<2. \]
For an arbitrary state-feedback gain \( \mathbf{K}=\begin{bmatrix}k_1&k_2\end{bmatrix} \),
\[ \mathbf{A}-\mathbf{B}\mathbf{K}= \begin{bmatrix}-k_1&-k_2\\0&2\end{bmatrix}. \]
Therefore,
\[ \det\left(s\mathbf{I}-(\mathbf{A}-\mathbf{B}\mathbf{K})\right) =(s+k_1)(s-2). \]
The pole \( -k_1 \) is assignable, but the pole \( 2 \) remains fixed. Since \( \operatorname{Re}(2)>0 \), this system cannot be stabilized by any state-feedback matrix.
7. Software Implementations
The following implementations compute controllability, apply the PBH
test, and demonstrate that uncontrollable poles remain fixed under
feedback. Python uses numpy and scipy.signal;
MATLAB uses Control System Toolbox functions when available; the C++ and
Java examples implement the small matrix operations from scratch; the
Mathematica notebook uses symbolic and exact matrix operations.
Chapter25_Lesson1.py
"""
Chapter25_Lesson1.py
Uncontrollable Modes and Unassignable Poles
Requires:
numpy
scipy
Optional:
python-control (not required here)
This script demonstrates:
1. Kalman controllability rank test
2. PBH test
3. State-feedback pole assignment limitation
4. Invariance of uncontrollable eigenvalues under A_cl = A - B K
"""
import numpy as np
from numpy.linalg import matrix_rank, eigvals
from scipy.signal import place_poles
def controllability_matrix(A: np.ndarray, B: np.ndarray) -> np.ndarray:
"""Return C = [B, AB, ..., A^(n-1)B]."""
n = A.shape[0]
blocks = [B]
Ak = np.eye(n)
for _ in range(1, n):
Ak = Ak @ A
blocks.append(Ak @ B)
return np.hstack(blocks)
def pbh_controllability_report(A: np.ndarray, B: np.ndarray, tol: float = 1e-9) -> None:
"""Print PBH ranks rank([lambda I - A, B]) for each eigenvalue."""
n = A.shape[0]
print("PBH test:")
for lam in eigvals(A):
M = np.hstack((lam * np.eye(n) - A, B))
r = matrix_rank(M, tol=tol)
status = "controllable at this eigenvalue" if r == n else "UNCONTROLLABLE mode"
print(f" lambda = {lam: .6g}, rank = {r}/{n}: {status}")
def kalman_decomposition_by_reachable_basis(A: np.ndarray, B: np.ndarray):
"""
Construct a simple reachable-basis transformation using QR.
The first r columns of T span the reachable subspace.
"""
C = controllability_matrix(A, B)
Q, R = np.linalg.qr(C)
r = matrix_rank(C)
# Build a full orthonormal basis by completing Q[:, :r]
Qr = Q[:, :r]
random_block = np.eye(A.shape[0])
U, _ = np.linalg.qr(np.hstack([Qr, random_block]))
T = U[:, :A.shape[0]]
Abar = T.T @ A @ T
Bbar = T.T @ B
return T, Abar, Bbar, r
def main() -> None:
# Example: the second state is not actuated and produces an unassignable pole at +2.
A = np.array([[0.0, 0.0],
[0.0, 2.0]])
B = np.array([[1.0],
[0.0]])
print("A =\n", A)
print("B =\n", B)
C = controllability_matrix(A, B)
print("\nKalman controllability matrix C = [B, AB] =\n", C)
print("rank(C) =", matrix_rank(C), "out of n =", A.shape[0])
pbh_controllability_report(A, B)
# Try state feedback K = [k1, k2]. Only the first closed-loop pole can move.
print("\nClosed-loop poles for several gains K = [k1, k2]:")
for K in [np.array([[0.0, 0.0]]),
np.array([[3.0, 0.0]]),
np.array([[8.0, 100.0]]),
np.array([[-1.0, -50.0]])]:
Acl = A - B @ K
print(f" K = {K.tolist()} -> eig(A-BK) = {np.sort_complex(eigvals(Acl))}")
print("\nAttempting full pole placement at {-4, -5}:")
try:
result = place_poles(A, B, [-4.0, -5.0])
print("K =", result.gain_matrix)
print("eig(A-BK) =", eigvals(A - B @ result.gain_matrix))
except Exception as exc:
print("Pole placement failed because the pair (A,B) is not controllable.")
print("Reason:", exc)
print("\nReachable-basis decomposition:")
T, Abar, Bbar, r = kalman_decomposition_by_reachable_basis(A, B)
print("reachable dimension r =", r)
print("T =\n", T)
print("Abar = T^T A T =\n", Abar)
print("Bbar = T^T B =\n", Bbar)
print("The uncontrollable block contains the unassignable eigenvalue +2.")
if __name__ == "__main__":
main()
Chapter25_Lesson1.cpp
/*
Chapter25_Lesson1.cpp
Uncontrollable Modes and Unassignable Poles
A small from-scratch C++ example for a 2-state SISO system.
Compile:
g++ -std=c++17 Chapter25_Lesson1.cpp -o Chapter25_Lesson1
Run:
./Chapter25_Lesson1
*/
#include <cmath>
#include <iomanip>
#include <iostream>
#include <vector>
struct Mat2 {
double a11, a12, a21, a22;
};
struct Vec2 {
double x1, x2;
};
Vec2 mat_vec(const Mat2& A, const Vec2& x) {
return {A.a11 * x.x1 + A.a12 * x.x2,
A.a21 * x.x1 + A.a22 * x.x2};
}
double det2(double m11, double m12, double m21, double m22) {
return m11 * m22 - m12 * m21;
}
int rank_2_by_2_columns(const Vec2& c1, const Vec2& c2, double tol = 1e-10) {
double d = det2(c1.x1, c2.x1, c1.x2, c2.x2);
if (std::abs(d) > tol) return 2;
if (std::abs(c1.x1) > tol || std::abs(c1.x2) > tol ||
std::abs(c2.x1) > tol || std::abs(c2.x2) > tol) return 1;
return 0;
}
void print_eigenvalues_2x2(const Mat2& A) {
double tr = A.a11 + A.a22;
double det = A.a11 * A.a22 - A.a12 * A.a21;
double disc = tr * tr - 4.0 * det;
if (disc >= 0.0) {
double s = std::sqrt(disc);
std::cout << "{" << (tr + s) / 2.0 << ", " << (tr - s) / 2.0 << "}";
} else {
double real = tr / 2.0;
double imag = std::sqrt(-disc) / 2.0;
std::cout << "{" << real << " + " << imag << "i, "
<< real << " - " << imag << "i}";
}
}
int pbh_rank_for_diagonal_example(double lambda, const Mat2& A, const Vec2& B, double tol = 1e-10) {
// For n=2, PBH matrix is [lambda I - A, B], a 2 x 3 matrix.
// We compute whether any 2x2 minor is nonzero.
double c1_1 = lambda - A.a11, c1_2 = -A.a21;
double c2_1 = -A.a12, c2_2 = lambda - A.a22;
double c3_1 = B.x1, c3_2 = B.x2;
double m12 = det2(c1_1, c2_1, c1_2, c2_2);
double m13 = det2(c1_1, c3_1, c1_2, c3_2);
double m23 = det2(c2_1, c3_1, c2_2, c3_2);
return (std::abs(m12) > tol || std::abs(m13) > tol || std::abs(m23) > tol) ? 2 : 1;
}
int main() {
Mat2 A{0.0, 0.0, 0.0, 2.0};
Vec2 B{1.0, 0.0};
Vec2 AB = mat_vec(A, B);
int rankC = rank_2_by_2_columns(B, AB);
std::cout << std::fixed << std::setprecision(3);
std::cout << "A = [[0, 0], [0, 2]], B = [1, 0]^T\n";
std::cout << "Controllability matrix C = [B, AB] = [["
<< B.x1 << ", " << AB.x1 << "], ["
<< B.x2 << ", " << AB.x2 << "]]\n";
std::cout << "rank(C) = " << rankC << " out of n = 2\n\n";
std::cout << "PBH ranks:\n";
for (double lambda : {0.0, 2.0}) {
int r = pbh_rank_for_diagonal_example(lambda, A, B);
std::cout << " lambda = " << lambda << ", rank([lambda I - A, B]) = "
<< r << "/2";
if (r < 2) std::cout << " <-- uncontrollable mode";
std::cout << "\n";
}
std::cout << "\nClosed-loop eigenvalues for K = [k1, k2]:\n";
std::vector<std::pair<double, double>> gains = { {0, 0}, {3, 0}, {8, 100}, {-1, -50} };
for (auto [k1, k2] : gains) {
Mat2 Acl{A.a11 - B.x1 * k1, A.a12 - B.x1 * k2,
A.a21 - B.x2 * k1, A.a22 - B.x2 * k2};
std::cout << " K = [" << k1 << ", " << k2 << "] -> eig(A-BK) = ";
print_eigenvalues_2x2(Acl);
std::cout << "\n";
}
std::cout << "\nThe eigenvalue 2 remains fixed for every K, so it is unassignable.\n";
return 0;
}
Chapter25_Lesson1.java
/*
Chapter25_Lesson1.java
Uncontrollable Modes and Unassignable Poles
Compile:
javac Chapter25_Lesson1.java
Run:
java Chapter25_Lesson1
*/
public class Chapter25_Lesson1 {
static class Mat2 {
double a11, a12, a21, a22;
Mat2(double a11, double a12, double a21, double a22) {
this.a11 = a11; this.a12 = a12; this.a21 = a21; this.a22 = a22;
}
}
static class Vec2 {
double x1, x2;
Vec2(double x1, double x2) { this.x1 = x1; this.x2 = x2; }
}
static Vec2 matVec(Mat2 A, Vec2 x) {
return new Vec2(A.a11 * x.x1 + A.a12 * x.x2,
A.a21 * x.x1 + A.a22 * x.x2);
}
static double det2(double m11, double m12, double m21, double m22) {
return m11 * m22 - m12 * m21;
}
static int rank2By2Columns(Vec2 c1, Vec2 c2, double tol) {
double d = det2(c1.x1, c2.x1, c1.x2, c2.x2);
if (Math.abs(d) > tol) return 2;
if (Math.abs(c1.x1) > tol || Math.abs(c1.x2) > tol ||
Math.abs(c2.x1) > tol || Math.abs(c2.x2) > tol) return 1;
return 0;
}
static int pbhRank(double lambda, Mat2 A, Vec2 B, double tol) {
// PBH matrix is [lambda I - A, B], a 2 x 3 matrix.
double c1_1 = lambda - A.a11, c1_2 = -A.a21;
double c2_1 = -A.a12, c2_2 = lambda - A.a22;
double c3_1 = B.x1, c3_2 = B.x2;
double m12 = det2(c1_1, c2_1, c1_2, c2_2);
double m13 = det2(c1_1, c3_1, c1_2, c3_2);
double m23 = det2(c2_1, c3_1, c2_2, c3_2);
return (Math.abs(m12) > tol || Math.abs(m13) > tol || Math.abs(m23) > tol) ? 2 : 1;
}
static String eig2x2(Mat2 A) {
double tr = A.a11 + A.a22;
double det = A.a11 * A.a22 - A.a12 * A.a21;
double disc = tr * tr - 4.0 * det;
if (disc >= 0.0) {
double s = Math.sqrt(disc);
return String.format("{ %.3f, %.3f }", (tr + s) / 2.0, (tr - s) / 2.0);
} else {
double real = tr / 2.0;
double imag = Math.sqrt(-disc) / 2.0;
return String.format("{ %.3f + %.3fi, %.3f - %.3fi }", real, imag, real, imag);
}
}
public static void main(String[] args) {
Mat2 A = new Mat2(0.0, 0.0, 0.0, 2.0);
Vec2 B = new Vec2(1.0, 0.0);
Vec2 AB = matVec(A, B);
int rankC = rank2By2Columns(B, AB, 1e-10);
System.out.println("A = [[0, 0], [0, 2]], B = [1, 0]^T");
System.out.printf("Controllability matrix C = [[%.3f, %.3f], [%.3f, %.3f]]%n",
B.x1, AB.x1, B.x2, AB.x2);
System.out.println("rank(C) = " + rankC + " out of n = 2");
System.out.println("\nPBH ranks:");
for (double lambda : new double[] {0.0, 2.0}) {
int r = pbhRank(lambda, A, B, 1e-10);
System.out.printf(" lambda = %.3f, rank([lambda I - A, B]) = %d/2", lambda, r);
if (r < 2) System.out.print(" <-- uncontrollable mode");
System.out.println();
}
System.out.println("\nClosed-loop eigenvalues for K = [k1, k2]:");
double[][] gains = { {0, 0}, {3, 0}, {8, 100}, {-1, -50} };
for (double[] K : gains) {
double k1 = K[0], k2 = K[1];
Mat2 Acl = new Mat2(A.a11 - B.x1 * k1, A.a12 - B.x1 * k2,
A.a21 - B.x2 * k1, A.a22 - B.x2 * k2);
System.out.printf(" K = [%.3f, %.3f] -> eig(A-BK) = %s%n", k1, k2, eig2x2(Acl));
}
System.out.println("\nThe eigenvalue 2 remains fixed for every K, so it is unassignable.");
}
}
Chapter25_Lesson1.m
% Chapter25_Lesson1.m
% Uncontrollable Modes and Unassignable Poles
%
% Requires for ctrb/place:
% MATLAB Control System Toolbox
% If the toolbox is unavailable, the script still demonstrates the main result
% using explicit controllability matrices and eigenvalues.
clear; clc;
A = [0 0;
0 2];
B = [1;
0];
fprintf('A =\n'); disp(A);
fprintf('B =\n'); disp(B);
% Kalman controllability matrix from scratch
C = [B A*B];
fprintf('Kalman controllability matrix C = [B AB] =\n'); disp(C);
fprintf('rank(C) = %d out of n = %d\n', rank(C), size(A,1));
% Compare with Control System Toolbox if available
if exist('ctrb','file') == 2
C_toolbox = ctrb(A,B);
fprintf('ctrb(A,B) =\n'); disp(C_toolbox);
end
% PBH test at each eigenvalue
lambda = eig(A);
fprintf('\nPBH test:\n');
for i = 1:length(lambda)
M = [lambda(i)*eye(size(A)) - A, B];
r = rank(M);
fprintf(' lambda = %.4g, rank([lambda I - A, B]) = %d/%d', lambda(i), r, size(A,1));
if r < size(A,1)
fprintf(' <-- uncontrollable mode');
end
fprintf('\n');
end
% State feedback: only one closed-loop pole can move.
fprintf('\nClosed-loop poles for several gains K = [k1 k2]:\n');
Ks = [0 0;
3 0;
8 100;
-1 -50];
for i = 1:size(Ks,1)
K = Ks(i,:);
Acl = A - B*K;
fprintf(' K = [%8.3f %8.3f] -> eig(A-BK) = ', K(1), K(2));
disp(eig(Acl).');
end
% Full pole placement is not valid because the pair is not controllable.
fprintf('\nAttempting place(A,B,[-4 -5]):\n');
if exist('place','file') == 2
try
Kplace = place(A,B,[-4 -5]);
disp(Kplace);
catch ME
fprintf('Pole placement failed: %s\n', ME.message);
end
else
fprintf('Control System Toolbox place() was not found.\n');
end
% A controllable comparison system
Ac = [0 1;
-2 -3];
Bc = [0; 1];
fprintf('\nControllable comparison system:\n');
fprintf('rank([Bc Ac*Bc]) = %d\n', rank([Bc Ac*Bc]));
if exist('place','file') == 2
Kc = place(Ac,Bc,[-4 -5]);
fprintf('Kc from place = '); disp(Kc);
fprintf('eig(Ac-Bc*Kc) = '); disp(eig(Ac-Bc*Kc).');
end
Chapter25_Lesson1.nb
Notebook[{
Cell["Chapter25_Lesson1.nb", "Title"],
Cell["Uncontrollable Modes and Unassignable Poles", "Subtitle"],
Cell["This notebook computes the Kalman controllability matrix, applies the PBH test, and demonstrates that an uncontrollable eigenvalue is invariant under state feedback.", "Text"],
Cell[BoxData[ToBoxes[
ClearAll[A, B, K, controllabilityMatrix, pbhRank, gains];
A = { {0, 0}, {0, 2} };
B = { {1}, {0} };
]], "Input"],
Cell[BoxData[ToBoxes[
controllabilityMatrix[A_, B_] := Module[{n = Length[A]},
ArrayFlatten[{Table[MatrixPower[A, k].B, {k, 0, n - 1}]}]
];
Cmat = controllabilityMatrix[A, B];
{"C =", MatrixForm[Cmat], "rank(C) =", MatrixRank[Cmat]}
]], "Input"],
Cell[BoxData[ToBoxes[
pbhRank[lambda_] := MatrixRank[ArrayFlatten[{ {lambda IdentityMatrix[Length[A]] - A, B} }]];
Table[{lambda, pbhRank[lambda]}, {lambda, Eigenvalues[A]}]
]], "Input"],
Cell[BoxData[ToBoxes[
gains = { {0, 0}, {3, 0}, {8, 100}, {-1, -50} };
Table[
K = {gain};
{"K =", gain, "closed-loop eigenvalues =", Eigenvalues[A - B.K]},
{gain, gains}
]
]], "Input"],
Cell["Symbolic proof for the example: for K = {k1,k2}, the characteristic polynomial of A - B K contains the fixed factor (s - 2).", "Text"],
Cell[BoxData[ToBoxes[
ClearAll[k1, k2, s];
K = { {k1, k2} };
CharacteristicPolynomial[A - B.K, s] // Factor
]], "Input"]
}]
8. Problems and Solutions
Problem 1 (Kalman Test and Fixed Pole): For \( \mathbf{A}=\begin{bmatrix}0&0\\0&2\end{bmatrix} \) and \( \mathbf{B}=\begin{bmatrix}1\\0\end{bmatrix} \), compute the controllability matrix and determine which pole is unassignable.
Solution:
\[ \mathcal{C}=\begin{bmatrix}\mathbf{B}&\mathbf{A}\mathbf{B}\end{bmatrix} =\begin{bmatrix}1&0\\0&0\end{bmatrix}, \qquad \operatorname{rank}(\mathcal{C})=1<2. \]
The first state is reachable but the second state is not. With \( \mathbf{K}=\begin{bmatrix}k_1&k_2\end{bmatrix} \), the closed-loop matrix is upper triangular:
\[ \mathbf{A}-\mathbf{B}\mathbf{K}= \begin{bmatrix}-k_1&-k_2\\0&2\end{bmatrix}. \]
Hence the eigenvalue \( 2 \) is fixed for all \( \mathbf{K} \). It is the unassignable pole.
Problem 2 (PBH Certificate): Show by the PBH test that the eigenvalue \( 2 \) in Problem 1 is uncontrollable.
Solution:
\[ \begin{bmatrix}2\mathbf{I}-\mathbf{A}&\mathbf{B}\end{bmatrix} =\begin{bmatrix}2&0&1\\0&0&0\end{bmatrix}. \]
The rank is \( 1<2 \), so PBH declares \( \lambda=2 \) uncontrollable. Equivalently, \( \mathbf{q}^*=\begin{bmatrix}0&1\end{bmatrix} \) satisfies \( \mathbf{q}^*\mathbf{A}=2\mathbf{q}^* \) and \( \mathbf{q}^*\mathbf{B}=0 \).
Problem 3 (General Factorization): Suppose a similarity transformation gives \( \bar{\mathbf{A} }=\begin{bmatrix}\mathbf{A}_r&\mathbf{A}_{12}\\ \mathbf{0}&\mathbf{A}_u\end{bmatrix} \) and \( \bar{\mathbf{B} }=\begin{bmatrix}\mathbf{B}_r\\\mathbf{0}\end{bmatrix} \). Prove that the eigenvalues of \( \mathbf{A}_u \) are unassignable.
Solution: For \( \bar{\mathbf{K} }=\begin{bmatrix}\mathbf{K}_r&\mathbf{K}_u\end{bmatrix} \),
\[ \bar{\mathbf{A} }-\bar{\mathbf{B} }\bar{\mathbf{K} }= \begin{bmatrix} \mathbf{A}_r-\mathbf{B}_r\mathbf{K}_r& \mathbf{A}_{12}-\mathbf{B}_r\mathbf{K}_u\\ \mathbf{0}&\mathbf{A}_u \end{bmatrix}. \]
The determinant of a block upper triangular matrix is the product of the determinants of its diagonal blocks. Thus the characteristic polynomial always contains \( \det(s\mathbf{I}-\mathbf{A}_u) \), independently of \( \mathbf{K} \).
Problem 4 (Stabilizability Decision): Let \( \sigma(\mathbf{A}_u)=\{-1,-3\} \). The controllable block can be assigned arbitrarily. Is the full system stabilizable? Is full pole assignment possible?
Solution: The uncontrollable poles are already stable because their real parts are negative. Therefore, one can choose feedback to place the controllable poles in the open left half-plane, making the full closed-loop matrix Hurwitz. The system is stabilizable. However, full pole assignment is not possible because the two uncontrollable poles \( -1 \) and \( -3 \) cannot be moved.
Problem 5 (Design Interpretation): A mechanical system has one actuator but two vibration modes. The controllability matrix has rank one, and the uncontrollable mode has eigenvalues \( 0.1\pm 4i \). Can state feedback stabilize the complete model?
Solution: No. The uncontrollable mode has real part \( 0.1>0 \), so it is unstable. Since feedback cannot move uncontrollable eigenvalues, the pair is not stabilizable. The engineering remedy is not a more aggressive gain; it is a structural redesign such as adding or relocating actuators so that this mode enters the reachable subspace.
9. Summary
State feedback modifies the matrix \( \mathbf{A} \) only through the input directions contained in \( \mathbf{B} \). If the pair \( (\mathbf{A},\mathbf{B}) \) is not controllable, the reachable subspace has dimension \( r<n \), and a similarity transformation separates assignable dynamics from unassignable dynamics. The PBH test provides a modal certificate: if a left eigenvector is orthogonal to \( \mathbf{B} \), its eigenvalue is fixed under all feedback gains. Full pole assignment requires controllability, while stabilization only requires that every uncontrollable mode be stable.
10. References
- Kalman, R.E. (1960). Contributions to the theory of optimal control. Boletín de la Sociedad Matemática Mexicana, 5, 102–119.
- Kalman, R.E., Ho, Y.C., & Narendra, K.S. (1963). Controllability of linear dynamical systems. Contributions to Differential Equations, 1(2), 189–213.
- Gilbert, E.G. (1963). Controllability and observability in multivariable control systems. SIAM Journal on Control, 1(2), 128–151.
- Hautus, M.L.J. (1969). Controllability and observability conditions of linear autonomous systems. Nederl. Akad. Wetensch. Proc. Ser. A, 72, 443–448.
- Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 12(6), 660–665.
- Brunovsky, P. (1970). A classification of linear controllable systems. Kybernetika, 6(3), 173–188.
- Morse, A.S. (1973). Structural invariants of linear multivariable systems. SIAM Journal on Control, 11(3), 446–465.
- Rosenbrock, H.H. (1968). State-space and multivariable theory. International Journal of Control, 8(4), 337–352.