Unobservable linearized model in ModelPredictiveControl.jl

I have a model that I am trying to linearize around x_0 in order to use a linear MPC in ModelPredictiveControl.jl.

println("linearize")
linmodel = ModelPredictiveControl.linearize(model; x=x_0)

println("sim")
u = [100, 100, -100]
res = sim!(linmodel, N, u; x_0 = x_0)
display(plot(res, plotu=false))

println("linear mpc")
skf = SteadyKalmanFilter(linmodel; nint_ym=0, nint_u=0)
mpc = LinMPC(skf; Hp, Hc, Mwt, Nwt, Cwt=Inf)
nmpc = setconstraint!(nmpc; umin=umin, umax=umax)
res = sim!(nmpc, N, wanted_outputs, x_0 = x_0, x̂_0 = x̂_0, lastu = [0, 0, -50.0])
display(plot(res))

But I am getting stuck when trying to create the SKF:

ERROR: LoadError: The augmented model is unobservable. You may try to use 0 integrator on model integrating outputs with nint_ym parameter. Adding integrators at both inputs (nint_u) and outputs (nint_ym) can also violate observability.

Setting the integrators to 0 does not make a difference. The simulation works fine. The observed variables (outputs) are also state variables (x). Are there any other things I can do / what can be the reasons for an unobservable linearized model?

This is the C matrix. It has a 1.0 for each output variable, as expected.

julia> println(linmodel.C)
[0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0]

Problem solved. As I understand it now: in the linear model in ModelPredictiveControl.jl it is assumed that only the outputs are measured state variables. So if any of the state variables cannot be calculated from the output variables (aka are not linearly dependent on some combination of the outputs), the system will be non-observable. @franckgaga does it make any sense what I am saying?

Outputs y may be any linear combination of the state variables, y = Cx. An unobservable model is one that has a rank-deficient observability matrix. TLDR: with an observable model it is possible to reconstruct the state given a sequence of outputs.

what you describe here is a much stronger notion of observability, the ability to reconstruct the state from a single measurement. This is generally not as important.

To understand the difference, consider estimating velocity from position measurements. With a single position measurement, you cannot figure out the velocity. However, with a sequence of position measurements you can estimate also the velocity. Hence, the space of positions and velocities are observable from position measurements only.

3 Likes

Thanks, really helpful explanation!

Also, it’s common that non minimal realizations are not observable. You may try sminreal and minreal on your linear model. Something like:

using ControlSystemsBase
uop, yop, dop, xop, fop = linmodel.uop, linmodel.yop, linmodel.dop, linmodel.xop, linmodel.fop
sys = ss(linmodel.A, linmodel.Bu, linmodel.C, 0, linmodel.Ts)
sys2 = sminreal(sys) # or minreal, also try to modify atol and rtol kwargs
linmodel_2 = setop!(LinModel(sys2); uop, yop, dop, xop, fop)

edit: FYI @baggepinnen I will modify the error message to guide the user a little bit. The new error message is:

ERROR: The augmented model is unobservable. You may try to use 0 integrator on model
integrating outputs with nint_ym parameter. Adding integrators at both inputs (nint_u) and 
outputs (nint_ym) can also violate observability. If the model is still unobservable without 
any integrators, you may need to call sminreal or minreal on your system.
2 Likes

Is it possible as well to have some observed states (outputs) that are not used as setpoints, but just as measurements? My first guess would be to change the Mwt to 0 for all outputs that should not be optimized.

That should work fine

1 Like

Yes exactly, that’s the way to do this.

1 Like