@@ -77,7 +77,7 @@ struct NonLinMPC{
77
77
d0, D̂0, D̂E,
78
78
Ŷop, Dop,
79
79
)
80
- init_optimization! (mpc, optim)
80
+ init_optimization! (mpc, model, optim)
81
81
return mpc
82
82
end
83
83
end
@@ -277,11 +277,11 @@ function addinfo!(info, mpc::NonLinMPC)
277
277
end
278
278
279
279
"""
280
- init_optimization!(mpc::NonLinMPC, optim::JuMP.GenericModel )
280
+ init_optimization!(mpc::NonLinMPC, model::SimModel, optim )
281
281
282
282
Init the nonlinear optimization for [`NonLinMPC`](@ref) controllers.
283
283
"""
284
- function init_optimization! (mpc:: NonLinMPC , optim :: JuMP.GenericModel{JNT} ) where JNT <: Real
284
+ function init_optimization! (mpc:: NonLinMPC , model :: SimModel , optim)
285
285
# --- variables and linear constraints ---
286
286
C, con = mpc. C, mpc. con
287
287
nΔŨ = length (mpc. ΔŨ)
@@ -300,65 +300,11 @@ function init_optimization!(mpc::NonLinMPC, optim::JuMP.GenericModel{JNT}) where
300
300
JuMP. set_attribute (optim, " nlp_scaling_max_gradient" , 10.0 / C)
301
301
end
302
302
end
303
- model = mpc. estim. model
304
- nu, ny, nx̂, Hp, ng = model. nu, model. ny, mpc. estim. nx̂, mpc. Hp, length (con. i_g)
305
- # inspired from https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/tips_and_tricks/#User-defined-operators-with-vector-outputs
306
- Jfunc, gfunc = let mpc= mpc, model= model, ng= ng, nΔŨ= nΔŨ, nŶ= Hp* ny, nx̂= nx̂, nu= nu, nU= Hp* nu
307
- Nc = nΔŨ + 3
308
- last_ΔŨtup_float, last_ΔŨtup_dual = nothing , nothing
309
- ΔŨ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nΔŨ), Nc)
310
- Ŷ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ), Nc)
311
- U_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU), Nc)
312
- g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Nc)
313
- x̂_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
314
- x̂next_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
315
- u_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
316
- û_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
317
- Ȳ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ), Nc)
318
- Ū_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU), Nc)
319
- function Jfunc (ΔŨtup:: T... ):: T where {T <: Real }
320
- ΔŨ1 = ΔŨtup[begin ]
321
- if T == JNT
322
- last_ΔŨtup_float = ΔŨtup
323
- else
324
- last_ΔŨtup_dual = ΔŨtup
325
- end
326
- ΔŨ, Ŷ = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (Ŷ_cache, ΔŨ1)
327
- x̂, x̂next = get_tmp (x̂_cache, ΔŨ1), get_tmp (x̂next_cache, ΔŨ1)
328
- u, û = get_tmp (u_cache, ΔŨ1), get_tmp (û_cache, ΔŨ1)
329
- ΔŨ .= ΔŨtup
330
- Ŷ, x̂end = predict! (Ŷ, x̂, x̂next, u, û, mpc, model, ΔŨ)
331
- g = get_tmp (g_cache, ΔŨ1)
332
- g = con_nonlinprog! (g, mpc, model, x̂end , Ŷ, ΔŨ)
333
- U, Ȳ, Ū = get_tmp (U_cache, ΔŨ1), get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
334
- return obj_nonlinprog! (U, Ȳ, Ū, mpc, model, Ŷ, ΔŨ):: T
335
- end
336
- function gfunc_i (i, ΔŨtup:: NTuple{N, T} ):: T where {N, T <: Real }
337
- ΔŨ1 = ΔŨtup[begin ]
338
- g = get_tmp (g_cache, ΔŨ1)
339
- if T == JNT
340
- isnewvalue = (ΔŨtup != = last_ΔŨtup_float)
341
- isnewvalue && (last_ΔŨtup_float = ΔŨtup)
342
- else
343
- isnewvalue = (ΔŨtup != = last_ΔŨtup_dual)
344
- isnewvalue && (last_ΔŨtup_dual = ΔŨtup)
345
- end
346
- if isnewvalue
347
- ΔŨ, Ŷ = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (Ŷ_cache, ΔŨ1)
348
- x̂, x̂next = get_tmp (x̂_cache, ΔŨ1), get_tmp (x̂next_cache, ΔŨ1)
349
- u, û = get_tmp (u_cache, ΔŨ1), get_tmp (û_cache, ΔŨ1)
350
- ΔŨ .= ΔŨtup
351
- Ŷ, x̂end = predict! (Ŷ, x̂, x̂next, u, û, mpc, model, ΔŨ)
352
- g = con_nonlinprog! (g, mpc, model, x̂end , Ŷ, ΔŨ)
353
- end
354
- return g[i]:: T
355
- end
356
- gfunc = [(ΔŨ... ) -> gfunc_i (i, ΔŨ) for i in 1 : ng]
357
- (Jfunc, gfunc)
358
- end
303
+ Jfunc, gfunc = get_optim_functions (mpc, mpc. optim)
359
304
register (optim, :Jfunc , nΔŨ, Jfunc, autodiff= true )
360
305
@NLobjective (optim, Min, Jfunc (ΔŨvar... ))
361
- if ng ≠ 0
306
+ ny, nx̂, Hp = model. ny, mpc. estim. nx̂, mpc. Hp
307
+ if length (con. i_g) ≠ 0
362
308
for i in eachindex (con. Ymin)
363
309
sym = Symbol (" g_Ymin_$i " )
364
310
register (optim, sym, nΔŨ, gfunc[i], autodiff= true )
@@ -382,6 +328,62 @@ function init_optimization!(mpc::NonLinMPC, optim::JuMP.GenericModel{JNT}) where
382
328
return nothing
383
329
end
384
330
331
+ """
332
+ get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel) -> Jfunc, gfunc
333
+
334
+ Get the objective `Jfunc` and constraints `gfunc` functions for [`NonLinMPC`](@ref).
335
+
336
+ Inspired from: [User-defined operators with vector outputs](https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/tips_and_tricks/#User-defined-operators-with-vector-outputs)
337
+ """
338
+ function get_optim_functions (mpc:: NonLinMPC , :: JuMP.GenericModel{JNT} ) where JNT<: Real
339
+ model = mpc. estim. model
340
+ nu, ny, nx̂, Hp = model. nu, model. ny, mpc. estim. nx̂, mpc. Hp
341
+ ng, nΔŨ, nU, nŶ = length (mpc. con. i_g), length (mpc. ΔŨ), Hp* nu, Hp* ny
342
+ Nc = nΔŨ + 3
343
+ ΔŨ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nΔŨ), Nc)
344
+ Ŷ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ), Nc)
345
+ U_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU), Nc)
346
+ g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Nc)
347
+ x̂_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
348
+ x̂next_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
349
+ u_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
350
+ û_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
351
+ Ȳ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŶ), Nc)
352
+ Ū_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nU), Nc)
353
+ function Jfunc (ΔŨtup:: T... ) where T<: Real
354
+ ΔŨ1 = ΔŨtup[begin ]
355
+ ΔŨ, g = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (g_cache, ΔŨ1)
356
+ for i in eachindex (ΔŨtup)
357
+ ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
358
+ end
359
+ Ŷ = get_tmp (Ŷ_cache, ΔŨ1)
360
+ x̂, x̂next = get_tmp (x̂_cache, ΔŨ1), get_tmp (x̂next_cache, ΔŨ1)
361
+ u, û = get_tmp (u_cache, ΔŨ1), get_tmp (û_cache, ΔŨ1)
362
+ Ŷ, x̂end = predict! (Ŷ, x̂, x̂next, u, û, mpc, model, ΔŨ)
363
+ g = get_tmp (g_cache, ΔŨ1)
364
+ g = con_nonlinprog! (g, mpc, model, x̂end , Ŷ, ΔŨ)
365
+ U, Ȳ, Ū = get_tmp (U_cache, ΔŨ1), get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
366
+ return obj_nonlinprog! (U, Ȳ, Ū, mpc, model, Ŷ, ΔŨ):: T
367
+ end
368
+ function gfunc_i (i, ΔŨtup:: NTuple{N, T} ) where {N, T<: Real }
369
+ ΔŨ1 = ΔŨtup[begin ]
370
+ ΔŨ, g = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (g_cache, ΔŨ1)
371
+ if any (new != = old for (new, old) in zip (ΔŨtup, ΔŨ)) # new ΔŨtup, update predictions:
372
+ for i in eachindex (ΔŨtup)
373
+ ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
374
+ end
375
+ Ŷ = get_tmp (Ŷ_cache, ΔŨ1)
376
+ x̂, x̂next = get_tmp (x̂_cache, ΔŨ1), get_tmp (x̂next_cache, ΔŨ1)
377
+ u, û = get_tmp (u_cache, ΔŨ1), get_tmp (û_cache, ΔŨ1)
378
+ Ŷ, x̂end = predict! (Ŷ, x̂, x̂next, u, û, mpc, model, ΔŨ)
379
+ g = con_nonlinprog! (g, mpc, model, x̂end , Ŷ, ΔŨ)
380
+ end
381
+ return g[i]:: T
382
+ end
383
+ gfunc = [(ΔŨ... ) -> gfunc_i (i, ΔŨ) for i in 1 : ng]
384
+ return Jfunc, gfunc
385
+ end
386
+
385
387
" Set the nonlinear constraints on the output predictions `Ŷ` and terminal states `x̂end`."
386
388
function setnonlincon! (mpc:: NonLinMPC , :: NonLinModel )
387
389
optim = mpc. optim
0 commit comments