# \[ANN\] ModelPredictiveControl.jl

**URL:** <https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147>\
**Category:** Package Announcements\
**Tags:** control, jump, controlsystems, nmpc\
**Created:** [June 10, 2023, 6:10pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147 "2023-06-10T18:10:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [June 10, 2023, 6:10pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/1 "2023-06-10T18:10:43Z")

</div>

**[`ModelPredictiveControl.jl`](https://github.com/franckgaga/ModelPredictiveControl.jl)**

![image](https://global.discourse-cdn.com/julialang/original/3X/a/8/a8d9da2087e1e66b8b7b0846adf1ecd10ca4f76d.png)

I’m currently writing a [model predictive control](https://en.wikipedia.org/wiki/Model_predictive_control) package for Julia. Here’s a quick list of the main features:

- Both linear and nonlinear plant models are supported. The implementation exploits multiple dispatch.
- The optimization is based on `JuMP.jl`, allowing to quickly compare the performances of many optimizers.
- The nonlinear predictive controller, and also the extended Kalman Filter and the moving horizon estimator (both will be added soon), uses automatic differentiation for the Jacobian.
- Both internal model structure (classical approach) and closed-loop state estimator (modern approach) are supported for the feedback.
- The nonlinear predictive controller based on a linear model (e.g. economic optimization of a linear plant model) computes the prediction with matrices instead of a `for` loop.
- The nonlinear predictive controller automatically designs an adequate state estimator for the feedback, contrarily to `nlmpc` in MATLAB.
- etc.

Feedback is certainly welcome!

Francis Gagnon

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [June 10, 2023, 7:24pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/2 "2023-06-10T19:24:02Z")

</div>

Did you look at [GitHub - infiniteopt/InfiniteOpt.jl: An intuitive modeling interface for infinite-dimensional optimization problems.](https://github.com/infiniteopt/InfiniteOpt.jl) and [https://web.casadi.org/](https://web.casadi.org/) ?

Both can be used to implement NMPC control systems…

And the link to your package is not working. This one should work: [GitHub - franckgaga/ModelPredictiveControl.jl: A model predictive control package for Julia.](https://github.com/franckgaga/ModelPredictiveControl.jl)

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [June 10, 2023, 9:33pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/3 "2023-06-10T21:33:57Z")

</div>

Yes, thanks! The link is modified.

I know about these two packages. They seems really powerful. My goal is to create a package that offer simpler implementations of both MPC and NMPC. You feed a plant model and you should be ready to go for quick simulations or control of a real plant (using additional DAC/ADC packages).

Francis

---

<div class="post-metadata">

**Author:** ![francis-gagnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/francis-gagnon/32/50424_2.png) [@francis-gagnon](https://discourse.julialang.org/u/francis-gagnon)\
**Post date:** [June 15, 2023, 5:57pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/4 "2023-06-15T17:57:11Z")

</div>

@odow I think I read somewhere that vector decision variables is planned in `JuMP.jl`. Is it true and is there any timeline for that ? I’m using the splatting syntax right now and, intuitively, there is probably some overhead that hurdles the performance of the NMPC.

Thanks!

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [June 15, 2023, 6:18pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/5 "2023-06-15T18:18:42Z")

</div>

Link to code example? The answer is a somewhat, maybe, it depends.

---

<div class="post-metadata">

**Author:** ![francis-gagnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/francis-gagnon/32/50424_2.png) [@francis-gagnon](https://discourse.julialang.org/u/francis-gagnon)\
**Post date:** [June 15, 2023, 6:28pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/6 "2023-06-15T18:28:48Z")

</div>

> <https://github.com/franckgaga/ModelPredictiveControl.jl/blob/73770d0abf25d5edc95b6fde29cbfd4f5e1d73a5/src/controller/nonlinmpc.jl#L287>

Here’s what I did. I memoized my objective and constrain functions using `PreallocationTools.jl`. I’m also using closure for the parameters so I applied the tip at [Performance of captured variables](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured).

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [September 7, 2023, 8:37pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/7 "2023-09-07T20:37:13Z")

</div>

**ModelPredictiveControl v8.0.0**

The release will be registered soon. Many features were added since the OP. Here is a short list:

- Added: `ExtendedKalmanFilter` with automatic Jacobian computations using `ForwardDiff.jl`
- Added: `ExplicitMPC` for linear predictive controllers without constraint and a small sample time
- Added: automatic model augmentation based on observability for offset-free tracking
- Added: support for both unmeasured disturbances at model input and output
- Debug: only update the linear coefficients in `LinMPC` quadratic programming objective
- Multiple improvements in documentation
- Multiple other bug corrections
- Improved coverage with many new tests

Feedback is welcome!

Francis Gagnon

---

<div class="post-metadata">

**Author:** ![afishy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/afishy/32/18870_2.png) [@afishy](https://discourse.julialang.org/u/afishy)\
**Post date:** [September 7, 2023, 8:52pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/8 "2023-09-07T20:52:58Z")

</div>

Is there an MPC package that can integrate with Flux/Zygote for optimization?

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [September 7, 2023, 9:00pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/9 "2023-09-07T21:00:12Z")

</div>

To my knowledge, I don’t think so. Mine will support the packages accordingly if the developers of `JuMP.jl` decide to support them. But I think it needs a lot of work on their part. (I assume you are referring to the optimization and AD tools, not the modeling part.)

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [September 8, 2023, 5:21am UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/10 "2023-09-08T05:21:43Z")

</div>

This package has shaped up to become really impressive, congratulations on the nice work!

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [September 8, 2023, 6:54pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/11 "2023-09-08T18:54:34Z")

</div>

Thanks Fredrik, the compliment is truly appreciated !

I found a major bug in the estimation of the unmeasured disturbances at the model input (`nint_u` option). The implementation is a bit more complex than the estimation of output disturbances.

I will release a fix soon. It should work as expected now. I also added a usage example of `nint_u` option in the [manual](https://franckgaga.github.io/ModelPredictiveControl.jl/dev/manual/linmpc/#Linear-Model-Predictive-Controller). I still need to add new tests that use the `nint_u` option.

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [September 28, 2023, 8:00pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/12 "2023-09-28T20:00:19Z")

</div>

**ModelPredictiveControl v0.9.1**

The release will be registered soon. I’ve worked on new features and improvements since the last announcement. Here’s the list:

- Added: changing the constraints at runtime is now supported
- Added: time-varying constraints over prediction/control horizon is now supported
- Added: Addionnal kwargs of `PredictiveController` constructors are passed to the `StateEstimator` constructor.
- Added: show integrators info when printing `StateEstimator` \ `PredictiveController` objects
- Added: `initstate!` now compute an adequate initial estimate for all `StateEstimator` based on `LinModel`, producing a bumpless transfer (incl. `InternalModel`)
- Added: feedforward example in the documentation manual
- Reduce allocations for `NonLinMPC`
- Reduce allocations for `KalmanFilter` and `ExtendedKalmanFilter`
- Debug: `sim!` calls on `ExplicitMPC` now works
- Debug: `LinModel` constructor now call `minreal` at the end by default (for controllability/observability, can be bypassed)
- Other minor debug
- Update documentation based on the last version of `Documenter.jl`.
- Improved coverage with new tests

IMO, the features, the testing and the stability of the package are starting to be really comprehensive.

Your feedback is welcome!

Francis Gagnon

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [October 6, 2023, 4:32pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/13 "2023-10-06T16:32:28Z")

</div>

**ModelPredictiveControl v0.10.0**

Added some important features in the last update:

- Added: terminal state constraints to ensure nominal closed-loop stability (both for `LinModel` and `NonLinModel`)
- Added: added terminal state field `:x̂end` in `getinfo` dictionnary
- Added: user-friendly constructor for `SimResult` objects (interface with `Plots.jl`)
- Code cleaning for `LinModel` prediction matrices

I still need to add some tests for the terminal constraints applied on `NonLinModel`.

Cheers!

Francis

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [November 2, 2023, 10:32pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/14 "2023-11-02T22:32:36Z")

</div>

**ModelPredictiveControl v.0.11.0**

The manual was significantly improved in the last commits. Here’s a summary of the new stuff since my last post:

- Debug : terminal constraints for `NonLinModel` now works
- Added : new terminal constraint tests
- Added: error log when the termination status means “no solution available”
- Added: more precise log in REPL (warning: we keep the solution anyway, error: we take the last solution)
- Changed: warning with `SLOW_PROGRESS` status (keep solution)
- Doc: update figures for the CSTR and the pendulum in manual
- Doc: add an economic MPC example on the inverted pendulum in manual
- Doc: cleaning for terminal constraints
- Reduce allocation for `NonLinMPC`

I’ll probably need to update the package with the new `JuMP` syntax for nonlinear modeling, I’m still using the legacy one. I’m not sure when the timing will be right since the solver support seems to be partial right now. @odow do you have an opinion on that matter ? The default solver is `Ipopt` for `NonLinMPC` in the package.

Cheers,

Francis

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [November 2, 2023, 10:50pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/15 "2023-11-02T22:50:57Z")

</div>

Its ready for prime time. Ipopt BARON AmplNLWriter work. KNITRO and NLopt dont.

Let me know if you encounter any issues.

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [November 23, 2023, 7:58pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/16 "2023-11-23T19:58:41Z")

</div>

**ModelPredictiveControl v0.13.0**

I watched @baggepinnen presentation at JuliaCon 2023 (nice presentation Fredrik btw!) and it gave me the idea of a new cool feature : the `linearize` function. Gain scheduling should be quite easy with this. It is not possible to modify the plant model of a `LinMPC` instance right now, but I will probably add this feature soon. Gain scheduling is still possible using multiple `LinMPC` objects.

Also, I did a major refactoring of the code to support generic number types across the package. Note that most solvers in `JuMP` only support `Float64` numbers. Thus, `PredictiveController` objects still default to `Float64`-based optimizers, even if the plant model or state estimator uses other number types.

In short, the new features are:

- added: linearization of `NonLinModel` based on `ForwardDiff.jl`
- added: generic number types in all `SimModel`, `StateEstimator` and `PredictiveController` objects
- doc: example of `linearize` on the [pendulum](https://franckgaga.github.io/ModelPredictiveControl.jl/stable/manual/nonlinmpc/#Linearizing-the-Model)
- doc: example of solving MPC with unstable plant model using `DAQP`
- tests for `linearize` function
- tests with `Float32` numbers

I will register the new version soon.

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [December 8, 2023, 9:01pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/17 "2023-12-08T21:01:44Z")

</div>

**ModelPredictiveControl v0.14.0**

I’m happy to share that I finished the implementation of the [`MovingHorizonEstimator`](https://franckgaga.github.io/ModelPredictiveControl.jl/dev/public/state_estim/#MovingHorizonEstimator), for the main features. If you don’t know about the MHE, it’s a nice addition since it can handle constraint on the estimates. Right now it only support bounds on the states `x̂`, but I will add bounds on the process noise `ŵ` in the next releases. It is also an elegant feedback strategy for MPC, since there is no linearization (e.g. EKF) and it is conceptually the analogue of predictive control for state estimation. It produces a control strategy with 3 settings:

- `He` : the estimation horizon, time steps in the past to consider for computing the plant states
- `Hp` : the prediction horizon, time steps in the future to consider for computing the control action
- `Hc` : the control horizon, time steps in the future in which moves are allowed

The computational cost are drastically higher since it solves a nonlinear optimization problem under constraints. Similarly to `Hc`, reducing the estimation horizons `He` decreases the number of decision variables. It’s a tradeoff between accuracy and algorithmic complexity.

I will register the release soon. Feedback is welcome !

Francis

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [December 12, 2023, 8:54pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/18 "2023-12-12T20:54:46Z")

</div>

> [@franckgaga](#):
>
> I will add bounds on the process noise `ŵ` in the next releases

Nice work. I assume you do _not_ mean bounds on the process noise, though. The process noise is what it is. Perhaps bounds on the _estimate_ of the process noise?

To me, it seems more logical to balance bounds on (i) estimated states (e.g., ensure positive mass, etc.), vs. (ii) bounds on “innovation”/prediction error??

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [December 13, 2023, 2:02am UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/19 "2023-12-13T02:02:42Z")

</div>

Yes, my bad, bounds on the _estimate_ of the process noise \mathbf{\hat{w}}.

That’s very good point. As a matter of fact, I’m not sure at all which bounds are the most useful, physically speaking. Clearly, bounds on the state estimate are crucial. Then:

> bounds on “innovation”/prediction error

by innovation error, you means bounds on \mathbf{y-\hat{y}} ? In the MHE, it boils down to simply constraining the _estimate_ of the sensor noise \mathbf{\hat{v}} (see \mathbf{\hat{V}} definition in the [documentation](https://franckgaga.github.io/ModelPredictiveControl.jl/dev/internals/state_estim/#Update-Estimate)). If that’s what you mean, do you have a application example for that? I’m genuinely curious.

In fact, the MHE literature almost exclusively talks about bounds on the state estimate. I only saw [this paper](https://aiche.onlinelibrary.wiley.com/doi/abs/10.1002/aic.690480111) that uses bounds on \mathbf{\hat{w}}, since the process noise in their case study was |\mathbf{w}(k)|, thus always positive. That is why I planned supporting this type of bounds.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [December 13, 2023, 4:10pm UTC](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/20 "2023-12-13T16:10:30Z")

</div>

I meant bounds on y\_k - \hat{y}\_k. This is easy to “interpret” in that one could say that the prediction error should not be too big/should be bounded.

To me, it is not intuitive that \hat{w}\_k is a natural quantity to put bound on – I’d think that it is more intuitive to put a bound on w\_k - \hat{w}\_k.

I first came across the MHE during a visit to UT Austin close to 30 years ago – the work there was from ca. 1990. If one considers a linear system with quadratic cost, it is fairly easy to show that with an _expanding_ horizon and no constraints, the resulting estimator can be re-formulated into a recursive form with the same equations as a Kalman filter… if the weight matrices are chosen as the inverse of noise covariance matrices.

When adding constraints, this is normally solved as an optimization problem, where it is necessary to use a moving horizon to avoid “blow-up” in the number of unknowns.

NOTE however: I was in touch with a PhD student from Sweden (I’ll have to think for a while to remember the name) who had developed a Riccati formulation that can be applied to linear quadratic control with _input_ constraint (no state constraint) – the same should be applicable to MHE with constraint on disturbance w\_k and not on states. The advantage to his formulation is a relatively dramatic improvement in efficiency. I never looked into this myself, though… had other things I had to prioritize.

[Next page](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147.md?page=2)
