Estimation

The state observer: a copy of the linear model, corrected by the output it mispredicts.

class minilink.estimation.observer.StateObserver(A, B, C, L, D=None, *, xbar=None, ubar=None, ybar=None, labels=None)[source]

Linear state observer dx̂ = A (x̂ − x̄) + B (u − ū) + L (y − ŷ), the estimate on x.

The observer runs the model (A, B, C, D) of the plant about the operating point (x̄, ū, ȳ) and corrects it with the innovation, the measured y minus the predicted ŷ = ȳ + C (x̂ − x̄) + D (u − ū), through the gain L. The estimation error then follows A − L C, so the gain sets its poles: luenberger() places them and kalman() makes them optimal for white noise. Both return this block.

Ports: the plant’s command u (dimension m) and measurement y (dimension p) in; the estimate x (dimension n, labelled with a hat) out. The initial estimate x0 starts at x̄. The matrices, the gain and the operating point live in params; ȳ defaults to C x̄ + D ū, the linear model’s own output, and the plant-taking designs pass h(x̄, ū). A box holding this block under the key observer and a state-feedback gain, with r, y -> u on its edge, is a controller for @.

property poles

the poles of the estimation error.

Type:

Eigenvalues of A − L C

f(x, u, t=0, params=None)[source]

State derivative dx = f(x, u, t; p).

Subclasses should treat this as a function of (x, u, t, params) only; the library does not verify purity.

Parameters:
  • x (array of shape (n,))

  • u (array of shape (m,))

  • t (float)

  • params (dict, optional) – None means “use self.params”.

Returns:

dx

Return type:

array of shape (n,)

estimate(x, u, t=0, params=None)[source]

The estimate x̂: the observer’s state.

State-observer design: a model or arrays in, a StateObserver out, the duals of the state-feedback designs.

minilink.estimation.design.luenberger_gain(A, C, poles)[source]

Return the observer gain L that puts the eigenvalues of A − L C at poles.

minilink.estimation.design.kalman_gain(A, C, Q_n, R_n)[source]

Return the Kalman gain L of the stationary filter for process noise Q_n and measurement noise R_n.

minilink.estimation.design.luenberger(sys, poles, *, x_bar=None, u_bar=None, t=0.0, params=None, method='auto', eps=1e-06)[source]

Design an observer for sys by pole placement and return a StateObserver.

sys is a linear model, used as is with the operating point it carries, or any plant, linearized first about its command port at (x_bar, u_bar), the nominal state and inputs when omitted. The block runs the model about that point and corrects it with L (y − ŷ), so the estimation error has the requested poles. Arguments as in lqr(), with poles in place of Q, R. On arrays the gain is luenberger_gain(), and the model LTISystem(A, B, C).

The observer reads the plant’s output y: a plant without one is refused (make the sensor part of the plant box, plant >> Gain(...)), and a design on another output is made on linearize(plant, x_bar, of=...).

minilink.estimation.design.kalman(sys, Q_n, R_n, *, x_bar=None, u_bar=None, t=0.0, params=None, method='auto', eps=1e-06)[source]

Design a stationary Kalman filter for sys and return a StateObserver.

sys is a linear model or any plant measured through y, as in luenberger(). On arrays the gain is kalman_gain(). Q_n is the intensity of the white process noise on the state, n × n (a noise w entering through B_w has Q_n = B_w W B_wᵀ), and R_n the intensity of the white measurement noise, p × p. The gain minimizes the steady-state estimation error covariance, and the block is the stationary Kalman–Bucy filter.