Chapter 13: Observability and Detectability – Concepts
Lesson 2: Observable States and Observable Subspace
This lesson formalizes what part of the initial state can be inferred from output measurements in a continuous-time LTI system. We define output-indistinguishability, the unobservable subspace, and the observable subspace, then show how these spaces explain why two different internal states may generate exactly the same measured signal.
1. From Output Measurements to State Information
Consider the continuous-time LTI model already introduced in previous chapters:
\[ \dot{\mathbf{x} }(t)=\mathbf{A}\mathbf{x}(t)+\mathbf{B}\mathbf{u}(t), \qquad \mathbf{y}(t)=\mathbf{C}\mathbf{x}(t)+\mathbf{D}\mathbf{u}(t). \]
Observability is about information carried by the output \( \mathbf{y}(t) \) about the initial condition \( \mathbf{x}(0) \). If the input \( \mathbf{u}(t) \) is known, its contribution to the output can be subtracted conceptually. Therefore, the essential question is the zero-input map \( \mathbf{x}_0 \mapsto \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0 \).
\[ \mathbf{y}_0(t)=\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0,\qquad t\ge 0. \]
A state direction is observable if changing the initial state in that direction necessarily changes the measured signal at some time. A state direction is unobservable if motion along that direction is perfectly hidden from all output measurements.
flowchart TD
A["Initial state x0"] --> B["Internal evolution exp(A t) x0"]
B --> C["Sensor map C"]
C --> D["Measured zero-input output y0(t)"]
D --> E["Can different initial states give the same output?"]
E -->|"yes"| F["Their difference is unobservable"]
E -->|"no"| G["Difference is detected by measurements"]
2. Output-Indistinguishable Initial States
Two initial states \( \mathbf{x}_{a0} \) and \( \mathbf{x}_{b0} \) are output-indistinguishable on the observation interval if they generate the same zero-input output signal:
\[ \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{a0}=\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{b0}, \qquad \text{for every } t\ge 0. \]
By linearity, this is equivalent to saying that the difference \( \mathbf{v}=\mathbf{x}_{a0}-\mathbf{x}_{b0} \) produces no output at all:
\[ \mathbf{C}e^{\mathbf{A}t}\mathbf{v}=\mathbf{0},\qquad \text{for every } t\ge 0. \]
Hence observability is not only a property of sensors, but a property of how sensors combine with the natural dynamics. A coordinate may not be measured directly, yet it may still be observable if it affects another measured coordinate through the dynamics.
3. The Unobservable Subspace
The unobservable subspace is the set of all initial state directions that are completely invisible at the output:
\[ \mathcal{N}_o=\left\{\mathbf{x}_0\in\mathbb{R}^{n}:\; \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0=\mathbf{0}\;\text{for every }t\ge 0\right\}. \]
This set is a subspace. Indeed, if \( \mathbf{x}_1,\mathbf{x}_2\in\mathcal{N}_o \) and \( \alpha,\beta\in\mathbb{R} \), then
\[ \mathbf{C}e^{\mathbf{A}t}(\alpha\mathbf{x}_1+\beta\mathbf{x}_2) =\alpha\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_1+ \beta\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_2=\mathbf{0}. \]
Thus \( \alpha\mathbf{x}_1+\beta\mathbf{x}_2\in\mathcal{N}_o \). The dimension of \( \mathcal{N}_o \) is the number of independent hidden state directions.
The subspace is also invariant under the state matrix \( \mathbf{A} \). Differentiating the zero-output condition gives
\[ \frac{d}{dt}\left(\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0\right) =\mathbf{C}e^{\mathbf{A}t}\mathbf{A}\mathbf{x}_0. \]
Therefore, if \( \mathbf{x}_0\in\mathcal{N}_o \), then \( \mathbf{A}\mathbf{x}_0\in\mathcal{N}_o \). Hidden directions remain hidden under the autonomous dynamics.
4. Observable Subspace and Orthogonal Decomposition
In the standard Euclidean inner product, the observable subspace is the orthogonal complement of the unobservable subspace:
\[ \mathcal{X}_o=\mathcal{N}_o^{\perp}. \]
Every state can be decomposed uniquely into an observable component and an unobservable component:
\[ \mathbf{x}_0=\mathbf{x}_{o0}+\mathbf{x}_{u0},\qquad \mathbf{x}_{o0}\in\mathcal{X}_o,\quad \mathbf{x}_{u0}\in\mathcal{N}_o. \]
Only the observable component affects the output signal:
\[ \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0 =\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{o0} +\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{u0} =\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{o0}. \]
Therefore, state reconstruction from outputs can at best identify the observable component. The unobservable component is not a numerical error; it is structurally absent from the data stream.
flowchart LR
X["State space R^n"] --> XO["Observable subspace Xo"]
X --> NU["Unobservable subspace No"]
XO --> Y["Creates measurable output information"]
NU --> Z["Creates zero output for all time"]
X --> SUM["x0 = observable part + hidden part"]
5. Finite Derivative Signatures and the Cayley–Hamilton Argument
The infinite condition \( \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0=\mathbf{0} \) can be expressed using a finite number of output derivatives at \( t=0 \). Since
\[ \frac{d^k\mathbf{y}_0}{dt^k}(0)=\mathbf{C}\mathbf{A}^{k}\mathbf{x}_0,\qquad k=0,1,2,\ldots, \]
an initial state is invisible if all of these derivative signatures are zero. By the Cayley–Hamilton theorem, powers \( \mathbf{A}^{k} \) with \( k\ge n \) are linear combinations of \( \mathbf{I},\mathbf{A},\ldots,\mathbf{A}^{n-1} \). Therefore it is enough to check the finite stack
\[ \mathbf{O}_{n-1}=\begin{bmatrix} \mathbf{C} \\ \mathbf{C}\mathbf{A} \\ \mathbf{C}\mathbf{A}^2 \\ \vdots \\ \mathbf{C}\mathbf{A}^{n-1} \end{bmatrix}. \]
The hidden and visible spaces can then be written as
\[ \mathcal{N}_o=\ker(\mathbf{O}_{n-1}),\qquad \mathcal{X}_o=\operatorname{range}(\mathbf{O}_{n-1}^{\top}). \]
Later, Chapter 14 will turn this finite matrix into standard algebraic observability tests. In this lesson, its role is geometric: its null space is the set of invisible directions, and its row space is the set of state directions that the output derivatives can sense.
6. Coordinate Decomposition into Observable and Hidden Parts
Choose a nonsingular transformation \( \mathbf{x}=\mathbf{T}\mathbf{z} \) whose last columns span \( \mathcal{N}_o \). In the coordinates \( \mathbf{z}=\begin{bmatrix}\mathbf{z}_o^{\top}&\mathbf{z}_u^{\top}\end{bmatrix}^{\top} \), the zero-input dynamics have the structure
\[ \begin{bmatrix}\dot{\mathbf{z} }_o\\\dot{\mathbf{z} }_u\end{bmatrix} =\begin{bmatrix}\mathbf{A}_{oo}&\mathbf{0}\\ \mathbf{A}_{uo}&\mathbf{A}_{uu}\end{bmatrix} \begin{bmatrix}\mathbf{z}_o\\\mathbf{z}_u\end{bmatrix},\qquad \mathbf{y}=\begin{bmatrix}\mathbf{C}_o&\mathbf{0}\end{bmatrix} \begin{bmatrix}\mathbf{z}_o\\\mathbf{z}_u\end{bmatrix}. \]
The zero block in the upper-right position follows from invariance of the unobservable subspace. The zero block in the output equation follows from the fact that states in \( \mathcal{N}_o \) are invisible. This form shows that hidden coordinates do not drive the measured coordinates in the zero-input model; otherwise they would be visible through the output.
7. Worked Example: One Hidden Mode
Consider
\[ \mathbf{A}=\begin{bmatrix}0&1&0\\-2&-3&0\\0&0&-4\end{bmatrix}, \qquad \mathbf{C}=\begin{bmatrix}1&0&0\end{bmatrix}. \]
The measured output is the first state coordinate. The finite output derivative signature matrix is
\[ \mathbf{O}_{2}=\begin{bmatrix} 1&0&0\\ 0&1&0\\ -2&-3&0 \end{bmatrix}. \]
Hence
\[ \ker(\mathbf{O}_{2})=\operatorname{span}\left\{\begin{bmatrix}0\\0\\1\end{bmatrix}\right\}, \qquad \mathcal{X}_o=\operatorname{span}\left\{\begin{bmatrix}1\\0\\0\end{bmatrix}, \begin{bmatrix}0\\1\\0\end{bmatrix}\right\}. \]
The third state is unobservable because it evolves independently and never enters the measured coordinates. However, the second state is observable even though it is not measured directly, because it appears in the derivative of the measured coordinate.
8. Python Implementation
Python implementations normally use NumPy and
SciPy; the python-control package is useful
for state-space simulation and classical/modern control workflows. The
code below computes \( \mathbf{O}_{n-1} \), its null
space, the observable subspace basis, and the observable/unobservable
projection of an initial condition using only NumPy.
Chapter13_Lesson2.py
# Chapter13_Lesson2.py
# Observable states and observable subspace for a continuous-time LTI system.
# Dependencies: numpy only. Optional modern-control packages: scipy.signal and python-control
# can be used for state-space simulation, but the subspace computation below is from scratch.
import numpy as np
def observability_signature_matrix(A: np.ndarray, C: np.ndarray) -> np.ndarray:
"""Build O = [C; C A; ...; C A^(n-1)]."""
A = np.asarray(A, dtype=float)
C = np.asarray(C, dtype=float)
n = A.shape[0]
blocks = []
Ak = np.eye(n)
for _ in range(n):
blocks.append(C @ Ak)
Ak = Ak @ A
return np.vstack(blocks)
def numerical_rank(M: np.ndarray, tol: float = 1e-10) -> int:
"""SVD-based numerical rank."""
s = np.linalg.svd(M, compute_uv=False)
return int(np.sum(s > tol))
def null_space(M: np.ndarray, tol: float = 1e-10) -> np.ndarray:
"""Return an orthonormal basis for the null space of M as columns."""
_, s, vh = np.linalg.svd(M, full_matrices=True)
rank = int(np.sum(s > tol))
return vh[rank:].T
def observable_projection(A: np.ndarray, C: np.ndarray, tol: float = 1e-10):
"""Compute the observable and unobservable subspace projectors.
The unobservable subspace is ker(O). The observable subspace, in the
standard Euclidean inner product, is ker(O)^perp = range(O.T).
"""
O = observability_signature_matrix(A, C)
N = null_space(O, tol)
# SVD row-space basis for range(O.T)
u, s, vh = np.linalg.svd(O, full_matrices=True)
rank = int(np.sum(s > tol))
V_o = vh[:rank].T
P_o = V_o @ V_o.T
P_u = N @ N.T if N.size else np.zeros((A.shape[0], A.shape[0]))
return O, V_o, N, P_o, P_u
def output_signature(A: np.ndarray, C: np.ndarray, x0: np.ndarray) -> np.ndarray:
"""Finite derivative signature [C x0, C A x0, ..., C A^(n-1) x0]."""
O = observability_signature_matrix(A, C)
return O @ np.asarray(x0, dtype=float)
if __name__ == "__main__":
# Example: x3 is dynamically separated from the measured coordinates.
A = np.array([[0.0, 1.0, 0.0],
[-2.0, -3.0, 0.0],
[0.0, 0.0, -4.0]])
C = np.array([[1.0, 0.0, 0.0]])
O, V_o, N_u, P_o, P_u = observable_projection(A, C)
print("Observability signature matrix O:")
print(O)
print("rank(O) =", numerical_rank(O))
print("Observable subspace basis columns (range of O.T):")
print(V_o)
print("Unobservable subspace basis columns (ker O):")
print(N_u)
x0 = np.array([2.0, -1.0, 5.0])
x_obs = P_o @ x0
x_unobs = P_u @ x0
print("x0 =", x0)
print("observable component =", x_obs)
print("unobservable component =", x_unobs)
print("finite output derivative signature of x0 =", output_signature(A, C, x0))
print("signature of observable component =", output_signature(A, C, x_obs))
print("signature of unobservable component =", output_signature(A, C, x_unobs))
9. C++ Implementation with Eigen
For C++, Eigen is a compact and widely used linear algebra
library. The following implementation builds the output derivative
signature and computes bases for hidden and visible directions using
singular value decomposition.
Chapter13_Lesson2.cpp
// Chapter13_Lesson2.cpp
// Observable states and observable subspace for an LTI system.
// Dependency: Eigen (https://eigen.tuxfamily.org). Compile for example with:
// g++ Chapter13_Lesson2.cpp -I /path/to/eigen -O2 -std=c++17 -o Chapter13_Lesson2
#include <Eigen/Dense>
#include <iostream>
#include <vector>
using Eigen::MatrixXd;
using Eigen::VectorXd;
MatrixXd observabilitySignatureMatrix(const MatrixXd& A, const MatrixXd& C) {
const int n = static_cast<int>(A.rows());
const int p = static_cast<int>(C.rows());
MatrixXd O(p * n, n);
MatrixXd Ak = MatrixXd::Identity(n, n);
for (int k = 0; k < n; ++k) {
O.block(k * p, 0, p, n) = C * Ak;
Ak = Ak * A;
}
return O;
}
int numericalRank(const MatrixXd& M, double tol = 1e-10) {
Eigen::JacobiSVD<MatrixXd> svd(M);
int r = 0;
for (int i = 0; i < svd.singularValues().size(); ++i) {
if (svd.singularValues()(i) > tol) ++r;
}
return r;
}
MatrixXd nullSpace(const MatrixXd& M, double tol = 1e-10) {
Eigen::JacobiSVD<MatrixXd> svd(M, Eigen::ComputeFullV);
const auto& s = svd.singularValues();
int r = 0;
for (int i = 0; i < s.size(); ++i) {
if (s(i) > tol) ++r;
}
return svd.matrixV().rightCols(M.cols() - r);
}
MatrixXd rowSpaceBasisAsColumns(const MatrixXd& M, double tol = 1e-10) {
Eigen::JacobiSVD<MatrixXd> svd(M, Eigen::ComputeFullV);
const auto& s = svd.singularValues();
int r = 0;
for (int i = 0; i < s.size(); ++i) {
if (s(i) > tol) ++r;
}
return svd.matrixV().leftCols(r);
}
int main() {
MatrixXd A(3, 3);
A << 0.0, 1.0, 0.0,
-2.0, -3.0, 0.0,
0.0, 0.0, -4.0;
MatrixXd C(1, 3);
C << 1.0, 0.0, 0.0;
MatrixXd O = observabilitySignatureMatrix(A, C);
MatrixXd Nu = nullSpace(O);
MatrixXd Vo = rowSpaceBasisAsColumns(O);
std::cout << "Observability signature matrix O:\n" << O << "\n\n";
std::cout << "rank(O) = " << numericalRank(O) << "\n\n";
std::cout << "Observable subspace basis columns (range of O^T):\n" << Vo << "\n\n";
std::cout << "Unobservable subspace basis columns (ker O):\n" << Nu << "\n\n";
VectorXd x0(3);
x0 << 2.0, -1.0, 5.0;
MatrixXd Po = Vo * Vo.transpose();
MatrixXd Pu = Nu.cols() > 0 ? Nu * Nu.transpose() : MatrixXd::Zero(3, 3);
std::cout << "x0:\n" << x0 << "\n\n";
std::cout << "observable component:\n" << Po * x0 << "\n\n";
std::cout << "unobservable component:\n" << Pu * x0 << "\n";
return 0;
}
10. Java Implementation
Java projects commonly use EJML,
Apache Commons Math, or ojAlgo for numerical
linear algebra. To expose the algorithmic structure, the following file
builds \( \mathbf{O}_{n-1} \) from scratch and
estimates rank using reduced row echelon form.
Chapter13_Lesson2.java
// Chapter13_Lesson2.java
// Observable states and observable subspace from scratch using basic linear algebra.
// For production-scale projects, use EJML, Apache Commons Math, or ojAlgo.
import java.util.Arrays;
public class Chapter13_Lesson2 {
static double[][] multiply(double[][] A, double[][] B) {
int m = A.length, n = A[0].length, p = B[0].length;
double[][] C = new double[m][p];
for (int i = 0; i < m; i++) {
for (int k = 0; k < n; k++) {
for (int j = 0; j < p; j++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
return C;
}
static double[][] identity(int n) {
double[][] I = new double[n][n];
for (int i = 0; i < n; i++) I[i][i] = 1.0;
return I;
}
static double[][] observabilitySignatureMatrix(double[][] A, double[][] C) {
int n = A.length;
int p = C.length;
double[][] O = new double[p * n][n];
double[][] Ak = identity(n);
for (int k = 0; k < n; k++) {
double[][] block = multiply(C, Ak);
for (int i = 0; i < p; i++) {
System.arraycopy(block[i], 0, O[k * p + i], 0, n);
}
Ak = multiply(Ak, A);
}
return O;
}
static double[][] rref(double[][] M, double tol) {
int m = M.length, n = M[0].length;
double[][] R = new double[m][n];
for (int i = 0; i < m; i++) R[i] = Arrays.copyOf(M[i], n);
int lead = 0;
for (int r = 0; r < m && lead < n; r++) {
int i = r;
while (i < m && Math.abs(R[i][lead]) < tol) i++;
if (i == m) { lead++; r--; continue; }
double[] temp = R[r]; R[r] = R[i]; R[i] = temp;
double pivot = R[r][lead];
for (int j = 0; j < n; j++) R[r][j] /= pivot;
for (int ii = 0; ii < m; ii++) {
if (ii == r) continue;
double factor = R[ii][lead];
for (int j = 0; j < n; j++) R[ii][j] -= factor * R[r][j];
}
lead++;
}
return R;
}
static int rank(double[][] M, double tol) {
double[][] R = rref(M, tol);
int rank = 0;
for (double[] row : R) {
boolean nonzero = false;
for (double v : row) if (Math.abs(v) > tol) { nonzero = true; break; }
if (nonzero) rank++;
}
return rank;
}
static void printMatrix(String name, double[][] M) {
System.out.println(name + ":");
for (double[] row : M) System.out.println(Arrays.toString(row));
System.out.println();
}
public static void main(String[] args) {
double[][] A = {
{0.0, 1.0, 0.0},
{-2.0, -3.0, 0.0},
{0.0, 0.0, -4.0}
};
double[][] C = { {1.0, 0.0, 0.0} };
double[][] O = observabilitySignatureMatrix(A, C);
printMatrix("Observability signature matrix O", O);
System.out.println("rank(O) = " + rank(O, 1e-10));
System.out.println("unobservable dimension = " + (A.length - rank(O, 1e-10)));
System.out.println("For this example, the unobservable direction is span{[0, 0, 1]^T}.");
}
}
11. MATLAB and Simulink Implementation
MATLAB provides rank, null, orth,
and, with Control System Toolbox, obsv. The script below
uses base MATLAB operations and optionally creates a simple Simulink
state-space block whose output is
\( \mathbf{y}=\mathbf{C}\mathbf{x} \).
Chapter13_Lesson2.m
% Chapter13_Lesson2.m
% Observable states and observable subspace for a continuous-time LTI system.
% Uses MATLAB base functions. If Control System Toolbox is installed, obsv(A,C)
% gives the same observability signature matrix.
clear; clc;
A = [ 0 1 0;
-2 -3 0;
0 0 -4];
C = [1 0 0];
n = size(A,1);
O = [];
for k = 0:n-1
O = [O; C*(A^k)]; %#ok<AGROW>
end
fprintf('Observability signature matrix O:\n');
disp(O);
fprintf('rank(O) = %d\n', rank(O));
Nu = null(O); % unobservable subspace basis
Vo = orth(O.'); % observable subspace basis in Euclidean coordinates
Po = Vo*Vo.'; % projection onto observable subspace
Pu = Nu*Nu.'; % projection onto unobservable subspace
fprintf('Observable subspace basis columns:\n');
disp(Vo);
fprintf('Unobservable subspace basis columns:\n');
disp(Nu);
x0 = [2; -1; 5];
fprintf('x0 =\n'); disp(x0);
fprintf('observable component =\n'); disp(Po*x0);
fprintf('unobservable component =\n'); disp(Pu*x0);
fprintf('finite output derivative signature O*x0 =\n'); disp(O*x0);
fprintf('signature of unobservable component O*(Pu*x0) =\n'); disp(O*(Pu*x0));
% Optional Simulink block generation: the measured output is y = C x.
% The input channel is set to zero because this lesson focuses on initial-state
% information, not control excitation.
try
if license('test','Simulink')
model = 'Chapter13_Lesson2_Simulink';
if bdIsLoaded(model), close_system(model, 0); end
new_system(model); open_system(model);
add_block('simulink/Sources/Constant', [model '/zero input'], 'Value', '0');
add_block('simulink/Continuous/State-Space', [model '/LTI system']);
set_param([model '/LTI system'], 'A', mat2str(A), ...
'B', mat2str(zeros(3,1)), 'C', mat2str(C), 'D', mat2str(0));
add_block('simulink/Sinks/Scope', [model '/output scope']);
add_line(model, 'zero input/1', 'LTI system/1');
add_line(model, 'LTI system/1', 'output scope/1');
save_system(model);
fprintf('Simulink model saved as %s.slx\n', model);
end
catch ME
fprintf('Simulink model generation skipped: %s\n', ME.message);
end
12. Wolfram Mathematica Implementation
Mathematica is convenient for symbolic and exact linear algebra. The code below computes the finite signature matrix, its rank, and its null space exactly for the worked example.
Chapter13_Lesson2.nb
(* Chapter13_Lesson2.nb *)
(* Observable states and observable subspace for a continuous-time LTI system. *)
ClearAll[ObservabilitySignatureMatrix, A, Cmat, Omat, unobservableBasis, observableBasis];
A = { {0, 1, 0}, {-2, -3, 0}, {0, 0, -4} };
Cmat = { {1, 0, 0} };
ObservabilitySignatureMatrix[A_, C_] := Module[{n = Length[A]},
Join @@ Table[C . MatrixPower[A, k], {k, 0, n - 1}]
];
Omat = ObservabilitySignatureMatrix[A, Cmat];
MatrixForm[Omat]
MatrixRank[Omat]
unobservableBasis = NullSpace[Omat]
observableBasis = Orthogonalize[Transpose[RowReduce[Omat]] /. {0, 0, 0} -> Sequence[]]
x0 = {2, -1, 5};
Omat . x0
Omat . {0, 0, 5}
(* The vector {0,0,5} produces zero output derivative signature and belongs to the unobservable subspace. *)
13. Problems and Solutions
Problem 1 (Output-Indistinguishability): Let \( \mathbf{x}_{a0} \) and \( \mathbf{x}_{b0} \) be two initial states of the zero-input LTI system. Prove that they generate the same output for all time exactly when \( \mathbf{x}_{a0}-\mathbf{x}_{b0}\in\mathcal{N}_o \).
Solution: The two outputs are equal exactly when
\[ \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{a0}- \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_{b0}=\mathbf{0},\qquad t\ge 0. \]
By linearity this becomes
\[ \mathbf{C}e^{\mathbf{A}t}(\mathbf{x}_{a0}-\mathbf{x}_{b0})=\mathbf{0}, \qquad t\ge 0. \]
This is precisely the definition of membership in \( \mathcal{N}_o \).
Problem 2 (Subspace Proof): Prove that \( \mathcal{N}_o \) is a vector subspace of \( \mathbb{R}^{n} \).
Solution: The zero vector belongs to \( \mathcal{N}_o \) because \( \mathbf{C}e^{\mathbf{A}t}\mathbf{0}=\mathbf{0} \). If \( \mathbf{x}_1,\mathbf{x}_2\in\mathcal{N}_o \) and \( \alpha,\beta\in\mathbb{R} \), then linearity gives
\[ \mathbf{C}e^{\mathbf{A}t}(\alpha\mathbf{x}_1+\beta\mathbf{x}_2) =\alpha\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_1+ \beta\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_2=\mathbf{0}. \]
Thus \( \mathcal{N}_o \) is closed under linear combinations and is a vector subspace.
Problem 3 (Computing Hidden Directions): For
\[ \mathbf{A}=\begin{bmatrix}0&1&0\\-2&-3&0\\0&0&-4\end{bmatrix}, \qquad \mathbf{C}=\begin{bmatrix}1&0&0\end{bmatrix}, \]
compute \( \mathcal{N}_o \) and \( \mathcal{X}_o \).
Solution: The finite signature matrix is
\[ \mathbf{O}_{2}=\begin{bmatrix} 1&0&0\\0&1&0\\-2&-3&0 \end{bmatrix}. \]
Solving \( \mathbf{O}_{2}\mathbf{x}=\mathbf{0} \) gives
\[ x_1=0,\qquad x_2=0,\qquad x_3\;\text{free}. \]
Therefore
\[ \mathcal{N}_o=\operatorname{span}\left\{\begin{bmatrix}0\\0\\1\end{bmatrix}\right\}, \qquad \mathcal{X}_o=\operatorname{span}\left\{\begin{bmatrix}1\\0\\0\end{bmatrix}, \begin{bmatrix}0\\1\\0\end{bmatrix}\right\}. \]
Problem 4 (Observable and Unobservable Components): For the same system, decompose \( \mathbf{x}_0=\begin{bmatrix}2&-1&5\end{bmatrix}^{\top} \) into observable and unobservable components.
Solution: Since \( \mathcal{X}_o=\operatorname{span}\{\mathbf{e}_1,\mathbf{e}_2\} \) and \( \mathcal{N}_o=\operatorname{span}\{\mathbf{e}_3\} \),
\[ \mathbf{x}_{o0}=\begin{bmatrix}2\\-1\\0\end{bmatrix}, \qquad \mathbf{x}_{u0}=\begin{bmatrix}0\\0\\5\end{bmatrix}. \]
The output generated by \( \mathbf{x}_{u0} \) is zero for all time, so all measured information comes from \( \mathbf{x}_{o0} \).
Problem 5 (Invariance of Hidden Dynamics): Prove that if \( \mathbf{x}_0\in\mathcal{N}_o \), then \( \mathbf{A}\mathbf{x}_0\in\mathcal{N}_o \).
Solution: Since \( \mathbf{x}_0\in\mathcal{N}_o \), the signal \( \mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0 \) is identically zero. Differentiating this identically zero signal gives
\[ \mathbf{0}=\frac{d}{dt}\left(\mathbf{C}e^{\mathbf{A}t}\mathbf{x}_0\right) =\mathbf{C}e^{\mathbf{A}t}\mathbf{A}\mathbf{x}_0. \]
Thus \( \mathbf{A}\mathbf{x}_0 \) also generates zero output for every time, so it belongs to \( \mathcal{N}_o \).
14. Summary
The observable subspace contains exactly the state directions that can influence the measured output, while the unobservable subspace contains directions that generate zero output for all time. Output data can distinguish initial states only up to an unobservable difference. The finite derivative signature matrix provides a concrete representation of these spaces: its null space is hidden, and its transpose range is visible. This geometric viewpoint prepares the algebraic tests of observability introduced in the next chapter.
15. References
- Kalman, R.E. (1960). On the general theory of control systems. Proceedings of the First International Congress on Automatic Control, Moscow, 481–492.
- 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. SIAM Journal on Control, 1(2), 128–151.
- Luenberger, D.G. (1966). Observers for multivariable systems. IEEE Transactions on Automatic Control, 11(2), 190–197.
- Hautus, M.L.J. (1969). Controllability and observability conditions of linear autonomous systems. Indagationes Mathematicae, 31, 443–448.
- Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 12(6), 660–665.