Skip to content
Menu

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.

PowerPoint handouts: Dark · Light

Kalman decomposition of an uncontrollable system

Section titled “Kalman decomposition of an uncontrollable system”
link to download code

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 np
import control as ct
from scipy.linalg import orth
from scipy.linalg import null_space
b = 1
m = 1
k1 = 0.5
k2 = 1
A = 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) @ M
print("\ntilde A = inv(M) A M =")
print(tildeA)
tildeB = np.linalg.inv(M) @ B
print("\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.

← All chapters