Chapter 23: Pole Placement for Single-Input Systems
Lesson 5: Numerical Sensitivity and Conditioning in Pole Placement
This lesson studies why pole placement can be theoretically possible but numerically fragile. We analyze the conditioning of the controllability matrix, Ackermann’s formula, coordinate scaling, polynomial coefficient sensitivity, and closed-loop eigenvalue perturbation. The goal is to teach students how to diagnose unreliable pole-placement designs before implementing them in software or hardware.
1. Why Numerical Conditioning Matters in Pole Placement
In the previous lessons, we developed the single-input pole-placement problem for a controllable continuous-time LTI system
\[ \dot{\mathbf{x} } = \mathbf{A}\mathbf{x}+\mathbf{b}u,\qquad u=-\mathbf{k}\mathbf{x}. \]
The closed-loop matrix is \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{b}\mathbf{k} \), and pole placement asks for
\[ \sigma(\mathbf{A}-\mathbf{b}\mathbf{k}) =\{\lambda_1^\star,\lambda_2^\star,\dots,\lambda_n^\star\}. \]
The mathematical existence condition is controllability:
\[ \operatorname{rank}\mathcal{C}=n,\qquad \mathcal{C}=\begin{bmatrix}\mathbf{b}&\mathbf{A}\mathbf{b}& \cdots&\mathbf{A}^{n-1}\mathbf{b}\end{bmatrix}. \]
However, in floating-point computation, the condition \( \operatorname{rank}\mathcal{C}=n \) is not enough. If \( \mathcal{C} \) is nearly singular, the feedback gain can become extremely sensitive to small modeling errors, sensor calibration errors, discretization errors, or numerical roundoff. Thus, practical pole placement requires both controllability and acceptable numerical conditioning.
flowchart TD
A["State-space model A, b"] --> B["Check rank of controllability matrix"]
B --> C["Compute condition number of controllability matrix"]
C --> D["Choose desired closed-loop poles"]
D --> E["Compute feedback gain"]
E --> F["Evaluate gain size and closed-loop eigenvalue sensitivity"]
F --> G{"Sensitivity acceptable?"}
G -->|"yes"| H["Use design with validation"]
G -->|"no"| I["Rescale states or choose less aggressive poles"]
I --> D
2. Ackermann’s Formula and Its Numerical Weakness
For a single-input controllable system, Ackermann’s formula gives the feedback gain directly:
\[ \mathbf{k} =\mathbf{e}_n^{T}\mathcal{C}^{-1}p_d(\mathbf{A}),\qquad \mathbf{e}_n^{T}=\begin{bmatrix}0&0&\cdots&1\end{bmatrix}. \]
The desired characteristic polynomial is
\[ p_d(s)=\prod_{i=1}^{n}(s-\lambda_i^\star) =s^n+\alpha_{n-1}s^{n-1}+\cdots+\alpha_1s+\alpha_0. \]
Hence
\[ p_d(\mathbf{A}) =\mathbf{A}^n+\alpha_{n-1}\mathbf{A}^{n-1} +\cdots+\alpha_1\mathbf{A}+\alpha_0\mathbf{I}. \]
The formula contains two important sources of numerical sensitivity:
- Inversion of \( \mathcal{C} \): if \( \mathcal{C} \) is ill-conditioned, then small numerical errors are amplified.
- Polynomial evaluation \( p_d(\mathbf{A}) \): high powers of \( \mathbf{A} \) and large polynomial coefficients can cause cancellation and overflow-like scaling effects.
Let the computed controllability matrix be \( \mathcal{C}+\Delta\mathcal{C} \). To first order, the inverse perturbation is
\[ (\mathcal{C}+\Delta\mathcal{C})^{-1} \approx \mathcal{C}^{-1} -\mathcal{C}^{-1}(\Delta\mathcal{C})\mathcal{C}^{-1}. \]
Therefore, the relative amplification is governed approximately by
\[ \frac{\|\Delta\mathcal{C}^{-1}\|}{\|\mathcal{C}^{-1}\|} \lesssim \kappa(\mathcal{C}) \frac{\|\Delta\mathcal{C}\|}{\|\mathcal{C}\|},\qquad \kappa(\mathcal{C})=\|\mathcal{C}\|\|\mathcal{C}^{-1}\|. \]
A large condition number \( \kappa(\mathcal{C}) \) means that pole placement is numerically fragile even when the exact symbolic system is controllable.
3. Condition Number and Near Loss of Controllability
The singular value decomposition of the controllability matrix is
\[ \mathcal{C}=\mathbf{U}\boldsymbol{\Sigma}\mathbf{V}^{T},\qquad \boldsymbol{\Sigma}=\operatorname{diag}(\sigma_1,\dots,\sigma_n), \quad \sigma_1\ge\sigma_2\ge\cdots\ge\sigma_n\ge0. \]
In the 2-norm, the condition number is
\[ \kappa_2(\mathcal{C})=\frac{\sigma_{\max}(\mathcal{C})} {\sigma_{\min}(\mathcal{C})}. \]
If \( \sigma_{\min}(\mathcal{C}) \) is small, then some state direction is controllable only with very large input effort. This has both a physical and a numerical meaning:
\[ \sigma_{\min}(\mathcal{C})\approx 0 \quad\Longrightarrow\quad \text{nearly uncontrollable direction}. \]
The relationship to the finite-horizon controllability Gramian is also important. For continuous-time systems,
\[ \mathbf{W}_c(T)=\int_0^T e^{\mathbf{A}t}\mathbf{b}\mathbf{b}^{T} e^{\mathbf{A}^{T}t}\,dt. \]
Although \( \mathcal{C} \) and \( \mathbf{W}_c(T) \) are different objects, both reveal actuator authority. A nearly singular \( \mathcal{C} \) or a Gramian with very small eigenvalues indicates that certain directions are difficult to control.
\[ E_{\min}(\mathbf{x}_f,T) =\mathbf{x}_f^{T}\mathbf{W}_c(T)^{-1}\mathbf{x}_f. \]
Thus, directions associated with small eigenvalues of \( \mathbf{W}_c(T) \) require large control energy. Such directions often correspond to numerically sensitive pole-placement gains.
4. Coordinate Scaling and Similarity Transformations
Pole locations are invariant under similarity transformations, but numerical conditioning is not. Let
\[ \mathbf{x}=\mathbf{T}\mathbf{z},\qquad \dot{\mathbf{z} } =\mathbf{T}^{-1}\mathbf{A}\mathbf{T}\mathbf{z} +\mathbf{T}^{-1}\mathbf{b}u. \]
Define
\[ \bar{\mathbf{A} }=\mathbf{T}^{-1}\mathbf{A}\mathbf{T},\qquad \bar{\mathbf{b} }=\mathbf{T}^{-1}\mathbf{b}. \]
The transformed controllability matrix is
\[ \bar{\mathcal{C} } =\begin{bmatrix}\bar{\mathbf{b} }&\bar{\mathbf{A} }\bar{\mathbf{b} }& \cdots&\bar{\mathbf{A} }^{n-1}\bar{\mathbf{b} }\end{bmatrix} =\mathbf{T}^{-1}\mathcal{C}. \]
Therefore,
\[ \kappa(\bar{\mathcal{C} }) =\kappa(\mathbf{T}^{-1}\mathcal{C}), \]
which may be much better or much worse than \( \kappa(\mathcal{C}) \). This is why state scaling is not merely cosmetic. If one state is measured in millimeters and another in thousands of radians per second, the numerical problem may become artificially ill-conditioned.
If the feedback in transformed coordinates is \( u=-\bar{\mathbf{k} }\mathbf{z} \), then since \( \mathbf{z}=\mathbf{T}^{-1}\mathbf{x} \), the physical-coordinate feedback is
\[ u=-\bar{\mathbf{k} }\mathbf{T}^{-1}\mathbf{x} =-\mathbf{k}\mathbf{x},\qquad \mathbf{k}=\bar{\mathbf{k} }\mathbf{T}^{-1}. \]
5. Closed-Loop Eigenvalue Sensitivity
Even after a feedback gain is computed, the resulting closed-loop poles can be sensitive to perturbations. Let
\[ \mathbf{M}=\mathbf{A}-\mathbf{b}\mathbf{k}. \]
Suppose \( \lambda_i \) is a simple eigenvalue of \( \mathbf{M} \) with right and left eigenvectors
\[ \mathbf{M}\mathbf{v}_i=\lambda_i\mathbf{v}_i,\qquad \mathbf{w}_i^{T}\mathbf{M}=\lambda_i\mathbf{w}_i^{T}. \]
If \( \mathbf{M} \) is perturbed to \( \mathbf{M}+\Delta\mathbf{M} \), then first-order perturbation theory gives
\[ \Delta\lambda_i \approx \frac{\mathbf{w}_i^{T}(\Delta\mathbf{M})\mathbf{v}_i} {\mathbf{w}_i^{T}\mathbf{v}_i}. \]
Hence the eigenvalue condition number is
\[ \kappa(\lambda_i) = \frac{\|\mathbf{w}_i\|_2\|\mathbf{v}_i\|_2} {|\mathbf{w}_i^{T}\mathbf{v}_i|}. \]
If \( \mathbf{w}_i^{T}\mathbf{v}_i \) is small, then the pole is highly sensitive. This often happens when the closed-loop matrix is close to being defective, meaning that it is nearly non-diagonalizable.
\[ |\Delta\lambda_i| \le \kappa(\lambda_i)\|\Delta\mathbf{M}\|_2 +O(\|\Delta\mathbf{M}\|_2^2). \]
6. Aggressive Pole Placement and Large Feedback Gains
Moving poles far into the left half-plane usually increases speed of response, but it also tends to increase feedback gain magnitude. If desired poles are chosen as
\[ \lambda_i^\star=-\rho \mu_i,\qquad \rho>0, \]
then the desired polynomial coefficients often grow rapidly with \( \rho \). For example,
\[ p_d(s)=\prod_{i=1}^{n}(s+\rho\mu_i) =s^n+\rho c_{n-1}s^{n-1} +\rho^2c_{n-2}s^{n-2} +\cdots+\rho^n c_0. \]
Thus, fast poles can create large terms in \( p_d(\mathbf{A}) \). Since Ackermann’s formula multiplies this matrix polynomial by \( \mathcal{C}^{-1} \), the gain may become very large:
\[ \|\mathbf{k}\| \le \|\mathbf{e}_n^{T}\| \|\mathcal{C}^{-1}\| \|p_d(\mathbf{A})\|. \]
Large feedback gains are not merely a numerical issue. They can produce actuator saturation, noise amplification, unmodeled high-frequency dynamics, and poor robustness. Therefore, practical pole placement requires a trade-off between speed and sensitivity.
7. Practical Diagnostic Procedure for SISO Pole Placement
A reliable pole-placement workflow should check more than exact controllability. The following procedure is recommended before accepting a feedback gain:
flowchart TD
A["Build A and b from model"] --> B["Compute controllability matrix C"]
B --> C["Check numerical rank using SVD"]
C --> D["Compute cond(C)"]
D --> E["Select desired poles from time-domain specs"]
E --> F["Compute K using robust algorithm or Ackermann formula"]
F --> G["Check norm(K) and actuator feasibility"]
G --> H["Compute closed-loop eigenvalue condition numbers"]
H --> I["Perturb A and b and recompute closed-loop poles"]
I --> J{"Pole drift small?"}
J -->|"yes"| K["Accept design after simulation"]
J -->|"no"| L["Rescale states, reduce speed, or redesign"]
In software, the numerical rank is usually estimated by singular values:
\[ \operatorname{rank}_{tol}(\mathcal{C}) = \#\{i:\sigma_i>\tau\sigma_{\max}\}, \]
where \( \tau \) is a tolerance such as \( 10^{-10} \) or a machine-precision-based threshold.
8. Python Implementation — Conditioning and Perturbation Test
Chapter23_Lesson5.py
import numpy as np
from numpy.linalg import inv, cond, norm, eig
import scipy.linalg as la
import matplotlib.pyplot as plt
def controllability_matrix(A, B):
n = A.shape[0]
cols = []
Ak = np.eye(n)
for _ in range(n):
cols.append(Ak @ B)
Ak = A @ Ak
return np.hstack(cols)
def polynomial_matrix(A, coeffs):
n = A.shape[0]
P = np.zeros_like(A, dtype=float)
for c in coeffs:
P = P @ A + c * np.eye(n)
return P
def ackermann_gain(A, B, desired_poles):
n = A.shape[0]
C = controllability_matrix(A, B)
coeffs = np.poly(desired_poles)
pA = polynomial_matrix(A, coeffs)
eT = np.zeros((1, n))
eT[0, -1] = 1.0
K = eT @ inv(C) @ pA
return K, C, coeffs
def eigenvalue_condition_numbers(M):
eigvals, VL, VR = la.eig(M, left=True, right=True)
kappas = []
for i in range(len(eigvals)):
w = VL[:, i]
v = VR[:, i]
denom = abs(np.vdot(w, v))
kappas.append((norm(w) * norm(v)) / denom)
return eigvals, np.array(kappas)
def perturbation_experiment(A, B, K, eps=1e-7, trials=300, seed=1):
rng = np.random.default_rng(seed)
M0 = A - B @ K
lam0 = np.sort_complex(eig(M0)[0])
drifts = []
for _ in range(trials):
dA = rng.normal(size=A.shape)
dB = rng.normal(size=B.shape)
dA *= eps * max(1.0, norm(A, 2)) / norm(dA, 2)
dB *= eps * max(1.0, norm(B, 2)) / norm(dB, 2)
M = (A + dA) - (B + dB) @ K
lam = np.sort_complex(eig(M)[0])
drifts.append(norm(lam - lam0, 2))
return np.array(drifts)
A = np.array([[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
[-2.0, -3.0, -4.0]])
B = np.array([[0.0], [0.0], [1.0]])
desired_poles = np.array([-4.0, -5.0, -6.0])
K, C, coeffs = ackermann_gain(A, B, desired_poles)
M = A - B @ K
eigvals, eig_kappa = eigenvalue_condition_numbers(M)
drifts = perturbation_experiment(A, B, K)
print("Desired polynomial coefficients:", coeffs)
print("cond(C):", cond(C))
print("K:", K)
print("Closed-loop eigenvalues:", eig(M)[0])
print("Eigenvalue condition numbers:", eig_kappa)
print("Median pole drift:", np.median(drifts))
print("Maximum pole drift:", np.max(drifts))
In production Python workflows,
scipy.signal.place_poles and the
python-control package are preferable to manually inverting
the controllability matrix. The direct Ackermann formula is
pedagogically useful but may be numerically fragile for high-order
systems.
9. C++, Java, MATLAB, and Wolfram Mathematica Implementations
Chapter23_Lesson5.cpp
// Dependency: Eigen 3
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <iostream>
#include <vector>
using Matrix = Eigen::MatrixXd;
Matrix controllabilityMatrix(const Matrix& A, const Matrix& B) {
int n = A.rows();
Matrix C(n, n);
Matrix Ak = Matrix::Identity(n, n);
for (int k = 0; k < n; ++k) {
C.col(k) = Ak * B;
Ak = A * Ak;
}
return C;
}
Matrix polynomialMatrix(const Matrix& A, const std::vector<double>& coeffs) {
int n = A.rows();
Matrix P = Matrix::Zero(n, n);
Matrix I = Matrix::Identity(n, n);
for (double c : coeffs) {
P = P * A + c * I;
}
return P;
}
Matrix ackermannGain(const Matrix& A, const Matrix& B,
const std::vector<double>& coeffs) {
int n = A.rows();
Matrix C = controllabilityMatrix(A, B);
Matrix pA = polynomialMatrix(A, coeffs);
Matrix eT = Matrix::Zero(1, n);
eT(0, n - 1) = 1.0;
return eT * C.inverse() * pA;
}
int main() {
Matrix A(3, 3);
A << 0, 1, 0,
0, 0, 1,
-2,-3,-4;
Matrix B(3, 1);
B << 0, 0, 1;
std::vector<double> coeffs = {1.0, 15.0, 74.0, 120.0};
Matrix C = controllabilityMatrix(A, B);
Matrix K = ackermannGain(A, B, coeffs);
Matrix M = A - B * K;
Eigen::JacobiSVD<Matrix> svd(C);
double condC =
svd.singularValues()(0) /
svd.singularValues()(svd.singularValues().size() - 1);
std::cout << "cond(C) = " << condC << std::endl;
std::cout << "K = " << K << std::endl;
std::cout << "Closed-loop eigenvalues:" << std::endl;
Eigen::EigenSolver<Matrix> solver(M);
std::cout << solver.eigenvalues() << std::endl;
}
Chapter23_Lesson5.java
// Plain Java demonstration.
// For production use, prefer EJML or Apache Commons Math.
import java.util.Arrays;
public class Chapter23_Lesson5 {
static double[][] matMul(double[][] A, double[][] B) {
int m = A.length, n = B[0].length, p = B.length;
double[][] C = new double[m][n];
for (int i = 0; i < m; i++)
for (int k = 0; k < p; k++)
for (int j = 0; j < n; j++)
C[i][j] += A[i][k] * B[k][j];
return C;
}
static double[][] identity(int n) {
double[][] I = new double[n][n];
for (int i = 0; i < n; i++) I[i][i] = 1.0;
return I;
}
static double[][] controllabilityMatrix(double[][] A, double[][] B) {
int n = A.length;
double[][] C = new double[n][n];
double[][] Ak = identity(n);
for (int k = 0; k < n; k++) {
double[][] col = matMul(Ak, B);
for (int i = 0; i < n; i++) C[i][k] = col[i][0];
Ak = matMul(A, Ak);
}
return C;
}
public static void main(String[] args) {
double[][] A = {
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0},
{-2.0, -3.0, -4.0}
};
double[][] B = { {0.0}, {0.0}, {1.0} };
double[][] C = controllabilityMatrix(A, B);
System.out.println("Controllability matrix:");
for (double[] row : C) System.out.println(Arrays.toString(row));
System.out.println("Use EJML or Apache Commons Math for robust");
System.out.println("SVD condition numbers and eigenvalue computations.");
}
}
Chapter23_Lesson5.m
clear; clc; close all;
A = [0 1 0;
0 0 1;
-2 -3 -4];
B = [0; 0; 1];
desired_poles = [-4 -5 -6];
C = ctrb_local(A, B);
K = ackermann_local(A, B, desired_poles);
M = A - B*K;
fprintf("cond(C) = %.6e\n", cond(C));
disp("K = ");
disp(K);
disp("Closed-loop eigenvalues:");
disp(eig(M));
if exist("acker", "file") == 2
disp("MATLAB acker result:");
disp(acker(A, B, desired_poles));
end
if exist("place", "file") == 2
disp("MATLAB place result:");
disp(place(A, B, desired_poles));
end
function C = ctrb_local(A, B)
n = size(A, 1);
C = zeros(n, n);
Ak = eye(n);
for k = 1:n
C(:, k) = Ak * B;
Ak = A * Ak;
end
end
function K = ackermann_local(A, B, poles)
n = size(A, 1);
C = ctrb_local(A, B);
coeffs = poly(poles);
pA = zeros(n);
for k = 1:length(coeffs)
pA = pA * A + coeffs(k) * eye(n);
end
eT = zeros(1, n);
eT(n) = 1;
K = eT * (C \ pA);
end
Chapter23_Lesson5.nb
ClearAll["Global`*"];
A = { {0, 1, 0}, {0, 0, 1}, {-2, -3, -4} };
B = { {0}, {0}, {1} };
desiredPoles = {-4, -5, -6};
ControllabilityMatrixLocal[A_, B_] := Module[
{n = Length[A]},
Transpose[Table[Flatten[MatrixPower[A, k].B], {k, 0, n - 1}]]
];
PolynomialMatrix[A_, coeffs_] := Module[
{n = Length[A], P},
P = ConstantArray[0, {n, n}];
Do[
P = P.A + coeffs[[k]] IdentityMatrix[n],
{k, 1, Length[coeffs]}
];
P
];
AckermannGain[A_, B_, poles_] := Module[
{n = Length[A], C, poly, pA, eT},
C = ControllabilityMatrixLocal[A, B];
poly = CoefficientList[Expand[Times @@ (s - # & /@ poles)], s] // Reverse;
pA = PolynomialMatrix[A, poly];
eT = UnitVector[n, n];
{eT}.Inverse[C].pA
];
Cmat = ControllabilityMatrixLocal[A, B];
K = AckermannGain[A, B, desiredPoles];
M = A - B.K;
Print["Condition number of C = ", N[ConditionNumber[Cmat]]];
Print["K = ", MatrixForm[N[K]]];
Print["Closed-loop eigenvalues = ", N[Eigenvalues[M]]];
10. Worked Example: Comparing Two Coordinate Scalings
Consider
\[ \mathbf{A}= \begin{bmatrix} 0&1&0\\ 0&0&1\\ -2&-3&-4 \end{bmatrix},\qquad \mathbf{b}= \begin{bmatrix} 0\\0\\1 \end{bmatrix}. \]
The desired poles are
\[ \{-4,-5,-6\}. \]
Therefore,
\[ p_d(s)=(s+4)(s+5)(s+6) =s^3+15s^2+74s+120. \]
Because this example is already in controllable companion-like form, the gain is moderate. Now apply an artificial scaling
\[ \mathbf{T}=\operatorname{diag}(10^{-3},1,10^3). \]
The closed-loop poles are invariant in exact arithmetic, but the transformed controllability matrix \( \bar{\mathcal{C} }=\mathbf{T}^{-1}\mathcal{C} \) can become severely ill-conditioned. This means the same theoretical pole-placement problem can become numerically unreliable simply because the coordinates are badly scaled.
11. Problems and Solutions
Problem 1: Let \( \mathcal{C} \) be nonsingular but ill-conditioned. Show why Ackermann’s formula can produce a highly sensitive gain.
Solution: Ackermann’s formula is
\[ \mathbf{k} =\mathbf{e}_n^{T}\mathcal{C}^{-1}p_d(\mathbf{A}). \]
If \( \mathcal{C} \) is perturbed to \( \mathcal{C}+\Delta\mathcal{C} \), then
\[ \Delta(\mathcal{C}^{-1}) \approx -\mathcal{C}^{-1}(\Delta\mathcal{C})\mathcal{C}^{-1}. \]
Therefore, small errors in \( \mathcal{C} \) are multiplied by \( \mathcal{C}^{-1} \) twice. The error amplification is governed by \( \kappa(\mathcal{C}) \). Hence, even when the system is exactly controllable, the computed feedback can be unreliable if \( \kappa(\mathcal{C}) \) is large.
Problem 2: Prove that under \( \mathbf{x}=\mathbf{T}\mathbf{z} \), the controllability matrix transforms as \( \bar{\mathcal{C} }=\mathbf{T}^{-1}\mathcal{C} \).
Solution: The transformed matrices are
\[ \bar{\mathbf{A} }=\mathbf{T}^{-1}\mathbf{A}\mathbf{T},\qquad \bar{\mathbf{b} }=\mathbf{T}^{-1}\mathbf{b}. \]
Then
\[ \bar{\mathbf{A} }^j\bar{\mathbf{b} } = (\mathbf{T}^{-1}\mathbf{A}\mathbf{T})^j\mathbf{T}^{-1}\mathbf{b} = \mathbf{T}^{-1}\mathbf{A}^j\mathbf{b}. \]
Stacking the columns for \( j=0,1,\dots,n-1 \) gives
\[ \bar{\mathcal{C} } = \begin{bmatrix} \bar{\mathbf{b} }&\bar{\mathbf{A} }\bar{\mathbf{b} }&\cdots& \bar{\mathbf{A} }^{n-1}\bar{\mathbf{b} } \end{bmatrix} = \mathbf{T}^{-1} \begin{bmatrix} \mathbf{b}&\mathbf{A}\mathbf{b}&\cdots& \mathbf{A}^{n-1}\mathbf{b} \end{bmatrix} = \mathbf{T}^{-1}\mathcal{C}. \]
Problem 3: For the desired poles \( -4,-5,-6 \), compute the desired polynomial.
Solution:
\[ p_d(s)=(s+4)(s+5)(s+6). \]
\[ (s+4)(s+5)=s^2+9s+20. \]
\[ p_d(s)=(s^2+9s+20)(s+6) =s^3+15s^2+74s+120. \]
Problem 4: Derive the first-order eigenvalue perturbation formula for a simple eigenvalue.
Solution: Let \( \mathbf{M}\mathbf{v}=\lambda\mathbf{v} \) and perturb \( \mathbf{M} \) by \( \Delta\mathbf{M} \). Write
\[ (\mathbf{M}+\Delta\mathbf{M})(\mathbf{v}+\Delta\mathbf{v}) = (\lambda+\Delta\lambda)(\mathbf{v}+\Delta\mathbf{v}). \]
Neglecting second-order terms gives
\[ \mathbf{M}\Delta\mathbf{v} +\Delta\mathbf{M}\mathbf{v} = \lambda\Delta\mathbf{v} +\Delta\lambda\mathbf{v}. \]
Premultiply by the left eigenvector \( \mathbf{w}^{T} \). Since \( \mathbf{w}^{T}\mathbf{M}=\lambda\mathbf{w}^{T} \), the terms involving \( \Delta\mathbf{v} \) cancel:
\[ \mathbf{w}^{T}\Delta\mathbf{M}\mathbf{v} = \Delta\lambda\,\mathbf{w}^{T}\mathbf{v}. \]
Hence
\[ \Delta\lambda = \frac{\mathbf{w}^{T}\Delta\mathbf{M}\mathbf{v} } {\mathbf{w}^{T}\mathbf{v} }. \]
Problem 5: Explain why repeated or clustered desired poles may be numerically dangerous.
Solution: Repeated or tightly clustered poles can make the closed-loop eigenvector matrix nearly singular. In that case, the closed-loop matrix is close to a defective matrix, and the denominator \( |\mathbf{w}_i^{T}\mathbf{v}_i| \) in the eigenvalue condition number can become small:
\[ \kappa(\lambda_i) = \frac{\|\mathbf{w}_i\|_2\|\mathbf{v}_i\|_2} {|\mathbf{w}_i^{T}\mathbf{v}_i|}. \]
Therefore, small perturbations in the model can produce large pole movement. In practical designs, repeated poles should be used cautiously unless the numerical robustness has been carefully checked.
12. Summary
Exact controllability guarantees the theoretical existence of a state-feedback gain for SISO pole placement, but it does not guarantee a reliable numerical design. Ackermann’s formula is sensitive because it explicitly uses the inverse of the controllability matrix and evaluates high-order matrix polynomials. The key diagnostic quantities are the condition number of the controllability matrix, the magnitude of the feedback gain, the sensitivity of closed-loop eigenvalues, and the response of the poles under small model perturbations. State scaling, less aggressive pole choices, and robust numerical software can greatly improve practical reliability.
13. References
- Ackermann, J. (1972). Der Entwurf linearer Regelungssysteme im Zustandsraum. Regelungstechnik, 20, 297–300.
- Kautsky, J., Nichols, N.K., & Van Dooren, P. (1985). Robust pole assignment in linear state feedback. International Journal of Control, 41(5), 1129–1155.
- 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.
- Wilkinson, J.H. (1965). The algebraic eigenvalue problem. Oxford University Press.
- Van Loan, C.F. (1975). A study of the matrix exponential. Numerische Mathematik, 24, 131–146.
- Stewart, G.W. (1973). Error and perturbation bounds for subspaces associated with certain eigenvalue problems. SIAM Review, 15(4), 727–764.
- Paige, C.C. (1981). Properties of numerical algorithms related to computing controllability. IEEE Transactions on Automatic Control, 26(1), 130–138.
- Varga, A. (1981). A Schur method for pole assignment. IEEE Transactions on Automatic Control, 26(2), 517–519.
- Byers, R., & Nash, S.G. (1989). Approaches to robust pole assignment. International Journal of Control, 49(1), 97–117.
- Moore, B.C. (1981). Principal component analysis in linear systems: controllability, observability, and model reduction. IEEE Transactions on Automatic Control, 26(1), 17–32.