Skip to content

Commit 6cbbbce

Browse files
committed
test: new tests with AutoFiniteDiff
debug: temporarily fake a "filled" window for MHE gradient preparation (needed for some backend like FiniteDiff)
1 parent 77f0b14 commit 6cbbbce

File tree

4 files changed

+40
-7
lines changed

4 files changed

+40
-7
lines changed

src/estimator/mhe/construct.jl

+3
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,10 @@ function get_optim_functions(
13561356
Cache(g),
13571357
Cache(x̄),
13581358
)
1359+
# temporarily "fill" the estimation window for the preperation of the gradient:
1360+
estim.Nk[] = He
13591361
∇J_prep = prepare_gradient(Jfunc!, estim.gradient, Z̃_∇J, ∇J_context...; strict)
1362+
estim.Nk[] = 0
13601363
∇J = Vector{JNT}(undef, nZ̃)
13611364
∇Jfunc! = function (∇J::AbstractVector{T}, Z̃arg::Vararg{T, N}) where {N, T<:Real}
13621365
# only the multivariate syntax of JuMP.@operator, univariate is impossible for MHE

src/estimator/mhe/execute.jl

+9-2
Original file line numberDiff line numberDiff line change
@@ -522,14 +522,21 @@ Objective function of the MHE when `model` is not a [`LinModel`](@ref).
522522
The function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. This method mutates
523523
`x̄` vector arguments.
524524
"""
525-
function obj_nonlinprog!(x̄, estim::MovingHorizonEstimator, ::SimModel, V̂, Z̃)
525+
function obj_nonlinprog!(
526+
x̄, estim::MovingHorizonEstimator, ::SimModel, V̂, Z̃::AbstractVector{NT}
527+
) where NT<:Real
526528
nϵ, Nk = estim.nϵ, estim.Nk[]
527529
nYm, nŴ, nx̂, invP̄ = Nk*estim.nym, Nk*estim.nx̂, estim.nx̂, estim.invP̄
528530
nx̃ =+ nx̂
529531
invQ̂_Nk, invR̂_Nk = @views estim.invQ̂_He[1:nŴ, 1:nŴ], estim.invR̂_He[1:nYm, 1:nYm]
530532
x̂0arr, Ŵ, V̂ = @views Z̃[nx̃-nx̂+1:nx̃], Z̃[nx̃+1:nx̃+nŴ], V̂[1:nYm]
531533
x̄ .= estim.x̂0arr_old .- x̂0arr
532-
= 0 ? estim.C*Z̃[begin]^2 : 0
534+
= 0 ? estim.C*Z̃[begin]^2 : zero(NT)
535+
#println(x̂0arr)
536+
#println(invP̄)
537+
#println(dot(x̄, invP̄, x̄))
538+
#println(dot(Ŵ, invQ̂_Nk, Ŵ))
539+
#println(dot(V̂, invR̂_Nk, V̂))
533540
return dot(x̄, invP̄, x̄) + dot(Ŵ, invQ̂_Nk, Ŵ) + dot(V̂, invR̂_Nk, V̂) +
534541
end
535542

test/2_test_state_estim.jl

+12-4
Original file line numberDiff line numberDiff line change
@@ -781,11 +781,13 @@ end
781781
end
782782

783783
@testitem "MovingHorizonEstimator construction" setup=[SetupMPCtests] begin
784-
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra, JuMP, Ipopt
784+
using .SetupMPCtests, ControlSystemsBase, LinearAlgebra
785+
using JuMP, Ipopt, DifferentiationInterface
786+
import FiniteDiff
785787
linmodel1 = LinModel(sys,Ts,i_d=[3])
786-
f(x,u,d,_) = linmodel1.A*x + linmodel1.Bu*u + linmodel1.Bd*d
787-
h(x,d,_) = linmodel1.C*x + linmodel1.Du*d
788-
nonlinmodel = NonLinModel(f, h, Ts, 2, 4, 2, 1, solver=nothing)
788+
f(x,u,d,model) = model.A*x + model.Bu*u + model.Bd*d
789+
h(x,d,model) = model.C*x + model.Dd*d
790+
nonlinmodel = NonLinModel(f, h, Ts, 2, 4, 2, 1, solver=nothing, p=linmodel1)
789791

790792
mhe1 = MovingHorizonEstimator(linmodel1, He=5)
791793
@test mhe1.nym == 2
@@ -857,6 +859,12 @@ end
857859
mhe13 = MovingHorizonEstimator(linmodel2, He=5)
858860
@test isa(mhe13, MovingHorizonEstimator{Float32})
859861

862+
mhe14 = MovingHorizonEstimator(
863+
nonlinmodel, He=5, gradient=AutoFiniteDiff(), jacobian=AutoFiniteDiff()
864+
)
865+
@test mhe14.gradient == AutoFiniteDiff()
866+
@test mhe14.jacobian == AutoFiniteDiff()
867+
860868
@test_throws ArgumentError MovingHorizonEstimator(linmodel1)
861869
@test_throws ArgumentError MovingHorizonEstimator(linmodel1, He=0)
862870
@test_throws ArgumentError MovingHorizonEstimator(linmodel1, Cwt=-1)

test/3_test_predictive_control.jl

+16-1
Original file line numberDiff line numberDiff line change
@@ -614,10 +614,12 @@ end
614614
@test nmpc17.transcription == MultipleShooting()
615615
@test length(nmpc17.Z̃) == linmodel1.nu*nmpc17.Hc + nmpc17.estim.nx̂*nmpc17.Hp + nmpc17.
616616
@test size(nmpc17.con.Aeq, 1) == nmpc17.estim.nx̂*nmpc17.Hp
617-
@test_nowarn nmpc18 = NonLinMPC(nonlinmodel, Hp=10,
617+
nmpc18 = NonLinMPC(nonlinmodel, Hp=10,
618618
gradient=AutoFiniteDiff(),
619619
jacobian=AutoFiniteDiff()
620620
)
621+
@test nmpc18.gradient == AutoFiniteDiff()
622+
@test nmpc18.jacobian == AutoFiniteDiff()
621623

622624
nonlinmodel2 = NonLinModel{Float32}(f, h, Ts, 2, 4, 2, 1, solver=nothing)
623625
nmpc15 = NonLinMPC(nonlinmodel2, Hp=15)
@@ -724,6 +726,19 @@ end
724726
info = getinfo(nmpc9)
725727
@test info[:u] u
726728
@test info[:Ŷ][end] 20 atol=5e-2
729+
nmpc10 = setconstraint!(NonLinMPC(
730+
nonlinmodel, Nwt=[0], Hp=100, Hc=1,
731+
gradient=AutoFiniteDiff(),
732+
jacobian=AutoFiniteDiff()),
733+
ymax=[100], ymin=[-100]
734+
)
735+
preparestate!(nmpc10, [0], [0])
736+
u = moveinput!(nmpc10, [10], [0])
737+
@test u [2] atol=5e-2
738+
info = getinfo(nmpc10)
739+
@test info[:u] u
740+
@test info[:Ŷ][end] 10 atol=5e-2
741+
727742
@test_nowarn ModelPredictiveControl.info2debugstr(info)
728743
end
729744

0 commit comments

Comments
 (0)