1
1
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
13
14
end
14
15
15
16
"""
@@ -36,16 +37,17 @@ Simply call `plot` on them.
36
37
- `Ŷ_data=nothing` or *`Yhat_data`* : estimated outputs
37
38
- `Ry_data=nothing` : plant output setpoints
38
39
- `Ru_data=nothing` : manipulated input setpoints
40
+ - `plant=get_model(obj)` : simulated plant model, default to `obj` internal plant model
39
41
40
42
# Examples
41
43
```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);
43
45
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)
45
47
1×5 Matrix{Float64}:
46
48
0.632121 0.864665 0.950213 0.981684 0.993262
47
49
48
- julia> res = SimResult(plant , U_data, Y_data)
50
+ julia> res = SimResult(model , U_data, Y_data)
49
51
Simulation results of LinModel with 5 time steps.
50
52
```
51
53
"""
@@ -60,10 +62,12 @@ function SimResult(
60
62
Ry_data = nothing ,
61
63
Ru_data = nothing ,
62
64
X̂_data = Xhat_data,
63
- Ŷ_data = Yhat_data
65
+ Ŷ_data = Yhat_data,
66
+ plant = get_model (obj)
64
67
) where {NT<: Real , O<: Union{SimModel{NT}, StateEstimator{NT}, PredictiveController{NT}} }
65
68
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
67
71
N = size (U_data, 2 )
68
72
T_data = collect (Ts* (0 : N- 1 ))
69
73
isnothing (X_data) && (X_data = fill (NaN , nx, N))
@@ -72,13 +76,16 @@ function SimResult(
72
76
isnothing (Ru_data) && (Ru_data = fill (NaN , nu, N))
73
77
isnothing (Ŷ_data) && (Ŷ_data = fill (NaN , ny, N))
74
78
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Ŷ )
77
81
throw (ArgumentError (" All arguments must have the same number of columns (time steps)" ))
78
82
end
79
83
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
+ )
82
89
end
83
90
84
91
get_model (model:: SimModel ) = model
@@ -136,8 +143,11 @@ function sim!(
136
143
X_data[:, i] .= plant. x0 .+ plant. xop
137
144
updatestate! (plant, u, d)
138
145
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
+ )
141
151
end
142
152
143
153
@doc raw """
@@ -289,8 +299,11 @@ function sim_closedloop!(
289
299
x[:] += x_noise.* randn (plant. nx)
290
300
updatestate! (est_mpc, u, ym, d)
291
301
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
+ )
294
307
plant. x0 .= old_x0
295
308
return res
296
309
end
@@ -319,6 +332,13 @@ Plot the simulation results of a [`SimModel`](@ref).
319
332
- `plotu=true` : plot manipulated inputs ``\m athbf{u}``
320
333
- `plotd=true` : plot measured disturbances ``\m athbf{d}`` if applicable
321
334
- `plotx=false` : plot plant states ``\m athbf{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
+ ```
322
342
"""
323
343
plot (:: Nothing , :: SimResult{<:Real, <:SimModel} )
324
344
@@ -337,7 +357,7 @@ plot(::Nothing, ::SimResult{<:Real, <:SimModel})
337
357
uname = model. uname
338
358
yname = model. yname
339
359
dname = model. dname
340
- xname = model . xname
360
+ xname = res . xname
341
361
layout_mat = [(ny, 1 )]
342
362
plotu && (layout_mat = [layout_mat (nu, 1 )])
343
363
(plotd && nd ≠ 0 ) && (layout_mat = [layout_mat (nd, 1 )])
@@ -424,6 +444,13 @@ Plot the simulation results of a [`StateEstimator`](@ref).
424
444
- `plotx̂max=true` or *`plotxhatmax`* : plot estimated state upper bounds ``\m athbf{x̂_{max}}``
425
445
if applicable
426
446
- `<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
+ ```
427
454
"""
428
455
plot (:: Nothing , :: SimResult{<:Real, <:StateEstimator} )
429
456
@@ -454,7 +481,8 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
454
481
uname = model. uname
455
482
yname = model. yname
456
483
dname = model. dname
457
- xname = model. xname
484
+ x̂name = [model. xname; [" \$ x_{$i }\$ " for i in (nx+ 1 ): (nx̂)]]
485
+ xname = res. xname
458
486
layout_mat = [(ny, 1 )]
459
487
plotu && (layout_mat = [layout_mat (nu, 1 )])
460
488
(plotd && nd ≠ 0 ) && (layout_mat = [layout_mat (nd, 1 )])
@@ -541,7 +569,7 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
541
569
withPlantState = plotxwithx̂ && i ≤ nx
542
570
@series begin
543
571
i == nx̂ && (xguide --> " Time (s)" )
544
- yguide --> (withPlantState ? xname[i] : " \$\\ hat{x}_{ $i } \$ " )
572
+ yguide --> (withPlantState ? xname[i] : x̂name[i] )
545
573
color --> 2
546
574
subplot --> subplot_base + i
547
575
linestyle --> :dashdot
@@ -553,7 +581,7 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
553
581
if plotx̂min && ! isinf (X̂min[end - 2 * nx̂+ i])
554
582
@series begin
555
583
i == nx̂ && (xguide --> " Time (s)" )
556
- yguide --> (withPlantState ? xname[i] : " \$\\ hat{x}_{ $i } \$ " )
584
+ yguide --> (withPlantState ? xname[i] : x̂name[i] )
557
585
color --> 3
558
586
subplot --> subplot_base + i
559
587
linestyle --> :dot
@@ -566,7 +594,7 @@ plot(::Nothing, ::SimResult{<:Real, <:StateEstimator})
566
594
if plotx̂max && ! isinf (X̂max[end - 2 * nx̂+ i])
567
595
@series begin
568
596
i == nx̂ && (xguide --> " Time (s)" )
569
- yguide --> (withPlantState ? xname[i] : " \$\\ hat{x}_{ $i } \$ " )
597
+ yguide --> (withPlantState ? xname[i] : x̂name[i] )
570
598
color --> 4
571
599
subplot --> subplot_base + i
572
600
linestyle --> :dot
@@ -599,6 +627,15 @@ Plot the simulation results of a [`PredictiveController`](@ref).
599
627
- `<keyword arguments>` of [`plot(::SimResult{<:Real, <:SimModel})`](@ref)
600
628
- `<keyword arguments>` of [`plot(::SimResult{<:Real, <:StateEstimator})`](@ref)
601
629
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
+
602
639
"""
603
640
plot (:: Nothing , :: SimResult{<:Real, <:PredictiveController} )
604
641
@@ -635,7 +672,8 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
635
672
uname = model. uname
636
673
yname = model. yname
637
674
dname = model. dname
638
- xname = model. xname
675
+ x̂name = [model. xname; [" \$ x_{$i }\$ " for i in (nx+ 1 ): (nx̂)]]
676
+ xname = res. xname
639
677
layout_mat = [(ny, 1 )]
640
678
plotu && (layout_mat = [layout_mat (nu, 1 )])
641
679
(plotd && nd ≠ 0 ) && (layout_mat = [layout_mat (nd, 1 )])
@@ -803,7 +841,7 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
803
841
withPlantState = plotxwithx̂ && i ≤ nx
804
842
@series begin
805
843
i == nx̂ && (xguide --> " Time (s)" )
806
- yguide --> (withPlantState ? xname[i] : " \$\\ hat{x}_{ $i } \$ " )
844
+ yguide --> (withPlantState ? xname[i] : x̂name[i] )
807
845
color --> 2
808
846
subplot --> subplot_base + i
809
847
linestyle --> :dashdot
@@ -815,7 +853,7 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
815
853
if plotx̂min && ! isinf (X̂min[end - 2 * nx̂+ i])
816
854
@series begin
817
855
i == nx̂ && (xguide --> " Time (s)" )
818
- yguide --> (withPlantState ? xname[i] : " \$\\ hat{x}_{ $i } \$ " )
856
+ yguide --> (withPlantState ? xname[i] : x̂name[i] )
819
857
color --> 3
820
858
subplot --> subplot_base + i
821
859
linestyle --> :dot
@@ -828,7 +866,7 @@ plot(::Nothing, ::SimResult{<:Real, <:PredictiveController})
828
866
if plotx̂max && ! isinf (X̂max[end - 2 * nx̂+ i])
829
867
@series begin
830
868
i == nx̂ && (xguide --> " Time (s)" )
831
- yguide --> (withPlantState ? xname[i] : " \$\\ hat{x}_{ $i } \$ " )
869
+ yguide --> (withPlantState ? xname[i] : x̂name[i] )
832
870
color --> 4
833
871
subplot --> subplot_base + i
834
872
linestyle --> :dot
0 commit comments