Skip to content

Commit e6bd404

Browse files
committed
Soft constraints for MHE seems to work
1 parent 8ea618d commit e6bd404

File tree

4 files changed

+48
-10
lines changed

4 files changed

+48
-10
lines changed

src/controller/construct.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,25 +235,25 @@ function setconstraint!(
235235
size(C_ymin) == (ny*Hp,) || throw(ArgumentError("C_ymin size must be $((ny*Hp,))"))
236236
any(C_ymin .< 0) && error("C_ymin weights should be non-negative")
237237
con.C_ymin[:] = C_ymin
238-
size(con.A_Ymin, 1) 0 && (con.A_Ymin[:, end] = -C_ymin) # for LinModel
238+
size(con.A_Ymin, 1) 0 && (con.A_Ymin[:, end] = -con.C_ymin) # for LinModel
239239
end
240240
if !isnothing(C_ymax)
241241
size(C_ymax) == (ny*Hp,) || throw(ArgumentError("C_ymax size must be $((ny*Hp,))"))
242242
any(C_ymax .< 0) && error("C_ymax weights should be non-negative")
243243
con.C_ymax[:] = C_ymax
244-
size(con.A_Ymax, 1) 0 && (con.A_Ymax[:, end] = -C_ymax) # for LinModel
244+
size(con.A_Ymax, 1) 0 && (con.A_Ymax[:, end] = -con.C_ymax) # for LinModel
245245
end
246246
if !isnothing(c_x̂min)
247247
size(c_x̂min) == (nx̂,) || throw(ArgumentError("c_x̂min size must be $((nx̂,))"))
248248
any(c_x̂min .< 0) && error("c_x̂min weights should be non-negative")
249249
con.c_x̂min[:] = c_x̂min
250-
size(con.A_x̂min, 1) 0 && (con.A_x̂min[:, end] = -c_x̂min) # for LinModel
250+
size(con.A_x̂min, 1) 0 && (con.A_x̂min[:, end] = -con.c_x̂min) # for LinModel
251251
end
252252
if !isnothing(c_x̂max)
253253
size(c_x̂max) == (nx̂,) || throw(ArgumentError("c_x̂max size must be $((nx̂,))"))
254254
any(c_x̂max .< 0) && error("c_x̂max weights should be non-negative")
255255
con.c_x̂max[:] = c_x̂max
256-
size(con.A_x̂max, 1) 0 && (con.A_x̂max[:, end] = -c_x̂max) # for LinModel
256+
size(con.A_x̂max, 1) 0 && (con.A_x̂max[:, end] = -con.c_x̂max) # for LinModel
257257
end
258258
i_Umin, i_Umax = .!isinf.(con.Umin), .!isinf.(con.Umax)
259259
i_ΔŨmin, i_ΔŨmax = .!isinf.(con.ΔŨmin), .!isinf.(con.ΔŨmin)

src/estimator/mhe/construct.jl

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,17 +440,51 @@ function setconstraint!(
440440
size(V̂max) == (nym*He,) || throw(ArgumentError("V̂max size must be $((nym*He,))"))
441441
con.V̂max[:] = V̂max
442442
end
443+
if !isnothing(C_x̂min)
444+
size(C_x̂min) == (nX̂con,) || throw(ArgumentError("C_x̂min size must be $((nX̂con,))"))
445+
any(C_x̂min .< 0) && error("C_x̂min weights should be non-negative")
446+
con.A_x̃min[end-nx̂+1:end, end] = -C_x̂min[1:nx̂] # if C is finite : x̃ = [ϵ; x̂]
447+
con.C_x̂min[:] = C_x̂min[nx̂+1:end]
448+
size(con.A_X̂min) 0 && (con.A_X̂min[:, end] = -con.C_x̂min) # for LinModel
449+
end
450+
if !isnothing(C_x̂max)
451+
size(C_x̂max) == (nX̂con,) || throw(ArgumentError("C_x̂max size must be $((nX̂con,))"))
452+
any(C_x̂max .< 0) && error("C_x̂max weights should be non-negative")
453+
con.A_x̃max[end-nx̂+1:end, end] = -C_x̂max[1:nx̂] # if C is finite : x̃ = [ϵ; x̂]
454+
con.C_x̂max[:] = C_x̂max[nx̂+1:end]
455+
size(con.A_X̂max) 0 && (con.A_X̂max[:, end] = -con.C_x̂max) # for LinModel
456+
end
457+
if !isnothing(C_ŵmin)
458+
size(C_ŵmin) == (nŵ*He,) || throw(ArgumentError("C_ŵmin size must be $((nŵ*He,))"))
459+
any(C_ŵmin .< 0) && error("C_ŵmin weights should be non-negative")
460+
con.A_Ŵmin[:, end] = -C_ŵmin
461+
end
462+
if !isnothing(C_ŵmax)
463+
size(C_ŵmax) == (nŵ*He,) || throw(ArgumentError("C_ŵmax size must be $((nŵ*He,))"))
464+
any(C_ŵmax .< 0) && error("C_ŵmax weights should be non-negative")
465+
con.A_Ŵmax[:, end] = -C_ŵmax
466+
end
467+
if !isnothing(C_v̂min)
468+
size(C_v̂min) == (nym*He,) || throw(ArgumentError("C_v̂min size must be $((nym*He,))"))
469+
any(C_v̂min .< 0) && error("C_v̂min weights should be non-negative")
470+
con.C_V̂min[:] = C_v̂min
471+
size(con.A_V̂min) 0 && (con.A_V̂min[:, end] = -con.C_V̂min) # for LinModel
472+
end
473+
if !isnothing(C_v̂max)
474+
size(C_v̂max) == (nym*He,) || throw(ArgumentError("C_v̂max size must be $((nym*He,))"))
475+
any(C_v̂max .< 0) && error("C_v̂max weights should be non-negative")
476+
con.C_V̂max[:] = C_v̂max
477+
size(con.A_V̂max) 0 && (con.A_V̂max[:, end] = -con.C_V̂max) # for LinModel
478+
end
443479
i_x̃min, i_x̃max = .!isinf.(con.x̃min) , .!isinf.(con.x̃max)
444480
i_X̂min, i_X̂max = .!isinf.(con.X̂min) , .!isinf.(con.X̂max)
445481
i_Ŵmin, i_Ŵmax = .!isinf.(con.Ŵmin) , .!isinf.(con.Ŵmax)
446482
i_V̂min, i_V̂max = .!isinf.(con.V̂min) , .!isinf.(con.V̂max)
447483
if notSolvedYet
448484
con.i_b[:], con.i_g[:], con.A[:] = init_matconstraint_mhe(model,
449485
i_x̃min, i_x̃max, i_X̂min, i_X̂max, i_Ŵmin, i_Ŵmax, i_V̂min, i_V̂max,
450-
con.A_x̃min, con.A_x̃max,
451-
con.A_X̂min, con.A_X̂max,
452-
con.A_Ŵmin, con.A_Ŵmax,
453-
con.A_V̂min, con.A_V̂max
486+
con.A_x̃min, con.A_x̃max, con.A_X̂min, con.A_X̂max,
487+
con.A_Ŵmin, con.A_Ŵmax, con.A_V̂min, con.A_V̂max
454488
)
455489
A = con.A[con.i_b, :]
456490
b = con.b[con.i_b]

src/estimator/mhe/execute.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ dictionary `info` with the following fields:
9595
9696
- `:Ŵ` : optimal estimated process noise over ``N_k``, ``\mathbf{Ŵ}``.
9797
- `:x̂arr`: optimal estimated state at arrival, ``\mathbf{x̂}_k(k-N_k+1)``.
98+
- `:ϵ` : optimal slack variable, ``ϵ``.
9899
- `:J` : objective value optimum, ``J``.
99100
- `:X̂` : optimal estimated states over ``N_k+1``, ``\mathbf{X̂}``.
100101
- `:x̂` : optimal estimated state for the next time step, ``\mathbf{x̂}_k(k+1)``.
@@ -123,11 +124,12 @@ function getinfo(estim::MovingHorizonEstimator{NT}) where NT<:Real
123124
model, Nk = estim.model, estim.Nk[]
124125
nu, ny, nd = model.nu, model.ny, model.nd
125126
nx̂, nym, nŵ = estim.nx̂, estim.nym, estim.nx̂
127+
nx̃ = !isinf(estim.C) + nx̂
126128
MyTypes = Union{JuMP._SolutionSummary, Hermitian{NT, Matrix{NT}}, Vector{NT}, NT}
127129
info = Dict{Symbol, MyTypes}()
128130
V̂, X̂ = similar(estim.Ym[1:nym*Nk]), similar(estim.X̂[1:nx̂*Nk])
129131
V̂, X̂ = predict!(V̂, X̂, estim, model, estim.Z̃)
130-
x̂arr = estim.Z̃[1:nx̂]
132+
x̂arr = estim.Z̃[nx̃-nx̂+1:nx̃]
131133
= [x̂arr; X̂]
132134
Ym, U, D = estim.Ym[1:nym*Nk], estim.U[1:nu*Nk], estim.D[1:nd*Nk]
133135
= Vector{NT}(undef, ny*Nk)
@@ -139,6 +141,7 @@ function getinfo(estim::MovingHorizonEstimator{NT}) where NT<:Real
139141
Ŷm = Ym -
140142
info[:Ŵ] = estim.Ŵ[1:Nk*nŵ]
141143
info[:x̂arr] = x̂arr
144+
info[] = isinf(estim.C) ? NaN : estim.Z̃[begin]
142145
info[:J] = obj_nonlinprog(estim, estim.model, V̂, estim.Z̃)
143146
info[:X̂] =
144147
info[:x̂] = estim.

test/test_state_estim.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ end
603603

604604
I_6 = Matrix{Float64}(I, 6, 6)
605605
I_2 = Matrix{Float64}(I, 2, 2)
606-
mhe9 = MovingHorizonEstimator(nonlinmodel, 5, 1:2, 0, [1, 1], I_6, I_6, I_2, Model(Ipopt.Optimizer))
606+
optim = Model(Ipopt.Optimizer)
607+
mhe9 = MovingHorizonEstimator(nonlinmodel, 5, 1:2, 0, [1, 1], I_6, I_6, I_2, 1e5 ,optim)
607608
@test mhe9.P̂0 I(6)
608609
@test mhe9. I(6)
609610
@test mhe9. I(2)

0 commit comments

Comments
 (0)