Chapter 23: Pole Placement for Single-Input Systems
Lesson 1: Formulating the Pole Placement Problem (SISO)
This lesson formulates the single-input pole-placement problem as an algebraic closed-loop eigenvalue assignment problem. Starting from the state-feedback law introduced in Chapter 22, we define the desired characteristic polynomial, identify the role of controllability, prove the basic SISO existence statement, and implement the formulation in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica.
1. From State Feedback to Eigenvalue Assignment
In Chapter 22, state feedback was introduced in the form \( u=-Kx+r \). For pole placement, we first study the regulation problem with \( r=0 \). The continuous-time single-input LTI plant is
\[ \dot{x}(t)=Ax(t)+bu(t),\qquad A\in\mathbb{R}^{n\times n},\quad b\in\mathbb{R}^{n\times 1}. \]
A static full-state feedback row vector \( K\in\mathbb{R}^{1\times n} \) gives
\[ u(t)=-Kx(t),\qquad \dot{x}(t)=(A-bK)x(t). \]
The closed-loop state matrix is therefore \( A_{cl}=A-bK \). Pole placement asks us to select \( K \) so that the eigenvalues of \( A_{cl} \) coincide with a prescribed set of desired closed-loop poles. In state-space language, the word poles means the eigenvalues of the closed-loop state matrix, counted with algebraic multiplicity.
\[ \operatorname{spec}(A-bK)=\{\lambda_1^\star,\lambda_2^\star, \dots,\lambda_n^\star\}. \]
For real-valued physical systems and real-valued feedback gains, complex poles must be selected in conjugate pairs. This keeps the desired characteristic polynomial real.
2. Closed-Loop Characteristic Polynomial
Let the desired poles be \( \lambda_1^\star,\dots,\lambda_n^\star \). The desired monic polynomial is
\[ \phi_d(s)=\prod_{i=1}^n(s-\lambda_i^\star)=s^n+ \alpha_{n-1}s^{n-1}+\alpha_{n-2}s^{n-2}+\cdots+\alpha_1s+ \alpha_0. \]
The actual closed-loop polynomial induced by the unknown feedback gain is
\[ p_{cl}(s;K)=\det\left(sI-(A-bK)\right). \]
The SISO pole-placement problem is therefore the polynomial identity
\[ \boxed{\det\left(sI-(A-bK)\right)=\phi_d(s)}. \]
Equating coefficients converts the eigenvalue assignment statement into \( n \) scalar algebraic equations in the \( n \) unknown gain components of \( K=[k_1\;k_2\;\cdots\;k_n] \). The important issue is not merely the number of equations; the equations must be independent. Controllability is precisely the state-space property that guarantees independence for arbitrary pole assignment in the single-input case.
3. Controllability as the Feasibility Condition
The controllability matrix of the pair \( (A,b) \) is
\[ \mathcal{C}(A,b)=\begin{bmatrix} b & Ab & A^2b & \cdots & A^{n-1}b \end{bmatrix}. \]
The SISO pair is controllable if
\[ \operatorname{rank}\mathcal{C}(A,b)=n. \]
The fundamental pole-placement statement for this lesson is:
\[ \begin{aligned} \operatorname{rank}\mathcal{C}(A,b)=n &\quad\Longleftrightarrow\quad \forall\,\phi_d(s)\;\text{monic of degree}\;n,\;\exists K \;\text{such that} \\ &\det(sI-(A-bK))=\phi_d(s). \end{aligned} \]
For a controllable SISO pair, the gain vector that assigns a specified monic characteristic polynomial is unique. If the pair is not controllable, some modes of \( A \) cannot be moved by the scalar input channel. Such modes remain as unassignable closed-loop eigenvalues under any full-state feedback \( u=-Kx \).
4. Formal Statement of the SISO Pole-Placement Problem
Given a real SISO pair \( (A,b) \) and a desired real monic polynomial \( \phi_d(s) \), the pole-placement design problem is:
\[ \begin{aligned} \text{Find}\quad &K\in\mathbb{R}^{1\times n} \\ \text{such that}\quad &p_{cl}(s;K)=\det(sI-A+bK)=\phi_d(s),\\ \text{where}\quad &\phi_d(s)=s^n+\alpha_{n-1}s^{n-1}+ \cdots+\alpha_1s+\alpha_0. \end{aligned} \]
Notice the sign convention: because \( A_{cl}=A-bK \), the determinant may be written as \( \det(sI-(A-bK))=\det(sI-A+bK) \). Different books sometimes use \( u=Kx \) instead of \( u=-Kx \); the signs of the gain entries then change, but the closed-loop eigenvalue assignment idea is the same.
flowchart TD
A["Plant: x_dot = A x + b u"] --> B["Choose real desired pole set"]
B --> C["Build desired polynomial phi_d(s)"]
C --> D["Check rank of controllability matrix"]
D -->|"rank equals n"| E["Solve coefficient equations for K"]
D -->|"rank less than n"| F["Some modes are not assignable"]
E --> G["Validate eig(A - b K)"]
G --> H["Use K in closed-loop design"]
5. Desired Poles and Real Polynomial Restrictions
Because the state equation is real and the feedback gain is real, the desired polynomial must have real coefficients. Thus, if \( \lambda=a+jb \) is chosen as a desired pole with \( b\ne0 \), then \( \bar{\lambda}=a-jb \) must also be included. Their contribution to the desired polynomial is
\[ (s-(a+jb))(s-(a-jb))=(s-a)^2+b^2=s^2-2as+(a^2+b^2). \]
For continuous-time asymptotic stability, all desired closed-loop poles must lie in the open left half-plane:
\[ \operatorname{Re}(\lambda_i^\star)<0, \qquad i=1,2,\dots,n. \]
Repeated poles are algebraically allowed in the formulation. However, repeated or clustered desired poles can make numerical computation more sensitive, especially for high-order systems. This sensitivity issue is treated in a later lesson; here, it is enough to understand that the mathematical formulation allows multiplicities, while numerical practice requires caution.
6. Coefficient Matching in Companion Form
The algebra becomes transparent when the SISO system is already in controllable companion form:
\[ A_c=\begin{bmatrix} 0 & 1 & 0 & \cdots & 0\\ 0 & 0 & 1 & \cdots & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & 0 & \cdots & 1\\ -a_0 & -a_1 & -a_2 & \cdots & -a_{n-1} \end{bmatrix},\qquad b_c=\begin{bmatrix}0\\0\\\vdots\\0\\1\end{bmatrix}. \]
The open-loop characteristic polynomial is
\[ p_A(s)=s^n+a_{n-1}s^{n-1}+\cdots+a_1s+a_0. \]
With \( K_c=[k_0\;k_1\;\cdots\;k_{n-1}] \), the last row of \( A_c-b_cK_c \) becomes \( [-(a_0+k_0)\;-(a_1+k_1)\;\cdots\;-(a_{n-1}+k_{n-1})] \). Therefore
\[ \det(sI-(A_c-b_cK_c))=s^n+(a_{n-1}+k_{n-1})s^{n-1}+ \cdots+(a_1+k_1)s+(a_0+k_0). \]
Equating this expression with \( \phi_d(s)=s^n+\alpha_{n-1}s^{n-1}+\cdots+\alpha_1s+ \alpha_0 \) gives the direct coefficient equations
\[ k_i=\alpha_i-a_i, \qquad i=0,1,\dots,n-1. \]
This simple formula explains the structure behind later pole-placement algorithms: transform a controllable SISO system into a convenient coordinate basis, match polynomial coefficients, then transform the gain back to the original state coordinates.
flowchart TD
A["Feedback row K"] --> B["Closed-loop matrix A - bK"]
B --> C["Characteristic polynomial p_cl(s;K)"]
D["Desired poles"] --> E["Desired polynomial phi_d(s)"]
C --> F["Equate polynomial coefficients"]
E --> F
F --> G["Gain equations"]
7. Proof Sketch of the Controllable SISO Assignment Theorem
We prove the core idea using coordinate transformation, but without yet developing the full computational formula. Suppose \( \operatorname{rank}\mathcal{C}(A,b)=n \). Then there exists a nonsingular state transformation \( x=Tz \) such that
\[ T^{-1}AT=A_c, \qquad T^{-1}b=b_c, \]
where \( (A_c,b_c) \) is the controllable companion pair shown above. Under the feedback \( u=-Kx \), we have
\[ u=-Kx=-KTz=-K_cz, \qquad K_c=KT. \]
In the transformed coordinates,
\[ \dot{z}=(A_c-b_cK_c)z. \]
From coefficient matching in companion form, choosing \( k_i=\alpha_i-a_i \) assigns the desired polynomial. Finally, because \( K_c=KT \), the original-coordinate gain is
\[ K=K_cT^{-1}. \]
Hence a controllable SISO pair can realize every real monic polynomial of degree \( n \). Conversely, if \( \operatorname{rank}\mathcal{C}(A,b)<n \), the reachable subspace is a proper \( A \)-invariant subspace, and the input cannot independently affect all modal directions. Therefore arbitrary pole assignment is impossible.
8. Worked Second-Order Formulation
Consider the second-order single-input system
\[ A=\begin{bmatrix}0&1\\-2&-3\end{bmatrix}, \qquad b=\begin{bmatrix}0\\1\end{bmatrix}. \]
Its controllability matrix is
\[ \mathcal{C}(A,b)=\begin{bmatrix}b&Ab\end{bmatrix} =\begin{bmatrix}0&1\\1&-3\end{bmatrix}, \qquad \det\mathcal{C}(A,b)=-1\ne0. \]
Hence the pair is controllable. Let the desired poles be \( -4 \) and \( -5 \). Then
\[ \phi_d(s)=(s+4)(s+5)=s^2+9s+20. \]
Since the open-loop polynomial is
\[ p_A(s)=\det(sI-A)=s^2+3s+2, \]
and the system is already in companion form, coefficient matching gives
\[ K=\begin{bmatrix}20-2&9-3\end{bmatrix} =\begin{bmatrix}18&6\end{bmatrix}. \]
The closed-loop matrix is
\[ A-bK=\begin{bmatrix}0&1\\-20&-9\end{bmatrix}, \qquad \det(sI-(A-bK))=s^2+9s+20. \]
Thus the desired closed-loop poles are exactly assigned.
9. Python Implementation
Python libraries relevant to this topic include numpy for
matrix and eigenvalue computation, scipy.signal for
state-space simulation, and python-control for higher-level
pole-placement functions. The following file deliberately implements the
basic controllability and coefficient-matching steps from scratch.
Chapter23_Lesson1.py
# Chapter23_Lesson1.py
"""
Formulating the SISO pole-placement problem for a continuous-time LTI system.
System:
x_dot = A x + b u
u = -K x
Acl = A - b K
This file focuses on the formulation, controllability test, desired polynomial,
and coefficient matching for a second-order companion-form example.
"""
import numpy as np
def controllability_matrix(A: np.ndarray, b: np.ndarray) -> np.ndarray:
"""Return C = [b, A b, ..., A^(n-1) b]."""
n = A.shape[0]
cols = []
v = b.copy()
for _ in range(n):
cols.append(v)
v = A @ v
return np.hstack(cols)
def is_controllable(A: np.ndarray, b: np.ndarray, tol: float = 1e-9) -> bool:
"""Check Kalman's rank condition for a SISO pair (A,b)."""
Ctrb = controllability_matrix(A, b)
return np.linalg.matrix_rank(Ctrb, tol=tol) == A.shape[0]
def companion_feedback_from_coefficients(open_coeffs_ascending, desired_coeffs_ascending):
"""
For controllable companion form with
A bottom row = [-a0, -a1, ..., -a_{n-1}], b = e_n,
and feedback K = [k0, k1, ..., k_{n-1}], the closed-loop polynomial is
s^n + (a_{n-1}+k_{n-1})s^{n-1} + ... + (a0+k0).
Therefore k_i = alpha_i - a_i in ascending coefficient order.
"""
open_coeffs_ascending = np.asarray(open_coeffs_ascending, dtype=float)
desired_coeffs_ascending = np.asarray(desired_coeffs_ascending, dtype=float)
if open_coeffs_ascending.shape != desired_coeffs_ascending.shape:
raise ValueError("Coefficient arrays must have the same length.")
return (desired_coeffs_ascending - open_coeffs_ascending).reshape(1, -1)
def main():
# Second-order phase-variable system:
# x1_dot = x2
# x2_dot = -2 x1 - 3 x2 + u
A = np.array([[0.0, 1.0],
[-2.0, -3.0]])
b = np.array([[0.0],
[1.0]])
print("A =\n", A)
print("b =\n", b)
Ctrb = controllability_matrix(A, b)
print("Controllability matrix =\n", Ctrb)
print("rank(Ctrb) =", np.linalg.matrix_rank(Ctrb))
print("controllable =", is_controllable(A, b))
desired_poles = np.array([-4.0, -5.0])
desired_poly_desc = np.poly(desired_poles) # [1, alpha1, alpha0]
open_poly_desc = np.poly(A) # [1, a1, a0]
print("open-loop polynomial coefficients [1, a1, a0] =", open_poly_desc)
print("desired polynomial coefficients [1, alpha1, alpha0] =", desired_poly_desc)
# Convert [1, a1, a0] to ascending non-leading coefficients [a0, a1]
open_coeffs_ascending = open_poly_desc[:0:-1]
desired_coeffs_ascending = desired_poly_desc[:0:-1]
K = companion_feedback_from_coefficients(open_coeffs_ascending, desired_coeffs_ascending)
Acl = A - b @ K
print("K =", K)
print("A_cl = A - b K =\n", Acl)
print("closed-loop eigenvalues =", np.linalg.eigvals(Acl))
print("closed-loop polynomial coefficients =", np.poly(Acl))
# Residual check: p_cl(s) must match the desired polynomial.
residual = np.linalg.norm(np.poly(Acl) - desired_poly_desc)
print("polynomial matching residual =", residual)
if __name__ == "__main__":
main()
10. C++ Implementation
C++ control implementations commonly use matrix libraries such as Eigen, Armadillo, Blaze, or vendor BLAS/LAPACK bindings. The file below uses only the C++ standard library so that the algebra of the second-order formulation is completely visible.
Chapter23_Lesson1.cpp
// Chapter23_Lesson1.cpp
// Formulating the SISO pole-placement problem for a second-order companion-form system.
// This implementation uses only the C++ standard library.
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <utility>
struct Matrix2 {
double a11, a12, a21, a22;
};
std::pair<std::complex<double>, std::complex<double>> eigenvalues2x2(const Matrix2& M) {
double tr = M.a11 + M.a22;
double det = M.a11 * M.a22 - M.a12 * M.a21;
std::complex<double> disc = std::complex<double>(tr * tr - 4.0 * det, 0.0);
std::complex<double> root = std::sqrt(disc);
return {(tr + root) / 2.0, (tr - root) / 2.0};
}
double determinant2x2(const Matrix2& M) {
return M.a11 * M.a22 - M.a12 * M.a21;
}
int main() {
// A = [[0, 1], [-2, -3]], b = [[0], [1]]
Matrix2 A{0.0, 1.0, -2.0, -3.0};
double b1 = 0.0;
double b2 = 1.0;
// Controllability matrix C = [b, A b]
// b = [0, 1]^T, A b = [1, -3]^T
Matrix2 Ctrb{b1, A.a11 * b1 + A.a12 * b2,
b2, A.a21 * b1 + A.a22 * b2};
std::cout << std::fixed << std::setprecision(6);
std::cout << "det(Ctrb) = " << determinant2x2(Ctrb) << "\n";
std::cout << "controllable = " << (std::abs(determinant2x2(Ctrb)) > 1e-9 ? "true" : "false") << "\n";
// Open-loop polynomial: s^2 + 3 s + 2.
// Desired poles: -4 and -5, so desired polynomial: s^2 + 9 s + 20.
double a0 = 2.0;
double a1 = 3.0;
double alpha0 = 20.0;
double alpha1 = 9.0;
// For companion form: K = [alpha0 - a0, alpha1 - a1].
double k0 = alpha0 - a0;
double k1 = alpha1 - a1;
std::cout << "K = [" << k0 << ", " << k1 << "]\n";
// Acl = A - b K. Since b = [0, 1]^T, only the second row changes.
Matrix2 Acl{A.a11 - b1 * k0, A.a12 - b1 * k1,
A.a21 - b2 * k0, A.a22 - b2 * k1};
auto eigs = eigenvalues2x2(Acl);
std::cout << "A_cl = [[" << Acl.a11 << ", " << Acl.a12 << "], ["
<< Acl.a21 << ", " << Acl.a22 << "]]\n";
std::cout << "closed-loop eigenvalue 1 = " << eigs.first << "\n";
std::cout << "closed-loop eigenvalue 2 = " << eigs.second << "\n";
// Characteristic polynomial of 2x2 matrix: s^2 - tr(Acl)s + det(Acl).
double p1 = -(Acl.a11 + Acl.a22);
double p0 = determinant2x2(Acl);
std::cout << "closed-loop polynomial: s^2 + " << p1 << " s + " << p0 << "\n";
return 0;
}
11. Java Implementation
Java numerical work often uses libraries such as EJML, Apache Commons Math, or ojAlgo. To keep this lesson self-contained, the file below implements the required second-order determinant, polynomial, and eigenvalue checks directly.
Chapter23_Lesson1.java
// Chapter23_Lesson1.java
// Formulating the SISO pole-placement problem for a second-order companion-form system.
// Compile: javac Chapter23_Lesson1.java
// Run: java Chapter23_Lesson1
public class Chapter23_Lesson1 {
static class Matrix2 {
double a11, a12, a21, a22;
Matrix2(double a11, double a12, double a21, double a22) {
this.a11 = a11;
this.a12 = a12;
this.a21 = a21;
this.a22 = a22;
}
}
static double determinant(Matrix2 M) {
return M.a11 * M.a22 - M.a12 * M.a21;
}
static void printEigenvalues2x2(Matrix2 M) {
double trace = M.a11 + M.a22;
double det = determinant(M);
double disc = trace * trace - 4.0 * det;
if (disc >= 0.0) {
double root = Math.sqrt(disc);
double lambda1 = (trace + root) / 2.0;
double lambda2 = (trace - root) / 2.0;
System.out.printf("closed-loop eigenvalue 1 = %.6f%n", lambda1);
System.out.printf("closed-loop eigenvalue 2 = %.6f%n", lambda2);
} else {
double real = trace / 2.0;
double imag = Math.sqrt(-disc) / 2.0;
System.out.printf("closed-loop eigenvalue 1 = %.6f + %.6fi%n", real, imag);
System.out.printf("closed-loop eigenvalue 2 = %.6f - %.6fi%n", real, imag);
}
}
public static void main(String[] args) {
// A = [[0, 1], [-2, -3]], b = [[0], [1]]
Matrix2 A = new Matrix2(0.0, 1.0, -2.0, -3.0);
double b1 = 0.0;
double b2 = 1.0;
// Controllability matrix C = [b, A b]
Matrix2 Ctrb = new Matrix2(
b1, A.a11 * b1 + A.a12 * b2,
b2, A.a21 * b1 + A.a22 * b2
);
double detCtrb = determinant(Ctrb);
System.out.printf("det(Ctrb) = %.6f%n", detCtrb);
System.out.println("controllable = " + (Math.abs(detCtrb) > 1e-9));
// Open-loop polynomial: s^2 + 3 s + 2.
// Desired poles: -4 and -5, so desired polynomial: s^2 + 9 s + 20.
double a0 = 2.0;
double a1 = 3.0;
double alpha0 = 20.0;
double alpha1 = 9.0;
// For companion form: K = [alpha0 - a0, alpha1 - a1].
double k0 = alpha0 - a0;
double k1 = alpha1 - a1;
System.out.printf("K = [%.6f, %.6f]%n", k0, k1);
// Acl = A - b K. Since b = [0, 1]^T, only the second row changes.
Matrix2 Acl = new Matrix2(
A.a11 - b1 * k0, A.a12 - b1 * k1,
A.a21 - b2 * k0, A.a22 - b2 * k1
);
System.out.printf("A_cl = [[%.6f, %.6f], [%.6f, %.6f]]%n",
Acl.a11, Acl.a12, Acl.a21, Acl.a22);
printEigenvalues2x2(Acl);
// Characteristic polynomial of 2x2 matrix: s^2 - tr(Acl)s + det(Acl).
double p1 = -(Acl.a11 + Acl.a22);
double p0 = determinant(Acl);
System.out.printf("closed-loop polynomial: s^2 + %.6f s + %.6f%n", p1, p0);
}
}
12. MATLAB/Simulink Implementation
MATLAB's Control System Toolbox provides ctrb,
rank, eig, ss, and
place. This script uses manual coefficient matching for the
lesson derivation, compares it with place when available,
and optionally builds a simple closed-loop Simulink model.
Chapter23_Lesson1.m
% Chapter23_Lesson1.m
% Formulating the SISO pole-placement problem in MATLAB/Simulink.
% This script checks controllability, constructs the desired polynomial,
% performs second-order companion-form coefficient matching, and builds a
% simple Simulink closed-loop state-space model if Simulink is available.
clear; clc; close all;
A = [0 1; -2 -3];
b = [0; 1];
C = [1 0];
D = 0;
Ctrb = ctrb(A, b);
fprintf('rank(Ctrb) = %d\n', rank(Ctrb));
fprintf('controllable = %d\n', rank(Ctrb) == size(A, 1));
desired_poles = [-4 -5];
open_poly = poly(A); % [1 a1 a0]
desired_poly = poly(desired_poles); % [1 alpha1 alpha0]
fprintf('open-loop polynomial coefficients [1 a1 a0]:\n');
disp(open_poly);
fprintf('desired polynomial coefficients [1 alpha1 alpha0]:\n');
disp(desired_poly);
% For A = [0 1; -a0 -a1], b = [0; 1], K = [alpha0-a0, alpha1-a1].
a0 = open_poly(3);
a1 = open_poly(2);
alpha0 = desired_poly(3);
alpha1 = desired_poly(2);
K_manual = [alpha0 - a0, alpha1 - a1];
Acl = A - b * K_manual;
fprintf('K_manual =\n');
disp(K_manual);
fprintf('closed-loop eigenvalues from manual coefficient matching:\n');
disp(eig(Acl));
fprintf('closed-loop polynomial coefficients:\n');
disp(poly(Acl));
% MATLAB Control System Toolbox comparison.
% The command place(A,b,desired_poles) is a library implementation. It is shown
% here only as a verification tool; later lessons derive full formulas.
if exist('place', 'file') == 2
K_place = place(A, b, desired_poles);
fprintf('K_place =\n');
disp(K_place);
end
% Closed-loop state-space response to an initial condition.
sys_cl = ss(Acl, b, C, D);
t = linspace(0, 4, 400);
u = zeros(size(t));
x0 = [1; 0];
[y, t_out, x] = lsim(sys_cl, u, t, x0);
figure;
plot(t_out, x(:,1), 'LineWidth', 1.5); hold on;
plot(t_out, x(:,2), 'LineWidth', 1.5);
grid on;
xlabel('Time (s)');
ylabel('States');
legend('x_1', 'x_2');
title('Closed-loop state response after pole placement formulation');
% Optional Simulink model generation.
if exist('new_system', 'file') == 2
modelName = 'Chapter23_Lesson1_Simulink_Model';
if bdIsLoaded(modelName)
close_system(modelName, 0);
end
new_system(modelName);
open_system(modelName);
add_block('simulink/Sources/Constant', [modelName '/zero input'], ...
'Value', '0', 'Position', [80 90 130 120]);
add_block('simulink/Continuous/State-Space', [modelName '/ClosedLoopStateSpace'], ...
'A', 'Acl', 'B', 'b', 'C', 'C', 'D', 'D', ...
'X0', '[1;0]', 'Position', [190 75 340 135]);
add_block('simulink/Sinks/Scope', [modelName '/Scope'], ...
'Position', [420 82 470 128]);
add_line(modelName, 'zero input/1', 'ClosedLoopStateSpace/1');
add_line(modelName, 'ClosedLoopStateSpace/1', 'Scope/1');
set_param(modelName, 'StopTime', '4');
save_system(modelName);
fprintf('Simulink model saved as %s.slx\n', modelName);
end
13. Wolfram Mathematica Implementation
Wolfram Mathematica is useful for exact symbolic characteristic polynomials, symbolic coefficient comparison, and verification of closed-loop eigenvalue assignment.
Chapter23_Lesson1.nb
(* Chapter23_Lesson1.nb *)
(* Formulating the SISO pole-placement problem for a second-order companion-form system. *)
ClearAll["Global`*"];
A = { {0, 1}, {-2, -3} };
b = { {0}, {1} };
controllabilityMatrix[A_, b_] := Module[{n = Length[A]},
ArrayFlatten[{Table[MatrixPower[A, i].b, {i, 0, n - 1}]}]
];
Ctrb = controllabilityMatrix[A, b];
MatrixRank[Ctrb]
Det[Ctrb]
s = Unique["s"];
openPolynomial = CharacteristicPolynomial[A, s] // Expand
openCoefficientsAscending = CoefficientList[openPolynomial, s][[1 ;; 2]]
desiredPoles = {-4, -5};
desiredPolynomial = Times @@ (s - desiredPoles) // Expand
desiredCoefficientsAscending = CoefficientList[desiredPolynomial, s][[1 ;; 2]]
(* For companion form, K = {alpha0 - a0, alpha1 - a1}. *)
K = {desiredCoefficientsAscending - openCoefficientsAscending};
Acl = A - b.K;
K // MatrixForm
Acl // MatrixForm
Eigenvalues[Acl]
CharacteristicPolynomial[Acl, s] // Expand
(* Verify equality with the desired characteristic polynomial. *)
FullSimplify[CharacteristicPolynomial[Acl, s] == desiredPolynomial]
14. Problems and Solutions
Problem 1 (Polynomial formulation): For \( \dot{x}=Ax+bu \) and \( u=-Kx \), write the exact algebraic equation that defines the pole-placement problem for desired polynomial \( \phi_d(s)=s^n+\alpha_{n-1}s^{n-1}+\cdots+ \alpha_0 \).
Solution: The closed-loop matrix is \( A-bK \). Therefore the pole-placement equation is
\[ \det(sI-(A-bK))=s^n+\alpha_{n-1}s^{n-1}+\cdots+ \alpha_1s+ \alpha_0. \]
Equating coefficients produces \( n \) scalar equations in the \( n \) feedback entries.
Problem 2 (Real pole set): Determine whether the pole set \( \{-2+j, -3, -4\} \) can be assigned using a real feedback gain for a fourth-order real system.
Solution: No. The pole \( -2+j \) is complex, so its conjugate \( -2-j \) must also be included. A valid fourth-order real pole set would be \( \{-2+j, -2-j, -3, -4\} \).
Problem 3 (Second-order coefficient matching): Let
\[ A=\begin{bmatrix}0&1\\-5&-4\end{bmatrix}, \qquad b=\begin{bmatrix}0\\1\end{bmatrix}. \]
Find \( K=[k_0\;k_1] \) so that the desired poles are \( -3 \) and \( -6 \).
Solution: The open-loop polynomial is \( s^2+4s+5 \). The desired polynomial is
\[ (s+3)(s+6)=s^2+9s+18. \]
Therefore \( a_0=5 \), \( a_1=4 \), \( \alpha_0=18 \), and \( \alpha_1=9 \). Hence
\[ K=\begin{bmatrix}\alpha_0-a_0&\alpha_1-a_1\end{bmatrix} =\begin{bmatrix}13&5\end{bmatrix}. \]
Problem 4 (Uncontrollable pair): Let
\[ A=\begin{bmatrix}1&0\\0&2\end{bmatrix}, \qquad b=\begin{bmatrix}1\\0\end{bmatrix}. \]
Can both closed-loop poles be assigned arbitrarily by \( u=-Kx \)?
Solution: The controllability matrix is
\[ \mathcal{C}(A,b)=\begin{bmatrix}b&Ab\end{bmatrix} =\begin{bmatrix}1&1\\0&0\end{bmatrix}, \qquad \operatorname{rank}\mathcal{C}(A,b)=1<2. \]
Therefore the pair is not controllable. The second state direction is not influenced by the input, so the eigenvalue \( 2 \) is unassignable. Arbitrary two-pole placement is impossible.
Problem 5 (Proof of companion-form coefficient equations): For the companion pair \( (A_c,b_c) \), show why \( k_i=\alpha_i-a_i \) assigns the desired polynomial.
Solution: The feedback \( b_cK_c \) affects only the last row of \( A_c \). Hence the last row becomes \( [-(a_0+k_0)\;-(a_1+k_1)\;\cdots\;-(a_{n-1}+k_{n-1})] \). By the companion-matrix characteristic polynomial formula,
\[ \det(sI-(A_c-b_cK_c))=s^n+(a_{n-1}+k_{n-1})s^{n-1}+ \cdots+(a_1+k_1)s+(a_0+k_0). \]
Equating this expression with \( \phi_d(s) \) gives \( a_i+k_i=\alpha_i \), hence \( k_i=\alpha_i-a_i \).
15. Summary
Pole placement for SISO systems is the problem of selecting \( K \) so that the closed-loop characteristic polynomial \( \det(sI-(A-bK)) \) equals a desired monic polynomial \( \phi_d(s) \). Controllability of \( (A,b) \) is the exact feasibility condition for arbitrary assignment. In companion form, feedback changes the polynomial coefficients directly, which gives the basic coefficient-matching rule \( k_i=\alpha_i-a_i \). Later lessons develop the systematic transformations and explicit formulas used for general coordinate representations.
16. References
- Kalman, R.E. (1960). On the general theory of control systems. Proceedings of the First IFAC Congress, 1, 481–492.
- Kalman, R.E. (1963). Mathematical description of linear dynamical systems. SIAM Journal on Control, 1(2), 152–192.
- Brockett, R.W. (1965). Poles, zeros, and feedback: state space interpretation. IEEE Transactions on Automatic Control, 10(2), 129–135.
- Bass, R.W., & Gura, I. (1965). High-order system design via state-space considerations. Proceedings of the Joint Automatic Control Conference, Troy, New York.
- Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 12(6), 660–665.
- Kautsky, J., Nichols, N.K., & Van Dooren, P. (1985). Robust pole assignment in linear state feedback. International Journal of Control, 41(5), 1129–1155.
- Miminis, G.S., & Paige, C.C. (1988). A direct algorithm for pole assignment of time-invariant multi-input linear systems using state feedback. Automatica, 24(3), 343–356.
- Mehrmann, V. (1996). An analysis of the pole placement problem. I: The single-input case. Electronic Transactions on Numerical Analysis, 4, 89–105.
- Mehrmann, V., & Xu, H. (1998). Choosing poles so that the single-input pole placement problem is well conditioned. SIAM Journal on Matrix Analysis and Applications, 19(3), 664–681.