# Flexible linear constraints for MPC and codegen

**URL:** <https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285>\
**Category:** Optimization (Mathematical)\
**Tags:** controlsystems, mpc\
**Created:** [January 27, 2026, 3:30pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285 "2026-01-27T15:30:30Z")\
**Posts on this page:** 11\
**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:** [January 27, 2026, 3:30pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/1 "2026-01-27T15:30:30Z")

</div>

Following the subject [[ANN] ModelPredictiveControl.jl](https://discourse.julialang.org/t/ann-modelpredictivecontrol-jl/100147/65) with @langestefan and @darnstrom:

> The expressiveness of the linear MPC framework is already very limited and the current syntax limits it further. As long as my expression is mathematically valid within the linear MPC framework I think I should be able to define it.

Agree. I would like to support more flexible linear constraints in ModelPredictiveControl.jl.

> Unfortunately for commercial embedded systems every kilobyte matters so C codegen is a must. I think it’s already a modern miracle we can do MPC with a \<200 kB solver (thanks Boyd!).

And that’s also why I think running MPC on traditional embedded systems (e.g. not Raspberry Pi or Nvidia Jetson) is not ideal. Even by working very hard to make C codegen fully feature-complete, there is still one unsolvable issue: it’s another form of the two language problem. A major problem that comes with it is reproducibility (the numerical results will be presumably different, and possibly drastically different for ill-posed corner cases). But that’s another subject.

> > This feature is not supported by code generation (i.e. there is no C code equivalent of calling `setconstraint!` online).
> 
> Yeah this is very tricky but I think a requirement for practical applications. Between mild and cold weather with high supply temperatures maximum output power can drop from 5 to 3 kW.
> 
> Maybe you know this already, but cvxpygen will generate a function `cpg_update_<param>(idx, val)` to update each parameter in your problem. For that to work you would first need to know where the parameters are and there are some rules as to how parameters can enter the problem (DPP compliance).
> 
> Now for [LinearMPC.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/LinearMPC), you could say everything that is a constant in my problem is a parameter and thus could be updated and included in the codegen.

Since right now I rely on LinearMPC.jl for codegen, I need to include @darnstrom in the loop. My understanding is online updates of e.g. the `lb` and `ub` arguments of `add_constraint!` within the C code is not possible right now, am I right? Would it be something that is possible to add in LinearMPC.jl ?

About this @langestefan, do you think that the `add_constraint!` API provided by LinearMPC.jl is flexible enough for your specific constraint structure? Let’s assume that you are also able to update the value of `lb` and `ub` online in the generated C code.

> Really thinking out loud here so feel free to shoot this down, but why not use JuMP as the main problem creation interface instead? There’s a DSL, and there is `MOI.Parameter`.

It would not help here since I’m using LinearMPC.jl for C codegen, and JuMP is not used at all in this package.

---

<div class="post-metadata">

**Author:** ![darnstrom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/darnstrom/32/216558_2.png) [@darnstrom](https://discourse.julialang.org/u/darnstrom)\
**Post date:** [January 27, 2026, 4:30pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/2 "2026-01-27T16:30:23Z")

</div>

Actually, I created an interface to JuMP for [ParametricDAQP.jl](https://github.com/darnstrom/ParametricDAQP.jl) a month ago (see example in README). What it does is that it creates a multi-parametric quadratic program based on a JuMP model, which it then used to create an explicit solution.

My intention was also to add support for codegen also (i.e., given an mpQP → generate code for DAQP, which is basically what goes on underneath the hood of LinearMPC.jl.) I have a local branch with some progress here, but it was down-prioritized due to other projects. It would, however, not be too much work to finalize it. If there is interest from others (e.g., @franckgaga and @langestefan) I could bump the priority of that action point.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [January 27, 2026, 10:14pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/3 "2026-01-27T22:14:39Z")

</div>

> [@franckgaga](#):
>
> And that’s also why I think running MPC on traditional embedded systems (e.g. not Raspberry Pi or Nvidia Jetson) is not ideal.

Not ideal, but definitely feasible! In my case I am trying to add MPC to an existing product that is currently using basic PI control. Which does the job, but we can do better. I think there are hundreds of companies out there in similar situations. And personally I think the whole field of doing complicated stuff on limited hardware is very exciting and rewarding.

> [@franckgaga](#):
>
> Even by working very hard to make C codegen fully feature-complete,

So that already exists: cvxpygen does an amazing job. If you look at the source code it’s really not that complicated, it’s essentially just a wrapper around cvxpy that packages your solver of choice with a nice interface. It is ofcourse a generic tool and not purpose-made for MPC applications, which is where we can do a better job 🙂

> [@franckgaga](#):
>
> there is still one unsolvable issue: it’s another form of the two language problem.

Yes it is. I think in most situations you will have to resort to C codegen because the target MCU is also doing 10 other things.

> [@franckgaga](#):
>
> A major problem that comes with it is reproducibility (the numerical results will be presumably different, and possibly drastically different for ill-posed corner cases). But that’s another subject.

Not sure I am following you here, reproducibility of what?

> [@franckgaga](#):
>
> About this @langestefan, do you think that the `add_constraint!` API provided by [LinearMPC.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/LinearMPC) is flexible enough for your specific constraint structure? Let’s assume that you are also able to update the value of `lb` and `ub` online in the generated C code.

Yes, that looks quite flexible. Not entirely sure what this part means:

> (additional terms Ar rₖ, Aw wₖ, Ad dₖ, Aup u⁻ₖ are possible)

But I will have a look at the source code.

---

<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:** [January 27, 2026, 10:16pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/4 "2026-01-27T22:16:51Z")

</div>

Interesting, but would it solve the main issue discussed here? That is, would it be possible to change the upper bound and lower bound of the linear inequality constraints online in the generated C code (based on the DAQP solver)?

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [January 27, 2026, 10:24pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/5 "2026-01-27T22:24:37Z")

</div>

> [@darnstrom](#):
>
> Actually, I created an interface to JuMP for [ParametricDAQP.jl](https://github.com/darnstrom/ParametricDAQP.jl) a month ago (see example in README). What it does is that it creates a multi-parametric quadratic program based on a JuMP model, which it then used to create an explicit solution.

If I understand correctly we would be doing explicit MPC? My experience with explicit methods is that they only work for (very) small problems, the codegen quickly explodes in size. Happy to be proven wrong.

---

<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:** [January 27, 2026, 11:05pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/6 "2026-01-27T23:05:54Z")

</div>

> [@langestefan](#):
>
> Yes, that looks quite flexible. Not entirely sure what this part means:
> 
> > (additional terms Ar rₖ, Aw wₖ, Ad dₖ, Aup u⁻ₖ are possible)

The supported structure of `add_constraint!` is (using non-boldface font for scalars and boldface font for vectors and matrices):

\underline{b\_{k}} - \epsilon\_k \le \mathbf{A\_x} \mathbf{x}\_{k} + \mathbf{A\_u} \mathbf{u}\_{k} + \mathbf{A\_{up}} \mathbf{u}\_{k-1} + \mathbf{A\_r} \mathbf{r}\_{k} + \mathbf{A\_d} \mathbf{d}\_{k} + \mathbf{A\_w} \mathbf{w}\_{k} \le \overline{b\_k} + \epsilon\_k

in which :

- \underline{b\_{k}} is the lower bound (`lb` argument)
- \overline{b\_{k}} is the upper bound (`ub` argument)
- \epsilon is the slack for softening (can be disabled)
- \mathbf{x}\_{k} is the state at time step k
- \mathbf{u}\_{k} is the input at time step k
- \mathbf{u}\_{k-1} is the input at time step k-1
- \mathbf{r}\_{k} is the setpoint at time step k
- \mathbf{d}\_{k} is the known disturbance at time step k (if applicable, for feedforward comprensation)
- \mathbf{w}\_{k} is the unknown disturbances at time step k (if applicable, for robust MPC)

You can add an “infinite amount” of these constraints (with distinct `lb`, `ub`, `Ax`, `Au`, … values), and for each of them you select the k value that applies (the `ks` argument. The present time step is `1` and the terminal time step is `Np+1`). Is it clearer ?

---

<div class="post-metadata">

**Author:** ![darnstrom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/darnstrom/32/216558_2.png) [@darnstrom](https://discourse.julialang.org/u/darnstrom)\
**Post date:** [January 27, 2026, 11:19pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/7 "2026-01-27T23:19:18Z")

</div>

Any parameter that enters linearly in the objective / constraint will be handled, which is the case for upper/lower bounds.

---

<div class="post-metadata">

**Author:** ![darnstrom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/darnstrom/32/216558_2.png) [@darnstrom](https://discourse.julialang.org/u/darnstrom)\
**Post date:** [January 27, 2026, 11:22pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/8 "2026-01-27T23:22:30Z")

</div>

The current code for ParametricDAQP.jl is for explicit solutions to mpQPs, but what I was trying to say is that I also aim to add support for an implicit solver (DAQP). With that support, you will be able to generate solver code (implicit or explicit) for any JuMP model that is of the form of a multi-parameteric QP.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [January 28, 2026, 12:26am UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/9 "2026-01-28T00:26:17Z")

</div>

Wow! I think that is super exciting. Would that potentially support the B&B method as well?

---

<div class="post-metadata">

**Author:** ![darnstrom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/darnstrom/32/216558_2.png) [@darnstrom](https://discourse.julialang.org/u/darnstrom)\
**Post date:** [January 28, 2026, 6:59am UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/10 "2026-01-28T06:59:29Z")

</div>

Yes!

---

<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:** [January 29, 2026, 4:19pm UTC](https://discourse.julialang.org/t/flexible-linear-constraints-for-mpc-and-codegen/135285/11 "2026-01-29T16:19:39Z")

</div>

So FYI I’m working on adding the support of custom linear inequality constraint in ModelPredictiveControl.jl. It will support C codegen, except for online modification of \mathbf{G\_{min}} and \mathbf{G\_{max}}, at least for now. The API will looks like this (see the last inequality):

 ![image](https://global.discourse-cdn.com/julialang/original/3X/2/1/217c04b9f460231ae508f4eeafc4e68168c4987e.png)
