10. Kalman Decomposition
Real systems are rarely fully controllable and observable. The Kalman decomposition splits a system into controllable/uncontrollable and observable/unobservable subspaces, revealing exactly which parts feedback can and cannot influence.
Lecture videos
Section titled “Lecture videos”Slides
Section titled “Slides”PowerPoint handouts: Dark · Light
Interactive example
Section titled “Interactive example”Kalman decomposition of an uncontrollable system
Section titled “Kalman decomposition of an uncontrollable system”A three-state spring-mass system with damping b and two spring constants k1, k2 turns out to have rank(P)=2 — only 2 of its 3 states are controllable. This automatically builds the change-of-basis matrix M whose columns come from an orthonormal basis of the controllable subspace (orth(P)) and its complement (null_space(P^T)), rather than picking Mc by hand as the text also shows.
Transforming into that new basis, tilde A = M^-1 A M and tilde B = M^-1 B come out in the block-triangular Kalman decomposition form: the bottom row of both is (numerically) zero, cleanly isolating the single uncontrollable mode from the two controllable ones.
import numpy as npimport control as ctfrom scipy.linalg import orthfrom scipy.linalg import null_space
b = 1m = 1k1 = 0.5k2 = 1A = np.array([[-b / m, -1 / m, -1 / m], [k1, 0, 0], [k2, 0, 0]])B = np.array([[1 / m], [0], [0]])
P = ct.ctrb(A, B)print("rank(P) =", np.linalg.matrix_rank(P), "-- system is not fully controllable")
# Build the change-of-basis M automatically: its first columns span the# controllable subspace (orth(P)), and the rest span its orthogonal# complement / the uncontrollable subspace (null_space(P^T))Mc = orth(P)Muc = null_space(P.transpose())M = np.column_stack((Mc, Muc))print("\nM =")print(M)
tildeA = (np.linalg.inv(M) @ A) @ Mprint("\ntilde A = inv(M) A M =")print(tildeA)
tildeB = np.linalg.inv(M) @ Bprint("\ntilde B = inv(M) B =")print(tildeB)
print("\nNote the ~0 entries in the bottom row of tilde A and tilde B -- that's")print("the uncontrollable mode, cleanly separated out by the Kalman decomposition.")Kalman decomposition of an uncontrollable system (mcimp/codes/kalman_decompose/uncontrollablesys.py)
Click "Run" to execute.