Chapter 16: Controllable Canonical Form
Lesson 1: Companion Matrix and Controllable Canonical Form (CCF)
This lesson introduces the companion matrix and the standard single-input controllable canonical form. We connect a monic denominator polynomial to a state-space realization, prove controllability of the canonical pair, derive the transfer function from the resolvent, and implement the construction in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica.
1. Motivation and Position in the Course
In earlier chapters, we learned that a state-space model is not unique: many matrices \( (A,B,C,D) \) can represent the same input-output transfer function. The purpose of a canonical form is to choose a structured realization whose algebraic properties are transparent. The controllable canonical form, also called the controller companion form, is especially useful for single-input systems because controllability is built directly into the matrix pair \( (A,B) \).
For a monic denominator polynomial
\[ p(s)=s^n+a_{n-1}s^{n-1}+a_{n-2}s^{n-2}+\cdots+a_1s+a_0, \]
the companion matrix places the polynomial coefficients in one row and shifts the state variables through a chain of integrator-like dynamics. This gives a realization where the input enters the last state equation and propagates through the state chain.
flowchart TD
P["Monic polynomial p(s)"] --> C["Companion matrix A_c"]
C --> B["Input vector B_c = last unit vector"]
B --> Q["Controllability matrix Q_c"]
Q --> R["rank(Q_c) = n"]
C --> G["Transfer function from C(sI-A)^(-1)B + D"]
R --> D["CCF is ready for analysis and pole placement"]
2. Companion Matrix from a Monic Polynomial
Consider the monic polynomial \( p(s) \) of degree \( n \):
\[ p(s)=s^n+a_{n-1}s^{n-1}+a_{n-2}s^{n-2}+\cdots+a_1s+a_0. \]
The controller companion matrix associated with this polynomial is
\[ 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}. \]
The input vector in controllable canonical form is the last standard basis vector:
\[ B_c= \begin{bmatrix} 0\\ 0\\ \vdots\\ 0\\ 1 \end{bmatrix} =e_n. \]
The first \( n-1 \) rows of \( A_c \) shift the state components forward, while the final row imposes the polynomial relation determined by \( p(s) \). This is why the matrix is called a companion matrix: its characteristic polynomial is exactly the polynomial it accompanies.
3. Characteristic Polynomial of the Companion Matrix
The characteristic polynomial of \( A_c \) is
\[ \chi_{A_c}(s)=\det(sI-A_c). \]
For the companion matrix above,
\[ \chi_{A_c}(s) = s^n+a_{n-1}s^{n-1}+a_{n-2}s^{n-2}+\cdots+a_1s+a_0 = p(s). \]
Therefore, the eigenvalues of \( A_c \) are precisely the roots of the denominator polynomial \( p(s) \). Since the poles of a strictly proper transfer function are the roots of its denominator, CCF gives a direct bridge between transfer-function pole data and state-space eigenvalue data.
For example, for \( n=3 \),
\[ A_c= \begin{bmatrix} 0 & 1 & 0\\ 0 & 0 & 1\\ -a_0 & -a_1 & -a_2 \end{bmatrix}, \quad sI-A_c= \begin{bmatrix} s & -1 & 0\\ 0 & s & -1\\ a_0 & a_1 & s+a_2 \end{bmatrix}. \]
Expanding the determinant gives
\[ \det(sI-A_c)=s^3+a_2s^2+a_1s+a_0. \]
4. Transfer Function Realization in CCF
Consider a strictly proper SISO transfer function
\[ G(s)= \frac{b_{n-1}s^{n-1}+b_{n-2}s^{n-2}+\cdots+b_1s+b_0} {s^n+a_{n-1}s^{n-1}+a_{n-2}s^{n-2}+\cdots+a_1s+a_0}. \]
Under the CCF convention used in this lesson, the numerator coefficients are placed in ascending-power order in the output matrix:
\[ C_c= \begin{bmatrix} b_0 & b_1 & b_2 & \cdots & b_{n-1} \end{bmatrix}, \quad D=0. \]
The complete CCF realization is therefore
\[ \dot{x}=A_cx+B_cu,\qquad y=C_cx. \]
Equivalently,
\[ \begin{aligned} \dot{x}_1 &= x_2,\\ \dot{x}_2 &= x_3,\\ &\vdots\\ \dot{x}_{n-1} &= x_n,\\ \dot{x}_n &= -a_0x_1-a_1x_2-\cdots-a_{n-1}x_n+u,\\ y &= b_0x_1+b_1x_2+\cdots+b_{n-1}x_n. \end{aligned} \]
This form is not merely a notation. It encodes the denominator polynomial into the system dynamics and the numerator polynomial into the measurement equation.
5. Resolvent Derivation of the Transfer Function
The transfer function of a state-space model is
\[ G(s)=C_c(sI-A_c)^{-1}B_c+D. \]
To understand why CCF produces the desired numerator and denominator, solve
\[ (sI-A_c)z=B_c. \]
Since \( B_c=e_n \), the first \( n-1 \) equations imply the chain
\[ sz_1-z_2=0,\quad sz_2-z_3=0,\quad \ldots,\quad sz_{n-1}-z_n=0. \]
Hence
\[ z_2=sz_1,\quad z_3=s^2z_1,\quad \ldots,\quad z_n=s^{n-1}z_1. \]
The last equation gives
\[ a_0z_1+a_1z_2+\cdots+a_{n-1}z_n+sz_n=1. \]
Substituting the chain relation yields
\[ \left(a_0+a_1s+\cdots+a_{n-1}s^{n-1}+s^n\right)z_1=1. \]
Therefore,
\[ z= \frac{1}{p(s)} \begin{bmatrix} 1\\ s\\ s^2\\ \vdots\\ s^{n-1} \end{bmatrix}. \]
Multiplying by \( C_c \) gives
\[ C_c(sI-A_c)^{-1}B_c = \frac{b_0+b_1s+b_2s^2+\cdots+b_{n-1}s^{n-1} }{p(s)}. \]
Thus the CCF realization exactly recovers the transfer function.
6. Controllability Proof of the CCF Pair
The controllability matrix is
\[ \mathcal{C} = \begin{bmatrix} B_c & A_cB_c & A_c^2B_c & \cdots & A_c^{n-1}B_c \end{bmatrix}. \]
For the companion pair \( (A_c,B_c) \), \( B_c=e_n \). Repeated multiplication by \( A_c \) produces a sequence of vectors whose leading anti-diagonal part is independent of the coefficients \( a_i \). In particular, the controllability matrix has the structure
\[ \mathcal{C} = \begin{bmatrix} 0 & 0 & \cdots & 0 & 1\\ 0 & 0 & \cdots & 1 & *\\ \vdots & \vdots & & \vdots & \vdots\\ 0 & 1 & \cdots & * & *\\ 1 & * & \cdots & * & * \end{bmatrix} \]
where the asterisks depend on the polynomial coefficients. The anti-diagonal entries are all equal to one, and all entries above this anti-diagonal pattern are zero. Consequently, its determinant is
\[ \det(\mathcal{C}) = (-1)^{n(n-1)/2}. \]
Since this determinant is never zero,
\[ \operatorname{rank}(\mathcal{C})=n. \]
Hence the CCF pair \( (A_c,B_c) \) is completely controllable for every choice of denominator coefficients. This is the central reason CCF is important in state-feedback design.
7. Relation to Coordinate Transformations
A controllable SISO realization \( (A,B,C,D) \) can be transformed into CCF by an invertible coordinate change \( x=Tz \). Under this change,
\[ \dot{z}=T^{-1}ATz+T^{-1}Bu,\qquad y=CTz+Du. \]
The goal is to choose \( T \) such that
\[ T^{-1}AT=A_c,\qquad T^{-1}B=B_c. \]
This is possible when \( (A,B) \) is controllable. The construction of \( T \) will be studied more carefully in the next lesson. For now, the key point is that CCF is not only a transfer-function realization; it is also a coordinate-normalized representation of any controllable SISO dynamics.
flowchart TD
A["Original controllable pair (A, B)"] --> Q["Build controllability basis"]
Q --> T["Choose invertible coordinate map T"]
T --> Z["New coordinates z"]
Z --> CCF["Canonical pair (A_c, B_c)"]
CCF --> OUT["Same input-output behavior with structured dynamics"]
8. Numerical Conditioning and Practical Warnings
Although CCF is mathematically elegant, it can be numerically sensitive. The coefficients \( a_i \) of a high-order polynomial may vary across many orders of magnitude. Since CCF places these coefficients directly inside the last row of \( A_c \), small coefficient perturbations can cause large eigenvalue perturbations.
Therefore, CCF is excellent for theoretical derivations and moderate order examples, but high-order engineering models are often analyzed using balanced realizations, modal forms, or numerically conditioned state-space transformations. In this course, however, CCF remains a crucial conceptual bridge between controllability, transfer functions, and pole placement.
\[ \kappa(\mathcal{C})= \|\mathcal{C}\|\,\|\mathcal{C}^{-1}\| \]
is a useful diagnostic. A large value of \( \kappa(\mathcal{C}) \) indicates that the controllability basis is poorly conditioned, even if the symbolic rank condition is satisfied.
9. Python Implementation
Useful Python libraries for this lesson include
NumPy for matrix construction, SciPy for
numerical linear algebra and simulation, python-control for
control-system objects, and SymPy for symbolic
verification. The following implementation constructs CCF from scratch
using NumPy.
Chapter16_Lesson1.py
# Chapter16_Lesson1.py
"""
Companion Matrix and Controllable Canonical Form (CCF)
Convention:
denominator: p(s) = s^n + a_{n-1}s^{n-1} + ... + a_1 s + a_0
pass a = [a0, a1, ..., a_{n-1}]
strictly proper numerator:
q(s) = b_0 + b_1 s + ... + b_{n-1}s^{n-1}
pass b = [b0, b1, ..., b_{n-1}]
CCF:
A = [[0, 1, 0, ..., 0],
...
[0, 0, 0, ..., 1],
[-a0, -a1, ..., -a_{n-1}]]
B = [0, ..., 0, 1]^T
C = [b0, b1, ..., b_{n-1}]
D = direct feedthrough
"""
import numpy as np
def controllable_canonical_form(a, b, d=0.0):
"""Return A, B, C, D for controller companion / CCF realization."""
a = np.asarray(a, dtype=float).reshape(-1)
b = np.asarray(b, dtype=float).reshape(-1)
n = len(a)
if len(b) != n:
raise ValueError("For this strictly proper CCF example, b must have length n.")
A = np.zeros((n, n), dtype=float)
if n > 1:
A[:-1, 1:] = np.eye(n - 1)
A[-1, :] = -a
B = np.zeros((n, 1), dtype=float)
B[-1, 0] = 1.0
C = b.reshape(1, n)
D = np.array([[float(d)]])
return A, B, C, D
def controllability_matrix(A, B):
"""Q_c = [B, AB, ..., 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 evaluate_transfer(A, B, C, D, s):
"""Evaluate G(s)=C(sI-A)^(-1)B+D at one complex value s."""
n = A.shape[0]
return (C @ np.linalg.solve(s * np.eye(n) - A, B) + D)[0, 0]
def polynomial_value_ascending(coeffs, s):
"""Evaluate coeffs[0] + coeffs[1]s + ... in ascending-power order."""
value = 0.0 + 0.0j
power = 1.0 + 0.0j
for c in coeffs:
value += c * power
power *= s
return value
if __name__ == "__main__":
# Example: G(s) = (5 + 6s + 7s^2) / (s^3 + 4s^2 + 3s + 2)
a = [2.0, 3.0, 4.0] # a0, a1, a2
b = [5.0, 6.0, 7.0] # b0, b1, b2
A, B, C, D = controllable_canonical_form(a, b)
Qc = controllability_matrix(A, B)
print("A =\n", A)
print("B =\n", B)
print("C =\n", C)
print("D =\n", D)
print("Q_c =\n", Qc)
print("rank(Q_c) =", np.linalg.matrix_rank(Qc))
print("det(Q_c) =", np.linalg.det(Qc))
s = 1.0 + 2.0j
G_state = evaluate_transfer(A, B, C, D, s)
denominator = s ** len(a) + polynomial_value_ascending(a, s)
numerator = polynomial_value_ascending(b, s)
G_poly = numerator / denominator
print("G(s) from state-space =", G_state)
print("G(s) from polynomials =", G_poly)
print("absolute error =", abs(G_state - G_poly))
10. C++ Implementation
In C++, one may use Eigen, Armadillo, or
Boost.uBLAS for production-quality linear algebra. The
following version is written from scratch to show the matrix operations
explicitly.
Chapter16_Lesson1.cpp
// Chapter16_Lesson1.cpp
// Compile: g++ -std=c++17 Chapter16_Lesson1.cpp -o Chapter16_Lesson1
// Convention: p(s)=s^n+a[n-1]s^(n-1)+...+a[1]s+a[0]
#include <cmath>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <vector>
using Matrix = std::vector<std::vector<double>>;
using Vector = std::vector<double>;
Matrix companionA(const Vector& a) {
const int n = static_cast<int>(a.size());
Matrix A(n, Vector(n, 0.0));
for (int i = 0; i < n - 1; ++i) {
A[i][i + 1] = 1.0;
}
for (int j = 0; j < n; ++j) {
A[n - 1][j] = -a[j];
}
return A;
}
Vector inputB(int n) {
Vector B(n, 0.0);
B[n - 1] = 1.0;
return B;
}
Vector matVec(const Matrix& A, const Vector& x) {
const int n = static_cast<int>(A.size());
Vector y(n, 0.0);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
y[i] += A[i][j] * x[j];
}
}
return y;
}
Matrix controllabilityMatrix(const Matrix& A, const Vector& B) {
const int n = static_cast<int>(A.size());
Matrix Q(n, Vector(n, 0.0));
Vector v = B;
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
Q[i][k] = v[i];
}
v = matVec(A, v);
}
return Q;
}
double determinant(Matrix M) {
const int n = static_cast<int>(M.size());
double det = 1.0;
for (int k = 0; k < n; ++k) {
int pivot = k;
for (int i = k + 1; i < n; ++i) {
if (std::fabs(M[i][k]) > std::fabs(M[pivot][k])) {
pivot = i;
}
}
if (std::fabs(M[pivot][k]) < 1e-12) {
return 0.0;
}
if (pivot != k) {
std::swap(M[pivot], M[k]);
det *= -1.0;
}
det *= M[k][k];
const double pivotValue = M[k][k];
for (int i = k + 1; i < n; ++i) {
const double factor = M[i][k] / pivotValue;
for (int j = k; j < n; ++j) {
M[i][j] -= factor * M[k][j];
}
}
}
return det;
}
void printMatrix(const std::string& name, const Matrix& M) {
std::cout << name << " =\n";
for (const auto& row : M) {
for (double value : row) {
std::cout << std::setw(12) << value << " ";
}
std::cout << "\n";
}
}
int main() {
// Example: p(s)=s^3+4s^2+3s+2
Vector a{2.0, 3.0, 4.0}; // a0, a1, a2
Matrix A = companionA(a);
Vector B = inputB(static_cast<int>(a.size()));
Matrix Qc = controllabilityMatrix(A, B);
printMatrix("A", A);
std::cout << "B = [ ";
for (double value : B) {
std::cout << value << " ";
}
std::cout << "]^T\n";
printMatrix("Q_c", Qc);
std::cout << "det(Q_c) = " << determinant(Qc) << "\n";
std::cout << "The nonzero determinant confirms controllability in CCF.\n";
return 0;
}
11. Java Implementation
In Java, production implementations may use EJML,
Apache Commons Math, or ojAlgo. The following
version implements the CCF construction and controllability determinant
directly.
Chapter16_Lesson1.java
// Chapter16_Lesson1.java
// Compile: javac Chapter16_Lesson1.java
// Run: java Chapter16_Lesson1
// Convention: p(s)=s^n+a[n-1]s^(n-1)+...+a[1]s+a[0]
public class Chapter16_Lesson1 {
static double[][] companionA(double[] a) {
int n = a.length;
double[][] A = new double[n][n];
for (int i = 0; i < n - 1; i++) {
A[i][i + 1] = 1.0;
}
for (int j = 0; j < n; j++) {
A[n - 1][j] = -a[j];
}
return A;
}
static double[] inputB(int n) {
double[] B = new double[n];
B[n - 1] = 1.0;
return B;
}
static double[] matVec(double[][] A, double[] x) {
int n = A.length;
double[] y = new double[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
y[i] += A[i][j] * x[j];
}
}
return y;
}
static double[][] controllabilityMatrix(double[][] A, double[] B) {
int n = A.length;
double[][] Q = new double[n][n];
double[] v = B.clone();
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
Q[i][k] = v[i];
}
v = matVec(A, v);
}
return Q;
}
static double determinant(double[][] input) {
int n = input.length;
double[][] M = new double[n][n];
for (int i = 0; i < n; i++) {
System.arraycopy(input[i], 0, M[i], 0, n);
}
double det = 1.0;
for (int k = 0; k < n; k++) {
int pivot = k;
for (int i = k + 1; i < n; i++) {
if (Math.abs(M[i][k]) > Math.abs(M[pivot][k])) {
pivot = i;
}
}
if (Math.abs(M[pivot][k]) < 1e-12) {
return 0.0;
}
if (pivot != k) {
double[] temp = M[pivot];
M[pivot] = M[k];
M[k] = temp;
det *= -1.0;
}
det *= M[k][k];
double pivotValue = M[k][k];
for (int i = k + 1; i < n; i++) {
double factor = M[i][k] / pivotValue;
for (int j = k; j < n; j++) {
M[i][j] -= factor * M[k][j];
}
}
}
return det;
}
static void printMatrix(String name, double[][] M) {
System.out.println(name + " =");
for (double[] row : M) {
for (double value : row) {
System.out.printf("%12.6f ", value);
}
System.out.println();
}
}
public static void main(String[] args) {
// Example: p(s)=s^3+4s^2+3s+2
double[] a = {2.0, 3.0, 4.0}; // a0, a1, a2
double[][] A = companionA(a);
double[] B = inputB(a.length);
double[][] Qc = controllabilityMatrix(A, B);
printMatrix("A", A);
System.out.print("B = [ ");
for (double value : B) {
System.out.print(value + " ");
}
System.out.println("]^T");
printMatrix("Q_c", Qc);
System.out.println("det(Q_c) = " + determinant(Qc));
System.out.println("The nonzero determinant confirms controllability in CCF.");
}
}
12. MATLAB and Simulink Implementation
MATLAB is especially convenient for CCF because the Control System
Toolbox provides ss, tf, and
ctrb. The script below also creates a simple Simulink
state-space block when Simulink is available.
Chapter16_Lesson1.m
% Chapter16_Lesson1.m
% Companion Matrix and Controllable Canonical Form (CCF)
% Convention:
% p(s)=s^n+a_{n-1}s^{n-1}+...+a_1 s+a_0
% a=[a0 a1 ... a_{n-1}]
% q(s)=b0+b1 s+...+b_{n-1}s^{n-1}
% b=[b0 b1 ... b_{n-1}]
clear; clc;
a = [2 3 4]; % a0, a1, a2
b = [5 6 7]; % b0, b1, b2
n = length(a);
A = zeros(n);
A(1:n-1, 2:n) = eye(n-1);
A(n, :) = -a;
B = zeros(n, 1);
B(n) = 1;
C = b;
D = 0;
Qc = ctrb(A, B);
disp('A ='); disp(A);
disp('B ='); disp(B);
disp('C ='); disp(C);
disp('D ='); disp(D);
disp('Q_c ='); disp(Qc);
fprintf('rank(Q_c) = %d\n', rank(Qc));
fprintf('det(Q_c) = %.6g\n', det(Qc));
% Control System Toolbox verification
sys = ss(A, B, C, D);
G = tf(sys);
disp('Transfer function from CCF realization:');
G
% The expected transfer function is:
% (5 + 6s + 7s^2)/(s^3 + 4s^2 + 3s + 2)
expected = tf(fliplr(b), [1 fliplr(a)]);
disp('Expected transfer function:');
expected
% Optional Simulink model construction, if Simulink is available.
if exist('new_system', 'file') == 2
model = 'Chapter16_Lesson1_Simulink_CCF';
if bdIsLoaded(model)
close_system(model, 0);
end
new_system(model);
open_system(model);
add_block('simulink/Sources/Step', [model '/Step']);
add_block('simulink/Continuous/State-Space', [model '/CCF State Space']);
add_block('simulink/Sinks/Scope', [model '/Scope']);
set_param([model '/CCF State Space'], ...
'A', 'A', 'B', 'B', 'C', 'C', 'D', 'D');
add_line(model, 'Step/1', 'CCF State Space/1');
add_line(model, 'CCF State Space/1', 'Scope/1');
save_system(model);
disp(['Created Simulink model: ' model '.slx']);
end
13. Wolfram Mathematica Implementation
Mathematica is useful for symbolic confirmation of the companion matrix, characteristic polynomial, controllability determinant, and transfer function identity.
Chapter16_Lesson1.nb
(* Chapter16_Lesson1.nb *)
(* Companion Matrix and Controllable Canonical Form *)
a = {2, 3, 4}; (* a0, a1, a2 *)
b = {5, 6, 7}; (* b0, b1, b2 *)
n = Length[a];
A = ConstantArray[0, {n, n}];
Do[A[[i, i + 1]] = 1, {i, 1, n - 1}];
A[[n, All]] = -a;
B = UnitVector[n, n];
Cmat = {b};
Dmat = { {0} };
Qc = Transpose[Table[MatrixPower[A, k].B, {k, 0, n - 1}]];
detQc = Det[Qc];
s = Symbol["s"];
G = FullSimplify[(Cmat . Inverse[s IdentityMatrix[n] - A] . B)[[1]]];
den = s^n + Sum[a[[k]] s^(k - 1), {k, 1, n}];
num = Sum[b[[k]] s^(k - 1), {k, 1, n}];
{MatrixForm[A], MatrixForm[B], MatrixForm[Cmat], MatrixForm[Qc], detQc}
FullSimplify[G == num/den]
G
14. Problems and Solutions
Problem 1: Construct the controllable canonical form for
\[ G(s)=\frac{2s+5}{s^2+3s+4}. \]
Solution: Here,
\[ a_0=4,\qquad a_1=3,\qquad b_0=5,\qquad b_1=2. \]
Thus
\[ A_c= \begin{bmatrix} 0 & 1\\ -4 & -3 \end{bmatrix}, \quad B_c= \begin{bmatrix} 0\\ 1 \end{bmatrix}, \quad C_c= \begin{bmatrix} 5 & 2 \end{bmatrix}, \quad D=0. \]
Therefore,
\[ \dot{x}= \begin{bmatrix} 0 & 1\\ -4 & -3 \end{bmatrix}x+ \begin{bmatrix} 0\\ 1 \end{bmatrix}u, \qquad y= \begin{bmatrix} 5 & 2 \end{bmatrix}x. \]
Problem 2: Prove that the pair \( (A_c,B_c) \) for
\[ A_c= \begin{bmatrix} 0 & 1\\ -a_0 & -a_1 \end{bmatrix}, \quad B_c= \begin{bmatrix} 0\\ 1 \end{bmatrix} \]
is controllable for all real coefficients \( a_0,a_1 \).
Solution: The controllability matrix is
\[ \mathcal{C} = \begin{bmatrix} B_c & A_cB_c \end{bmatrix}. \]
Since
\[ A_cB_c= \begin{bmatrix} 1\\ -a_1 \end{bmatrix}, \]
we obtain
\[ \mathcal{C} = \begin{bmatrix} 0 & 1\\ 1 & -a_1 \end{bmatrix}. \]
Its determinant is
\[ \det(\mathcal{C})=-1. \]
Hence \( \mathcal{C} \) has rank 2 for all \( a_0,a_1 \), and the system is controllable.
Problem 3: For
\[ p(s)=s^3+6s^2+11s+6, \]
write the companion matrix and determine its eigenvalues from the polynomial.
Solution: The coefficients are
\[ a_0=6,\qquad a_1=11,\qquad a_2=6. \]
Therefore,
\[ A_c= \begin{bmatrix} 0 & 1 & 0\\ 0 & 0 & 1\\ -6 & -11 & -6 \end{bmatrix}. \]
Factoring the polynomial gives
\[ p(s)=(s+1)(s+2)(s+3). \]
Hence the eigenvalues of \( A_c \) are
\[ \lambda_1=-1,\qquad \lambda_2=-2,\qquad \lambda_3=-3. \]
Problem 4: Show that the CCF realization of
\[ G(s)=\frac{b_0+b_1s+\cdots+b_{n-1}s^{n-1} }{p(s)} \]
has the correct transfer function.
Solution: Let \( z=(sI-A_c)^{-1}B_c \). From the shift equations,
\[ z= \frac{1}{p(s)} \begin{bmatrix} 1\\ s\\ \vdots\\ s^{n-1} \end{bmatrix}. \]
Therefore,
\[ C_cz = \begin{bmatrix} b_0 & b_1 & \cdots & b_{n-1} \end{bmatrix} \frac{1}{p(s)} \begin{bmatrix} 1\\ s\\ \vdots\\ s^{n-1} \end{bmatrix}. \]
Hence
\[ C_c(sI-A_c)^{-1}B_c = \frac{b_0+b_1s+\cdots+b_{n-1}s^{n-1} }{p(s)}. \]
Problem 5: Explain why CCF is useful for pole placement but may be numerically undesirable for high-order systems.
Solution: CCF is useful for pole placement because the denominator coefficients appear directly in the final row of \( A_c \). State feedback changes this row in a structured way, making it easy to match a desired closed-loop characteristic polynomial. However, for high-order systems, polynomial coefficients may be badly scaled, and companion matrices may have poorly conditioned eigenvalues and controllability matrices. Therefore, CCF is theoretically clear but not always numerically robust.
15. Summary
The companion matrix converts a monic polynomial into a structured state matrix whose characteristic polynomial is exactly that polynomial. In controllable canonical form, \( B_c=e_n \), the controllability matrix has a nonzero determinant independent of the denominator coefficients, and the output matrix stores the numerator coefficients in ascending-power order. This makes CCF a central tool for understanding controllability, realization theory, and the pole placement methods developed later in the course.
16. References
- Kalman, R.E. (1960). On the general theory of control systems. Proceedings of the First International Congress on Automatic Control, Moscow.
- Kalman, R.E., Ho, Y.C., & Narendra, K.S. (1963). Controllability of linear dynamical systems. Contributions to Differential Equations, 1, 189–213.
- Gilbert, E.G. (1963). Controllability and observability in multivariable control systems. Journal of the Society for Industrial and Applied Mathematics, Series A: Control, 1(2), 128–151.
- Luenberger, D.G. (1967). Canonical forms for linear multivariable systems. IEEE Transactions on Automatic Control, AC-12(3), 290–293.
- Brunovský, P. (1970). A classification of linear controllable systems. Kybernetika, 6(3), 173–188.
- Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, AC-12(6), 660–665.
- Rosenbrock, H.H. (1962). Distinctive problems of process control. Chemical Engineering Progress, 58, 43–50.
- Kailath, T. (1966). Canonical forms for linear systems. IEEE Transactions on Automatic Control, AC-11, 361–362.