@@ -13,75 +13,49 @@ struct SimResult{O<:Union{SimModel, StateEstimator, PredictiveController}}
1313end
1414
1515@doc raw """
16- sim!(plant::SimModel, N::Int, u=plant.uop.+1, d=plant.dop; <keyword arguments> )
16+ sim!(plant::SimModel, N::Int, u=plant.uop.+1, d=plant.dop; x0=zeros(plant.nx) )
1717
18- Open-loop simulation of `plant` for `N` time steps, default to input bumps .
18+ Open-loop simulation of `plant` for `N` time steps, default to unit bump test on all inputs .
1919
20- See Arguments for the available options. The noises are provided as standard deviations σ
21- vectors. The simulated sensor and process noises of ` plant` are specified by `y_noise` and
22- `x_noise` arguments, respectively . The function returns `SimResult` instances that can be
23- visualized by calling `plot` from [`Plots.jl`](https://github.com/JuliaPlots/Plots.jl) on
20+ The manipulated inputs `` \m athbf{u}`` and measured disturbances `` \m athbf{d}`` are held
21+ constant at `u` and `d` values, respectively. The plant initial state `` \m athbf{x}(0)`` is
22+ specified by `x0` keyword arguments . The function returns `SimResult` instances that can be
23+ visualized by calling `plot` from [`Plots.jl`](https://github.com/JuliaPlots/Plots.jl) on
2424them (see Examples below).
2525
26- # Arguments
27- - `plant::SimModel` : plant model to simulate.
28- - `N::Int` : simulation length in time steps.
29- - `u = estim.model.uop .+ 1` : manipulated input ``\m athbf{u}`` value.
30- - `d = estim.model.dop` : plant measured disturbance ``\m athbf{d}`` value.
31- - `u_step = zeros(plant.nu)` : step load disturbance on plant inputs ``\m athbf{u}``.
32- - `u_noise = zeros(plant.nu)` : additive gaussian noise on plant inputs ``\m athbf{u}``.
33- - `y_step = zeros(plant.ny)` : step disturbance on plant outputs ``\m athbf{y}``.
34- - `y_noise = zeros(plant.ny)` : additive gaussian noise on plant outputs ``\m athbf{y}``.
35- - `d_step = zeros(plant.nd)` : step on measured disturbances ``\m athbf{d}``.
36- - `d_noise = zeros(plant.nd)` : additive gaussian noise on measured dist. ``\m athbf{d}``.
37- - `x_noise = zeros(plant.nx)` : additive gaussian noise on plant states ``\m athbf{x}``.
38- - `x0 = zeros(plant.nx)` : plant initial state ``\m athbf{x}(0)``.
39-
4026# Examples
4127```julia-repl
42- julia> plant = NonLinModel((x,u,d)->0.1x+u+d, (x,_)->2x, 10, 1, 1, 1, 1);
28+ julia> plant = NonLinModel((x,u,d)->0.1x+u+d, (x,_)->2x, 10.0 , 1, 1, 1, 1);
4329
4430julia> res = sim!(plant, 15, [0], [0], x0=[1]);
4531
4632julia> using Plots; plot(res, plotu=false, plotd=false, plotx=true)
33+
4734```
4835"""
4936function sim! (
50- plant:: SimModel ,
37+ plant:: SimModel ,
5138 N:: Int ,
52- u:: Vector{<:Real} = plant. uop .+ 1 ,
53- d:: Vector{<:Real} = plant. dop;
54- u_step :: Vector{<:Real} = zeros (plant. nu),
55- u_noise:: Vector{<:Real} = zeros (plant. nu),
56- y_step :: Vector{<:Real} = zeros (plant. ny),
57- y_noise:: Vector{<:Real} = zeros (plant. ny),
58- d_step :: Vector{<:Real} = zeros (plant. nd),
59- d_noise:: Vector{<:Real} = zeros (plant. nd),
60- x_noise:: Vector{<:Real} = zeros (plant. nx),
39+ u:: Vector = plant. uop.+ 1 ,
40+ d:: Vector = plant. dop;
6141 x0 = zeros (plant. nx)
6242)
6343 T_data = collect (plant. Ts* (0 : (N- 1 )))
6444 Y_data = Matrix {Float64} (undef, plant. ny, N)
6545 U_data = Matrix {Float64} (undef, plant. nu, N)
66- Ud_data = Matrix {Float64} (undef, plant. nu, N)
6746 D_data = Matrix {Float64} (undef, plant. nd, N)
6847 X_data = Matrix {Float64} (undef, plant. nx, N)
6948 setstate! (plant, x0)
70- d0 = d
7149 for i= 1 : N
72- d = d0 + d_step + d_noise.* randn (plant. nd)
73- y = evaloutput (plant, d) + y_step + y_noise.* randn (plant. ny)
74- ud = u + u_step + u_noise.* randn (plant. nu)
50+ y = evaloutput (plant, d)
7551 Y_data[:, i] = y
7652 U_data[:, i] = u
77- Ud_data[:, i] = ud
7853 D_data[:, i] = d
7954 X_data[:, i] = plant. x
80- x = updatestate! (plant, ud, d);
81- x[:] += x_noise.* randn (plant. nx)
55+ updatestate! (plant, u, d);
8256 end
8357 return SimResult (
84- T_data, Y_data, U_data, Y_data, U_data, Ud_data , D_data, X_data, X_data, plant
58+ T_data, Y_data, U_data, Y_data, U_data, U_data , D_data, X_data, X_data, plant
8559 )
8660end
8761
9670
9771Closed-loop simulation of `estim` estimator for `N` time steps, default to input bumps.
9872
99- See Arguments for the available options.
73+ See Arguments for the available options. The noises are provided as standard deviations σ
74+ vectors. The simulated sensor and process noises of `plant` are specified by `y_noise` and
75+ `x_noise` arguments, respectively.
10076
10177# Arguments
10278- `estim::StateEstimator` : state estimator to simulate.
10379- `N::Int` : simulation length in time steps.
10480- `u = estim.model.uop .+ 1` : manipulated input ``\m athbf{u}`` value.
10581- `d = estim.model.dop` : plant measured disturbance ``\m athbf{d}`` value.
10682- `plant::SimModel = estim.model` : simulated plant model.
83+ - `u_step = zeros(plant.nu)` : step load disturbance on plant inputs ``\m athbf{u}``.
84+ - `u_noise = zeros(plant.nu)` : gaussian load disturbance on plant inputs ``\m athbf{u}``.
85+ - `y_step = zeros(plant.ny)` : step disturbance on plant outputs ``\m athbf{y}``.
86+ - `y_noise = zeros(plant.ny)` : additive gaussian noise on plant outputs ``\m athbf{y}``.
87+ - `d_step = zeros(plant.nd)` : step on measured disturbances ``\m athbf{d}``.
88+ - `d_noise = zeros(plant.nd)` : additive gaussian noise on measured dist. ``\m athbf{d}``.
89+ - `x_noise = zeros(plant.nx)` : additive gaussian noise on plant states ``\m athbf{x}``.
90+ - `x0 = zeros(plant.nx)` : plant initial state ``\m athbf{x}(0)``.
10791- `x̂0 = nothing` : `mpc.estim` state estimator initial state ``\m athbf{x̂}(0)``, if `nothing`
10892 then ``\m athbf{x̂}`` is initialized with [`initstate!`](@ref).
10993- `lastu = plant.uop` : last plant input ``\m athbf{u}`` for ``\m athbf{x̂}`` initialization.
110- - `<keyword arguments>` of [`sim!(::SimModel, ::Int)`](@ref).
11194
11295# Examples
11396```julia-repl
@@ -118,19 +101,19 @@ julia> estim = SteadyKalmanFilter(model, σR=[0.5], σQ=[0.25], σQ_int=[0.01]);
118101julia> res = sim!(estim, 50, [0], y_noise=[0.5], x_noise=[0.25], x0=[-10], x̂0=[0, 0]);
119102
120103julia> using Plots; plot(res, plotŷ=true, plotu=false, plotx=true, plotx̂=true)
104+
121105```
122106"""
123107function sim! (
124108 estim:: StateEstimator ,
125109 N:: Int ,
126- u:: Vector{<:Real} = estim. model. uop .+ 1 ,
127- d:: Vector{<:Real} = estim. model. dop;
110+ u:: Vector = estim. model. uop .+ 1 ,
111+ d:: Vector = estim. model. dop;
128112 kwargs...
129113)
130114 return sim_closedloop! (estim, estim, N, u, d; kwargs... )
131115end
132116
133-
134117@doc raw """
135118 sim!(
136119 mpc::PredictiveController,
142125
143126Closed-loop simulation of `mpc` controller for `N` time steps, default to setpoint bumps.
144127
145- The argument `ry` is output setpoint ``\m athbf{r_y}`` value applied at ``t = 0`` . The
146- keyword arguments are identical to [`sim!(::StateEstimator, ::Int)`](@ref).
128+ The output setpoints ``\m athbf{r_y}`` are held constant at `r_y` . The keyword arguments are
129+ identical to [`sim!(::StateEstimator, ::Int)`](@ref).
147130
148131# Examples
149132```julia-repl
@@ -154,34 +137,34 @@ julia> mpc = setconstraint!(LinMPC(model, Mwt=[0, 1], Nwt=[0.01], Hp=30), ŷmin
154137julia> res = sim!(mpc, 25, [0, 0], y_noise=[0.1], y_step=[-10, 0]);
155138
156139julia> using Plots; plot(res, plotry=true, plotŷ=true, plotŷmin=true, plotu=true)
140+
157141```
158142"""
159143function sim! (
160144 mpc:: PredictiveController ,
161145 N:: Int ,
162- ry:: Vector{<:Real} = mpc. estim. model. yop .+ 1 ,
163- d :: Vector{<:Real} = mpc. estim. model. dop;
146+ ry:: Vector = mpc. estim. model. yop .+ 1 ,
147+ d :: Vector = mpc. estim. model. dop;
164148 kwargs...
165149)
166150 return sim_closedloop! (mpc, mpc. estim, N, ry, d; kwargs... )
167151end
168152
169-
170153" Quick simulation function for `StateEstimator` and `PredictiveController` instances."
171154function sim_closedloop! (
172155 est_mpc:: Union{StateEstimator, PredictiveController} ,
173156 estim:: StateEstimator ,
174157 N:: Int ,
175- u_ry:: Vector{<:Real} ,
176- d:: Vector{<:Real} ;
158+ u_ry:: Vector ,
159+ d:: Vector ;
177160 plant:: SimModel = estim. model,
178- u_step :: Vector{<:Real} = zeros (plant. nu),
179- u_noise:: Vector{<:Real} = zeros (plant. nu),
180- y_step :: Vector{<:Real} = zeros (plant. ny),
181- y_noise:: Vector{<:Real} = zeros (plant. ny),
182- d_step :: Vector{<:Real} = zeros (plant. nd),
183- d_noise:: Vector{<:Real} = zeros (plant. nd),
184- x_noise:: Vector{<:Real} = zeros (plant. nx),
161+ u_step :: Vector = zeros (plant. nu),
162+ u_noise:: Vector = zeros (plant. nu),
163+ y_step :: Vector = zeros (plant. ny),
164+ y_noise:: Vector = zeros (plant. ny),
165+ d_step :: Vector = zeros (plant. nd),
166+ d_noise:: Vector = zeros (plant. nd),
167+ x_noise:: Vector = zeros (plant. nx),
185168 x0 = zeros (plant. nx),
186169 x̂0 = nothing ,
187170 lastu = plant. uop,
@@ -230,9 +213,12 @@ function sim_closedloop!(
230213 return res
231214end
232215
216+ " Keep manipulated input `u` unchanged for state estimator simulation."
233217sim_getu! (:: StateEstimator , u, _ , _ ) = u
218+ " Compute new `u` for predictive controller simulation."
234219sim_getu! (mpc:: PredictiveController , ry, d, ym) = moveinput! (mpc, ry, d; ym)
235220
221+ " Plots.jl recipe for `SimResult` objects constructed with `SimModel` objects."
236222@recipe function simresultplot (
237223 res:: SimResult{<:SimModel} ;
238224 plotu = true ,
@@ -308,6 +294,7 @@ sim_getu!(mpc::PredictiveController, ry, d, ym) = moveinput!(mpc, ry, d; ym)
308294 end
309295end
310296
297+ " Plots.jl recipe for `SimResult` objects constructed with `StateEstimator` objects."
311298@recipe function simresultplot (
312299 res:: SimResult{<:StateEstimator} ;
313300 plotŷ = true ,
414401 end
415402end
416403
404+ " Plots.jl recipe for `SimResult` objects constructed with `PredictiveController` objects."
417405@recipe function simresultplot (
418406 res:: SimResult{<:PredictiveController} ;
419407 plotry = true ,
0 commit comments