Skip to content

Commit b6f0928

Browse files
committed
added: linear eq. constraints with CollocationMethod
1 parent 075f955 commit b6f0928

File tree

2 files changed

+54
-38
lines changed

2 files changed

+54
-38
lines changed

src/controller/construct.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,7 @@ function init_defaultcon_mpc(
881881
nu, ny, nx̂ = model.nu, model.ny, estim.nx̂
882882
nw = size(Wy, 1)
883883
nW = nw*(Hp+1)
884+
nFŝ = size(Eŝ, 1)
884885
= weights.isinf_C ? 0 : 1
885886
u0min, u0max = fill(convert(NT,-Inf), nu), fill(convert(NT,+Inf), nu)
886887
Δumin, Δumax = fill(convert(NT,-Inf), nu), fill(convert(NT,+Inf), nu)
@@ -922,7 +923,7 @@ function init_defaultcon_mpc(
922923
Aeq
923924
)
924925
# dummy fx̂, Fw and Fŝ vectors (updated just before optimization)
925-
fx̂, Fw, Fŝ = zeros(NT, nx̂), zeros(NT, nW), zeros(NT, nx̂*Hp)
926+
fx̂, Fw, Fŝ = zeros(NT, nx̂), zeros(NT, nW), zeros(NT, nFŝ)
926927
# dummy b and beq vectors (updated just before optimization)
927928
b, beq = zeros(NT, size(A, 1)), zeros(NT, size(Aeq, 1))
928929
con = ControllerConstraint{NT, GCfunc}(

src/controller/transcription.jl

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ function init_defectmat(
684684
Vŝ = repeat(B̂u, Hp)
685685
# --- decision variables Z ---
686686
nI_nx̂ = Matrix{NT}(-I, nx̂, nx̂)
687-
Eŝ = [zeros(nx̂*Hp, nu*Hc) repeatdiag(nI_nx̂, Hp)]
687+
Eŝ = [zeros(NT, nx̂*Hp, nu*Hc) repeatdiag(nI_nx̂, Hp)]
688688
for j=1:Hc
689689
iCol = (1:nu) .+ nu*(j-1)
690690
for i=j:Hc
@@ -700,36 +700,50 @@ function init_defectmat(
700700
Eŝ[iRow, iCol] =
701701
end
702702
# --- current measured disturbances d0 and predictions D̂0 ---
703-
Gŝ = [B̂d; zeros(NT, (Hp-1)*nx̂, nd)]
704-
Jŝ = [zeros(nx̂, nd*Hp); repeatdiag(B̂d, Hp-1) zeros(NT, nx̂*(Hp-1), nd)]
703+
Gŝ = [B̂d; zeros(NT, nx̂*(Hp-1), nd)]
704+
Jŝ = [zeros(NT, nx̂, nd*Hp); repeatdiag(B̂d, Hp-1) zeros(NT, nx̂*(Hp-1), nd)]
705705
# --- state x̂op and state update f̂op operating points ---
706706
Bŝ = repeat(estim.f̂op - estim.x̂op, Hp)
707707
return Eŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ
708708
end
709709

710710
function init_defectmat(
711-
model::NonLinModel, estim::StateEstimator{NT}, transcription::CollocationMethod, Hp, Hc, _
711+
model::SimModel, estim::StateEstimator{NT}, transcription::CollocationMethod, Hp, Hc, _
712712
) where {NT<:Real}
713-
nx̂, nu, nd = estim.nx̂, model.nu, model.nd
713+
nu, nx, nd, nx̂, nxs = model.nu, model.nx, model.nd, estim.nx̂, estim.nxs
714714
nZ = get_nZ(estim, transcription, Hp, Hc)
715-
Eŝ = zeros(NT, 0, nZ)
716-
Gŝ = zeros(NT, 0, nd)
717-
Jŝ = zeros(NT, 0, nd*Hp)
718-
Kŝ = zeros(NT, 0, nx̂)
719-
Vŝ = zeros(NT, 0, nu)
720-
Bŝ = zeros(NT, 0)
715+
nK = nZ - nu*Hc - nx̂*Hp
716+
As = estim.As
717+
# --- current state estimates x̂0 ---
718+
Kŝ = zeros(NT, nxs*Hp, nx̂)
719+
Kŝ[1:nxs, nx+1:end] = As
720+
# --- previous manipulated inputs lastu0 ---
721+
Vŝ = zeros(nxs*Hp, nu)
722+
# --- decision variables Z ---
723+
zeros_nI = [zeros(NT, nxs, nx) -I]
724+
Eŝ = [zeros(NT, nxs*Hp, nu*Hc) repeatdiag(zeros_nI, Hp) zeros(NT, nxs*Hp, nK)]
725+
for j=1:Hp-1
726+
iRow = (1:nxs) .+ nxs*j
727+
iCol = (nx+1:nx̂) .+ nx̂*(j-1) .+ nu*Hc
728+
Eŝ[iRow, iCol] = As
729+
end
730+
# --- current measured disturbances d0 and predictions D̂0 ---
731+
Gŝ = zeros(NT, nxs*Hp, nd)
732+
Jŝ = zeros(NT, nxs*Hp, nd*Hp)
733+
# --- state x̂op and state update f̂op operating points ---
734+
Bŝ = zeros(NT, nxs*Hp)
721735
return Eŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ
722736
end
723737

724738
"""
725739
init_defectmat(
726-
model::NonLinModel, estim::InternalModel{NT}, transcription::CollocationMethod, Hp, Hc, _
740+
model::SimModel, estim::InternalModel{NT}, transcription::CollocationMethod, Hp, Hc, _
727741
) -> Eŝ, Gŝ, Jŝ, Kŝ, Vŝ, Bŝ
728742
729743
Return empty matrices for [`InternalModel`](@ref) (state vector is not augmented).
730744
"""
731745
function init_defectmat(
732-
model::NonLinModel, estim::InternalModel{NT}, transcription::CollocationMethod, Hp, Hc, _
746+
model::SimModel, estim::InternalModel{NT}, transcription::CollocationMethod, Hp, Hc, _
733747
) where {NT<:Real}
734748
nx̂, nu, nd = estim.nx̂, model.nu, model.nd
735749
nZ = get_nZ(estim, transcription, Hp, Hc)
@@ -812,7 +826,7 @@ function init_matconstraint_mpc(
812826
A_Wmin; A_Wmax
813827
A_x̂min; A_x̂max;
814828
]
815-
neq = 0
829+
neq = 0 # number of nonlinear equality constraints
816830
end
817831
i_b = [i_Umin; i_Umax; i_ΔŨmin; i_ΔŨmax; i_Ymin; i_Ymax; i_Wmin; i_Wmax; i_x̂min; i_x̂max]
818832
i_g = trues(nc)
@@ -830,7 +844,7 @@ function init_matconstraint_mpc(
830844
else
831845
A_Umin, A_Umax, A_ΔŨmin, A_ΔŨmax, _ , _ , A_Wmin, A_Wmax, _ , _ , Aeq = args
832846
A = [A_Umin; A_Umax; A_ΔŨmin; A_ΔŨmax; A_Wmin; A_Wmax]
833-
neq = 0
847+
neq = 0 # number of nonlinear equality constraints
834848
end
835849
i_b = [i_Umin; i_Umax; i_ΔŨmin; i_ΔŨmax; i_Wmin; i_Wmax]
836850
i_g = [i_Ymin; i_Ymax; i_x̂min; i_x̂max; trues(nc)]
@@ -849,7 +863,7 @@ function init_matconstraint_mpc(
849863
A_Umin, A_Umax, A_ΔŨmin, A_ΔŨmax, _ , _ , A_Wmin, A_Wmax, A_x̂min, A_x̂max, Aeq = args
850864
A = [A_Umin; A_Umax; A_ΔŨmin; A_ΔŨmax; A_Wmin; A_Wmax; A_x̂min; A_x̂max]
851865
nΔŨ, nZ̃ = size(A_ΔŨmin)
852-
neq = nZ̃ - nΔŨ
866+
neq = nZ̃ - nΔŨ - size(Aeq, 1) # number of nonlinear equality constraints
853867
end
854868
i_b = [i_Umin; i_Umax; i_ΔŨmin; i_ΔŨmax; i_Wmin; i_Wmax; i_x̂min; i_x̂max]
855869
i_g = [i_Ymin; i_Ymax; trues(nc)]
@@ -960,15 +974,17 @@ end
960974

961975
@doc raw"""
962976
linconstrainteq!(
963-
mpc::PredictiveController, model::LinModel, transcription::MultipleShooting
977+
mpc::PredictiveController, model::LinModel, ::StateEstimator, ::MultipleShooting
964978
)
965979
966980
Set `beq` vector for the linear model equality constraints (``\mathbf{A_{eq} Z̃ = b_{eq}}``).
967981
968982
Also init ``\mathbf{F_ŝ} = \mathbf{G_ŝ d_0}(k) + \mathbf{J_ŝ D̂_0} + \mathbf{K_ŝ x̂_0}(k) +
969983
\mathbf{V_ŝ u_0}(k-1) + \mathbf{B_ŝ}``, see [`init_defectmat`](@ref).
970984
"""
971-
function linconstrainteq!(mpc::PredictiveController, model::LinModel, ::MultipleShooting)
985+
function linconstrainteq!(
986+
mpc::PredictiveController, model::LinModel, ::StateEstimator, ::MultipleShooting
987+
)
972988
Fŝ = mpc.con.Fŝ
973989
Fŝ .= mpc.con.Bŝ
974990
mul!(Fŝ, mpc.con.Kŝ, mpc.estim.x̂0, 1, 1)
@@ -982,7 +998,20 @@ function linconstrainteq!(mpc::PredictiveController, model::LinModel, ::Multiple
982998
JuMP.set_normalized_rhs(linconeq, mpc.con.beq)
983999
return nothing
9841000
end
985-
linconstrainteq!(::PredictiveController, ::SimModel, ::TranscriptionMethod) = nothing
1001+
1002+
function linconstrainteq!(
1003+
mpc::PredictiveController, ::SimModel, ::StateSpace, ::CollocationMethod
1004+
)
1005+
Fŝ = mpc.con.Fŝ
1006+
# the only non-zeros matrices are Eŝ and Kŝ:
1007+
mul!(Fŝ, mpc.con.Kŝ, mpc.estim.x̂0)
1008+
mpc.con.beq .= @. -Fŝ
1009+
linconeq = mpc.optim[:linconstrainteq]
1010+
JuMP.set_normalized_rhs(linconeq, mpc.con.beq)
1011+
return nothing
1012+
end
1013+
linconstrainteq!(::PredictiveController, ::SimModel, ::InternalModel, ::TranscriptionMethod) = nothing
1014+
linconstrainteq!(::PredictiveController, ::SimModel, ::StateEstimator, ::TranscriptionMethod) = nothing
9861015

9871016
@doc raw"""
9881017
set_warmstart!(mpc::PredictiveController, ::SingleShooting, Z̃var) -> Z̃s
@@ -1420,18 +1449,11 @@ function con_nonlinprogeq!(
14201449
end
14211450
= @views K̇[(1 + nk*(j-1)):(nk*j)]
14221451
d̂0next = @views D̂0[(1 + nd*(j-1)):(nd*j)]
1423-
x̂0next = @views X̂0[(1 + nx̂*(j-1)):(nx̂*j)]
14241452
x̂0next_Z̃ = @views X̂0_Z̃[(1 + nx̂*(j-1)):(nx̂*j)]
1425-
sdnext = @views geq[(1 + nx̂*(j-1) ):(nx̂*(j-1) + nx)]
1426-
ssnext = @views geq[(1 + nx̂*(j-1) + nx):(nx̂*j )]
1453+
sdnext = @views geq[(1 + nx*(j-1) ):(nx*(j-1) + nx)]
14271454
x0_Z̃ = @views x̂0_Z̃[1:nx]
14281455
x0next_Z̃ = @views x̂0next_Z̃[1:nx]
14291456
k̇1, k̇2 = @views k̇[1:nx], k̇[nx+1:2*nx]
1430-
# ----------------- stochastic defects -----------------------------------------
1431-
xsnext = @views x̂0next[nx+1:end]
1432-
xsnext_Z̃ = @views x̂0next_Z̃[nx+1:end]
1433-
fs!(x̂0next, mpc.estim, model, x̂0_Z̃)
1434-
ssnext .= @. xsnext - xsnext_Z̃
14351457
# ----------------- deterministic defects: trapezoidal collocation -------------
14361458
û0 = @views Û0[(1 + nu*(j-1)):(nu*j)]
14371459
if f_threads || h < 1 || j < 2
@@ -1524,7 +1546,7 @@ function con_nonlinprogeq!(
15241546
no, τ = transcription.no, transcription.τ
15251547
Mo, Co, λo = mpc.Mo, mpc.Co, mpc.λo
15261548
nk = get_nk(model, transcription)
1527-
nx̂_nk = nx̂ + nk
1549+
nx_nk = nx + nk
15281550
D̂0 = mpc.D̂0
15291551
X̂0_Z̃, K_Z̃ = @views Z̃[(nΔU+1):(nΔU+nX̂)], Z̃[(nΔU+nX̂+1):(nΔU+nX̂+nk*Hp)]
15301552
D̂temp = mpc.buffer.
@@ -1540,18 +1562,11 @@ function con_nonlinprogeq!(
15401562
= @views K̇[(1 + nk*(j-1)):(nk*j)]
15411563
k_Z̃ = @views K_Z̃[(1 + nk*(j-1)):(nk*j)]
15421564
d̂0next = @views D̂0[(1 + nd*(j-1)):(nd*j)]
1543-
x̂0next = @views X̂0[(1 + nx̂*(j-1)):(nx̂*j)]
15441565
x̂0next_Z̃ = @views X̂0_Z̃[(1 + nx̂*(j-1)):(nx̂*j)]
1545-
scnext = @views geq[(1 + nx̂_nk*(j-1) ):(nx̂_nk*(j-1) + nx)]
1546-
ssnext = @views geq[(1 + nx̂_nk*(j-1) + nx):(nx̂_nk*(j-1) + nx̂)]
1547-
sk = @views geq[(1 + nx̂_nk*(j-1) + nx̂):(nx̂_nk*j )]
1566+
scnext = @views geq[(1 + nx_nk*(j-1) ):(nx_nk*(j-1) + nx)]
1567+
sk = @views geq[(1 + nx_nk*(j-1) + nx):(nx_nk*j )]
15481568
x0_Z̃ = @views x̂0_Z̃[1:nx]
15491569
x0next_Z̃ = @views x̂0next_Z̃[1:nx]
1550-
# ----------------- stochastic defects -----------------------------------------
1551-
xsnext = @views x̂0next[nx+1:end]
1552-
xsnext_Z̃ = @views x̂0next_Z̃[nx+1:end]
1553-
fs!(x̂0next, mpc.estim, model, x̂0_Z̃)
1554-
ssnext .= @. xsnext - xsnext_Z̃
15551570
# ----------------- collocation constraint defects -----------------------------
15561571
û0 = @views Û0[(1 + nu*(j-1)):(nu*j)]
15571572
Δk =

0 commit comments

Comments
 (0)