@@ -48,9 +48,9 @@ struct NonLinMPC{
4848 Yop:: Vector{NT}
4949 Dop:: Vector{NT}
5050 buffer:: PredictiveControllerBuffer{NT}
51- function NonLinMPC {NT, SE, JM, JEFunc , P} (
52- estim:: SE , Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt, Ewt, JE:: JEFunc , p:: P , optim:: JM
53- ) where {NT<: Real , SE<: StateEstimator , JM<: JuMP.GenericModel , JEFunc <: Function , P<: Any }
51+ function NonLinMPC {NT, SE, JM, JEfunc , P} (
52+ estim:: SE , Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt, Ewt, JE:: JEfunc , gE, nE , p:: P , optim:: JM
53+ ) where {NT<: Real , SE<: StateEstimator , JM<: JuMP.GenericModel , JEfunc <: Function , P<: Any }
5454 model = estim. model
5555 nu, ny, nd, nx̂ = model. nu, model. ny, model. nd, estim. nx̂
5656 ŷ = copy (model. yop) # dummy vals (updated just before optimization)
@@ -68,7 +68,7 @@ struct NonLinMPC{
6868 # dummy vals (updated just before optimization):
6969 F, fx̂ = zeros (NT, ny* Hp), zeros (NT, nx̂)
7070 con, nϵ, S̃, Ñ_Hc, Ẽ = init_defaultcon_mpc (
71- estim, Hp, Hc, Cwt, S, N_Hc, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂
71+ estim, Hp, Hc, Cwt, S, N_Hc, E, ex̂, fx̂, gx̂, jx̂, kx̂, vx̂, bx̂, gE, nE
7272 )
7373 H̃ = init_quadprog (model, Ẽ, S̃, M_Hp, Ñ_Hc, L_Hp)
7474 # dummy vals (updated just before optimization):
@@ -80,7 +80,7 @@ struct NonLinMPC{
8080 nΔŨ = size (Ẽ, 2 )
8181 ΔŨ = zeros (NT, nΔŨ)
8282 buffer = PredictiveControllerBuffer {NT} (nu, ny, nd, Hp)
83- mpc = new {NT, SE, JM, JEFunc , P} (
83+ mpc = new {NT, SE, JM, JEfunc , P} (
8484 estim, optim, con,
8585 ΔŨ, ŷ,
8686 Hp, Hc, nϵ,
@@ -115,14 +115,14 @@ controller minimizes the following objective function at each discrete time ``k`
115115 + E J_E(\m athbf{U}_E, \m athbf{Ŷ}_E, \m athbf{D̂}_E, \m athbf{p})
116116\e nd{aligned}
117117```
118- subject to [`setconstraint!`](@ref) bounds, and the custom economic inequality constraints:
118+ subject to [`setconstraint!`](@ref) bounds, and the economic inequality constraints:
119119```math
120- \m athbf{g}_E(\m athbf{U}_E, \m athbf{Ŷ}_E, \m athbf{D̂}_E, \m athbf{p}, ε ) ≤ \m athbf{0}
121- ````
120+ \m athbf{g}_E(\m athbf{U}_E, \m athbf{Ŷ}_E, \m athbf{D̂}_E, ϵ, \m athbf{p}) ≤ \m athbf{0}
121+ ```
122122The economic function ``J_E`` can penalizes solutions with high economic costs. Setting all
123123the weights to 0 except ``E`` creates a pure economic model predictive controller (EMPC).
124- The arguments of ``J_E`` include the manipulated inputs, the predicted outputs and measured
125- disturbances from ``k`` to ``k+H_p`` inclusively:
124+ The arguments of ``J_E`` and `` \m athbf{g}_E`` include the manipulated inputs, the predicted
125+ outputs and measured disturbances from ``k`` to ``k+H_p`` inclusively:
126126```math
127127 \m athbf{U}_E = \b egin{bmatrix} \m athbf{U} \\ \m athbf{u}(k+H_p-1) \e nd{bmatrix} , \q uad
128128 \m athbf{Ŷ}_E = \b egin{bmatrix} \m athbf{ŷ}(k) \\ \m athbf{Ŷ} \e nd{bmatrix} , \q uad
@@ -134,7 +134,8 @@ over ``H_p``. The argument ``\mathbf{p}`` is a custom parameter object of any ty
134134mutable one if you want to modify it later e.g.: a vector.
135135
136136!!! tip
137- Replace any of the 4 arguments with `_` if not needed (see `JE` default value below).
137+ Replace any of the arguments of ``J_E`` and ``\m athbf{g}_E`` functions with `_` if not
138+ needed (details in Extended Help).
138139
139140See [`LinMPC`](@ref) for the definition of the other variables. This method uses the default
140141state estimator :
@@ -158,11 +159,12 @@ state estimator :
158159- `L_Hp=diagm(repeat(Lwt,Hp))` : positive semidefinite symmetric matrix ``\m athbf{L}_{H_p}``.
159160- `Cwt=1e5` : slack variable weight ``C`` (scalar), use `Cwt=Inf` for hard constraints only.
160161- `Ewt=0.0` : economic costs weight ``E`` (scalar).
161- - `JE=(_,_,_,_)->0.0` : economic (or custom) cost function
162- ``J_E(\m athbf{U}_E, \m athbf{Ŷ}_E, \m athbf{D̂}_E, \m athbf{p})``.
163- - `gE=(_,_,_,_,_)->[]` : economic (or custom) constraint function
164- ``\m athbf{g}_E(\m athbf{U}_E, \m athbf{Ŷ}_E, \m athbf{D̂}_E, \m athbf{p}, ε)``.
165- - `p=model.p` : ``J_E`` function parameter ``\m athbf{p}`` (any type).
162+ - `JE=(_,_,_,_)->0.0` : economic (or custom) cost function ``J_E(\m athbf{U}_E, \m athbf{Ŷ}_E,
163+ \m athbf{D̂}_E, \m athbf{p})`` (details in Extended Help).
164+ - `gE=(_,_,_,_,_,_)->nothing` : economic (or custom) constraint function ``\m athbf{g}_E(
165+ \m athbf{U}_E, \m athbf{Ŷ}_E, \m athbf{D̂}_E, ϵ, \m athbf{p})`` (details in Extended Help).
166+ - `nE=0` : number of economic constraints.
167+ - `p=model.p` : ``J_E`` and ``\m athbf{g}_E`` functions parameter ``\m athbf{p}`` (any type).
166168- `optim=JuMP.Model(Ipopt.Optimizer)` : nonlinear optimizer used in the predictive
167169 controller, provided as a [`JuMP.Model`](https://jump.dev/JuMP.jl/stable/api/JuMP/#JuMP.Model)
168170 (default to [`Ipopt`](https://github.com/jump-dev/Ipopt.jl) optimizer).
@@ -191,6 +193,15 @@ NonLinMPC controller with a sample time Ts = 10.0 s, Ipopt optimizer, UnscentedK
191193 algebra instead of a `for` loop. This feature can accelerate the optimization, especially
192194 for the constraint handling, and is not available in any other package, to my knowledge.
193195
196+ The J
197+
198+ 1. **Non-mutating functions** (out-of-place): define them as `f(x, u, d, p) -> ẋ` and
199+ `h(x, d, p) -> y`. This syntax is simple and intuitive but it allocates more memory.
200+ 2. **Mutating functions** (in-place): define them as `f!(ẋ, x, u, d, p) -> nothing` and
201+ `h!(y, x, d, p) -> nothing`. This syntax reduces the allocations and potentially the
202+ computational burden as well.
203+
204+
194205 The optimization relies on [`JuMP`](https://github.com/jump-dev/JuMP.jl) automatic
195206 differentiation (AD) to compute the objective and constraint derivatives. Optimizers
196207 generally benefit from exact derivatives like AD. However, the [`NonLinModel`](@ref)
@@ -212,13 +223,18 @@ function NonLinMPC(
212223 L_Hp = diagm (repeat (Lwt, Hp)),
213224 Cwt = DEFAULT_CWT,
214225 Ewt = DEFAULT_EWT,
215- JE:: Function = (args... ) -> 0.0 ,
226+ JE:: Function = (_,_,_,_) -> 0.0 ,
227+ gE:: Function = (_,_,_,_,_,_) -> nothing ,
228+ nE = 0 ,
216229 p = model. p,
217230 optim:: JuMP.GenericModel = JuMP. Model (DEFAULT_NONLINMPC_OPTIMIZER, add_bridges= false ),
218231 kwargs...
219232)
220233 estim = UnscentedKalmanFilter (model; kwargs... )
221- NonLinMPC (estim; Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, JE, p, M_Hp, N_Hc, L_Hp, optim)
234+ return NonLinMPC (
235+ estim;
236+ Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, JE, gE, nE, p, M_Hp, N_Hc, L_Hp, optim
237+ )
222238end
223239
224240function NonLinMPC (
@@ -233,13 +249,18 @@ function NonLinMPC(
233249 L_Hp = diagm (repeat (Lwt, Hp)),
234250 Cwt = DEFAULT_CWT,
235251 Ewt = DEFAULT_EWT,
236- JE:: Function = (args... ) -> 0.0 ,
252+ JE:: Function = (_,_,_,_) -> 0.0 ,
253+ gE:: Function = (_,_,_,_,_,_) -> nothing ,
254+ nE = 0 ,
237255 p = model. p,
238256 optim:: JuMP.GenericModel = JuMP. Model (DEFAULT_NONLINMPC_OPTIMIZER, add_bridges= false ),
239257 kwargs...
240258)
241259 estim = SteadyKalmanFilter (model; kwargs... )
242- NonLinMPC (estim; Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, JE, p, M_Hp, N_Hc, L_Hp, optim)
260+ return NonLinMPC (
261+ estim;
262+ Hp, Hc, Mwt, Nwt, Lwt, Cwt, Ewt, JE, gE, nE, p, M_Hp, N_Hc, L_Hp, optim
263+ )
243264end
244265
245266
@@ -278,17 +299,26 @@ function NonLinMPC(
278299 L_Hp = diagm (repeat (Lwt, Hp)),
279300 Cwt = DEFAULT_CWT,
280301 Ewt = DEFAULT_EWT,
281- JE:: JEFunc = (args... ) -> 0.0 ,
302+ JE:: JEfunc = (_,_,_,_) -> 0.0 ,
303+ gE:: GEfunc = (_,_,_,_,_,_) -> nothing ,
304+ nE = 0 ,
282305 p:: P = estim. model. p,
283306 optim:: JM = JuMP. Model (DEFAULT_NONLINMPC_OPTIMIZER, add_bridges= false ),
284- ) where {NT<: Real , SE<: StateEstimator{NT} , JM<: JuMP.GenericModel , JEFunc<: Function , P<: Any }
307+ ) where {
308+ NT<: Real ,
309+ SE<: StateEstimator{NT} ,
310+ JM<: JuMP.GenericModel ,
311+ JEfunc<: Function ,
312+ GEfunc<: Function ,
313+ P<: Any
314+ }
285315 nk = estimate_delays (estim. model)
286316 if Hp ≤ nk
287317 @warn (" prediction horizon Hp ($Hp ) ≤ estimated number of delays in model " *
288318 " ($nk ), the closed-loop system may be unstable or zero-gain (unresponsive)" )
289319 end
290- return NonLinMPC {NT, SE, JM, JEFunc , P} (
291- estim, Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt, Ewt, JE, p, optim
320+ return NonLinMPC {NT, SE, JM, JEfunc , P} (
321+ estim, Hp, Hc, M_Hp, N_Hc, L_Hp, Cwt, Ewt, JE, gE, nE, p, optim
292322 )
293323end
294324
0 commit comments