Skip to content

Commit 66e600b

Browse files
committed
removed evaloutput for InternalModel
useless public method, internal method `evalŷ` does the job
1 parent 36aa43c commit 66e600b

File tree

12 files changed

+113
-29
lines changed

12 files changed

+113
-29
lines changed

docs/src/internals/sim_model.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
Pages = ["sim_model.md"]
55
```
66

7+
## Steady-State Calculation
8+
9+
```@docs
10+
ModelPredictiveControl.steadystate!
11+
```
12+
13+
## State-Space Functions
14+
715
```@docs
816
ModelPredictiveControl.f
917
ModelPredictiveControl.h

docs/src/internals/state_estim.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ ModelPredictiveControl.f̂
2121
ModelPredictiveControl.ĥ
2222
```
2323

24+
## Evaluate Estimated Output
25+
26+
```@docs
27+
ModelPredictiveControl.evalŷ
28+
```
29+
2430
## Remove Operating Points
2531

2632
```@docs

docs/src/manual/linmpc.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# [Manual: Linear Design](@id man_lin)
22

3+
```@contents
4+
Pages = ["linmpc.md"]
5+
```
6+
37
## Linear Model
48

59
The example considers a continuously stirred-tank reactor (CSTR) with a cold and hot water

docs/src/manual/nonlinmpc.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# [Manual: Nonlinear Design](@id man_nonlin)
22

3+
```@contents
4+
Pages = ["nonlinmpc.md"]
5+
```
6+
37
## Nonlinear Model
48

59
In this example, the goal is to control the angular position ``θ`` of a pendulum

src/estimator/internal_model.jl

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,16 @@ matrices_internalmodel(::SimModel) = tuple(fill(zeros(0, 0), 5)...)
135135
@doc raw"""
136136
f̂(estim::InternalModel, x̂, u, d)
137137
138-
State function ``\mathbf{f̂}`` of the [`InternalModel`].
138+
State function ``\mathbf{f̂}`` of [`InternalModel`](@ref).
139139
140-
It calls `f(estim.model, x̂, u ,d)` since this estimator does not augment the state vector.
140+
It calls [`f(estim.model, x̂, u ,d)`](@ref) since this estimator does not augment the states.
141141
"""
142142
(estim::InternalModel, x̂, u, d) = f(estim.model, x̂, u, d)
143143

144144
@doc raw"""
145145
ĥ(estim::InternalModel, x̂, d)
146146
147-
Output function ``\mathbf{ĥ}`` of the [`InternalModel`], it calls `h(estim.model, x̂, d)`.
147+
Output function ``\mathbf{ĥ}`` of [`InternalModel`](@ref), it calls [`h`](@ref) directly.
148148
"""
149149
(estim::InternalModel, x̂, d) = h(estim.model, x̂, d)
150150

@@ -221,21 +221,6 @@ function initstate_post!(estim::InternalModel)
221221
return nothing
222222
end
223223

224-
@doc raw"""
225-
evaloutput(estim::InternalModel, ym, d=Float64[]) -> ŷ
226-
227-
Evaluate `InternalModel` outputs `ŷ` from `estim.x̂d` states and measured outputs `ym`.
228-
229-
[`InternalModel`](@ref) estimator needs current measured outputs ``\mathbf{y^m}(k)`` to
230-
estimate its outputs ``\mathbf{ŷ}(k)``, since the strategy imposes that
231-
``\mathbf{ŷ^m}(k) = \mathbf{y^m}(k)`` is always true.
232-
"""
233-
function evaloutput(estim::InternalModel, ym, d=Float64[])
234-
= h(estim.model, estim.x̂d, d - estim.model.dop) + estim.model.yop
235-
ŷ[estim.i_ym] = ym
236-
return
237-
end
238-
239224
"Print InternalModel information without i/o integrators."
240225
function print_estim_dim(io::IO, estim::InternalModel, n)
241226
nu, nd = estim.model.nu, estim.model.nd

src/model/linmodel.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,26 @@ is not called). Care must be taken to ensure that the model is controllable and
193193
"""
194194
LinModel(A, Bu, C, Bd, Dd, Ts, nu, nx, ny, nd)
195195

196+
197+
@doc raw"""
198+
steadystate!(model::LinModel, u, d)
199+
200+
Set `model.x` to `u` and `d` steady-state if `model` is a [`LinModel`](@ref).
201+
202+
Following [`setop!`](@ref) notation, the method evaluates the equilibrium ``\mathbf{x}``
203+
from:
204+
```math
205+
\mathbf{x} = \mathbf{(I - A)^{-1}(B_u u_0 + B_d d_0)}
206+
```
207+
with constant manipulated inputs ``\mathbf{u_0 = u - u_{op}}`` and measured
208+
disturbances ``\mathbf{d_0 = d - d_{op}}``. The Moore-Penrose pseudo-inverse computes
209+
``\mathbf{(I - A)^{-1}}`` to support integrating `model` (integrator states will be 0).
210+
"""
211+
function steadystate!(model::LinModel, u, d)
212+
model.x[:] = pinv(I - model.A)*(model.Bu*(u - model.uop) + model.Bd*(d - model.dop))
213+
return nothing
214+
end
215+
196216
"""
197217
f(model::LinModel, x, u, d)
198218

src/model/nonlinmodel.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ function validate_fcts(f, h)
8787
end
8888
end
8989

90+
"Do nothing if `model` is a [`NonLinModel`](@ref)."
91+
steadystate!(::SimModel, _ , _ ) = nothing
92+
93+
9094
"Call ``\\mathbf{f(x, u, d)}`` with `model.f` function for [`NonLinModel`](@ref)."
9195
f(model::NonLinModel, x, u, d) = model.f(x, u, d)
9296

src/precompile_calls.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ y = model()
66

77
mpc_im = setconstraint!(LinMPC(InternalModel(model)), ymin=[45, -Inf])
88
initstate!(mpc_im, model.uop, y)
9-
mpc_im.estim([50, 30])
109
u = mpc_im([55, 30], ym=y)
1110
sim!(mpc_im, 3)
1211

src/sim_model.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,34 @@ function Base.show(io::IO, model::SimModel)
9898
print(io, "$(lpad(nd, n)) measured disturbances d")
9999
end
100100

101+
@doc raw"""
102+
initstate!(model::SimModel, u, d=Float64[]) -> x
103+
104+
Init `model.x` with manipulated inputs `u` and measured disturbances `d` steady-state.
105+
106+
It calls [`steadystate!(u, d)`](@ref):
107+
108+
- If `estim.model` is a [`LinModel`](@ref), the method computes the steady-state of current
109+
inputs `u` and measured disturbances `d`.
110+
- Else, `model.x` is left unchanged. Use [`setstate!`](@ref) to manually modify it.
111+
112+
# Examples
113+
```jldoctest
114+
julia> model = LinModel(tf(6, [10, 1]), 2.0);
115+
116+
julia> u = [1]; x = initstate!(model, u); y = round.(evaloutput(model), digits=3)
117+
1-element Vector{Float64}:
118+
6.0
119+
julia> x ≈ updatestate!(model, u)
120+
true
121+
```
122+
123+
"""
124+
function initstate!(model::SimModel, u, d=Float64[])
125+
steadystate!(model, u, d)
126+
return model.x
127+
end
128+
101129
"""
102130
updatestate!(model::SimModel, u, d=Float64[]) -> x
103131

src/state_estim.jl

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,9 @@ The method tries to find a good stead-state for the initial esitmate ``\mathbf{x
296296
removes the operating points with [`remove_op!`](@ref) and call [`init_estimate!`](@ref):
297297
298298
- If `estim.model` is a [`LinModel`](@ref), it finds the steady-state of the augmented model
299-
using `u` and `d` arguments, and uses the `ym` argument to enforce that ``\mathbf{ŷ^m} =
300-
\mathbf{y^m}``. For control applications, this solution produces a bumpless manual to
301-
automatic transfer. See [`init_estimate!`](@ref) for details.
299+
using `u` and `d` arguments, and uses the `ym` argument to enforce that
300+
``\mathbf{ŷ^m}(0) = \mathbf{y^m}(0)``. For control applications, this solution produces a
301+
bumpless manual to automatic transfer. See [`init_estimate!`](@ref) for details.
302302
- Else, `estim.x̂` is left unchanged. Use [`setstate!`](@ref) to manually modify it.
303303
304304
If applicable, it also sets the error covariance `estim.P̂` to ``\mathbf{P̂}(0)``.
@@ -414,7 +414,27 @@ include("estimator/kalman.jl")
414414
include("estimator/luenberger.jl")
415415
include("estimator/internal_model.jl")
416416

417-
"Get [`InternalModel`](@ref) output `ŷ` from current measured outputs `ym` and dist. `d`."
418-
evalŷ(estim::InternalModel, ym, d) = evaloutput(estim,ym, d)
419-
"Other [`StateEstimator`](@ref) ignores `ym` to evaluate `ŷ`."
420-
evalŷ(estim::StateEstimator, _, d) = evaloutput(estim, d)
417+
"""
418+
evalŷ(estim::StateEstimator, _ , d) -> ŷ
419+
420+
Evaluate [`StateEstimator`](@ref) output `ŷ` from measured disturbance `d` and `estim.x̂`.
421+
422+
Second argument is ignored, except for [`InternalModel`](@ref).
423+
"""
424+
evalŷ(estim::StateEstimator, _ , d) = evaloutput(estim, d)
425+
426+
@doc raw"""
427+
evalŷ(estim::InternalModel, ym, d) -> ŷ
428+
429+
Get [`InternalModel`](@ref) output `ŷ` from current measured outputs `ym` and dist. `d`.
430+
431+
[`InternalModel`](@ref) estimator needs current measured outputs ``\mathbf{y^m}(k)`` to
432+
estimate its outputs ``\mathbf{ŷ}(k)``, since the strategy imposes that
433+
``\mathbf{ŷ^m}(k) = \mathbf{y^m}(k)`` is always true.
434+
"""
435+
function evalŷ(estim::InternalModel, ym, d)
436+
= h(estim.model, estim.x̂d, d - estim.model.dop) + estim.model.yop
437+
ŷ[estim.i_ym] = ym
438+
return
439+
end
440+

0 commit comments

Comments
 (0)