Skip to content

Commit 9f7997c

Browse files
committed
handle variables marked as disturbance when building controlled dynamics
1 parent cf7ac66 commit 9f7997c

File tree

3 files changed

+32
-26
lines changed

3 files changed

+32
-26
lines changed

src/inputoutput.jl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ t = 0
188188
f[1](x, inputs, p, t)
189189
```
190190
"""
191-
function generate_control_function(sys::AbstractODESystem, inputs = unbound_inputs(sys), disturbance_inputs = nothing;
191+
function generate_control_function(sys::AbstractODESystem, inputs = unbound_inputs(sys),
192+
disturbance_inputs = disturbances(sys);
192193
implicit_dae = false,
193194
simplify = false,
194195
kwargs...)
@@ -329,7 +330,7 @@ The structure represents a model of a disturbance, along with the input variable
329330
- `model::M`: A model of the disturbance. This is typically an `ODESystem`, but type that implements [`ModelingToolkit.get_disturbance_system`](@ref)`(dist::DisturbanceModel) -> ::ODESystem` is supported.
330331
"""
331332
struct DisturbanceModel{M}
332-
input
333+
input::Any
333334
model::M
334335
end
335336

@@ -387,18 +388,17 @@ dist = ModelingToolkit.DisturbanceModel(model.torque.tau.u, dmodel)
387388
`f_oop` will have an extra state corresponding to the integrator in the disturbance model. This state will not be affected by any input, but will affect the dynamics from where it enters, in this case it will affect additively from `model.torque.tau.u`.
388389
"""
389390
function add_input_disturbance(sys, dist::DisturbanceModel)
390-
t = ModelingToolkit.get_iv(sys)
391-
@variables d(t)=0
392-
@variables u(t)=0 [input=true]
391+
t = get_iv(sys)
392+
@variables d(t)=0 [disturbance = true]
393+
@variables u(t)=0 [input = true]
393394
dsys = get_disturbance_system(dist)
394395

395-
eqs = [
396-
dsys.input.u[1] ~ d
397-
dist.input ~ u + dsys.output.u[1]
398-
]
396+
eqs = [dsys.input.u[1] ~ d
397+
dist.input ~ u + dsys.output.u[1]]
398+
399+
augmented_sys = ODESystem(eqs, t, systems = [sys, dsys], name = gensym(:outer))
399400

400-
augmented_sys = ODESystem(eqs, t, systems=[sys, dsys], name=gensym(:outer))
401-
402-
(f_oop, f_ip), dvs, p = ModelingToolkit.generate_control_function(augmented_sys, [u], [d])
401+
(f_oop, f_ip), dvs, p = generate_control_function(augmented_sys, [u],
402+
[d])
403403
(f_oop, f_ip), augmented_sys, dvs, p
404-
end
404+
end

src/variables.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ function isdisturbance(x)
158158
Symbolics.getmetadata(x, VariableDisturbance, false)
159159
end
160160

161+
function disturbances(sys)
162+
[filter(isdisturbance, states(sys)); filter(isdisturbance, parameters(sys))]
163+
end
164+
161165
## Tunable =====================================================================
162166
struct VariableTunable end
163167
Symbolics.option_to_metadata_type(::Val{:tunable}) = VariableTunable

test/input_output_handling.jl

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,6 @@ eqs = [Differential(t)(x) ~ u]
196196
@named sys = ODESystem(eqs, t)
197197
@test_nowarn structural_simplify(sys)
198198

199-
200-
201199
#=
202200
## Disturbance input handling
203201
We test that the generated disturbance dynamics is correct by calling the dynamics in two different points that differ in the disturbance state, and check that we get the same result as when we call the linearized dynamics in the same two points. The true system is linear so the linearized dynamics are exact.
@@ -222,15 +220,21 @@ c = 10 # Damping coefficient
222220
@named damper = Rotational.Damper(; d = c)
223221
@named torque = Rotational.Torque()
224222

225-
function SystemModel(u=nothing; name=:model)
226-
eqs = [
227-
connect(torque.flange, inertia1.flange_a)
228-
connect(inertia1.flange_b, spring.flange_a, damper.flange_a)
229-
connect(inertia2.flange_a, spring.flange_b, damper.flange_b)
230-
]
223+
function SystemModel(u = nothing; name = :model)
224+
eqs = [connect(torque.flange, inertia1.flange_a)
225+
connect(inertia1.flange_b, spring.flange_a, damper.flange_a)
226+
connect(inertia2.flange_a, spring.flange_b, damper.flange_b)]
231227
if u !== nothing
232228
push!(eqs, connect(torque.tau, u.output))
233-
return @named model = ODESystem(eqs, t; systems = [torque, inertia1, inertia2, spring, damper, u])
229+
return @named model = ODESystem(eqs, t;
230+
systems = [
231+
torque,
232+
inertia1,
233+
inertia2,
234+
spring,
235+
damper,
236+
u,
237+
])
234238
end
235239
ODESystem(eqs, t; systems = [torque, inertia1, inertia2, spring, damper], name)
236240
end
@@ -259,7 +263,5 @@ pn = ModelingToolkit.varmap_to_vars(def, p)
259263
xp0 = f_oop(x0, u, pn, 0)
260264
xp1 = f_oop(x1, u, pn, 0)
261265

262-
@test xp0 matrices.A*x0 + matrices.B*[u; 0]
263-
@test xp1 matrices.A*x1 + matrices.B*[u; 0]
264-
265-
266+
@test xp0 matrices.A * x0 + matrices.B * [u; 0]
267+
@test xp1 matrices.A * x1 + matrices.B * [u; 0]

0 commit comments

Comments
 (0)