Skip to content

Commit 910359f

Browse files
committed
debug: plot plant state names instead of estim/mpc model state names
1 parent 367af1b commit 910359f

File tree

2 files changed

+72
-34
lines changed

2 files changed

+72
-34
lines changed

docs/src/public/plot_sim.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ sim!
2222
SimResult
2323
```
2424

25-
## Plots
25+
## Plotting Results
2626

2727
```@docs
2828
ModelPredictiveControl.plot

src/plot_sim.jl

Lines changed: 71 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
struct SimResult{NT<:Real, O<:Union{SimModel, StateEstimator, PredictiveController}}
2-
obj::O # simulated instance
3-
T_data ::Vector{NT} # time in seconds
4-
Y_data ::Matrix{NT} # plant outputs (both measured and unmeasured)
5-
Ry_data::Matrix{NT} # output setpoints
6-
Ŷ_data ::Matrix{NT} # estimated outputs
7-
U_data ::Matrix{NT} # manipulated inputs
8-
Ud_data::Matrix{NT} # manipulated inputs including load disturbances
9-
Ru_data::Matrix{NT} # manipulated input setpoints
10-
D_data ::Matrix{NT} # measured disturbances
11-
X_data ::Matrix{NT} # plant states
12-
X̂_data ::Matrix{NT} # estimated states
2+
obj::O # simulated instance
3+
xname ::Vector{String} # plant state names
4+
T_data ::Vector{NT} # time in seconds
5+
Y_data ::Matrix{NT} # plant outputs (both measured and unmeasured)
6+
Ry_data::Matrix{NT} # output setpoints
7+
Ŷ_data ::Matrix{NT} # estimated outputs
8+
U_data ::Matrix{NT} # manipulated inputs
9+
Ud_data::Matrix{NT} # manipulated inputs including load disturbances
10+
Ru_data::Matrix{NT} # manipulated input setpoints
11+
D_data ::Matrix{NT} # measured disturbances
12+
X_data ::Matrix{NT} # plant states
13+
X̂_data ::Matrix{NT} # estimated states
1314
end
1415

1516
"""
@@ -36,16 +37,17 @@ Simply call `plot` on them.
3637
- `Ŷ_data=nothing` or *`Yhat_data`* : estimated outputs
3738
- `Ry_data=nothing` : plant output setpoints
3839
- `Ru_data=nothing` : manipulated input setpoints
40+
- `plant=get_model(obj)` : simulated plant model, default to `obj` internal plant model
3941
4042
# Examples
4143
```jldoctest
42-
julia> plant = LinModel(tf(1, [1, 1]), 1.0); N = 5; U_data = fill(1.0, 1, N);
44+
julia> model = LinModel(tf(1, [1, 1]), 1.0); N = 5; U_data = fill(1.0, 1, N);
4345
44-
julia> Y_data = reduce(hcat, (updatestate!(plant, U_data[:, i]); plant()) for i=1:N)
46+
julia> Y_data = reduce(hcat, (updatestate!(model, U_data[:, i]); model()) for i=1:N)
4547
1×5 Matrix{Float64}:
4648
0.632121 0.864665 0.950213 0.981684 0.993262
4749
48-
julia> res = SimResult(plant, U_data, Y_data)
50+
julia> res = SimResult(model, U_data, Y_data)
4951
Simulation results of LinModel with 5 time steps.
5052
```
5153
"""
@@ -60,10 +62,12 @@ function SimResult(
6062
Ry_data = nothing,
6163
Ru_data = nothing,
6264
X̂_data = Xhat_data,
63-
Ŷ_data = Yhat_data
65+
Ŷ_data = Yhat_data,
66+
plant = get_model(obj)
6467
) where {NT<:Real, O<:Union{SimModel{NT}, StateEstimator{NT}, PredictiveController{NT}}}
6568
model = get_model(obj)
66-
Ts, nu, ny, nx, nx̂ = model.Ts, model.nu, model.ny, model.nx, get_nx̂(obj)
69+
Ts, nu, ny, nx̂ = model.Ts, model.nu, model.ny, get_nx̂(obj)
70+
nx = plant.nx
6771
N = size(U_data, 2)
6872
T_data = collect(Ts*(0:N-1))
6973
isnothing(X_data) && (X_data = fill(NaN, nx, N))
@@ -72,13 +76,16 @@ function SimResult(
7276
isnothing(Ru_data) && (Ru_data = fill(NaN, nu, N))
7377
isnothing(Ŷ_data) && (Ŷ_data = fill(NaN, ny, N))
7478
NU, NY, NX, NX̂ = size(U_data, 2), size(Y_data, 2), size(X_data, 2), size(X̂_data, 2)
75-
NRy, NRu = size(Ry_data, 2), size(Ru_data, 2)
76-
if !(NU == NY == NX == NX̂ == NRy == NRu)
79+
NRy, NRu, NŶ = size(Ry_data, 2), size(Ru_data, 2), size(Ŷ_data, 2)
80+
if !(NU == NY == NX == NX̂ == NRy == NRu == NŶ)
7781
throw(ArgumentError("All arguments must have the same number of columns (time steps)"))
7882
end
7983
size(Y_data, 2) == N || error("Y_data must be of size ($ny, $N)")
80-
return SimResult{NT, O}(obj, T_data, Y_data, Ry_data, Ŷ_data, U_data, U_data,
81-
Ru_data, D_data, X_data, X̂_data)
84+
return SimResult{NT, O}(
85+
obj, plant.xname,
86+
T_data, Y_data, Ry_data, Ŷ_data,
87+
U_data, U_data, Ru_data, D_data, X_data, X̂_data
88+
)
8289
end
8390

8491
get_model(model::SimModel) = model
@@ -136,8 +143,11 @@ function sim!(
136143
X_data[:, i] .= plant.x0 .+ plant.xop
137144
updatestate!(plant, u, d)
138145
end
139-
return SimResult(plant, T_data, Y_data, U_data, Y_data,
140-
U_data, U_data, U_data, D_data, X_data, X_data)
146+
return SimResult(
147+
plant, plant.xname,
148+
T_data, Y_data, U_data, Y_data,
149+
U_data, U_data, U_data, D_data, X_data, X_data
150+
)
141151
end
142152

143153
@doc raw"""
@@ -289,8 +299,11 @@ function sim_closedloop!(
289299
x[:] += x_noise.*randn(plant.nx)
290300
updatestate!(est_mpc, u, ym, d)
291301
end
292-
res = SimResult(est_mpc, T_data, Y_data, U_Ry_data, Ŷ_data,
293-
U_data, Ud_data, Ru_data, D_data, X_data, X̂_data)
302+
res = SimResult(
303+
est_mpc, plant.xname,
304+
T_data, Y_data, U_Ry_data, Ŷ_data,
305+
U_data, Ud_data, Ru_data, D_data, X_data, X̂_data
306+
)
294307
plant.x0 .= old_x0
295308
return res
296309
end
@@ -319,6 +332,13 @@ Plot the simulation results of a [`SimModel`](@ref).
319332
- `plotu=true` : plot manipulated inputs ``\mathbf{u}``
320333
- `plotd=true` : plot measured disturbances ``\mathbf{d}`` if applicable
321334
- `plotx=false` : plot plant states ``\mathbf{x}``
335+
336+
# Examples
337+
```julia-repl
338+
julia> res = sim!(LinModel(tf(2, [10, 1]), 2.0), 25);
339+
340+
julia> plot(res, plotu=false);
341+
```
322342
"""
323343
plot(::Nothing, ::SimResult{<:Real, <:SimModel})
324344

@@ -337,7 +357,7 @@ plot(::Nothing, ::SimResult{<:Real, <:SimModel})
337357
uname = model.uname
338358
yname = model.yname
339359
dname = model.dname
340-
xname = model.xname
360+
xname = res.xname
341361
layout_mat = [(ny, 1)]
342362
plotu && (layout_mat = [layout_mat (nu, 1)])
343363
(plotd && nd 0) && (layout_mat = [layout_mat (nd, 1)])
@@ -424,6 +444,13 @@ Plot the simulation results of a [`StateEstimator`](@ref).
424444
- `plotx̂max=true` or *`plotxhatmax`* : plot estimated state upper bounds ``\mathbf{x̂_{max}}``
425445
if applicable
426446
- `<keyword arguments>` of [`plot(::SimResult{<:Real, <:SimModel})`](@ref)
447+
448+
# Examples
449+
```julia-repl
450+
julia> res = sim!(KalmanFilter(LinModel(tf(3, [2.0, 1]), 1.0)), 25, [0], y_step=[1]);
451+
452+
julia> plot(res, plotu=false, plotŷ=true, plotxwithx̂=true);
453+
```
427454
"""
428455
plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
429456

@@ -454,7 +481,8 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
454481
uname = model.uname
455482
yname = model.yname
456483
dname = model.dname
457-
xname = model.xname
484+
x̂name = [model.xname; ["\$x_{$i}\$" for i in (nx+1):(nx̂)]]
485+
xname = res.xname
458486
layout_mat = [(ny, 1)]
459487
plotu && (layout_mat = [layout_mat (nu, 1)])
460488
(plotd && nd 0) && (layout_mat = [layout_mat (nd, 1)])
@@ -541,7 +569,7 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
541569
withPlantState = plotxwithx̂ && i nx
542570
@series begin
543571
i == nx̂ && (xguide --> "Time (s)")
544-
yguide --> (withPlantState ? xname[i] : "\$\\hat{x}_{$i}\$")
572+
yguide --> (withPlantState ? xname[i] : x̂name[i])
545573
color --> 2
546574
subplot --> subplot_base + i
547575
linestyle --> :dashdot
@@ -553,7 +581,7 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
553581
if plotx̂min && !isinf(X̂min[end-2*nx̂+i])
554582
@series begin
555583
i == nx̂ && (xguide --> "Time (s)")
556-
yguide --> (withPlantState ? xname[i] : "\$\\hat{x}_{$i}\$")
584+
yguide --> (withPlantState ? xname[i] : x̂name[i])
557585
color --> 3
558586
subplot --> subplot_base + i
559587
linestyle --> :dot
@@ -566,7 +594,7 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
566594
if plotx̂max && !isinf(X̂max[end-2*nx̂+i])
567595
@series begin
568596
i == nx̂ && (xguide --> "Time (s)")
569-
yguide --> (withPlantState ? xname[i] : "\$\\hat{x}_{$i}\$")
597+
yguide --> (withPlantState ? xname[i] : x̂name[i])
570598
color --> 4
571599
subplot --> subplot_base + i
572600
linestyle --> :dot
@@ -599,6 +627,15 @@ Plot the simulation results of a [`PredictiveController`](@ref).
599627
- `<keyword arguments>` of [`plot(::SimResult{<:Real, <:SimModel})`](@ref)
600628
- `<keyword arguments>` of [`plot(::SimResult{<:Real, <:StateEstimator})`](@ref)
601629
630+
# Examples
631+
```julia-repl
632+
julia> model = LinModel(tf(2, [5.0, 1]), 1.0);
633+
634+
julia> res = sim!(setconstraint!(LinMPC(model), umax=[1.0]), 30, [0], u_step=[-1]);
635+
636+
julia> plot(res, plotŷ=true, plotry=true, plotumax=true);
637+
```
638+
602639
"""
603640
plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
604641

@@ -635,7 +672,8 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
635672
uname = model.uname
636673
yname = model.yname
637674
dname = model.dname
638-
xname = model.xname
675+
x̂name = [model.xname; ["\$x_{$i}\$" for i in (nx+1):(nx̂)]]
676+
xname = res.xname
639677
layout_mat = [(ny, 1)]
640678
plotu && (layout_mat = [layout_mat (nu, 1)])
641679
(plotd && nd 0) && (layout_mat = [layout_mat (nd, 1)])
@@ -803,7 +841,7 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
803841
withPlantState = plotxwithx̂ && i nx
804842
@series begin
805843
i == nx̂ && (xguide --> "Time (s)")
806-
yguide --> (withPlantState ? xname[i] : "\$\\hat{x}_{$i}\$")
844+
yguide --> (withPlantState ? xname[i] : x̂name[i])
807845
color --> 2
808846
subplot --> subplot_base + i
809847
linestyle --> :dashdot
@@ -815,7 +853,7 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
815853
if plotx̂min && !isinf(X̂min[end-2*nx̂+i])
816854
@series begin
817855
i == nx̂ && (xguide --> "Time (s)")
818-
yguide --> (withPlantState ? xname[i] : "\$\\hat{x}_{$i}\$")
856+
yguide --> (withPlantState ? xname[i] : x̂name[i])
819857
color --> 3
820858
subplot --> subplot_base + i
821859
linestyle --> :dot
@@ -828,7 +866,7 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
828866
if plotx̂max && !isinf(X̂max[end-2*nx̂+i])
829867
@series begin
830868
i == nx̂ && (xguide --> "Time (s)")
831-
yguide --> (withPlantState ? xname[i] : "\$\\hat{x}_{$i}\$")
869+
yguide --> (withPlantState ? xname[i] : x̂name[i])
832870
color --> 4
833871
subplot --> subplot_base + i
834872
linestyle --> :dot

0 commit comments

Comments
 (0)