control//controllability and observability//controllability//controllability matrix

The controllability matrix is the block matrix built from the input matrix and its images under the dynamics, whose rank tells whether the inputs of a linear system can reach every direction of its \(n\)-dimensional state, and it is the first computation an engineer runs to check that a set of actuators is enough. Each block is a step of a push travelling through the system: \(B\) holds the directions the input pushes directly, \(AB\) those it reaches once the dynamics have carried the push one step, \(A^2B\) one step further.


The controllability matrix is the block matrix built from the input matrix and its images under the dynamics, whose rank tells whether the inputs of a linear system can reach every direction of its nnn-dimensional state, and it is the first computation an engineer runs to check that a set of actuators is enough. Each block is a step of a push travelling through the system: BBB holds the directions the input pushes directly, ABABAB those it reaches once the dynamics have carried the push one step, A2BA^2BA2B one step further.

C=[BABA2B⋯An−1B],rank⁡C=n.\mathcal C=\begin{bmatrix}B & AB & A^2B & \cdots & A^{n-1}B\end{bmatrix},\qquad \operatorname{rank}\mathcal C=n .C=[B​AB​A2B​⋯​An−1B​],rankC=n.

If the columns together span the nnn dimensions of the state, the system is controllable. Further powers of AAA bring no new directions (the Cayley-Hamilton theorem guarantees it), which is why the stack stops at An−1BA^{n-1}BAn−1B; the test is Kalman's, from 1960.

On a hovering planar drone, with lateral position xxx, its velocity x˙\dot xx˙, the tilt θ\thetaθ and the tilt rate θ˙\dot\thetaθ˙, the input (a difference of thrust between the two motors) pushes θ˙\dot\thetaθ˙. ABABAB reaches θ\thetaθ, A2BA^2BA2B reaches x˙\dot xx˙, multiplied by ggg because a tilt turns thrust into sideways acceleration, and A3BA^3BA3B reaches xxx. Four independent directions: controllable. The matrix has the drone's chain of four integrators printed on it, and that same chain is why a single PID cannot hold lateral position while nested loops, one per link, can (cascade control).

The rank is computed numerically, numpy.linalg.matrix_rank(control.ctrb(A, B)) with python-control, and a computed rank is itself a threshold on singular values. How hard the weakest direction is to move is read from the smallest of them (SVD): a tiny value means huge actuator effort.

With several inputs BBB has several columns and the matrix is wide, n×nmn\times nmn×nm; the condition is still rank nnn, and often fewer powers of AAA are needed.

The test belongs to a linear model. For a nonlinear plant it is run on the linearization at an operating point, and it says nothing about the plant far from that point.

Its mirror is the observability matrix, the same construction with CCC in place of BBB and the blocks stacked in rows.