Chapter 22: Fundamentals of State-Feedback Control
Lesson 2: Closed-Loop State Matrix and Mode Relocation
This lesson studies how full-state feedback changes the internal dynamics of a linear state-space system. Starting from \( \dot{\mathbf{x} }=\mathbf{A}\mathbf{x}+\mathbf{B}\mathbf{u} \) and the feedback law \( \mathbf{u}=-\mathbf{K}\mathbf{x}+\mathbf{r} \), we derive the closed-loop state matrix \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} \), interpret its eigenvalues as relocated closed-loop modes, and prove which modes can and cannot be moved by state feedback.
1. From Open-Loop Dynamics to Closed-Loop Dynamics
Consider the continuous-time LTI system \( \dot{\mathbf{x} }(t)=\mathbf{A}\mathbf{x}(t)+\mathbf{B}\mathbf{u}(t) \), where \( \mathbf{x}(t)\in\mathbb{R}^{n} \), \( \mathbf{u}(t)\in\mathbb{R}^{m} \), \( \mathbf{A}\in\mathbb{R}^{n\times n} \), and \( \mathbf{B}\in\mathbb{R}^{n\times m} \). Under full-state feedback,
\[ \mathbf{u}(t)=-\mathbf{K}\mathbf{x}(t)+\mathbf{r}(t),\qquad \mathbf{K}\in\mathbb{R}^{m\times n}. \]
Substitution gives
\[ \dot{\mathbf{x} }(t)= \mathbf{A}\mathbf{x}(t)+\mathbf{B}\big(-\mathbf{K}\mathbf{x}(t)+\mathbf{r}(t)\big) =(\mathbf{A}-\mathbf{B}\mathbf{K})\mathbf{x}(t)+\mathbf{B}\mathbf{r}(t). \]
Therefore, the autonomous part of the closed-loop system is governed by the matrix
\[ \boxed{\mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} }. \]
The reference input \( \mathbf{r}(t) \) affects the forced response, but the internal closed-loop modes are determined by \( \mathbf{A}_{cl} \).
flowchart TD
R["reference r"] --> SUM["sum: r minus Kx"]
X["state x"] --> FB["gain K"]
FB --> SUM
SUM --> U["control input u"]
U --> PLANT["plant: x_dot = A x + B u"]
PLANT --> X
PLANT --> ACL["closed-loop matrix: Acl = A - B K"]
2. Closed-Loop Modes
The open-loop modes are the eigenvalues of \( \mathbf{A} \). The closed-loop modes are the eigenvalues of \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} \). Thus the closed-loop characteristic polynomial is
\[ p_{cl}(s)=\det\!\left(s\mathbf{I}-\mathbf{A}_{cl}\right) =\det\!\left(s\mathbf{I}-\mathbf{A}+\mathbf{B}\mathbf{K}\right). \]
The homogeneous closed-loop solution is
\[ \mathbf{x}(t)=e^{(\mathbf{A}-\mathbf{B}\mathbf{K})t}\mathbf{x}(0). \]
Hence, if all eigenvalues of \( \mathbf{A}-\mathbf{B}\mathbf{K} \) satisfy \( \operatorname{Re}(\lambda_i)<0 \), then the closed-loop origin is asymptotically stable. More generally, the qualitative response is shaped by the spectral data of \( \mathbf{A}_{cl} \): real modes yield exponential decay or growth, complex modes yield oscillatory exponentials, and repeated defective modes may introduce polynomial factors multiplying exponentials.
\[ \lambda_i(\mathbf{A}) \quad \text{open-loop modes},\qquad \lambda_i(\mathbf{A}-\mathbf{B}\mathbf{K}) \quad \text{closed-loop modes}. \]
3. Meaning of Mode Relocation
Mode relocation means modifying the eigenvalues of the autonomous state matrix by choosing the feedback gain \( \mathbf{K} \). In classical transfer-function language, one often speaks of moving closed-loop poles. In state-space language, the same idea is expressed as relocating the eigenvalues of \( \mathbf{A}_{cl} \).
For a desired set of closed-loop modes \( \{\mu_1,\mu_2,\dots,\mu_n\} \), the desired characteristic polynomial is
\[ p_d(s)=\prod_{i=1}^{n}(s-\mu_i) =s^n+\alpha_{n-1}s^{n-1}+\cdots+\alpha_1s+\alpha_0. \]
The design goal is to choose \( \mathbf{K} \) such that
\[ \det\!\left(s\mathbf{I}-\mathbf{A}+\mathbf{B}\mathbf{K}\right) =p_d(s). \]
In later lessons, we will study systematic pole-placement algorithms. In this lesson, the emphasis is conceptual: feedback replaces the internal generator \( \mathbf{A} \) by \( \mathbf{A}-\mathbf{B}\mathbf{K} \), and this changes the state-transition matrix from \( e^{\mathbf{A}t} \) to \( e^{(\mathbf{A}-\mathbf{B}\mathbf{K})t} \).
4. Mode Relocation Workflow
A practical state-feedback design workflow separates analysis from gain computation. First, inspect the open-loop modes and controllability. Then choose desired closed-loop modes based on stability and transient response. Finally, compute and verify \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} \).
flowchart TD
A["Model: A and B"] --> B["Compute open-loop modes"]
B --> C["Check controllability or controllable subspace"]
C --> D["Select desired closed-loop modes"]
D --> E["Choose feedback gain K"]
E --> F["Form Acl = A - B K"]
F --> G["Verify eigenvalues of Acl"]
G --> H["Simulate x_dot = Acl x"]
5. Second-Order SISO Example by Coefficient Matching
Consider the controllable second-order SISO system in phase-variable form:
\[ \dot{\mathbf{x} }= \begin{bmatrix}0 & 1\\ -a_0 & -a_1\end{bmatrix}\mathbf{x} +\begin{bmatrix}0\\1\end{bmatrix}u. \]
Let \( \mathbf{K}=\begin{bmatrix}k_1 & k_2\end{bmatrix} \). Then
\[ \mathbf{A}_{cl}= \begin{bmatrix}0 & 1\\ -a_0 & -a_1\end{bmatrix} -\begin{bmatrix}0\\1\end{bmatrix} \begin{bmatrix}k_1 & k_2\end{bmatrix} = \begin{bmatrix}0 & 1\\ -(a_0+k_1) & -(a_1+k_2)\end{bmatrix}. \]
The closed-loop characteristic polynomial is
\[ p_{cl}(s)=\det(s\mathbf{I}-\mathbf{A}_{cl}) =s^2+(a_1+k_2)s+(a_0+k_1). \]
Suppose the desired modes are \( \mu_1 \) and \( \mu_2 \). Then
\[ p_d(s)=(s-\mu_1)(s-\mu_2) =s^2-\left(\mu_1+\mu_2\right)s+\mu_1\mu_2. \]
Matching coefficients gives
\[ a_1+k_2=-(\mu_1+\mu_2),\qquad a_0+k_1=\mu_1\mu_2. \]
Therefore,
\[ \boxed{k_1=\mu_1\mu_2-a_0},\qquad \boxed{k_2=-(\mu_1+\mu_2)-a_1}. \]
For example, if
\[ \mathbf{A}=\begin{bmatrix}0 & 1\\ -2 & -0.4\end{bmatrix}, \qquad \mathbf{B}=\begin{bmatrix}0\\1\end{bmatrix}, \]
and the desired modes are \( -2 \) and \( -3 \), then
\[ p_d(s)=(s+2)(s+3)=s^2+5s+6. \]
Since \( a_0=2 \) and \( a_1=0.4 \),
\[ k_1=6-2=4,\qquad k_2=5-0.4=4.6. \]
Thus
\[ \mathbf{K}=\begin{bmatrix}4 & 4.6\end{bmatrix},\qquad \mathbf{A}_{cl}= \begin{bmatrix}0 & 1\\ -6 & -5\end{bmatrix}. \]
Its characteristic polynomial is
\[ \det(s\mathbf{I}-\mathbf{A}_{cl})=s^2+5s+6, \]
so the closed-loop modes are exactly \( -2 \) and \( -3 \).
6. Which Modes Can Be Moved?
State feedback can relocate modes only through directions influenced by the input matrix \( \mathbf{B} \). This is why controllability, studied earlier, is fundamental for state-feedback design.
Theorem: Suppose there exists a nonzero left eigenvector \( \mathbf{q}^{T} \) such that
\[ \mathbf{q}^{T}\mathbf{A}=\lambda\mathbf{q}^{T}, \qquad \mathbf{q}^{T}\mathbf{B}=\mathbf{0}. \]
Then \( \lambda \) is an eigenvalue of \( \mathbf{A}-\mathbf{B}\mathbf{K} \) for every feedback gain \( \mathbf{K} \).
Proof:
\[ \mathbf{q}^{T}(\mathbf{A}-\mathbf{B}\mathbf{K}) =\mathbf{q}^{T}\mathbf{A}-\mathbf{q}^{T}\mathbf{B}\mathbf{K} =\lambda\mathbf{q}^{T}-\mathbf{0}\mathbf{K} =\lambda\mathbf{q}^{T}. \]
Hence \( \mathbf{q}^{T} \) remains a left eigenvector of the closed-loop matrix with the same eigenvalue \( \lambda \). Therefore this mode is unaltered by any state-feedback gain. This proves that uncontrollable modes are unassignable by state feedback.
In contrast, if the pair \( (\mathbf{A},\mathbf{B}) \) is controllable, then all modes of the finite-dimensional LTI system can be assigned by a suitable full-state feedback gain. The constructive algorithms for doing this systematically are introduced in the next chapter.
7. Stability and Transient Interpretation
Once \( \mathbf{K} \) has been selected, stability is assessed from \( \mathbf{A}_{cl} \), not from \( \mathbf{A} \). The closed-loop equilibrium at the origin for the homogeneous system is asymptotically stable if and only if
\[ \operatorname{Re}\left(\lambda_i(\mathbf{A}-\mathbf{B}\mathbf{K})\right)<0, \qquad i=1,\dots,n. \]
If \( \mathbf{A}_{cl} \) is diagonalizable, then
\[ \mathbf{A}_{cl}=\mathbf{V}\boldsymbol{\Lambda}\mathbf{V}^{-1}, \qquad e^{\mathbf{A}_{cl}t} =\mathbf{V}e^{\boldsymbol{\Lambda}t}\mathbf{V}^{-1}. \]
Therefore the closed-loop response is a superposition of modal terms \( e^{\lambda_i t} \). Moving eigenvalues farther left generally increases decay rate, but also usually requires larger control effort because the control signal \( \mathbf{u}=-\mathbf{K}\mathbf{x}+\mathbf{r} \) becomes more aggressive. Thus mode relocation is not merely a stability operation; it is also a performance and actuator-demand decision.
8. Effect of Reference Input on Modes
With reference input, the closed-loop system is
\[ \dot{\mathbf{x} }(t)=\mathbf{A}_{cl}\mathbf{x}(t)+\mathbf{B}\mathbf{r}(t). \]
For a constant reference \( \mathbf{r}(t)=\mathbf{r}_0 \), if \( \mathbf{A}_{cl} \) is nonsingular, the equilibrium satisfies
\[ \mathbf{0}=\mathbf{A}_{cl}\mathbf{x}_{e}+\mathbf{B}\mathbf{r}_0, \qquad \mathbf{x}_{e}=-\mathbf{A}_{cl}^{-1}\mathbf{B}\mathbf{r}_0. \]
Define \( \tilde{\mathbf{x} }=\mathbf{x}-\mathbf{x}_{e} \). Then
\[ \dot{\tilde{\mathbf{x} } }=\mathbf{A}_{cl}\tilde{\mathbf{x} }. \]
Thus the reference changes the equilibrium and forced response, but it does not change the modal matrix \( \mathbf{A}_{cl} \). Closed-loop modes remain the eigenvalues of \( \mathbf{A}-\mathbf{B}\mathbf{K} \).
9. Python Implementation — Closed-Loop Modes
Chapter22_Lesson2.py
"""
Chapter22_Lesson2.py
Closed-Loop State Matrix and Mode Relocation
"""
from __future__ import annotations
import numpy as np
from numpy.typing import NDArray
try:
from scipy.linalg import expm
from scipy.signal import place_poles
SCIPY_AVAILABLE = True
except Exception:
SCIPY_AVAILABLE = False
def closed_loop_matrix(A: NDArray[np.float64],
B: NDArray[np.float64],
K: NDArray[np.float64]) -> NDArray[np.float64]:
"""Return Acl = A - B K."""
return A - B @ K
def characteristic_coefficients_2x2(A: NDArray[np.float64]) -> tuple[float, float]:
"""
For a 2 x 2 matrix A, return coefficients a1, a0 of
s^2 + a1 s + a0.
Since det(sI - A) = s^2 - tr(A) s + det(A),
a1 = -tr(A), a0 = det(A).
"""
trace = float(np.trace(A))
determinant = float(np.linalg.det(A))
return -trace, determinant
def second_order_feedback_by_matching(A: NDArray[np.float64],
B: NDArray[np.float64],
desired_poles: list[complex]) -> NDArray[np.float64]:
"""
From-scratch gain computation for a controllable second-order SISO system.
"""
if A.shape != (2, 2) or B.shape != (2, 1):
raise ValueError("This scratch implementation is only for 2x2 SISO systems.")
p1, p2 = desired_poles
desired_a1 = float(np.real(-(p1 + p2)))
desired_a0 = float(np.real(p1 * p2))
def coeffs_for(k1: float, k2: float) -> NDArray[np.float64]:
K = np.array([[k1, k2]], dtype=float)
Acl = closed_loop_matrix(A, B, K)
a1, a0 = characteristic_coefficients_2x2(Acl)
return np.array([a1, a0], dtype=float)
c00 = coeffs_for(0.0, 0.0)
c10 = coeffs_for(1.0, 0.0)
c01 = coeffs_for(0.0, 1.0)
M = np.column_stack([c10 - c00, c01 - c00])
target = np.array([desired_a1, desired_a0], dtype=float)
k = np.linalg.solve(M, target - c00)
return k.reshape(1, 2)
def simulate_homogeneous(Acl: NDArray[np.float64],
x0: NDArray[np.float64],
t_grid: NDArray[np.float64]) -> NDArray[np.float64]:
"""Return x(t) = exp(Acl t) x0 for all t in t_grid."""
if not SCIPY_AVAILABLE:
raise RuntimeError("scipy.linalg.expm is required for simulation.")
states = []
for t in t_grid:
states.append(expm(Acl * t) @ x0)
return np.asarray(states)
def main() -> None:
A = np.array([[0.0, 1.0],
[-2.0, -0.4]])
B = np.array([[0.0],
[1.0]])
print("Open-loop modes:", np.linalg.eigvals(A))
desired_poles = [-2.0, -3.0]
K_scratch = second_order_feedback_by_matching(A, B, desired_poles)
Acl_scratch = closed_loop_matrix(A, B, K_scratch)
print("K from coefficient matching:")
print(K_scratch)
print("Closed-loop modes:", np.linalg.eigvals(Acl_scratch))
if SCIPY_AVAILABLE:
result = place_poles(A, B, desired_poles)
K_library = result.gain_matrix
Acl_library = closed_loop_matrix(A, B, K_library)
print("K from scipy.signal.place_poles:")
print(K_library)
print("Closed-loop modes:", np.linalg.eigvals(Acl_library))
t = np.linspace(0.0, 5.0, 201)
x0 = np.array([1.0, 0.0])
X = simulate_homogeneous(Acl_library, x0, t)
print("Final state:", X[-1])
if __name__ == "__main__":
main()
10. C++ Implementation — From-Scratch 2x2 Relocation
Chapter22_Lesson2.cpp
/*
Chapter22_Lesson2.cpp
Closed-Loop State Matrix and Mode Relocation
*/
#include <array>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <vector>
struct Matrix2 {
double a11, a12, a21, a22;
};
struct Vector2 {
double v1, v2;
};
Matrix2 closedLoopMatrix(const Matrix2& A, const Vector2& B, const Vector2& K) {
return Matrix2{
A.a11 - B.v1 * K.v1, A.a12 - B.v1 * K.v2,
A.a21 - B.v2 * K.v1, A.a22 - B.v2 * K.v2
};
}
double trace(const Matrix2& M) {
return M.a11 + M.a22;
}
double determinant(const Matrix2& M) {
return M.a11 * M.a22 - M.a12 * M.a21;
}
std::pair<double, double> characteristicCoefficients(const Matrix2& M) {
return {-trace(M), determinant(M)};
}
std::pair<std::complex<double>, std::complex<double>> eigenvalues2x2(const Matrix2& M) {
const double tr = trace(M);
const double det = determinant(M);
const double disc = tr * tr - 4.0 * det;
if (disc >= 0.0) {
const double root = std::sqrt(disc);
return { {0.5 * (tr + root), 0.0}, {0.5 * (tr - root), 0.0} };
}
const double root = std::sqrt(-disc);
return { {0.5 * tr, 0.5 * root}, {0.5 * tr, -0.5 * root} };
}
Vector2 solve2x2(double m11, double m12, double m21, double m22,
double b1, double b2) {
const double det = m11 * m22 - m12 * m21;
if (std::abs(det) < 1e-12) {
throw std::runtime_error("Singular coefficient-matching equations.");
}
return Vector2{
( b1 * m22 - m12 * b2) / det,
( m11 * b2 - b1 * m21) / det
};
}
Vector2 secondOrderFeedbackByMatching(const Matrix2& A,
const Vector2& B,
double p1,
double p2) {
const double desiredA1 = -(p1 + p2);
const double desiredA0 = p1 * p2;
auto coeffsFor = [&](double k1, double k2) {
Matrix2 Acl = closedLoopMatrix(A, B, Vector2{k1, k2});
return characteristicCoefficients(Acl);
};
auto c00 = coeffsFor(0.0, 0.0);
auto c10 = coeffsFor(1.0, 0.0);
auto c01 = coeffsFor(0.0, 1.0);
const double m11 = c10.first - c00.first;
const double m21 = c10.second - c00.second;
const double m12 = c01.first - c00.first;
const double m22 = c01.second - c00.second;
const double rhs1 = desiredA1 - c00.first;
const double rhs2 = desiredA0 - c00.second;
return solve2x2(m11, m12, m21, m22, rhs1, rhs2);
}
int main() {
Matrix2 A{0.0, 1.0, -2.0, -0.4};
Vector2 B{0.0, 1.0};
auto openModes = eigenvalues2x2(A);
std::cout << std::fixed << std::setprecision(6);
std::cout << "Open-loop modes:\n";
std::cout << "lambda1 = " << openModes.first << "\n";
std::cout << "lambda2 = " << openModes.second << "\n\n";
Vector2 K = secondOrderFeedbackByMatching(A, B, -2.0, -3.0);
Matrix2 Acl = closedLoopMatrix(A, B, K);
auto closedModes = eigenvalues2x2(Acl);
auto coeffs = characteristicCoefficients(Acl);
std::cout << "K = [" << K.v1 << ", " << K.v2 << "]\n";
std::cout << "Closed-loop modes:\n";
std::cout << "lambda1 = " << closedModes.first << "\n";
std::cout << "lambda2 = " << closedModes.second << "\n";
std::cout << "Characteristic polynomial: s^2 + "
<< coeffs.first << " s + " << coeffs.second << "\n";
return 0;
}
11. Java Implementation — From-Scratch 2x2 Relocation
Chapter22_Lesson2.java
/*
Chapter22_Lesson2.java
Closed-Loop State Matrix and Mode Relocation
*/
public class Chapter22_Lesson2 {
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 class Vector2 {
double v1, v2;
Vector2(double v1, double v2) {
this.v1 = v1;
this.v2 = v2;
}
}
static class Complex {
double re, im;
Complex(double re, double im) {
this.re = re;
this.im = im;
}
@Override
public String toString() {
if (Math.abs(im) < 1e-12) {
return String.format("%.6f", re);
}
return String.format("%.6f%+.6fi", re, im);
}
}
static Matrix2 closedLoopMatrix(Matrix2 A, Vector2 B, Vector2 K) {
return new Matrix2(
A.a11 - B.v1 * K.v1, A.a12 - B.v1 * K.v2,
A.a21 - B.v2 * K.v1, A.a22 - B.v2 * K.v2
);
}
static double trace(Matrix2 M) {
return M.a11 + M.a22;
}
static double determinant(Matrix2 M) {
return M.a11 * M.a22 - M.a12 * M.a21;
}
static double[] characteristicCoefficients(Matrix2 M) {
return new double[]{-trace(M), determinant(M)};
}
static Complex[] eigenvalues2x2(Matrix2 M) {
double tr = trace(M);
double det = determinant(M);
double disc = tr * tr - 4.0 * det;
if (disc >= 0.0) {
double root = Math.sqrt(disc);
return new Complex[]{
new Complex(0.5 * (tr + root), 0.0),
new Complex(0.5 * (tr - root), 0.0)
};
}
double root = Math.sqrt(-disc);
return new Complex[]{
new Complex(0.5 * tr, 0.5 * root),
new Complex(0.5 * tr, -0.5 * root)
};
}
static Vector2 solve2x2(double m11, double m12, double m21, double m22,
double b1, double b2) {
double det = m11 * m22 - m12 * m21;
if (Math.abs(det) < 1e-12) {
throw new IllegalArgumentException("Singular coefficient-matching equations.");
}
return new Vector2(
( b1 * m22 - m12 * b2) / det,
( m11 * b2 - b1 * m21) / det
);
}
static Vector2 secondOrderFeedbackByMatching(Matrix2 A, Vector2 B,
double p1, double p2) {
double desiredA1 = -(p1 + p2);
double desiredA0 = p1 * p2;
double[] c00 = characteristicCoefficients(closedLoopMatrix(A, B, new Vector2(0.0, 0.0)));
double[] c10 = characteristicCoefficients(closedLoopMatrix(A, B, new Vector2(1.0, 0.0)));
double[] c01 = characteristicCoefficients(closedLoopMatrix(A, B, new Vector2(0.0, 1.0)));
double m11 = c10[0] - c00[0];
double m21 = c10[1] - c00[1];
double m12 = c01[0] - c00[0];
double m22 = c01[1] - c00[1];
double rhs1 = desiredA1 - c00[0];
double rhs2 = desiredA0 - c00[1];
return solve2x2(m11, m12, m21, m22, rhs1, rhs2);
}
public static void main(String[] args) {
Matrix2 A = new Matrix2(0.0, 1.0, -2.0, -0.4);
Vector2 B = new Vector2(0.0, 1.0);
Complex[] openModes = eigenvalues2x2(A);
System.out.println("Open-loop modes:");
System.out.println("lambda1 = " + openModes[0]);
System.out.println("lambda2 = " + openModes[1]);
Vector2 K = secondOrderFeedbackByMatching(A, B, -2.0, -3.0);
Matrix2 Acl = closedLoopMatrix(A, B, K);
Complex[] closedModes = eigenvalues2x2(Acl);
System.out.printf("%nK = [%.6f, %.6f]%n", K.v1, K.v2);
System.out.println("Closed-loop modes:");
System.out.println("lambda1 = " + closedModes[0]);
System.out.println("lambda2 = " + closedModes[1]);
}
}
12. MATLAB / Simulink Implementation
Chapter22_Lesson2.m
% Chapter22_Lesson2.m
% Closed-Loop State Matrix and Mode Relocation
clear; clc; close all;
A = [0 1;
-2 -0.4];
B = [0;
1];
C = [1 0];
D = 0;
disp('Open-loop modes:');
disp(eig(A));
desiredPoles = [-2 -3];
if exist('place', 'file') == 2
K_place = place(A, B, desiredPoles);
else
K_place = secondOrderFeedbackByMatching(A, B, desiredPoles);
end
Acl = A - B*K_place;
disp('K:');
disp(K_place);
disp('Acl = A - B*K:');
disp(Acl);
disp('Closed-loop modes:');
disp(eig(Acl));
disp('Closed-loop characteristic polynomial coefficients:');
disp(poly(Acl));
if exist('ss', 'file') == 2
sys_cl = ss(Acl, B, C, D);
t = linspace(0, 5, 250);
x0 = [1; 0];
initial(sys_cl, x0, t);
title('Closed-loop initial response: x_dot = (A - B K)x');
end
% Simulink implementation note:
% 1. Put a State-Space block with A = A, B = B, C = eye(2), D = zeros(2,1).
% 2. Feed its state output x into a Gain block K.
% 3. Use a Sum block to implement u = -K*x + r.
% 4. Feed u back into the State-Space block input.
function K = secondOrderFeedbackByMatching(A, B, desiredPoles)
p1 = desiredPoles(1);
p2 = desiredPoles(2);
desiredA1 = -(p1 + p2);
desiredA0 = p1 * p2;
coeffsFor = @(k1, k2) charCoeffs2(A - B*[k1 k2]);
c00 = coeffsFor(0, 0);
c10 = coeffsFor(1, 0);
c01 = coeffsFor(0, 1);
M = [(c10 - c00), (c01 - c00)];
target = [desiredA1; desiredA0];
k = M \ (target - c00);
K = k.';
end
function c = charCoeffs2(M)
c = [-trace(M); det(M)];
end
13. Wolfram Mathematica Implementation
Chapter22_Lesson2.nb
A = { {0, 1}, {-2, -0.4} };
B = { {0}, {1} };
Eigenvalues[A]
desiredPoles = {-2, -3};
charCoeffs2[M_] := {-Tr[M], Det[M]}
coeffsFor[k1_, k2_] := charCoeffs2[A - B.{ {k1, k2} }]
c00 = coeffsFor[0, 0];
c10 = coeffsFor[1, 0];
c01 = coeffsFor[0, 1];
M = Transpose[{c10 - c00, c01 - c00}];
target = {-Total[desiredPoles], Times @@ desiredPoles};
k = LinearSolve[M, target - c00];
K = {k};
Acl = A - B.K;
MatrixForm[Acl]
Eigenvalues[Acl]
CharacteristicPolynomial[Acl, s]
Expand[Det[s IdentityMatrix[2] - Acl] - Times @@ (s - desiredPoles)]
14. Problems and Solutions
Problem 1: Consider \( \dot{\mathbf{x} }=\mathbf{A}\mathbf{x}+\mathbf{B}\mathbf{u} \) with \( \mathbf{u}=-\mathbf{K}\mathbf{x}+\mathbf{r} \). Derive the closed-loop state equation and identify the matrix that determines the closed-loop modes.
Solution: Substitute the feedback law into the state equation:
\[ \dot{\mathbf{x} }= \mathbf{A}\mathbf{x}+\mathbf{B}(-\mathbf{K}\mathbf{x}+\mathbf{r}) =(\mathbf{A}-\mathbf{B}\mathbf{K})\mathbf{x}+\mathbf{B}\mathbf{r}. \]
Therefore, the closed-loop state matrix is \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} \), and the closed-loop modes are the eigenvalues of \( \mathbf{A}_{cl} \).
Problem 2: For
\[ \mathbf{A}=\begin{bmatrix}0 & 1\\ -2 & -0.4\end{bmatrix}, \qquad \mathbf{B}=\begin{bmatrix}0\\1\end{bmatrix},\qquad \mathbf{K}=\begin{bmatrix}4 & 4.6\end{bmatrix}, \]
compute \( \mathbf{A}_{cl} \) and its characteristic polynomial.
Solution:
\[ \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} = \begin{bmatrix}0 & 1\\ -2 & -0.4\end{bmatrix} - \begin{bmatrix}0\\1\end{bmatrix} \begin{bmatrix}4 & 4.6\end{bmatrix} = \begin{bmatrix}0 & 1\\ -6 & -5\end{bmatrix}. \]
\[ \det(s\mathbf{I}-\mathbf{A}_{cl}) = \det\begin{bmatrix}s & -1\\ 6 & s+5\end{bmatrix} =s(s+5)+6=s^2+5s+6. \]
Hence the closed-loop modes are \( -2 \) and \( -3 \).
Problem 3: Show that if \( \mathbf{q}^{T}\mathbf{A}=\lambda\mathbf{q}^{T} \) and \( \mathbf{q}^{T}\mathbf{B}=\mathbf{0} \), then \( \lambda \) remains a closed-loop eigenvalue for all feedback gains \( \mathbf{K} \).
Solution:
\[ \mathbf{q}^{T}(\mathbf{A}-\mathbf{B}\mathbf{K}) = \mathbf{q}^{T}\mathbf{A}-\mathbf{q}^{T}\mathbf{B}\mathbf{K} = \lambda\mathbf{q}^{T}-\mathbf{0}\mathbf{K} = \lambda\mathbf{q}^{T}. \]
Therefore, \( \mathbf{q}^{T} \) is still a left eigenvector of the closed-loop matrix with eigenvalue \( \lambda \). The mode cannot be relocated by state feedback.
Problem 4: A closed-loop matrix has eigenvalues \( -1 \), \( -4 \), and \( -2\pm 3j \). Is the closed-loop homogeneous system asymptotically stable?
Solution: Yes. Every eigenvalue has negative real part:
\[ \operatorname{Re}(-1)=-1,\qquad \operatorname{Re}(-4)=-4,\qquad \operatorname{Re}(-2\pm 3j)=-2. \]
Therefore \( \operatorname{Re}(\lambda_i)<0 \) for all modes, so the closed-loop origin is asymptotically stable.
Problem 5: For the second-order phase-variable system
\[ \mathbf{A}=\begin{bmatrix}0 & 1\\ -a_0 & -a_1\end{bmatrix}, \qquad \mathbf{B}=\begin{bmatrix}0\\1\end{bmatrix}, \]
derive the gain \( \mathbf{K}=\begin{bmatrix}k_1 & k_2\end{bmatrix} \) that relocates the modes to \( \mu_1 \) and \( \mu_2 \).
Solution: The closed-loop matrix is
\[ \mathbf{A}_{cl}= \begin{bmatrix}0 & 1\\ -(a_0+k_1) & -(a_1+k_2)\end{bmatrix}. \]
Thus
\[ p_{cl}(s)=s^2+(a_1+k_2)s+(a_0+k_1). \]
The desired polynomial is
\[ p_d(s)=(s-\mu_1)(s-\mu_2) =s^2-(\mu_1+\mu_2)s+\mu_1\mu_2. \]
Matching coefficients yields
\[ k_1=\mu_1\mu_2-a_0,\qquad k_2=-(\mu_1+\mu_2)-a_1. \]
15. Summary
State feedback replaces the open-loop state matrix \( \mathbf{A} \) by the closed-loop matrix \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} \). The eigenvalues of this matrix are the closed-loop modes, and relocating them changes stability and transient behavior. If the pair \( (\mathbf{A},\mathbf{B}) \) is controllable, full mode relocation is possible; if a mode is uncontrollable, it cannot be moved by any state-feedback gain. The next chapter develops systematic pole-placement procedures for computing \( \mathbf{K} \).
16. 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. (1963). Mathematical description of linear dynamical systems. Journal of the Society for Industrial and Applied Mathematics Series A: Control, 1(2), 152–192.
- Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 12(6), 660–665.
- Heymann, M. (1968). Comments on pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 13(6), 748–749.
- Rosenbrock, H.H. (1970). State-space and multivariable theory. Proceedings of the Institution of Electrical Engineers, 117(6), 1191–1193.
- Davison, E.J. (1968). On pole assignment in linear systems with incomplete state feedback. IEEE Transactions on Automatic Control, 13(3), 348–351.
- Kailath, T. (1980). Linear systems. Prentice-Hall theoretical systems series.
- Kautsky, J., Nichols, N.K., & Van Dooren, P. (1985). Robust pole assignment in linear state feedback. International Journal of Control, 41(5), 1129–1155.