explainer
Luenberger observer: estimate velocity from position
Build a Luenberger observer for a cart with a position sensor. Calculate observer gains, follow estimation error, and see why a small position residual can hide a velocity error.
What you will learn
- Build a state observer from a model, a known input, and a measured output.
- Calculate gains that assign the observer error poles.
- Distinguish a measured innovation from full-state estimation error.
- Explain the assumptions behind error convergence and faster observer poles.
Before you start
A position sensor tells you where a cart is. A controller may also need its velocity. A Luenberger observer combines a motion model, the known input, and position measurements to estimate both states over time.
Estimate a state that the sensor does not report
The observer runs a model alongside the system. It predicts the output, compares that prediction with the measurement, and uses the difference to correct its state estimate. You choose correction gains that control how initial estimation errors evolve.
Åström and Murray's Output Feedback chapter gives this construction for linear systems. Here, an original cart example makes every state, gain, and error inspectable. The measurements are exact synthetic values, and the observer has the correct model.
Declare the cart and its measurement
Use a horizontal cart with mass m = 2 kg and viscous damping b = 1 N·s/m. The input u is the applied force in newtons. The true cart starts at p(0) = 0 m and v(0) = 0 m/s.
ṗ = v, m v̇ = u − bv
x = [p, v]ᵀ, y = p
A = [[0, 1], [0, −0.5]], B = [0, 0.5]ᵀ
C = [1, 0], D = 0
These are numeric matrices in the stated SI coordinates. Position and velocity have different units, as the state-space lesson explains. The lab omits springs, unknown loads, noise, delays, and actuator limits.
The observer receives u and y, plus an initial guess. It receives no direct velocity measurement. True velocity is available only to the teaching display so you can audit the estimate.
Correct the predicted output with an innovation
Write the estimated state as x̂ = [p̂, v̂]ᵀ. Its predicted output is ŷ = Cx̂ = p̂. The innovation, y − ŷ, measures the disagreement in position.
x̂̇ = Ax̂ + Bu + L(y − Cx̂)
L = [L₁, L₂]ᵀ
p̂̇ = v̂ + L₁(y − p̂)
v̂̇ = (u − bv̂)/m + L₂(y − p̂)
The position correction L₁(y − p̂) has units m/s, so L₁ has units 1/s. The velocity correction has units m/s², so L₂ has units 1/s². Both corrections use the same position residual, with different effects on the estimate.
The observer is a dynamical model. Its estimated position derivative includes the correction, so p̂̇ need not equal v̂ while an innovation remains. The MathWorks observer design reference gives the general form, including subtraction of Du when the measurement has direct feedthrough.
Derive the Luenberger observer error dynamics
Define the estimation error with one sign convention: e = x − x̂, or true state minus estimate. With exact measurements, y − Cx̂ = Ce. Subtract the observer equation from the true system equation:
ė = Ax + Bu − Ax̂ − Bu − LCe
ė = (A − LC)e
A − LC = [[−L₁, 1], [−L₂, −0.5]]
The common known input cancels. Changing u changes the true motion and the estimate, while the same initial error follows the same error trajectory. That cancellation requires the observer to know the actual applied input and use the matching model.
If every eigenvalue of A − LC has a negative real part, e approaches zero in this continuous-time model. This describes estimation error. The cart itself can keep moving while the estimate catches up.
Choose gains from two desired poles
The observer's characteristic polynomial follows from the determinant:
det(sI − (A − LC)) = s² + (L₁ + 0.5)s + 0.5L₁ + L₂
Desired poles: −ρ and −2ρ
(s + ρ)(s + 2ρ) = s² + 3ρs + 2ρ²
L₁ = 3ρ − 0.5, L₂ = 2ρ² − 0.5L₁
The numeric 0.5 represents b/m = 0.5 s⁻¹. The rate ρ uses 1/s; each coefficient retains the units from the observer equations. For ρ = 1 s⁻¹, the gains are L₁ = 2.5 s⁻¹ and L₂ = 0.75 s⁻².
Controller pole placement assigns eigenvalues of A − BK. Observer pole placement assigns eigenvalues of A − LC. The two matrices describe different dynamics, and the gains have different dimensions and roles.
Check the estimate after one second
Start with p̂(0) = −1 m and v̂(0) = 0 m/s. The true state starts at zero, giving eₚ(0) = 1 m and eᵥ(0) = 0 m/s. Use the default gains and hold u = 1 N.
Let τ = t/(1 s). The exact error is:
eₚ(t) = [−0.5 exp(−τ) + 1.5 exp(−2τ)] m
eᵥ(t) = 0.75[exp(−2τ) − exp(−τ)] m/s
At t = 1 s, the true position is 0.213061 m and true velocity is 0.393469 m/s. Subtracting eₚ = 0.019063 m and eᵥ = −0.174408 m/s gives p̂ = 0.193998 m and v̂ = 0.567877 m/s.
The observer estimates a velocity above the true value at that instant. Its initial velocity estimate was correct, yet correcting the position offset created a temporary velocity error. Negative poles guarantee eventual decay; they do not require every error component to decrease at every instant.
Separate true motion from estimation error
Start with Correct a position offset, then change the known force from 1 N to −1 N. Position and velocity change direction, but the error readouts stay unchanged at the same inspection time. The observer and cart still share the applied force.
Next, choose Faster error poles. At one second, its velocity error is −0.216830 m/s, compared with −0.174408 m/s in the default case. A faster asymptotic rate does not promise a smaller error at every selected time.
Choose Start with the correct state to make both curves coincide. The lab evaluates the exact exponential solution, with 0.025 s samples used only to draw the lines. Inspecting time moves the markers without changing the complete six-second trajectories.
Check observability and detectability
For position sensing, the observability matrix is [C; CA] = [[1, 0], [0, 1]]. Its rank is two, so output history can reveal both cart states. This is the structural condition that lets us assign both observer poles.
Full observability is stronger than the condition needed for some stable observer. Detectability allows hidden modes provided all of them already decay asymptotically. In continuous time, those unobservable modes must have negative real parts; the observer cannot move them through a measurement that contains no information about them.
Oppenheim and Verghese's MIT notes, Chapter 6 explain this distinction and the observer-gain tradeoff. Their main observer derivation uses discrete time; stable poles then lie inside the unit circle. Our lab uses the continuous-time condition above.
If this cart measured only velocity, a constant position offset would remain hidden. Its unobservable position mode has eigenvalue zero, so it is not asymptotically stable. A velocity-only observer cannot make every initial position error vanish; the observability lesson shows the indistinguishable states.
Account for noise and model mismatch
The lab's innovation is a measured-position residual. It does not expose the whole error vector. At t = ln(3) s in the default run, the position error is exactly zero while the velocity error is −1/6 m/s.
With additive measurement noise n, the sensor reports y = Cx + n. Keeping e = x − x̂ gives:
ė = (A − LC)e − Ln
L changes both the error dynamics and how measurement noise enters. Larger gains can increase noise sensitivity and transient correction; pole speed alone gives no accuracy ranking. The lab includes no noise process and makes no claim about a particular sensor's performance.
Other departures need explicit models:
- Unknown force: if the observer uses u_known while the cart receives u_actual, the error gains an input B(u_actual − u_known).
- Position bias: a constant sensor offset can look like a real position shift. A stable observer does not automatically discover that bias.
- Sampling and delay: a digital observer needs discrete equations and a stated measurement schedule. Continuous poles alone do not validate its implementation.
- Parameter errors: an incorrect mass or damping prevents the exact cancellation used above.
A Kalman filter chooses correction using specified uncertainty models. Connecting this observer to a controller also changes the problem: the controller would use x̂ to choose u. This lab holds force independently and leaves that feedback connection for a separate design.
Reproduce the estimates in Python
This standard-library example uses two exponential error modes and the exact force-driven cart response. Time uses seconds, force newtons, position meters, and velocity meters per second. It generates the displayed audit values without a numerical integration step.
from math import exp, log
def observe(rate, ph0, vh0, force, t):
l1 = 3*rate - 0.5
l2 = 2*rate**2 - 0.5*l1
ep0, ev0 = -ph0, -vh0
a = ((2*rate-l1)*ep0 + ev0)/rate
b = ep0-a
ep = a*exp(-rate*t) + b*exp(-2*rate*t)
ev = (l1-rate)*a*exp(-rate*t) + (l1-2*rate)*b*exp(-2*rate*t)
v = force*(1-exp(-t/2))
p = force*(t-2*(1-exp(-t/2)))
return p, v, p-ep, v-ev, ep, ev, l1, l2
for name, rate, ph0, vh0 in [("Default", 1, -1, 0),
("Faster", 3, -1, 0),
("Velocity offset", 1, 0, 1)]:
p, v, ph, vh, ep, ev, l1, l2 = observe(rate, ph0, vh0, 1, 1)
print(f"{name}: L=({l1:.6f}, {l2:.6f})")
print(f" estimate=({ph:.6f} m, {vh:.6f} m/s), "
f"error=({ep:.6f} m, {ev:.6f} m/s)")
row = observe(1, -1, 0, 1, log(3))
print(f"At ln(3) s: position error={abs(row[4]):.6f} m, "
f"velocity error={row[5]:.6f} m/s")
row = observe(1, -1, 0, -1, 1)
print(f"Reverse force: error=({row[4]:.6f} m, {row[5]:.6f} m/s)")
Expected output:
Default: L=(2.500000, 0.750000)
estimate=(0.193998 m, 0.567877 m/s), error=(0.019063 m, -0.174408 m/s)
Faster: L=(8.500000, 13.750000)
estimate=(0.250006 m, 0.610299 m/s), error=(-0.036945 m, -0.216830 m/s)
Velocity offset: L=(2.500000, 0.750000)
estimate=(0.445605 m, 0.877621 m/s), error=(-0.232544 m, -0.484152 m/s)
At ln(3) s: position error=0.000000 m, velocity error=-0.166667 m/s
Reverse force: error=(0.019063 m, -0.174408 m/s)
Try two observer exercises
Exercise 1. Choose observer poles −2 and −4 s⁻¹ for this cart. Calculate L₁ and L₂, including units. If the current position innovation is 0.1 m, what does each correction term contribute?
Check the gains and correction units
With ρ = 2 s⁻¹, L₁ = 6 − 0.5 = 5.5 s⁻¹. Then L₂ = 8 − 0.5 × 5.5 = 5.25 s⁻². The trace of A − LC is −6 s⁻¹ and its determinant is 8 s⁻², matching the sum and product of the requested poles.
The corrections are L₁ × 0.1 m = 0.55 m/s in p̂̇ and L₂ × 0.1 m = 0.525 m/s² in v̂̇. They correct the estimator's derivatives; they are not forces applied to the cart.
Exercise 2. Use the default initial guess and gains. At t = ln(3) s, exp(−τ) = 1/3 and exp(−2τ) = 1/9. Calculate both error components. Would the observer have a correct full-state estimate at that instant?
Check the zero-residual instant
Position error is −0.5/3 + 1.5/9 = 0 m. Velocity error is 0.75(1/9 − 1/3) = −1/6 m/s. Estimated velocity exceeds true velocity by 1/6 m/s.
The position innovation and both instantaneous correction terms are zero. The velocity error persists, so the full-state estimate is still wrong. The error equation gives ėₚ = eᵥ at this instant; the position residual immediately starts changing again.
Sources and further study
- Karl J. Åström and Richard M. Murray, Feedback Systems: Output Feedback: observer construction, observability, and error-pole assignment.
- MathWorks, Pole Placement: State Estimator Design: the continuous observer, A − LC, direct-feedthrough correction, and combining state estimation with feedback.
- Alan V. Oppenheim and George C. Verghese, Signals, Systems and Inference, Chapter 6, MIT, 2010: hidden modes, detectability, and the tradeoff between error decay and measurement-noise sensitivity.
Next, compare this observer gain with the controller gain in pole placement. Then use linear quadratic regulation to make the cost of state error and control effort explicit before deciding how the controller will obtain its state.