You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/inputoutput.jl
+112-4Lines changed: 112 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -160,15 +160,24 @@ has_var(ex, x) = x ∈ Set(get_variables(ex))
160
160
# Build control function
161
161
162
162
"""
163
-
(f_oop, f_ip), dvs, p = generate_control_function(sys::AbstractODESystem, inputs = unbound_inputs(sys); implicit_dae = false, ddvs = if implicit_dae
163
+
(f_oop, f_ip), dvs, p = generate_control_function(
164
+
sys::AbstractODESystem,
165
+
inputs = unbound_inputs(sys),
166
+
disturbance_inputs = nothing;
167
+
implicit_dae = false,
168
+
simplify = false,
169
+
)
164
170
165
171
For a system `sys` with inputs (as determined by [`unbound_inputs`](@ref) or user specified), generate a function with additional input argument `in`
166
172
```
167
-
f_oop : (u,in,p,t) -> rhs
168
-
f_ip : (uout,u,in,p,t) -> nothing
173
+
f_oop : (x,u,p,t) -> rhs
174
+
f_ip : (xout,x,u,p,t) -> nothing
169
175
```
170
176
The return values also include the remaining states and parameters, in the order they appear as arguments to `f`.
171
177
178
+
If `disturbance_inputs` is an array of variables, the generated dynamics function will preserve any state and dynamics associated with distrubance inputs, but the distrubance inputs themselves will not be included as inputs to the generated function. The use case for this is to generate dynamics for state observers that estimate the influence of unmeasured disturbances, and thus require state variables for the disturbance model, but without disturbance inputs since the disturbances are not available for measurement.
179
+
See [`add_input_disturbance`](@ref) for a higher-level interface to this functionality.
180
+
172
181
# Example
173
182
```
174
183
using ModelingToolkit: generate_control_function, varmap_to_vars, defaults
The structure represents a model of a disturbance, along with the input variable that is affected by the disturbance. See [`add_input_disturbance`](@ref) for additional details and an example.
327
+
328
+
# Fields:
329
+
- `input`: The variable affected by the disturbance.
330
+
- `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.
331
+
"""
332
+
struct DisturbanceModel{M}
333
+
input::Any
334
+
model::M
335
+
end
336
+
337
+
# Point of overloading for libraries, e.g., to be able to support disturbance models from ControlSystemsBase
(f_oop, f_ip), augmented_sys, dvs, p = add_input_disturbance(sys, dist::DisturbanceModel)
344
+
345
+
Add a model of an unmeasured disturbance to `sys`. The disturbance model is an instance of [`DisturbanceModel`](@ref).
346
+
347
+
The generated dynamics functions `(f_oop, f_ip)` will preserve any state and dynamics associated with disturbance inputs, but the disturbance inputs themselves will not be included as inputs to the generated function. The use case for this is to generate dynamics for state observers that estimate the influence of unmeasured disturbances, and thus require state variables for the disturbance model, but without disturbance inputs since the disturbances are not available for measurement.
348
+
349
+
`dvs` will be the states of the simplified augmented system, consisting of the states of `sys` as well as the states of the disturbance model.
350
+
351
+
# Example
352
+
The example below builds a double-mass model and adds an integrating disturbance to the input
353
+
```julia
354
+
using ModelingToolkit
355
+
using ModelingToolkitStandardLibrary.Mechanical.Rotational
(f_oop, f_ip), augmented_sys, dvs, p = ModelingToolkit.add_input_disturbance(model, dist)
387
+
```
388
+
`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`.
Copy file name to clipboardExpand all lines: test/input_output_handling.jl
+74-4Lines changed: 74 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -140,21 +140,21 @@ function Mass(; name, m = 1.0, p = 0, v = 0)
140
140
ODESystem(eqs, t, [pos, vel, y], ps; name)
141
141
end
142
142
143
-
functionSpring(; name, k =1e4)
143
+
functionMySpring(; name, k =1e4)
144
144
ps =@parameters k = k
145
145
@variablesx(t) =0# Spring deflection
146
146
ODESystem(Equation[], t, [x], ps; name)
147
147
end
148
148
149
-
functionDamper(; name, c =10)
149
+
functionMyDamper(; name, c =10)
150
150
ps =@parameters c = c
151
151
@variablesvel(t) =0
152
152
ODESystem(Equation[], t, [vel], ps; name)
153
153
end
154
154
155
155
functionSpringDamper(; name, k =false, c =false)
156
-
spring =Spring(; name =:spring, k)
157
-
damper =Damper(; name =:damper, c)
156
+
spring =MySpring(; name =:spring, k)
157
+
damper =MyDamper(; name =:damper, c)
158
158
compose(ODESystem(Equation[], t; name),
159
159
spring, damper)
160
160
end
@@ -195,3 +195,73 @@ i = findfirst(isequal(u[1]), out)
195
195
eqs = [Differential(t)(x) ~ u]
196
196
@named sys =ODESystem(eqs, t)
197
197
@test_nowarnstructural_simplify(sys)
198
+
199
+
#=
200
+
## Disturbance input handling
201
+
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.
202
+
203
+
The test below builds a double-mass model and adds an integrating disturbance to the input
204
+
=#
205
+
206
+
using ModelingToolkit
207
+
using ModelingToolkitStandardLibrary.Mechanical.Rotational
0 commit comments