Skip to content

Commit c0c6ae3

Browse files
authored
Merge pull request #110 from JuliaControl/mtk_corr
doc: MTK example throw error for non-strictly proper systems
2 parents 3d69e82 + 4f907e3 commit c0c6ae3

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

docs/src/manual/mtk.md

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,39 +60,61 @@ function generate_f_h(model, inputs, outputs)
6060
if any(ModelingToolkit.is_alg_equation, equations(io_sys))
6161
error("Systems with algebraic equations are not supported")
6262
end
63-
h_ = ModelingToolkit.build_explicit_observed_function(io_sys, outputs; inputs = inputs)
64-
nx = length(dvs)
63+
nu, nx, ny = length(inputs), length(dvs), length(outputs)
6564
vx = string.(dvs)
66-
par = varmap_to_vars(defaults(io_sys), psym)
67-
function f!(ẋ, x, u, _ , _ )
68-
f_ip(ẋ, x, u, par, 1)
69-
nothing
65+
p = varmap_to_vars(defaults(io_sys), psym)
66+
function f!(ẋ, x, u, _ , p)
67+
try
68+
f_ip(ẋ, x, u, p, nothing)
69+
catch err
70+
if err isa MethodError
71+
error("NonLinModel does not support a time argument t in the f function, "*
72+
"see the constructor docstring for a workaround.")
73+
else
74+
rethrow()
75+
end
76+
end
77+
return nothing
7078
end
71-
function h!(y, x, _ , _ )
72-
y .= h_(x, 1, par, 1)
73-
nothing
79+
h_ = ModelingToolkit.build_explicit_observed_function(io_sys, outputs; inputs)
80+
u_nothing = fill(nothing, nu)
81+
function h!(y, x, _ , p)
82+
y .= try
83+
# MTK.jl supports a `u` argument in `h_` function but not this package. We set
84+
# `u` as a vector of nothing and `h_` function will presumably throw an
85+
# MethodError it this argument is used inside the function
86+
h_(x, u_nothing, p, nothing)
87+
catch err
88+
if err isa MethodError
89+
error("NonLinModel only support strictly proper systems (no manipulated "*
90+
"input argument u in the output function h)")
91+
else
92+
rethrow()
93+
end
94+
end
95+
return nothing
7496
end
75-
return f!, h!, nx, vx
97+
return f!, h!, p, nu, nx, ny, vx
7698
end
7799
inputs, outputs = [mtk_model.τ], [mtk_model.y]
78-
f!, h!, nx, vx = generate_f_h(mtk_model, inputs, outputs)
79-
nu, ny, Ts = length(inputs), length(outputs), 0.1
100+
f!, h!, p, nu, nx, ny, vx = generate_f_h(mtk_model, inputs, outputs)
101+
Ts = 0.1
80102
vu, vy = ["\$τ\$ (Nm)"], ["\$θ\$ (°)"]
81103
nothing # hide
82104
```
83105

84106
A [`NonLinModel`](@ref) can now be constructed:
85107

86108
```@example 1
87-
model = setname!(NonLinModel(f!, h!, Ts, nu, nx, ny); u=vu, x=vx, y=vy)
109+
model = setname!(NonLinModel(f!, h!, Ts, nu, nx, ny; p); u=vu, x=vx, y=vy)
88110
```
89111

90112
We also instantiate a plant model with a 25 % larger friction coefficient ``K``:
91113

92114
```@example 1
93115
mtk_model.K = defaults(mtk_model)[mtk_model.K] * 1.25
94-
f_plant, h_plant, _, _ = generate_f_h(mtk_model, inputs, outputs)
95-
plant = setname!(NonLinModel(f_plant, h_plant, Ts, nu, nx, ny); u=vu, x=vx, y=vy)
116+
f_plant, h_plant, p = generate_f_h(mtk_model, inputs, outputs)
117+
plant = setname!(NonLinModel(f_plant, h_plant, Ts, nu, nx, ny; p); u=vu, x=vx, y=vy)
96118
```
97119

98120
## Controller Design

src/model/linmodel.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ function LinModel(
150150
sysu = sminreal(sys[:,i_u]) # remove states associated to measured disturbances d
151151
sysd = sminreal(sys[:,i_d]) # remove states associated to manipulates inputs u
152152
if !iszero(sysu.D)
153-
error("State matrix D must be 0 for columns associated to manipulated inputs u")
153+
error("LinModel only supports strictly proper systems (state matrix D must be 0 "*
154+
"for columns associated to manipulated inputs u)")
154155
end
155156
if iscontinuous(sys)
156157
isnothing(Ts) && error("Sample time Ts must be specified if sys is continuous")

src/model/solver.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ function get_solver_functions(NT::DataType, solver::RungeKutta, fc!, hc!, Ts, _
5454
k2 = get_tmp(k2_cache, var)
5555
k3 = get_tmp(k3_cache, var)
5656
k4 = get_tmp(k4_cache, var)
57+
xterm = xnext
5758
@. xcur = x
5859
for i=1:solver.supersample
59-
xterm = xnext # TODO: move this out of the loop, just above (to test) ?
6060
@. xterm = xcur
6161
fc!(k1, xterm, u, d, p)
6262
@. xterm = xcur + k1 * Ts_inner/2

0 commit comments

Comments
 (0)