Chapter 10: Controllability and Reachability – Concepts
Lesson 1: Intuitive Notion of Controllability and State Steering
This lesson introduces controllability as the ability of an input channel to steer the internal state of a dynamical system. We begin from the continuous-time state equation, derive the final-state steering equation, interpret actuator authority geometrically, and implement finite-horizon steering numerically. The formal Kalman rank test is intentionally deferred to Chapter 11; here the emphasis is conceptual, mathematical, and computational.
1. Why Controllability Matters
In classical control, one often asks whether a transfer function can be stabilized, shaped, or made to track a reference. In state-space control, a deeper internal question appears: can the input move the system from one internal condition to another? This is the intuitive meaning of \( \text{controllability} \).
Consider the continuous-time LTI model already developed in earlier chapters:
\[ \dot{\mathbf{x} }(t)=\mathbf{A}\mathbf{x}(t)+\mathbf{B}\mathbf{u}(t), \qquad \mathbf{x}(t)\in\mathbb{R}^{n},\quad \mathbf{u}(t)\in\mathbb{R}^{m}. \]
The state vector \( \mathbf{x} \) stores the internal memory of the system, while \( \mathbf{u} \) is the external signal injected through actuators. Controllability is not merely the existence of an input; it is the ability of the input, after being filtered through the dynamics \( \mathbf{A} \) and the input matrix \( \mathbf{B} \), to influence all independent state directions.
flowchart TD
A["Initial state x0"] --> B["Natural dynamics: A spreads and mixes states"]
U["Input u(t)"] --> C["Actuator directions: columns of B"]
B --> D["Forced state trajectory x(t)"]
C --> D
D --> E["Final state x(T)"]
E --> F["Question: can we choose u(t) so x(T) equals desired xf?"]
Informally, a system is controllable if every target state is attainable from every initial state in some finite time. For this lesson, think of controllability as state steering:
\[ \mathbf{x}(0)=\mathbf{x}_{0},\qquad \text{choose } \mathbf{u}(t) \text{ on } [0,T] \text{ so that } \mathbf{x}(T)=\mathbf{x}_{f},\quad T>0. \]
2. State Steering from the Variation-of-Constants Formula
From Chapter 7, the forced solution of an LTI state equation is
\[ \mathbf{x}(T)=e^{\mathbf{A}T}\mathbf{x}_{0} +\int_{0}^{T} e^{\mathbf{A}(T-s)}\mathbf{B}\mathbf{u}(s)\,ds. \]
This formula separates the final state into two parts:
\[ \underbrace{e^{\mathbf{A}T}\mathbf{x}_{0} }_{\text{free response} } + \underbrace{\int_{0}^{T} e^{\mathbf{A}(T-s)} \mathbf{B}\mathbf{u}(s)\,ds}_{\text{input-produced displacement} }. \]
Therefore, steering \( \mathbf{x}_{0} \) to \( \mathbf{x}_{f} \) means solving the operator equation
\[ \int_{0}^{T} e^{\mathbf{A}(T-s)}\mathbf{B}\mathbf{u}(s)\,ds = \mathbf{x}_{f}-e^{\mathbf{A}T}\mathbf{x}_{0}. \]
The right-hand side is the displacement that the input must create. If the integral term can produce every vector in \( \mathbb{R}^{n} \), then arbitrary state steering is possible. If it can only produce vectors in a lower-dimensional subspace, some state directions are unreachable no matter how large the input amplitude becomes.
Proof sketch of the steering equation. Define \( \mathbf{z}(t)=e^{-\mathbf{A}t}\mathbf{x}(t) \). Differentiating gives
\[ \dot{\mathbf{z} }(t) = -\mathbf{A}e^{-\mathbf{A}t}\mathbf{x}(t) +e^{-\mathbf{A}t}\dot{\mathbf{x} }(t) = e^{-\mathbf{A}t}\mathbf{B}\mathbf{u}(t). \]
Integrating from \( 0 \) to \( T \) and multiplying by \( e^{\mathbf{A}T} \) yields the formula above.
3. Geometric Intuition: Actuator Directions and Dynamic Mixing
The columns of \( \mathbf{B} \) identify the directions into which the input is injected instantaneously. However, the state matrix \( \mathbf{A} \) can rotate, shear, or mix those directly actuated directions into other state directions. Hence a system with fewer inputs than states may still be controllable.
For a single-input system with \( \mathbf{B}=\mathbf{b} \), the input first pushes along \( \mathbf{b} \). The dynamics then generate additional directions such as \( \mathbf{A}\mathbf{b} \), \( \mathbf{A}^{2}\mathbf{b} \), and so on. This idea will become the Kalman controllability matrix in Chapter 11, but here it is enough to remember the physical meaning:
\[ \begin{gathered} \text{direct actuator direction combined with dynamic propagation creates} \\ \text{possible motion directions}. \end{gathered} \]
flowchart TD
B["Input column b"] --> AB["A b: direction after one dynamic mixing"]
AB --> A2B["A^2 b: direction after further mixing"]
A2B --> SPAN["Span of generated directions"]
SPAN --> YES["If span fills state space: \nsteering is possible"]
SPAN --> NO["If span is smaller: \nsome internal states cannot be reached"]
This explains why controllability is a property of the pair \( (\mathbf{A},\mathbf{B}) \), not of \( \mathbf{A} \) alone and not of \( \mathbf{B} \) alone.
4. Two Introductory Examples
Example 1: Double Integrator
Let \( x_{1} \) be position and \( x_{2} \) be velocity:
\[ \dot{x}_{1}=x_{2},\qquad \dot{x}_{2}=u. \]
In matrix form,
\[ \dot{\mathbf{x} } = \begin{bmatrix}0&1\\0&0\end{bmatrix}\mathbf{x} + \begin{bmatrix}0\\1\end{bmatrix}u. \]
The input directly changes acceleration and therefore velocity. Position is not directly actuated, but because \( \dot{x}_{1}=x_{2} \), changing velocity over time changes position. Thus the input can steer both state components.
Example 2: A State That Cannot Be Moved
Now consider
\[ \dot{x}_{1}=0,\qquad \dot{x}_{2}=u. \]
The first state remains \( x_{1}(t)=x_{1}(0) \) for all time. No input can change it. Therefore, a target requiring \( x_{1}(T)\neq x_{1}(0) \) is impossible. This system has an actuator, but it is not controllable because one internal direction is completely isolated from the input.
\[ \mathbf{x}_{f}-e^{\mathbf{A}T}\mathbf{x}_{0} = \begin{bmatrix}\Delta x_{1}\\ \Delta x_{2}\end{bmatrix}, \qquad \Delta x_{1}\neq 0 \quad \Longrightarrow \quad \text{no steering input exists}. \]
5. Piecewise-Constant Inputs and a Finite-Dimensional Steering Map
To compute a steering signal on a computer, we often approximate the continuous input by a sequence of constant inputs:
\[ \mathbf{u}(t)=\mathbf{u}_{k},\qquad t\in[kh,(k+1)h),\qquad h=\frac{T}{N}. \]
The exact zero-order-hold discretization is
\[ \mathbf{x}_{k+1}=\boldsymbol{\Phi}\mathbf{x}_{k} +\boldsymbol{\Gamma}\mathbf{u}_{k},\qquad \boldsymbol{\Phi}=e^{\mathbf{A}h},\qquad \boldsymbol{\Gamma}=\int_{0}^{h}e^{\mathbf{A}s}\mathbf{B}\,ds. \]
Repeated substitution gives the final state:
\[ \mathbf{x}_{N} = \boldsymbol{\Phi}^{N}\mathbf{x}_{0} + \begin{bmatrix} \boldsymbol{\Phi}^{N-1}\boldsymbol{\Gamma}& \boldsymbol{\Phi}^{N-2}\boldsymbol{\Gamma}& \cdots& \boldsymbol{\Gamma} \end{bmatrix} \begin{bmatrix} \mathbf{u}_{0}\\ \mathbf{u}_{1}\\ \vdots\\ \mathbf{u}_{N-1} \end{bmatrix}. \]
Define the finite-horizon steering matrix \( \mathbf{S}_{N} \) by
\[ \mathbf{S}_{N} = \begin{bmatrix} \boldsymbol{\Phi}^{N-1}\boldsymbol{\Gamma}& \boldsymbol{\Phi}^{N-2}\boldsymbol{\Gamma}& \cdots& \boldsymbol{\Gamma} \end{bmatrix}. \]
Then state steering becomes a linear algebra problem:
\[ \mathbf{S}_{N}\mathbf{U} = \mathbf{x}_{f}-\boldsymbol{\Phi}^{N}\mathbf{x}_{0}. \]
If this equation has a solution, the input sequence \( \mathbf{U} \) steers the sampled system from \( \mathbf{x}_{0} \) to \( \mathbf{x}_{f} \). If there are many solutions, the minimum-norm sequence is
\[ \mathbf{U}^{\star} = \mathbf{S}_{N}^{T} \left(\mathbf{S}_{N}\mathbf{S}_{N}^{T}\right)^{-1} \left(\mathbf{x}_{f}-\boldsymbol{\Phi}^{N}\mathbf{x}_{0}\right), \]
provided \( \mathbf{S}_{N}\mathbf{S}_{N}^{T} \) is nonsingular. This formula is a computational introduction to the energy viewpoint that will be studied more formally in Chapter 12.
6. What Controllability Is Not
Controllability should not be confused with stability. A system can be unstable and controllable, meaning that the uncontrolled natural motion diverges but the input has enough authority to move the state as needed. Conversely, a system can be stable but uncontrollable, meaning that some internal state component decays naturally but cannot be independently placed by an input.
\[ \text{stability concerns } e^{\mathbf{A}t}\mathbf{x}_{0}, \qquad \text{controllability concerns } \int_{0}^{T}e^{\mathbf{A}(T-s)}\mathbf{B}\mathbf{u}(s)\,ds. \]
Controllability also does not mean that every trajectory is physically acceptable. Real actuators saturate, inputs cost energy, states may have safety constraints, and some steering times may require impractically large inputs. The mathematical property answers an existence question; engineering design later adds amplitude, energy, robustness, and implementation constraints.
7. Python Implementation — Finite-Horizon State Steering
The following script computes a minimum-norm piecewise-constant input
sequence for the double integrator. The principal libraries are
NumPy for linear algebra, SciPy for optional
matrix utilities, and Matplotlib for visualization. In more
advanced lessons, packages such as python-control can be
used for state-space analysis and feedback design.
Chapter10_Lesson1.py
"""
Chapter10_Lesson1.py
State steering for a continuous-time double integrator using a
piecewise-constant input sequence.
System:
x_dot = A x + B u
A = [[0, 1],
[0, 0]]
B = [[0],
[1]]
The script builds the finite-horizon input-to-final-state map S such that
x(T) = Phi^N x(0) + S u_sequence
and solves the minimum-norm steering sequence.
"""
import numpy as np
import matplotlib.pyplot as plt
try:
from scipy.linalg import matrix_power
except Exception:
matrix_power = np.linalg.matrix_power
def build_double_integrator_maps(T: float, N: int):
"""Return Phi and Gamma for exact zero-order-hold discretization."""
if T <= 0:
raise ValueError("T must be positive.")
if N <= 0:
raise ValueError("N must be positive.")
dt = T / N
Phi = np.array([[1.0, dt], [0.0, 1.0]])
Gamma = np.array([[0.5 * dt**2], [dt]])
return Phi, Gamma, dt
def build_steering_matrix(Phi: np.ndarray, Gamma: np.ndarray, N: int):
"""
Build S = [Phi^(N-1)Gamma, Phi^(N-2)Gamma, ..., Gamma].
For scalar input, S has shape (state_dimension, N).
"""
n = Phi.shape[0]
S = np.zeros((n, N))
for k in range(N):
S[:, [k]] = matrix_power(Phi, N - 1 - k) @ Gamma
return S
def minimum_norm_input(S: np.ndarray, target_shift: np.ndarray):
"""
Solve S u = target_shift with minimum Euclidean norm:
u* = S^T (S S^T)^(-1) target_shift
This formula assumes S has full row rank.
"""
gram = S @ S.T
rank = np.linalg.matrix_rank(S)
if rank < S.shape[0]:
raise ValueError(
f"The steering map is rank deficient: rank(S)={rank}, "
f"state dimension={S.shape[0]}."
)
return S.T @ np.linalg.solve(gram, target_shift)
def simulate(Phi: np.ndarray, Gamma: np.ndarray, x0: np.ndarray, u: np.ndarray):
"""Simulate x_{k+1} = Phi x_k + Gamma u_k."""
x = np.zeros((Phi.shape[0], len(u) + 1))
x[:, 0] = x0
for k, uk in enumerate(u):
x[:, k + 1] = Phi @ x[:, k] + (Gamma[:, 0] * uk)
return x
def main():
T = 2.0
N = 60
x0 = np.array([0.0, 0.0])
xf = np.array([1.0, 0.0])
Phi, Gamma, dt = build_double_integrator_maps(T, N)
S = build_steering_matrix(Phi, Gamma, N)
free_response = np.linalg.matrix_power(Phi, N) @ x0
target_shift = xf - free_response
u = minimum_norm_input(S, target_shift)
x = simulate(Phi, Gamma, x0, u)
print("Rank of finite-horizon steering map S:", np.linalg.matrix_rank(S))
print("Requested final state:", xf)
print("Achieved final state:", x[:, -1])
print("Final steering error norm:", np.linalg.norm(x[:, -1] - xf))
print("Input energy approximation:", dt * np.sum(u**2))
time = np.linspace(0.0, T, N + 1)
input_time = np.linspace(0.0, T - dt, N)
plt.figure()
plt.plot(time, x[0, :], label="position")
plt.plot(time, x[1, :], label="velocity")
plt.xlabel("time")
plt.ylabel("state")
plt.title("State steering: double integrator")
plt.legend()
plt.grid(True)
plt.figure()
plt.step(input_time, u, where="post")
plt.xlabel("time")
plt.ylabel("input u")
plt.title("Minimum-norm piecewise-constant steering input")
plt.grid(True)
plt.show()
if __name__ == "__main__":
main()
8. C++ Implementation — Steering with Eigen
This C++ version uses the Eigen library, a standard choice
for numerical linear algebra in C++ control and robotics software.
Chapter10_Lesson1.cpp
/*
Chapter10_Lesson1.cpp
Compile example:
g++ -std=c++17 Chapter10_Lesson1.cpp -I /path/to/eigen -O2 -o steer
This program demonstrates finite-horizon state steering for the double integrator
using Eigen. The input sequence is piecewise constant.
*/
#include <Eigen/Dense>
#include <iostream>
#include <vector>
#include <cmath>
#include <stdexcept>
using Eigen::Matrix2d;
using Eigen::Vector2d;
using Eigen::MatrixXd;
using Eigen::VectorXd;
Matrix2d matrixPower(Matrix2d M, int p) {
Matrix2d result = Matrix2d::Identity();
for (int i = 0; i < p; ++i) {
result = result * M;
}
return result;
}
int main() {
const double T = 2.0;
const int N = 60;
const double dt = T / static_cast<double>(N);
Matrix2d Phi;
Phi << 1.0, dt,
0.0, 1.0;
Vector2d Gamma;
Gamma << 0.5 * dt * dt, dt;
Vector2d x0(0.0, 0.0);
Vector2d xf(1.0, 0.0);
MatrixXd S(2, N);
for (int k = 0; k < N; ++k) {
S.col(k) = matrixPower(Phi, N - 1 - k) * Gamma;
}
Eigen::FullPivLU<MatrixXd> lu(S);
int rankS = lu.rank();
if (rankS < 2) {
throw std::runtime_error("The finite-horizon steering map is rank deficient.");
}
Vector2d freeResponse = matrixPower(Phi, N) * x0;
Vector2d targetShift = xf - freeResponse;
Matrix2d gram = S * S.transpose();
VectorXd u = S.transpose() * gram.ldlt().solve(targetShift);
MatrixXd x(2, N + 1);
x.col(0) = x0;
for (int k = 0; k < N; ++k) {
x.col(k + 1) = Phi * x.col(k) + Gamma * u(k);
}
double energy = dt * u.squaredNorm();
std::cout << "Rank of finite-horizon steering map S: " << rankS << "\n";
std::cout << "Requested final state: " << xf.transpose() << "\n";
std::cout << "Achieved final state: " << x.col(N).transpose() << "\n";
std::cout << "Final steering error norm: " << (x.col(N) - xf).norm() << "\n";
std::cout << "Input energy approximation: " << energy << "\n";
return 0;
}
9. Java Implementation — Steering from Scratch
Java control projects often use libraries such as EJML, Apache Commons Math, or Hipparchus for matrix computation. To keep this first controllability lesson transparent, the following program implements the small required linear algebra directly.
Chapter10_Lesson1.java
/*
Chapter10_Lesson1.java
Run:
javac Chapter10_Lesson1.java
java Chapter10_Lesson1
This program implements finite-horizon state steering for the double integrator
using basic arrays only. It solves a 2-by-2 linear system for the minimum-norm
piecewise-constant input sequence.
*/
public class Chapter10_Lesson1 {
static double[][] multiply(double[][] A, double[][] B) {
int m = A.length;
int p = A[0].length;
int n = B[0].length;
double[][] C = new double[m][n];
for (int i = 0; i < m; i++) {
for (int k = 0; k < p; k++) {
for (int j = 0; j < n; j++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
return C;
}
static double[] multiply(double[][] A, double[] x) {
double[] y = new double[A.length];
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < x.length; j++) {
y[i] += A[i][j] * x[j];
}
}
return y;
}
static double[][] matrixPower(double[][] A, int p) {
double[][] R = { {1.0, 0.0}, {0.0, 1.0} };
for (int i = 0; i < p; i++) {
R = multiply(R, A);
}
return R;
}
static double[] solve2x2(double[][] A, double[] b) {
double det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
if (Math.abs(det) < 1e-12) {
throw new IllegalArgumentException("Singular 2-by-2 system.");
}
return new double[] {
( b[0] * A[1][1] - A[0][1] * b[1]) / det,
(-b[0] * A[1][0] + A[0][0] * b[1]) / det
};
}
static double norm(double[] v) {
double s = 0.0;
for (double value : v) {
s += value * value;
}
return Math.sqrt(s);
}
public static void main(String[] args) {
double T = 2.0;
int N = 60;
double dt = T / N;
double[][] Phi = { {1.0, dt}, {0.0, 1.0} };
double[] Gamma = {0.5 * dt * dt, dt};
double[] x0 = {0.0, 0.0};
double[] xf = {1.0, 0.0};
double[][] S = new double[2][N];
for (int k = 0; k < N; k++) {
double[][] P = matrixPower(Phi, N - 1 - k);
double[] col = multiply(P, Gamma);
S[0][k] = col[0];
S[1][k] = col[1];
}
double[][] PhiN = matrixPower(Phi, N);
double[] freeResponse = multiply(PhiN, x0);
double[] targetShift = {xf[0] - freeResponse[0], xf[1] - freeResponse[1]};
double[][] gram = new double[2][2];
for (int k = 0; k < N; k++) {
gram[0][0] += S[0][k] * S[0][k];
gram[0][1] += S[0][k] * S[1][k];
gram[1][0] += S[1][k] * S[0][k];
gram[1][1] += S[1][k] * S[1][k];
}
double[] lambda = solve2x2(gram, targetShift);
double[] u = new double[N];
for (int k = 0; k < N; k++) {
u[k] = S[0][k] * lambda[0] + S[1][k] * lambda[1];
}
double[][] x = new double[2][N + 1];
x[0][0] = x0[0];
x[1][0] = x0[1];
for (int k = 0; k < N; k++) {
x[0][k + 1] = Phi[0][0] * x[0][k] + Phi[0][1] * x[1][k] + Gamma[0] * u[k];
x[1][k + 1] = Phi[1][0] * x[0][k] + Phi[1][1] * x[1][k] + Gamma[1] * u[k];
}
double[] error = {x[0][N] - xf[0], x[1][N] - xf[1]};
double energy = 0.0;
for (double uk : u) {
energy += dt * uk * uk;
}
System.out.printf("Requested final state: [%.12f, %.12f]%n", xf[0], xf[1]);
System.out.printf("Achieved final state: [%.12f, %.12f]%n", x[0][N], x[1][N]);
System.out.printf("Final steering error norm: %.6e%n", norm(error));
System.out.printf("Input energy approximation: %.12f%n", energy);
}
}
10. MATLAB/Simulink Implementation
MATLAB is especially natural for state-space control because
ss, expm, rank, and Control
System Toolbox routines operate directly on matrix models. The same
system can be reproduced in Simulink using a State-Space block driven by
a zero-order-hold input signal.
Chapter10_Lesson1.m
% Chapter10_Lesson1.m
%
% State steering for a continuous-time double integrator using a
% piecewise-constant input sequence.
%
% MATLAB/Simulink note:
% In Simulink, the same system can be represented by a State-Space block with
% A = [0 1; 0 0], B = [0; 1], C = eye(2), D = zeros(2,1), driven by a
% zero-order-hold signal containing the computed input samples u.
clear; clc; close all;
T = 2.0;
N = 60;
dt = T / N;
Phi = [1 dt; 0 1];
Gamma = [0.5 * dt^2; dt];
x0 = [0; 0];
xf = [1; 0];
S = zeros(2, N);
for k = 1:N
S(:, k) = Phi^(N-k) * Gamma;
end
free_response = Phi^N * x0;
target_shift = xf - free_response;
rankS = rank(S);
if rankS < 2
error("The finite-horizon steering map is rank deficient.");
end
u = S' * ((S*S') \ target_shift);
x = zeros(2, N+1);
x(:, 1) = x0;
for k = 1:N
x(:, k+1) = Phi*x(:, k) + Gamma*u(k);
end
fprintf("Rank of finite-horizon steering map S: %d\n", rankS);
fprintf("Requested final state: [%g, %g]\n", xf(1), xf(2));
fprintf("Achieved final state: [%g, %g]\n", x(1,end), x(2,end));
fprintf("Final steering error norm: %.6e\n", norm(x(:,end)-xf));
fprintf("Input energy approximation: %.12f\n", dt*sum(u.^2));
time = linspace(0, T, N+1);
input_time = linspace(0, T-dt, N);
figure;
plot(time, x(1,:), "LineWidth", 1.5); hold on;
plot(time, x(2,:), "LineWidth", 1.5);
grid on;
xlabel("time");
ylabel("state");
legend("position", "velocity");
title("State steering: double integrator");
figure;
stairs(input_time, u, "LineWidth", 1.5);
grid on;
xlabel("time");
ylabel("input u");
title("Minimum-norm piecewise-constant steering input");
11. Wolfram Mathematica Implementation
Mathematica is useful for symbolic and exact matrix computations. In later lessons, it can be used to manipulate matrix exponentials, characteristic polynomials, and canonical forms.
Chapter10_Lesson1.nb
(* ::Package:: *)
(* Chapter10_Lesson1.nb
Mathematica / Wolfram Language code for finite-horizon state steering. *)
ClearAll["Global`*"];
T = 2.0;
Nsteps = 60;
dt = T/Nsteps;
Phi = { {1, dt}, {0, 1} };
Gamma = { {0.5 dt^2}, {dt} };
x0 = { {0}, {0} };
xf = { {1}, {0} };
S = Transpose[
Table[
Flatten[MatrixPower[Phi, Nsteps - 1 - k].Gamma],
{k, 0, Nsteps - 1}
]
];
freeResponse = MatrixPower[Phi, Nsteps].x0;
targetShift = xf - freeResponse;
rankS = MatrixRank[S];
u = Transpose[S].Inverse[S.Transpose[S]].targetShift;
x = ConstantArray[0, {2, Nsteps + 1}];
x[[All, 1]] = Flatten[x0];
Do[
x[[All, k + 1]] = Phi.x[[All, k]] + Flatten[Gamma] Flatten[u][[k]],
{k, 1, Nsteps}
];
finalError = Norm[x[[All, -1]] - Flatten[xf]];
energy = dt Total[Flatten[u]^2];
Print["Rank of finite-horizon steering map S: ", rankS];
Print["Requested final state: ", Flatten[xf]];
Print["Achieved final state: ", x[[All, -1]]];
Print["Final steering error norm: ", ScientificForm[finalError]];
Print["Input energy approximation: ", energy];
ListLinePlot[
{
Transpose[{Subdivide[0, T, Nsteps], x[[1, All]]}],
Transpose[{Subdivide[0, T, Nsteps], x[[2, All]]}]
},
PlotLegends -> {"position", "velocity"},
AxesLabel -> {"time", "state"},
PlotLabel -> "State steering: double integrator"
]
ListStepPlot[
Transpose[{Subdivide[0, T - dt, Nsteps - 1], Flatten[u]}],
AxesLabel -> {"time", "input u"},
PlotLabel -> "Minimum-norm piecewise-constant steering input"
]
12. Problems and Solutions
Problem 1 (Scalar Integrator Steering): Consider \( \dot{x}(t)=u(t) \). Find an input that steers \( x(0)=x_{0} \) to \( x(T)=x_{f} \) for \( T>0 \).
Solution: Integrating gives \( x(T)=x_{0}+\int_{0}^{T}u(s)\,ds \). A constant input is sufficient:
\[ u(t)=\frac{x_{f}-x_{0} }{T},\qquad 0\leq t\leq T. \]
Then \( \int_{0}^{T}u(s)\,ds=x_{f}-x_{0} \), so \( x(T)=x_{f} \).
Problem 2 (Double Integrator with Constant Acceleration): For \( \dot{x}_{1}=x_{2},\ \dot{x}_{2}=u \), suppose \( u(t)=a \) is constant. Derive \( x_{1}(T) \) and \( x_{2}(T) \). Can a single constant input generally steer both position and velocity to arbitrary targets?
Solution: Direct integration gives
\[ x_{2}(T)=x_{2}(0)+aT,\qquad x_{1}(T)=x_{1}(0)+Tx_{2}(0)+\frac{1}{2}aT^{2}. \]
The same scalar \( a \) must satisfy two final constraints. Therefore, a constant input cannot generally satisfy arbitrary \( x_{1}(T) \) and \( x_{2}(T) \). More flexible time-varying or piecewise-constant inputs are needed.
Problem 3 (Unreachable Coordinate): For \( \dot{x}_{1}=0,\ \dot{x}_{2}=u \), prove that the system cannot be controllable.
Solution: Since \( \dot{x}_{1}=0 \), integration gives \( x_{1}(T)=x_{1}(0) \) for every admissible input. Choose a target \( \mathbf{x}_{f} \) with \( x_{f,1}\neq x_{1}(0) \). No input can satisfy this requirement. Hence arbitrary state steering is impossible.
Problem 4 (Finite-Horizon Steering Matrix): For the sampled system \( \mathbf{x}_{k+1}=\boldsymbol{\Phi}\mathbf{x}_{k} +\boldsymbol{\Gamma}\mathbf{u}_{k} \), prove that
\[ \mathbf{x}_{N}=\boldsymbol{\Phi}^{N}\mathbf{x}_{0} +\mathbf{S}_{N}\mathbf{U}. \]
Solution: Substitute recursively:
\[ \begin{aligned} \mathbf{x}_{1}&=\boldsymbol{\Phi}\mathbf{x}_{0} +\boldsymbol{\Gamma}\mathbf{u}_{0},\\ \mathbf{x}_{2}&=\boldsymbol{\Phi}^{2}\mathbf{x}_{0} +\boldsymbol{\Phi}\boldsymbol{\Gamma}\mathbf{u}_{0} +\boldsymbol{\Gamma}\mathbf{u}_{1},\\ \mathbf{x}_{3}&=\boldsymbol{\Phi}^{3}\mathbf{x}_{0} +\boldsymbol{\Phi}^{2}\boldsymbol{\Gamma}\mathbf{u}_{0} +\boldsymbol{\Phi}\boldsymbol{\Gamma}\mathbf{u}_{1} +\boldsymbol{\Gamma}\mathbf{u}_{2}. \end{aligned} \]
Continuing to \( N \) steps gives the stated formula with \( \mathbf{S}_{N}=[\boldsymbol{\Phi}^{N-1}\boldsymbol{\Gamma}\; \boldsymbol{\Phi}^{N-2}\boldsymbol{\Gamma}\;\cdots\; \boldsymbol{\Gamma}] \).
Problem 5 (Minimum-Norm Steering Sequence): Suppose \( \mathbf{S}_{N}\in\mathbb{R}^{n\times q} \) has full row rank. Show that the minimum-norm solution of \( \mathbf{S}_{N}\mathbf{U}=\mathbf{d} \) is \( \mathbf{U}^{\star}=\mathbf{S}_{N}^{T} (\mathbf{S}_{N}\mathbf{S}_{N}^{T})^{-1}\mathbf{d} \).
Solution: Minimize \( J(\mathbf{U})=\frac{1}{2}\mathbf{U}^{T}\mathbf{U} \) subject to \( \mathbf{S}_{N}\mathbf{U}=\mathbf{d} \). With Lagrange multiplier \( \boldsymbol{\lambda} \),
\[ \mathcal{L}(\mathbf{U},\boldsymbol{\lambda}) = \frac{1}{2}\mathbf{U}^{T}\mathbf{U} +\boldsymbol{\lambda}^{T}(\mathbf{d}-\mathbf{S}_{N}\mathbf{U}). \]
Stationarity gives \( \mathbf{U}-\mathbf{S}_{N}^{T}\boldsymbol{\lambda}=\mathbf{0} \), hence \( \mathbf{U}=\mathbf{S}_{N}^{T}\boldsymbol{\lambda} \). Enforcing the constraint:
\[ \mathbf{S}_{N}\mathbf{S}_{N}^{T}\boldsymbol{\lambda} =\mathbf{d}. \]
Since \( \mathbf{S}_{N} \) has full row rank, \( \mathbf{S}_{N}\mathbf{S}_{N}^{T} \) is nonsingular, giving the desired formula.
13. Summary
Controllability is the state-space property that asks whether inputs can steer the internal state from an initial value to a desired final value. The variation-of-constants formula shows that steering depends on the range of the input-produced displacement. Physically, the columns of \( \mathbf{B} \) are direct actuator directions, while \( \mathbf{A} \) spreads those directions through the state dynamics. Computationally, piecewise-constant inputs reduce state steering to a finite-dimensional linear equation \( \mathbf{S}_{N}\mathbf{U}=\mathbf{x}_{f} -\boldsymbol{\Phi}^{N}\mathbf{x}_{0} \). This prepares the next lessons on reachable states, reachable subspaces, and formal controllability tests.
14. References
- Kalman, R.E. (1960). On the general theory of control systems. Proceedings of the First International Congress on Automatic Control, 1, 481–492.
- Kalman, R.E. (1963). Mathematical description of linear dynamical systems. SIAM Journal on Control, 1(2), 152–192.
- Gilbert, E.G. (1963). Controllability and observability in multivariable control systems. SIAM Journal on Control, 1(2), 128–151.
- Kalman, R.E., Ho, Y.C., & Narendra, K.S. (1963). Controllability of linear dynamical systems. Contributions to Differential Equations, 1, 189–213.
- Silverman, L.M., & Meadows, H.E. (1967). Controllability and observability in time-variable linear systems. SIAM Journal on Control, 5(1), 64–73.
- Hautus, M.L.J. (1969). Controllability and observability conditions of linear autonomous systems. Nederl. Akad. Wetensch. Proc. Ser. A, 72, 443–448.
- Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 12(6), 660–665.
- Brockett, R.W. (1972). System theory on group manifolds and coset spaces. SIAM Journal on Control, 10(2), 265–284.