Skip to content

Commit 49215a0

Browse files
committed
update to MTKv10
1 parent 758ea1f commit 49215a0

File tree

3 files changed

+46
-167
lines changed

3 files changed

+46
-167
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ControlSystemsMTK"
22
uuid = "687d7614-c7e5-45fc-bfc3-9ee385575c88"
33
authors = ["Fredrik Bagge Carlson"]
4-
version = "2.3.2"
4+
version = "2.4.0"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
@@ -17,7 +17,7 @@ UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
1717
[compat]
1818
ControlSystemsBase = "1.0.1"
1919
DataInterpolations = "3, 4, 5, 6, 7"
20-
ModelingToolkit = "9.61"
20+
ModelingToolkit = "10.0"
2121
ModelingToolkitStandardLibrary = "2"
2222
MonteCarloMeasurements = "1.1"
2323
RobustAndOptimalControl = "0.4.14"

src/ode_system.jl

Lines changed: 22 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ const AP = Union{Symbol, AnalysisPoint}
33
import ModelingToolkitStandardLibrary.Blocks as Blocks
44
conn = ModelingToolkit.connect
55
t = Blocks.t
6-
ModelingToolkit.ODESystem(sys::LTISystem; kwargs...) = ODESystem(ss(sys); kwargs...)
6+
ModelingToolkit.System(sys::LTISystem; kwargs...) = System(ss(sys); kwargs...)
77

88
"""
9-
ModelingToolkit.ODESystem(sys::AbstractStateSpace; name::Symbol, x0 = zeros(sys.nx), x_names, u_names, y_names)
9+
ModelingToolkit.System(sys::AbstractStateSpace; name::Symbol, x0 = zeros(sys.nx), x_names, u_names, y_names)
1010
11-
Create an ODESystem from `sys::StateSpace`.
11+
Create an System from `sys::StateSpace`.
1212
1313
# Arguments:
1414
- `sys`: An instance of `StateSpace` or `NamedStateSpace`.
@@ -19,7 +19,7 @@ The arguments below are automatically set if the system is a `NamedStateSpace`.
1919
- `u_names`: A vector of symbols with input names.
2020
- `y_names`: A vector of symbols with output names.
2121
"""
22-
function ModelingToolkit.ODESystem(
22+
function ModelingToolkit.System(
2323
sys::AbstractStateSpace;
2424
name::Symbol,
2525
x0 = zeros(sys.nx),
@@ -39,112 +39,14 @@ function ModelingToolkit.ODESystem(
3939
[uc[i].u ~ input.u[i] for i in 1:length(uc)];
4040
[yc[i].u ~ output.u[i] for i in 1:length(yc)];
4141
]
42-
extend(ODESystem(eqs, t; name, systems), ssblock)
43-
end
44-
45-
"""
46-
sconnect(input::Function, sys::T; name)
47-
sconnect(input::Num, sys::T; name)
48-
49-
Connect a function `input(t)` to `sys.input`
50-
51-
# Examples:
52-
```julia
53-
sconnect(sin, sys) # Connect a funciton, assumed to be a function of time
54-
sconnect(sin(t), sys) # Connect a Num
55-
```
56-
"""
57-
function sconnect(
58-
input::Union{Function, Num},
59-
sys::T;
60-
name = Symbol("$(sys.name) with input"),
61-
) where {T<:ModelingToolkit.AbstractTimeDependentSystem}
62-
@named output = Blocks.RealOutput()
63-
T(
64-
[
65-
sys.input.u ~ (input isa Num ? input : input(t))
66-
output.u ~ sys.output.u
67-
],
68-
t;
69-
systems = [sys, output],
70-
name,
71-
)
72-
end
73-
74-
"""
75-
sconnect(sys1::T, sys2::T; name)
76-
77-
Connect systems in series, equivalent to `sys2*sys1` or `series(sys1, sys2)` in ControlSystems.jl terminology
78-
"""
79-
function sconnect(
80-
sys1::T,
81-
sys2::T;
82-
name = Symbol("$(sys1.name)*$(sys2.name)"),
83-
) where {T<:ModelingToolkit.AbstractTimeDependentSystem}
84-
@named output = Blocks.RealOutput() # TODO: missing size
85-
@named input = Blocks.RealInput() # TODO: missing size
86-
T(
87-
[
88-
conn(input, sys2.input)
89-
conn(output, sys1.output)
90-
conn(sys2.output, sys1.input)
91-
],
92-
t;
93-
name,
94-
systems = [sys1, sys2, output, input],
95-
)
96-
end
97-
98-
"""
99-
G = ControlSystemsBase.feedback(loopgain::T; name)
100-
101-
Form the feedback-interconnection
102-
\$G = L/(1+L)\$
103-
104-
The system `G` will be a new system with `input` and `output` connectors.
105-
"""
106-
function ControlSystemsBase.feedback(
107-
loopgain::T;
108-
name = Symbol("feedback $(loopgain.name)"),
109-
) where {T<:ModelingToolkit.AbstractTimeDependentSystem}
110-
add = Blocks.Add(k1 = 1, k2 = -1, name = :feedback)
111-
@named input = Blocks.RealInput()
112-
@named output = Blocks.RealOutput()
113-
T(
114-
[
115-
input.u ~ add.input1.u
116-
output.u ~ loopgain.output.u
117-
conn(loopgain.output, add.input2)
118-
conn(add.output, loopgain.input)
119-
],
120-
t;
121-
systems = [input, output, loopgain, add],
122-
name,
123-
)
124-
end
125-
126-
function Base.:(*)(s1::T, s2::T) where {T<:ModelingToolkit.AbstractTimeDependentSystem}
127-
name = Symbol(string(s1.name) * "_" * string(s2.name))
128-
@named input = Blocks.RealInput()
129-
@named output = Blocks.RealOutput()
130-
eqs = [
131-
conn(s1.input, s2.output)
132-
output.u ~ s1.output.u
133-
]
134-
systems = [output, s1, s2]
135-
if any(s.name == :input for s in s2.systems)
136-
push!(eqs, input.u ~ s2.input.u)
137-
push!(systems, input)
138-
end
139-
T(eqs, t; systems, name)
42+
extend(System(eqs, t; name, systems), ssblock)
14043
end
14144

14245

14346
numeric(x::Num) = x.val
14447

145-
14648
function ControlSystemsBase.ss(
147-
sys::ModelingToolkit.AbstractTimeDependentSystem,
49+
sys::ModelingToolkit.AbstractSystem,
14850
inputs,
14951
outputs;
15052
kwargs...
@@ -154,9 +56,9 @@ end
15456

15557

15658
"""
157-
RobustAndOptimalControl.named_ss(sys::ModelingToolkit.AbstractTimeDependentSystem, inputs, outputs; descriptor=true, kwargs...)
59+
RobustAndOptimalControl.named_ss(sys::ModelingToolkit.AbstractSystem, inputs, outputs; descriptor=true, kwargs...)
15860
159-
Convert an `ODESystem` to a `NamedStateSpace` using linearization. `inputs, outputs` are vectors of variables determining the inputs and outputs respectively. See docstring of `ModelingToolkit.linearize` for more info on `kwargs`.
61+
Convert an `System` to a `NamedStateSpace` using linearization. `inputs, outputs` are vectors of variables determining the inputs and outputs respectively. See docstring of `ModelingToolkit.linearize` for more info on `kwargs`.
16062
16163
If `descriptor = true` (default), this method automatically converts systems that MTK has failed to produce a proper form for into a proper linear statespace system using the method described here:
16264
https://juliacontrol.github.io/ControlSystemsMTK.jl/dev/#Internals:-Transformation-of-non-proper-models-to-proper-statespace-form
@@ -166,7 +68,7 @@ If `descriptor = false`, the system is instead converted to a statespace realiza
16668
See also [`ModelingToolkit.linearize`](@ref) which is the lower-level function called internally. The functions [`get_named_sensitivity`](@ref), [`get_named_comp_sensitivity`](@ref), [`get_named_looptransfer`](@ref) similarily provide convenient ways to compute sensitivity functions while retaining signal names in the same way as `named_ss`. The corresponding lower-level functions `get_sensitivity`, `get_comp_sensitivity` and `get_looptransfer` are available in ModelingToolkitStandardLibrary.Blocks and are documented in [MTKstdlib: Linear analysis](https://docs.sciml.ai/ModelingToolkitStandardLibrary/stable/API/linear_analysis/).
16769
"""
16870
function RobustAndOptimalControl.named_ss(
169-
sys::ModelingToolkit.AbstractTimeDependentSystem,
71+
sys::ModelingToolkit.AbstractSystem,
17072
inputs,
17173
outputs;
17274
descriptor = true,
@@ -177,12 +79,12 @@ function RobustAndOptimalControl.named_ss(
17779
outputs = vcat(outputs)
17880

17981
inputs = map(inputs) do inp
180-
if inp isa ODESystem
82+
if inp isa System
18183
@variables u(t)
18284
if u Set(unknowns(inp))
18385
inp.u
18486
else
185-
error("Input $(inp.name) is an ODESystem and not a variable")
87+
error("Input $(inp.name) is an System and not a variable")
18688
end
18789
else
18890
inp
@@ -191,12 +93,12 @@ function RobustAndOptimalControl.named_ss(
19193
nu = length(inputs)
19294

19395
outputs = map(outputs) do out
194-
if out isa ODESystem
96+
if out isa System
19597
@variables u(t)
19698
if u Set(unknowns(out))
19799
out.u
198100
else
199-
error("Outut $(out.name) is an ODESystem and not a variable")
101+
error("Outut $(out.name) is an System and not a variable")
200102
end
201103
else
202104
out
@@ -286,19 +188,19 @@ get_named_looptransfer
286188

287189
function named_sensitivity_function(
288190
fun,
289-
sys::ModelingToolkit.AbstractTimeDependentSystem,
191+
sys::ModelingToolkit.AbstractSystem,
290192
inputs, args...;
291193
kwargs...,
292194
)
293195

294196
inputs = vcat(inputs)
295197
inputs = map(inputs) do inp
296-
if inp isa ODESystem
198+
if inp isa System
297199
@variables u(t)
298200
if u Set(unknowns(inp))
299201
inp.u
300202
else
301-
error("Input $(inp.name) is an ODESystem and not a variable")
203+
error("Input $(inp.name) is an System and not a variable")
302204
end
303205
else
304206
inp
@@ -347,7 +249,7 @@ if isdefined(ModelingToolkit, :get_disturbance_system)
347249
end
348250

349251
"""
350-
build_quadratic_cost_matrix(linear_sys, ssys::ODESystem, costs::Vector{Pair})
252+
build_quadratic_cost_matrix(linear_sys, ssys::System, costs::Vector{Pair})
351253
352254
For a system that has been linearized, assemble a quadratic cost matrix (for LQR or Kalman filtering) that penalizes states or outputs of simplified system `ssys` according to the vector of pairs `costs`.
353255
@@ -362,7 +264,7 @@ The second problem above, the ordering of the states, can be worked around using
362264
- `ssys`: Output of [`linearize`](@ref).
363265
- `costs`: A vector of pairs
364266
"""
365-
function build_quadratic_cost_matrix(matrices::NamedTuple, ssys::ODESystem, costs::AbstractVector{<:Pair})
267+
function build_quadratic_cost_matrix(matrices::NamedTuple, ssys::System, costs::AbstractVector{<:Pair})
366268
x = ModelingToolkit.unknowns(ssys)
367269
y = ModelingToolkit.outputs(ssys)
368270
# y = getproperty.(ModelingToolkit.observed(ssys), :lhs)
@@ -382,7 +284,7 @@ function build_quadratic_cost_matrix(matrices::NamedTuple, ssys::ODESystem, cost
382284
end
383285

384286
"""
385-
build_quadratic_cost_matrix(sys::ODESystem, inputs::Vector, costs::Vector{Pair}; kwargs...)
287+
build_quadratic_cost_matrix(sys::System, inputs::Vector, costs::Vector{Pair}; kwargs...)
386288
387289
Assemble a quadratic cost matrix (for LQR or Kalman filtering) that penalizes states or outputs of system `sys` according to the vector of pairs `costs`.
388290
@@ -397,7 +299,7 @@ The second problem above, the ordering of the states, can be worked around using
397299
- `inputs`: A vector of variables that are to be considered controlled inputs for the LQR controller.
398300
- `costs`: A vector of pairs.
399301
"""
400-
function build_quadratic_cost_matrix(sys::ODESystem, inputs::AbstractVector, costs::AbstractVector{<:Pair}; kwargs...)
302+
function build_quadratic_cost_matrix(sys::System, inputs::AbstractVector, costs::AbstractVector{<:Pair}; kwargs...)
401303
matrices, ssys = ModelingToolkit.linearize(sys, inputs, first.(costs); kwargs...)
402304
x = ModelingToolkit.unknowns(ssys)
403305
y = ModelingToolkit.outputs(ssys)
@@ -455,7 +357,7 @@ eqs = [D(x) ~ v
455357
y ~ x]
456358
457359
458-
@named duffing = ODESystem(eqs, t)
360+
@named duffing = System(eqs, t)
459361
460362
bounds = getbounds(duffing, unknowns(duffing))
461363
sample_within_bounds((l, u)) = (u - l) * rand() + l
@@ -699,7 +601,7 @@ function GainScheduledStateSpace(systems, vt; interpolator, x = zeros(systems[1]
699601
for i in 1:nx];
700602
collect(output.u .~ C * x .+ D * (input.u .- u0) .+ y0)
701603
]
702-
compose(ODESystem(eqs, t, name = name), [input, output, scheduling_input])
604+
compose(System(eqs, t, name = name), [input, output, scheduling_input])
703605
end
704606

705607
"LPVStateSpace is equivalent to GainScheduledStateSpace, see the docs for GainScheduledStateSpace."

0 commit comments

Comments
 (0)