Skip to content
LIBRARY
LinearMPCObserver.md

LinearMPCObserver ​

Steady-state (fixed-gain) state observer of the discrete-time linear model

Misplaced &

run as a clocked component. At every tick the prediction x(t|t-1) is corrected with the sampled measurements y, the filtered estimate x(t|t) is output as xhat, and the control u applied at this tick is used to predict the estimate for the next tick:

Misplaced &

With K the stationary gain of a Kalman filter (ControlSystemsBase kalman(Discrete(Ts), A, C, R1, R2; direct = true)), this is the steady-state Kalman filter; see SqKalmanObserver for the time-varying filter. In LinearMPCController the matrices are those of the (possibly disturbance-augmented) estimator stored in the MPC object, with the measured disturbances and affine offsets supplied through the signals (see there).

The matrices are structural and the initial estimate x0 is tunable. The component is plain matrix arithmetic, so it is exported to C like any other discrete component. Measurements must be sampled before this component. With a nonzero D the correction uses the control of the tick, so the control must not be computed from xhat of the same tick.

Usage ​

MPCComponents.LinearMPCObserver(D_o=_obs_D(D, ny, nu), x0=fill(0.0, nx), u_dummy=fill(0.0, nu))

Parameters: ​

NameDescriptionUnitsDefault value
AState matrix (nx × nx)–fill(0.0, 0, 0)
BInput matrix (nx × nu)–fill(0.0, 0, 0)
CMeasurement matrix (ny × nx)–fill(0.0, 0, 0)
DFeedthrough from the control to the measurements (ny × nu); empty for zero–fill(0.0, 0, 0)
KObserver gain (nx × ny)–fill(0.0, 0, 0)
nxState dimension (derived from A)–_obs_nx(A, B, C, K)
nuNumber of control inputs (derived from B)–size(B, 2)
nyNumber of measurements (derived from C)–size(C, 1)
has_DWhether D is nonzero, so that the correction uses the control of the tick (derived)–_obs_has_D(D)
x0Initial state estimate, the prediction for the first tick; tunable, read at initialization–fill(0.0, nx)

Connectors ​

  • y - This connector represents a real signal as an input to a component (RealInput)

  • u - This connector represents a real signal as an input to a component (RealInput)

  • xhat - This connector represents a real signal as an output from a component (RealOutput)

Variables ​

NameDescriptionUnits
xPrediction x(t|t-1) for the current tick–
xtFiltered estimate x(t|t)–
u_corrControl used by the correction–

Behavior ​

Behavior of this component cannot be rendered because it includes path variables.

Source ​

dyad
"""
Steady-state (fixed-gain) state observer of the discrete-time linear model

```math
\\begin{aligned}
x(t+1) &= A x(t) + B u(t) \\\\
y(t) &= C x(t) + D u(t)
\\end{aligned}
```

run as a clocked component. At every tick the prediction `x(t|t-1)` is corrected with the sampled
measurements `y`, the filtered estimate `x(t|t)` is output as `xhat`, and the control `u` applied at
this tick is used to predict the estimate for the next tick:

```math
\\begin{aligned}
x(t|t) &= x(t|t-1) + K\\,(y(t) - C x(t|t-1) - D u(t)) \\\\
x(t+1|t) &= A x(t|t) + B u(t)
\\end{aligned}
```

With `K` the stationary gain of a Kalman filter (ControlSystemsBase
`kalman(Discrete(Ts), A, C, R1, R2; direct = true)`), this is the steady-state Kalman filter; see
`SqKalmanObserver` for the time-varying filter. In `LinearMPCController` the matrices are those of
the (possibly disturbance-augmented) estimator stored in the MPC object, with the measured
disturbances and affine offsets supplied through the signals (see there).

The matrices are structural and the initial estimate `x0` is tunable. The component is plain matrix
arithmetic, so it is exported to C like any other discrete component. Measurements must be sampled
before this component. With a nonzero `D` the correction uses the control of the tick, so the
control must not be computed from `xhat` of the same tick.
"""
component LinearMPCObserver@[input clk extends Discrete]
  "Sampled measurements"
  y = [RealInput@[clk]() for i in 1:ny] {
    "Dyad": {"placement": {"diagram": {"x1": -100, "y1": 700, "x2": 0, "y2": 800}}}
  }
  "Control applied at the current tick, used to predict the estimate for the next tick"
  u = [RealInput@[clk]() for i in 1:nu] {
    "Dyad": {"placement": {"diagram": {"x1": -100, "y1": 200, "x2": 0, "y2": 300}}}
  }
  "State estimate filtered with the measurements of the current tick, x(t|t)"
  xhat = [RealOutput@[clk]() for i in 1:nx] {
    "Dyad": {"placement": {"diagram": {"x1": 1000, "y1": 450, "x2": 1100, "y2": 550}}}
  }
  "State matrix (nx × nx)"
  structural parameter A::Real[:, :] = fill(0.0, 0, 0)
  "Input matrix (nx × nu)"
  structural parameter B::Real[:, :] = fill(0.0, 0, 0)
  "Measurement matrix (ny × nx)"
  structural parameter C::Real[:, :] = fill(0.0, 0, 0)
  "Feedthrough from the control to the measurements (ny × nu); empty for zero"
  structural parameter D::Real[:, :] = fill(0.0, 0, 0)
  "Observer gain (nx × ny)"
  structural parameter K::Real[:, :] = fill(0.0, 0, 0)
  "State dimension (derived from A)"
  final structural parameter nx::Integer = _obs_nx(A, B, C, K)
  "Number of control inputs (derived from B)"
  final structural parameter nu::Integer = size(B, 2)
  "Number of measurements (derived from C)"
  final structural parameter ny::Integer = size(C, 1)
  "Whether D is nonzero, so that the correction uses the control of the tick (derived)"
  final structural parameter has_D::Boolean = _obs_has_D(D)
  "Feedthrough as an ny × nu matrix (derived from D)"
  final parameter D_o::Real[ny, nu] = _obs_D(D, ny, nu)
  "Initial state estimate, the prediction for the first tick; tunable, read at initialization"
  parameter x0::Real[nx] = fill(0.0, nx)
  "Zero placeholder used as the control of the correction when D is zero"
  final parameter u_dummy::Real[nu] = fill(0.0, nu)
  "Prediction x(t|t-1) for the current tick"
  variable x::Real[nx]
  "Filtered estimate x(t|t)"
  variable xt::Real[nx]
  "Control used by the correction"
  variable u_corr::Real[nu]
relations
  if has_D
    u_corr = u
  else
    u_corr = u_dummy
  end
  initial x@(clk-1) = x0
  xt@clk = x@(clk-1) + K * (y@clk - C * x@(clk-1) - D_o * u_corr@clk)
  x@clk = A * xt@clk + B * u@clk
  for i in 1:nx
    xhat[i] = xt[i]
  end
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MPCComponents/LinearMPCObserver.svg"},
    "doc": {"behavior": false}
  }
}
end
Flattened Source
dyad
"""
Steady-state (fixed-gain) state observer of the discrete-time linear model

```math
\\begin{aligned}
x(t+1) &= A x(t) + B u(t) \\\\
y(t) &= C x(t) + D u(t)
\\end{aligned}
```

run as a clocked component. At every tick the prediction `x(t|t-1)` is corrected with the sampled
measurements `y`, the filtered estimate `x(t|t)` is output as `xhat`, and the control `u` applied at
this tick is used to predict the estimate for the next tick:

```math
\\begin{aligned}
x(t|t) &= x(t|t-1) + K\\,(y(t) - C x(t|t-1) - D u(t)) \\\\
x(t+1|t) &= A x(t|t) + B u(t)
\\end{aligned}
```

With `K` the stationary gain of a Kalman filter (ControlSystemsBase
`kalman(Discrete(Ts), A, C, R1, R2; direct = true)`), this is the steady-state Kalman filter; see
`SqKalmanObserver` for the time-varying filter. In `LinearMPCController` the matrices are those of
the (possibly disturbance-augmented) estimator stored in the MPC object, with the measured
disturbances and affine offsets supplied through the signals (see there).

The matrices are structural and the initial estimate `x0` is tunable. The component is plain matrix
arithmetic, so it is exported to C like any other discrete component. Measurements must be sampled
before this component. With a nonzero `D` the correction uses the control of the tick, so the
control must not be computed from `xhat` of the same tick.
"""
component LinearMPCObserver
  "Sampled measurements"
  y = [RealInput@[clk]() for i in 1:ny] {
    "Dyad": {"placement": {"diagram": {"x1": -100, "y1": 700, "x2": 0, "y2": 800}}}
  }
  "Control applied at the current tick, used to predict the estimate for the next tick"
  u = [RealInput@[clk]() for i in 1:nu] {
    "Dyad": {"placement": {"diagram": {"x1": -100, "y1": 200, "x2": 0, "y2": 300}}}
  }
  "State estimate filtered with the measurements of the current tick, x(t|t)"
  xhat = [RealOutput@[clk]() for i in 1:nx] {
    "Dyad": {"placement": {"diagram": {"x1": 1000, "y1": 450, "x2": 1100, "y2": 550}}}
  }
  "State matrix (nx × nx)"
  structural parameter A::Real[:, :] = fill(0.0, 0, 0)
  "Input matrix (nx × nu)"
  structural parameter B::Real[:, :] = fill(0.0, 0, 0)
  "Measurement matrix (ny × nx)"
  structural parameter C::Real[:, :] = fill(0.0, 0, 0)
  "Feedthrough from the control to the measurements (ny × nu); empty for zero"
  structural parameter D::Real[:, :] = fill(0.0, 0, 0)
  "Observer gain (nx × ny)"
  structural parameter K::Real[:, :] = fill(0.0, 0, 0)
  "State dimension (derived from A)"
  final structural parameter nx::Integer = _obs_nx(A, B, C, K)
  "Number of control inputs (derived from B)"
  final structural parameter nu::Integer = size(B, 2)
  "Number of measurements (derived from C)"
  final structural parameter ny::Integer = size(C, 1)
  "Whether D is nonzero, so that the correction uses the control of the tick (derived)"
  final structural parameter has_D::Boolean = _obs_has_D(D)
  "Feedthrough as an ny × nu matrix (derived from D)"
  final parameter D_o::Real[ny, nu] = _obs_D(D, ny, nu)
  "Initial state estimate, the prediction for the first tick; tunable, read at initialization"
  parameter x0::Real[nx] = fill(0.0, nx)
  "Zero placeholder used as the control of the correction when D is zero"
  final parameter u_dummy::Real[nu] = fill(0.0, nu)
  "Prediction x(t|t-1) for the current tick"
  variable x::Real[nx]
  "Filtered estimate x(t|t)"
  variable xt::Real[nx]
  "Control used by the correction"
  variable u_corr::Real[nu]
relations
  if has_D
    u_corr = u
  else
    u_corr = u_dummy
  end
  initial x@(clk-1) = x0
  xt@clk = x@(clk-1) + K * (y@clk - C * x@(clk-1) - D_o * u_corr@clk)
  x@clk = A * xt@clk + B * u@clk
  for i in 1:nx
    xhat[i] = xt[i]
  end
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MPCComponents/LinearMPCObserver.svg"},
    "doc": {"behavior": false}
  }
}
end


Test Cases ​

No test cases defined.

  • Examples

  • Experiments

  • Analyses