# How fast does a model has to be for NMPC

**URL:** <https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694>\
**Category:** Modelling & Simulations\
**Tags:** question, package, modelpredictivecontr\
**Created:** [September 29, 2024, 7:43pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694 "2024-09-29T19:43:35Z")\
**Posts on this page:** 20\
**Page:** 1

<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:** [September 29, 2024, 7:43pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/1 "2024-09-29T19:43:35Z")

</div>

How many times faster than real-time does a model has to be to be feasible for using model predictive control?

Assumptions:

- 20Hz update rate
- 5s required horizon
- controller with three scalar outputs

Of course this depends a lot on the system dynamics, but could anybody make an educated guess?

---

<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 30, 2024, 2:48am UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/2 "2024-09-30T02:48:48Z")

</div>

This is almost impossible to answer, it depends on at least the following things, likely more

- How do you define real-time in this context?
- How hard is the optimization problem?
  - Is the model very nonlinear?
  - Does it have things like events?
  - Does it have constraints that make it hard to find a feasible solution?
  - Will the problem have many local minima?
  - Do you have tight accuracy requirements?
  - Is the optimization problem non-smooth?
  - Is it even differentiable anywhere?
  - What happens if the solver cannot meet a deadline?
  - Do you use an interior-point solver or something like SQP with real-time iterations?
  - Do you have a DAE or an ODE system?
  - What’s the state dimension of the system?
  - Is the system stiff?

- Will (or can) your controller run in cascade with MPC in the outer loop and a faster controller in inner loop?

---

<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:** [September 30, 2024, 8:51am UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/3 "2024-09-30T08:51:08Z")

</div>

Thanks for your detailed reply!

I am trying to answer your question:

- real-time is more soft real-time: a new control signal is required every 50 or 100 ms, but if an update is missed in worst case a constraint will be exceeded by a few percent, which is not a big deal if it doesn’t happen too often. Only if 10 or 20 updates are missed I would expect a catastrophic failure.
- Is it very nonlinear: ? Pretty nonlinear. Hard to quantify.
- while it has events (switching between different modes of operation), I would already be happy with a controller that works well without any events
- it has constraints, but if it becomes too hard to find a feasible solution we can always switch to a different mode of operation
- local minima: can be, depending on the wind profile
- no tight accuracy required. 1% is fine.
- DAE system, but doesn’t MTK removes the algebraic equations before solving the differential equations?
- the system is very stiff
- yes, I am using a cascaded controller

Lets start with a simple example. Steering a kite, keeping the nose pointing against the wind, and then applying different steering signals.

So we have a model with about 66 states, one input and one output.

Linearizing the system is problematic because the limited rate of the steering motors has a major impact on the behavior.

I plot the input and the output of the system. In the first example you can see that the turn rate is pretty much proportional to the steering signal, but in the second example this is not the case. Only difference is amplitude and shape of the steering signal.  
 ![Example one](https://global.discourse-cdn.com/julialang/original/3X/8/a/8ac306aa4884a680c9198e4a7c5cb0143696f331.png)

![Example two](https://global.discourse-cdn.com/julialang/original/3X/4/f/4f7a4888f8bd48f98c4fbc43ad0ea0feac23dde3.png)

Any idea how fast the model must be to make NMPC work?

I have a linearized controller that - somewhat - works, but the performance is not so good and it needs a lot of tuning for different wind speeds etc., and my hope would be that I could achieve better performance with less tuning with an NMPC controller.

I did not understand the question: “Do you use an interior-point solver or something like SQP with real-time iterations?” Currently I use no solver.

---

<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:** [September 30, 2024, 9:16am UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/4 "2024-09-30T09:16:32Z")

</div>

Performance of a PID controller for the given problem as reference:

 ![Azimuth_and_Heading](https://global.discourse-cdn.com/julialang/original/3X/8/c/8c069172bb2873be852b5d67506fc3f766b6531b.png)

The controller tries to keep the azimuth angle zero such that the nose of the kite is always pointing against the wind. At 20s there is a disturbance (1s 10% set\_steering). The controller is active before and after the disturbance and compensates it, but:

- the performance is not so good
- the robustness is bad
- the tuning is very difficult
- the performance degrades if the disturbance is longer or has a different amplitude
- there are quite long oscillations at the end

 ![Block diagram](https://global.discourse-cdn.com/julialang/original/3X/1/9/19dd730a08287d274ce3d88351df15588fd2822c.png)

So I thought trying an NMPC controller might be worth it.

---

<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 30, 2024, 3:19pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/5 "2024-09-30T15:19:47Z")

</div>

It seems that your linear controller is sensitive to operating points and your nonlinear model is a bit too complex for realtime nonlinear MPC.

For that, you might want to try successive linearization MPC. In short, a new linearization is computed at each control period (using ForwardDiff.jl), and the plant model of a linear MPC is updated with this new linearization. See an example [here](https://juliacontrol.github.io/ModelPredictiveControl.jl/stable/manual/nonlinmpc/#Adapting-the-Model-via-Successive-Linearization).

---

<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:** [September 30, 2024, 4:53pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/6 "2024-09-30T16:53:55Z")

</div>

Well, currently my model does not work with `ForwardDiff.jl`, because it is not everywhere differentiable. OK, that could be fixed.

But does this approach work well with actuator limitations (max force, max speed, max power)?

---

<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 30, 2024, 5:09pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/7 "2024-09-30T17:09:33Z")

</div>

It the actuators are at the plant manipulated inputs u (from the MPC controller perspective), yes it will work very well since linear MPC can easily handle constraints on u (and possibly time-varying).

If the actuators are elsewhere, it depends. The local linearization can be quite bad near a saturation point. Reducing the control period and increasing the move suppression weight can sometimes mitigate these kind of modelling errors.

---

<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:** [September 30, 2024, 5:14pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/8 "2024-09-30T17:14:30Z")

</div>

Does a rate limit at the input of the plant counts as constraint on u ?

---

<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 30, 2024, 5:26pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/9 "2024-09-30T17:26:06Z")

</div>

Yes, rate limits on the plant inputs are also easily handled by linear MPCs. The are called \Delta \mathbf{u\_{min}} and \Delta \mathbf{u\_{max}} in ModelPredictiveControl.jl

---

<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 30, 2024, 5:28pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/10 "2024-09-30T17:28:03Z")

</div>

> [@ufechner7](#):
>
> the tuning is very difficult

Out of curiosity, how have you approached the tuning?

---

<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:** [September 30, 2024, 5:37pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/11 "2024-09-30T17:37:17Z")

</div>

So I guess the only limit that might be difficult to handle are power limits? And perhaps speed limits, if the plant has a set-torque input, but the actuator (winch) also has a speed limit?

---

<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:** [September 30, 2024, 5:40pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/12 "2024-09-30T17:40:11Z")

</div>

So far:

- manually
- using Bayesian optimization

Of course I could try some tuning based on the transfer function in the frequency domain, but that is changing so much depending on the wind speed, height and the actuator saturation that I did not yet consider it worth the effort.

---

<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 30, 2024, 6:43pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/13 "2024-09-30T18:43:26Z")

</div>

Yes, but you need to try it to confirms. If it turns out that these nonlinear constraints are problematic, there might be potential workaround: a NMPC with successive linearized plant model + a custom nonlinear constraint function. Custom nonlinear constraints are not available right now in `NonLinMPC` objects, but it’s the next feature on my TODO list. For that, you need to be able to estimate your constrained signals using the plant input and output. Would you be able to estimate power or winch speed using the steering and and turnrate signals only?

No matter what, you will probably needs to make your model differentiable, since many NMPC toolkit relies on AD for the optimization.

---

<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:** [October 1, 2024, 6:25am UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/14 "2024-10-01T06:25:04Z")

</div>

The way to approach this with PID controllers would probably be [gain scheduling](https://juliacontrol.github.io/ControlSystemsMTK.jl/dev/batch_linearization/), but I agree with Francis, a continuously linearizing MPC controller would be a sensible thing to try. On another note, a state dimension of 60+ is rather large, are you sure that you need such an accurate model for the real-time controller? Does a discretization of a tether contribute a large number of variables? If so, could you reduce this number and maintain an acceptable accuracy?

When solving MPC problems, your final performance will be dictated both by how accurately you can simulate the dynamics, but also by how fast you can respond to disturbances. If your control performance is primarily dictated by disturbances, it can be better to trade off some model accuracy for faster response times (higher sample rate). Especially if your accurate prediction isn’t so accurate anyway, due to unpredictable disturbances.

---

<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:** [October 1, 2024, 7:30am UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/15 "2024-10-01T07:30:22Z")

</div>

> [@baggepinnen](#):
>
> Does a discretization of a tether contribute a large number of variables? If so, could you reduce this number and maintain an acceptable accuracy?

Well, I currently use only 6 tether segments, using less is not really an option. But it would be possible to use a quasi static tether model like this one by Paul Williams: [https://arc.aiaa.org/doi/abs/10.2514/1.G002354](https://arc.aiaa.org/doi/abs/10.2514/1.G002354) .

Gain scheduling is the standard for the control of conventional wind turbines, but I doubt that it works well for airborne wind energy systems (I did that a lot in the past, but the results where debatable, also finding the right scheduling tables is time consuming and hard to automate).

---

<div class="post-metadata">

**Author:** ![Bart\_van\_de\_Lint](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bart_van_de_lint/32/212161_2.png) [@Bart\_van\_de\_Lint](https://discourse.julialang.org/u/Bart_van_de_Lint)\
**Post date:** [October 1, 2024, 12:58pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/16 "2024-10-01T12:58:09Z")

</div>

Why is using less segments not an option? I suspect that using a MPC with a bad model already is a lot better than using a PID controller. Anyways, will have to test to find out what works. Another question: how are you going to estimate the state of the points of all the tether segments?

---

<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:** [October 1, 2024, 2:22pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/17 "2024-10-01T14:22:31Z")

</div>

> [@Bart\_van\_de\_Lint](#):
>
> I suspect that using a MPC with a bad model already is a lot better than using a PID controller.

Well, the point is that with six segments you already get a force error of 10% at low wind speeds. This is less relevant for steering, but a problem for tether force control. At high tether tensions the error is lower.

---

<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:** [October 1, 2024, 2:26pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/18 "2024-10-01T14:26:57Z")

</div>

10% error sounds like nothing, it’s not uncommon to design controllers to be robust enough to handle gains between 50%-200% of nominal model (gain margin of 2).

---

<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:** [October 1, 2024, 2:42pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/19 "2024-10-01T14:42:56Z")

</div>

> [@baggepinnen](#):
>
> 10% error sounds like nothing

In this application this is not the case. We have a minimal force and a maximal force. The minimal force might be 10% of the max force. It shall never become zero, because when the tether becomes loose you loose the controllability of the kite. And the max force must never be exceeded, otherwise your tether might break.

---

<div class="post-metadata">

**Author:** ![zdenek\_hurak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zdenek_hurak/32/53118_2.png) [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak)\
**Post date:** [October 1, 2024, 2:56pm UTC](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694/20 "2024-10-01T14:56:43Z")

</div>

The fact that the min value of the (control?) variable is 10 % of the max value does not imply anything about the error, does it?

[Next page](https://discourse.julialang.org/t/how-fast-does-a-model-has-to-be-for-nmpc/120694.md?page=2)
