Skip to content

Commit 8ae0694

Browse files
committed
test: improve coverage of NonLinMPC with MultipleShooting
1 parent 4154ee8 commit 8ae0694

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

src/controller/nonlinmpc.jl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,8 @@ This method is really indicated and I'm not proud of it. That's because of 3 ele
531531
and as efficient as possible.
532532
- The `JuMP` NLP syntax forces splatting for the decision variable, which implies use
533533
of `Vararg{T,N}` (see the [performance tip](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing))
534-
and memoization to avoid redundant computations. This is already complex,
535-
but it's even worse knowing that AD tools for gradients do not support splatting.
534+
and memoization to avoid redundant computations. This is already complex, but it's even
535+
worse knowing that most automatic differentiation tools do not support splatting.
536536
- The signature of gradient and hessian functions is not the same for univariate (`nZ̃ == 1`)
537537
and multivariate (`nZ̃ > 1`) operators in `JuMP`. Both must be defined.
538538
@@ -546,6 +546,7 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
546546
nΔŨ, nUe, nŶe = nu*Hc + nϵ, nU + nu, nŶ + ny
547547
Ncache = nZ̃ + 3
548548
myNaN = convert(JNT, NaN) # fill Z̃ with NaNs to force update_simulations! at 1st call:
549+
# ---------------------- differentiation cache ---------------------------------------
549550
Z̃_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(fill(myNaN, nZ̃), Ncache)
550551
ΔŨ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nΔŨ), Ncache)
551552
x̂0end_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Ncache)
@@ -586,14 +587,14 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
586587
end
587588
return nothing
588589
end
589-
# --------------------- cache for the AD functions -----------------------------------
590+
# --------------------- normal cache for the AD functions ----------------------------
590591
Z̃arg_vec = Vector{JNT}(undef, nZ̃)
591-
∇J = Vector{JNT}(undef, nZ̃) # gradient of J
592+
∇J = Vector{JNT}(undef, nZ̃) # gradient of objective J
592593
g_vec = Vector{JNT}(undef, ng)
593-
∇g = Matrix{JNT}(undef, ng, nZ̃) # Jacobian of g
594+
∇g = Matrix{JNT}(undef, ng, nZ̃) # Jacobian of inequality constraints g
594595
geq_vec = Vector{JNT}(undef, neq)
595-
∇geq = Matrix{JNT}(undef, neq, nZ̃) # Jacobian of geq
596-
# --------------------- objective function --------------------------------------------
596+
∇geq = Matrix{JNT}(undef, neq, nZ̃) # Jacobian of equality constraints geq
597+
# --------------------- objective functions -------------------------------------------
597598
function Jfunc(Z̃arg::Vararg{T, N}) where {N, T<:Real}
598599
update_simulations!(Z̃arg, get_tmp(Z̃_cache, T))
599600
ΔŨ = get_tmp(ΔŨ_cache, T)
@@ -674,7 +675,7 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
674675
∇geqfuncs! = Vector{Function}(undef, neq)
675676
for i in eachindex(∇geqfuncs!)
676677
# only multivariate syntax, univariate is impossible since nonlinear equality
677-
# constraints imply MultipleShooting thus input AND state in Z̃:
678+
# constraints imply MultipleShooting, thus input increment ΔU and state X̂0 in Z̃:
678679
∇geqfuncs![i] =
679680
function (∇geq_i, Z̃arg::Vararg{T, N}) where {N, T<:Real}
680681
Z̃arg_vec .= Z̃arg

test/3_test_predictive_control.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,12 @@ end
602602
LHS = zeros(1)
603603
nmpc15.con.gc!(LHS,[1,2],[3,4],[4,6],10,0.1)
604604
@test LHS [10*dot([1,2],[3,4])+sum([4,6])+0.1]
605-
nmpc16 = NonLinMPC(nonlinmodel, Hp=10, transcription=MultipleShooting())
605+
gc! = (LHS,_,_,_,_,_)-> (LHS .= 0.0) # useless, only for coverage
606+
nmpc16 = NonLinMPC(nonlinmodel, Hp=10, transcription=MultipleShooting(), nc=10, gc=gc!)
606607
@test nmpc16.transcription == MultipleShooting()
607608
@test length(nmpc16.Z̃) == nonlinmodel.nu*nmpc16.Hc + nmpc16.estim.nx̂*nmpc16.Hp + nmpc16.
608609
@test nmpc16.con.neq == nmpc16.estim.nx̂*nmpc16.Hp
610+
@test nmpc16.con.nc == 10
609611
nmpc17 = NonLinMPC(linmodel1, Hp=10, transcription=MultipleShooting())
610612
@test nmpc17.transcription == MultipleShooting()
611613
@test length(nmpc17.Z̃) == linmodel1.nu*nmpc17.Hc + nmpc17.estim.nx̂*nmpc17.Hp + nmpc17.

0 commit comments

Comments
 (0)