explainer
Controllability and observability: move and reveal state
Find which states an actuator can reach and which a sensor can reveal. Use exact cart motion, two held commands, matrix rank, and indistinguishable initial states.
What you will learn
- Explain controllability and observability as different properties of a state-space model.
- Calculate both rank tests for a two-state cart.
- Solve two held commands that reach a requested position and velocity.
- Exhibit an initial-state difference that a velocity sensor cannot reveal.
- Separate structural rank from input capacity, sensor noise, and numerical conditioning.
Before you start
A cart can have enough actuation to reach a position while its sensor cannot tell where it started. Controllability asks what inputs can change. Observability asks what measurements can reveal.
You will calculate both properties for the same two-state model. Then you will verify them with actual commands and sensor histories, including a pair of physically different states that produces identical measurements.
Ask what commands and measurements can do
For a continuous-time linear model, controllability means that an input can move the system from any initial state to any requested final state in a finite interval. This structural definition allows unrestricted input magnitude and assumes the model is exact. A force limit changes the reachable set for a given time budget.
Observability means that the initial state can be determined from the known input and measured output history over an interval. The basic test assumes exact, noiseless measurements. One instantaneous output need not reveal the whole state.
Reachability from zero and controllability coincide for continuous-time linear time-invariant systems. MIT's reachability and observability lecture explains that relationship and the role of indistinguishable states. This lesson uses that continuous-time setting throughout.
Define a cart with one input and two states
The cart moves horizontally with position p in meters and velocity v in meters per second. Mass m is 1 kg, damping b is 1 N·s/m, and command u has units of newtons. A dimensionless effectiveness g converts the command to applied force gu.
ṗ = v
m v̇ = gu − bv
The lab offers g = 1, 0.25, or 0. At zero, the actuator is disconnected. The model has no spring, force saturation, contact, noise, or unknown parameters.
Write state x = [p, v]ᵀ. With time in seconds and the stated SI coordinates, the numeric state-space matrices are:
ẋ = Ax + Bu, y = Cx, D = 0
A = [[0, 1], [0, −1]], B = [0, g]ᵀ
A position sensor uses C = [1, 0] and reports meters. A velocity sensor uses C = [0, 1] and reports meters per second. The matrix entries carry the unit conversions implied by those coordinates; position and velocity remain different physical quantities.
Reach a target and compare output histories
The left plot starts at rest and applies one command for each of two one-second intervals. It shows position versus velocity, with the requested final state marked by a cross. This state-space path uses two coordinates to describe physical motion along one line.
The right plot runs a separate experiment. Both carts receive zero input; one starts at rest at the origin, while the other has either a position offset or a velocity offset. Choose the sensor and compare their output histories.
Start with Reach a position and stop, then choose A hidden position offset. The control solution stays the same, but the velocity sensor reports identical histories for states separated by one meter. All plot axes stay fixed as settings change.
Test controllability with independent directions
For an n-state linear system, the controllability matrix collects directions generated by the input and dynamics:
𝒞 = [B, AB, …, Aⁿ⁻¹B]
controllable when rank(𝒞) = n
Rank counts independent directions. MathWorks' controllability reference states this full-rank criterion. For the two-state cart, only B and AB are needed:
B = [0, g]ᵀ, AB = [g, −g]ᵀ
𝒞 = [[0, g], [g, −g]], det(𝒞) = −g²
For any nonzero g, the determinant is nonzero and the rank is 2. The actuator directly changes velocity; velocity then changes position. One input can therefore control both states over time.
At g = 0, both columns vanish and the rank is 0. From rest, every command leaves the cart at rest. That still reaches the particular zero target, but it cannot reach every requested state.
Construct two commands that reach the target
A rank test establishes existence. We can also construct a specific input for this cart: command u₀ for the first second and u₁ for the second. Both values remain constant within their intervals.
For a one-second interval, define r = exp(−1) and q = 1 − r. The exact numeric update in the stated SI coordinates is:
xₖ₊₁ = Φxₖ + Γuₖ
Φ = [[1, q], [0, r]], Γ = g[r, q]ᵀ
These coefficients come from integrating the damped velocity equation exactly. The exponential uses (b/m) × 1 s = 1. No numerical time-step approximation enters the command solve.
Starting from zero, the two commands produce x₂ = ΦΓu₀ + Γu₁. Write that as a two-by-two linear system:
x₂ = R[u₀, u₁]ᵀ
R = g[[1 − r + r², r], [rq, q]]
det(R) = g²q²
For nonzero g, this particular two-pulse input family can reach any target position and velocity at two seconds. The lab solves R[u₀, u₁]ᵀ = [p_target, v_target]ᵀ. Reaching a different target just changes the right-hand side.
For g = 0 and a nonzero target, no solution exists. For the zero target, any commands produce zero applied force; the lab chooses zero commands as one possible solution. It does not label that choice a unique inverse.
Move one meter and stop after two seconds
Use g = 1 and target [1 m, 0 m/s]. The zero final velocity requires u₁ = −ru₀. Substituting into the position equation gives qu₀ = 1 in the stated numerical units.
u₀ = 1/(1 − exp(−1)) = 1.581977 N
u₁ = −exp(−1)/(1 − exp(−1)) = −0.581977 N
At the switch, p₁ = 0.581977 m and v₁ = 1 m/s. The second command brings the endpoint to 1 m and 0 m/s. The displayed values round an exact analytic result.
Now choose A weaker connected actuator, with g = 0.25. The needed commands become 6.327907 N and −2.327907 N. Their applied forces gu match the original case, so the entire state path stays the same.
The controllability rank remains 2, even though command magnitudes quadruple. A real actuator's capacity could make these commands unavailable. This calculation includes no force or command limit.
Test observability over an output history
For an n-state model, stack the output map and its evolution through the dynamics:
𝒪 = [C; CA; …; CAⁿ⁻¹]
observable when rank(𝒪) = n
Here, semicolons mean new rows. The observability rank criterion tests whether the full state can affect the output history in distinguishable ways. For position sensing:
C_p = [1, 0], C_pA = [0, 1]
𝒪_p = [[1, 0], [0, 1]], rank(𝒪_p) = 2
Position reveals p directly, and its change over time carries information about v. With zero input, two exact position samples one second apart are enough here: p₀ is the first sample, and v₀ = (p₁ − p₀)/q.
Velocity sensing gives a different result:
C_v = [0, 1], C_vA = [0, −1]
𝒪_v = [[0, 1], [0, −1]], rank(𝒪_v) = 1
Velocity reports v, but a constant shift in p changes neither v nor its dynamics. Absolute initial position remains hidden. Choosing a different actuator effectiveness does not change this sensor limitation.
Find states that a sensor cannot distinguish
Consider two states receiving the same known input. Their difference follows Δẋ = AΔx because the shared input cancels. The resulting output difference is Δy(t) = CeᴬᵗΔx₀.
For a 1 m position offset, choose x_A(0) = [0 m, 0 m/s] and x_B(0) = [1 m, 0 m/s]. With zero input, both velocities remain zero and the position difference stays one meter. A velocity sensor produces identical outputs for the entire interval, and for all later times under this model.
That one indistinguishable nonzero difference disproves full observability. A position sensor immediately separates this pair. Distinguishing one selected pair, however, cannot prove that every possible pair is distinguishable; the rank test supplies the general result.
For a 1 m/s velocity offset, both carts initially occupy the same position. Their position outputs agree at t = 0, then separate:
Δp(t) = (1 s)[1 − exp(−t/(1 s))](1 m/s)
Δv(t) = exp(−t/(1 s))(1 m/s)
At two seconds, Δp = 0.864665 m and Δv = 0.135335 m/s. The whole history matters. A velocity sensor also distinguishes this particular pair while remaining unable to distinguish the position-offset pair.
Separate rank from practical control and estimation
Full rank answers a structural question under the chosen model. It leaves several engineering questions open:
- Input capacity: the required commands may exceed force, voltage, or power limits.
- Noise: estimating velocity from small position differences can amplify measurement error.
- Timing: a sampled or delayed sensor supplies a specific history that needs its own analysis.
- Model mismatch: unknown friction, loads, or bias can change prediction and inference.
- Numerical conditioning: state scaling and nearly dependent directions can make calculations sensitive to roundoff.
This lab derives its ranks from exact two-state matrix structure. It never decides rank by rounding a tiny determinant to zero. MathWorks' observability documentation also warns that explicitly forming and testing the observability matrix can become numerically unreliable for larger systems; use numerically suitable analysis tools for those models.
An estimator such as a Kalman filter adds assumptions about uncertainty and measurement quality. Repeated velocity measurements still contain no absolute-position information in this cart model. A prior position value can supply an initial assumption, but these measurements cannot correct a constant error in that value.
The Luenberger observer lesson turns the observable position-sensing case into a working estimator. Choose correction gains, follow both state errors, and see why stable observer poles do not require each error component to shrink at every instant.
Controllability and observability are also distinct from stability. A model can have full rank and unstable open-loop dynamics. The pole-placement lesson uses state feedback to choose closed-loop dynamics once the relevant controllability condition holds.
The multivariable control lesson shows two actuator directions becoming nearly dependent. The system keeps full rank before the singular limit, while the commands needed for cancellation grow sharply.
Reproduce the commands and output pairs in Python
This standard-library example computes the two-command solve and exact state evolution. The output-pair calculation stays separate and uses zero input. The rank calculation uses the explicit two-by-two matrices from this lesson.
from math import exp, expm1
def step(state, command, gain, duration):
p, v = state
r = exp(-duration)
q = -expm1(-duration)
force = gain * command
return p + q*v + (duration-q)*force, r*v + q*force
def rank2(matrix):
a, b = matrix[0]
c, d = matrix[1]
if a*d - b*c != 0:
return 2
return int(any(value != 0 for row in matrix for value in row))
def commands(target, gain):
if gain == 0:
return (0.0, 0.0) if target == (0.0, 0.0) else None
r = exp(-1)
q = 1-r
a, b = gain*(1-r+r*r), gain*r
c, d = gain*r*q, gain*q
det = a*d-b*c
p, v = target
return (d*p-b*v)/det, (-c*p+a*v)/det
def fmt(value):
return f"{0.0 if abs(value) < 0.0000005 else value:.6f}"
co = [[0, 1], [1, -1]]
op = [[1, 0], [0, 1]]
ov = [[0, 1], [0, -1]]
print(f"Ranks: control={rank2(co)}, position={rank2(op)}, velocity={rank2(ov)}")
u0, u1 = commands((1.0, 0.0), 1.0)
mid = step((0.0, 0.0), u0, 1.0, 1.0)
end = step(mid, u1, 1.0, 1.0)
print(f"Commands: {fmt(u0)}, {fmt(u1)} N")
print(f"Switch: p={fmt(mid[0])} m, v={fmt(mid[1])} m/s")
print(f"Endpoint: p={fmt(end[0])} m, v={fmt(end[1])} m/s")
weak = commands((1.0, 0.0), 0.25)
print(f"Weak actuator: {fmt(weak[0])}, {fmt(weak[1])} N")
for name, initial in [("Position offset", (1.0, 0.0)),
("Velocity offset", (0.0, 1.0))]:
p, v = step(initial, 0.0, 1.0, 2.0)
print(f"{name} at 2 s: delta p={fmt(p)} m, delta v={fmt(v)} m/s")
print(f"Disconnected: nonzero target={commands((1.0, 0.0), 0.0)}, "
f"zero target={commands((0.0, 0.0), 0.0)}")
Expected output:
Ranks: control=2, position=2, velocity=1
Commands: 1.581977, -0.581977 N
Switch: p=0.581977 m, v=1.000000 m/s
Endpoint: p=1.000000 m, v=0.000000 m/s
Weak actuator: 6.327907, -2.327907 N
Position offset at 2 s: delta p=1.000000 m, delta v=0.000000 m/s
Velocity offset at 2 s: delta p=0.864665 m, delta v=0.135335 m/s
Disconnected: nonzero target=None, zero target=(0.0, 0.0)
Try it yourself
Exercise 1. Keep the one-meter, zero-velocity target and the two-second schedule. If g changes from 1 to 0.25, calculate both commands and both applied forces. What does an unchanged controllability rank fail to tell you?
Show the command and capacity check
Commands grow by a factor of four: 6.327907 N and −2.327907 N. Multiplication by g = 0.25 gives applied forces 1.581977 N and −0.581977 N, matching the original force schedule.
The state path therefore stays the same and the rank remains 2. Rank does not specify whether the command interface or actuator can supply those values. A capacity claim needs actual limits and the allowed time interval.
Exercise 2. Two carts begin at the same position, with velocities 0 and 1 m/s, and receive zero input. Their position readings agree initially. Find the differences at two seconds, then explain why velocity sensing still has rank 1 even though it distinguishes this pair.
Show the history and hidden-state check
The velocity difference is exp(−2) × 1 m/s = 0.135335 m/s. Integrating that difference gives 0.864665 m of position separation. Equal initial position readings do not make the complete histories equal.
Velocity sensing distinguishes these different initial velocities. It cannot distinguish equal velocities at positions separated by a constant offset. That other pair produces identical velocity histories and disproves full two-state observability.
Sources and further study
- Emilio Frazzoli, MIT 6.241, Lecture 20: Reachability and Observability, April 20, 2011: continuous-time reachability, its relation to controllability, and indistinguishable states.
- MathWorks, Controllability of state-space models: the controllability matrix and full-rank criterion.
- MathWorks, Observability of state-space models: the observability matrix, full-rank criterion, and numerical limitations.
Next, use pole placement to turn a controllable model into a state-feedback design. Carry the actuator limits and available measurements into that design, even when the rank tests pass.