Skip to content

Commit c4a6746

Browse files
authored
Merge pull request #70 from JuliaControl/ap
handle analysis points in addition to symbols
2 parents 23739c4 + e4a0cde commit c4a6746

File tree

4 files changed

+42
-47
lines changed

4 files changed

+42
-47
lines changed

docs/src/batch_linearization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,10 @@ code = SymbolicControlSystems.print_c_array(stdout, Cs_disc[1:7:end], xs[1:7:end
152152
The generated code starts by defining the interpolation vector `xs`, this variable is called `Cs_interp_vect` in the generated code. The code then defines all the ``A`` matrices as a 3-dimensional array, followed by a function that performs the interpolation `interpolate_Cs_A`. This function takes the output array as the first argument, a pointer to the 3D array with interpolation matrices, the interpolation vector as well as the interpolation variable `t`, in this document called ``v``. The same code is then repeated for the matrices ``B,C,D`` as well if they require interpolation (if they are all the same, no interpolation code is written).
153153

154154
## Linearize around a trajectory
155-
We can linearize around a trajectory obtained from `solve` using the function [`trajectory_ss`](@ref). We provide it with a vector of time points along the trajectory at which to linearize, and in this case we specify the inputs and outputs to linearize between as analysis points `:r` and `:y`.
155+
We can linearize around a trajectory obtained from `solve` using the function [`trajectory_ss`](@ref). We provide it with a vector of time points along the trajectory at which to linearize, and in this case we specify the inputs and outputs to linearize between as analysis points `r` and `y`.
156156
```@example BATCHLIN
157157
timepoints = 0:0.01:8
158-
Ps2, ssys = trajectory_ss(closed_loop, :r, :y, sol; t=timepoints)
158+
Ps2, ssys = trajectory_ss(closed_loop, closed_loop.r, closed_loop.y, sol; t=timepoints)
159159
bodeplot(Ps2, w, legend=false)
160160
```
161161

src/ode_system.jl

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using ModelingToolkit: AnalysisPoint
2+
const AP = Union{Symbol, AnalysisPoint}
13
import ModelingToolkitStandardLibrary.Blocks as Blocks
24
conn = ModelingToolkit.connect
35
t = Blocks.t
@@ -168,42 +170,38 @@ function RobustAndOptimalControl.named_ss(
168170
kwargs...,
169171
)
170172

171-
if isa(inputs, Symbol)
172-
nu = 1
173-
else
174-
inputs = map(inputs) do inp
175-
if inp isa ODESystem
176-
@variables u(t)
177-
if u Set(unknowns(inp))
178-
inp.u
179-
else
180-
error("Input $(inp.name) is an ODESystem and not a variable")
181-
end
173+
inputs = vcat(inputs)
174+
outputs = vcat(outputs)
175+
176+
inputs = map(inputs) do inp
177+
if inp isa ODESystem
178+
@variables u(t)
179+
if u Set(unknowns(inp))
180+
inp.u
182181
else
183-
inp
182+
error("Input $(inp.name) is an ODESystem and not a variable")
184183
end
184+
else
185+
inp
185186
end
186-
nu = length(inputs)
187187
end
188-
if isa(outputs, Symbol)
189-
ny = 1
190-
else
191-
outputs = map(outputs) do out
192-
if out isa ODESystem
193-
@variables u(t)
194-
if u Set(unknowns(out))
195-
out.u
196-
else
197-
error("Outut $(out.name) is an ODESystem and not a variable")
198-
end
188+
nu = length(inputs)
189+
190+
outputs = map(outputs) do out
191+
if out isa ODESystem
192+
@variables u(t)
193+
if u Set(unknowns(out))
194+
out.u
199195
else
200-
out
196+
error("Outut $(out.name) is an ODESystem and not a variable")
201197
end
198+
else
199+
out
202200
end
203-
ny = length(outputs)
204201
end
202+
ny = length(outputs)
205203
matrices, ssys = ModelingToolkit.linearize(sys, inputs, outputs; kwargs...)
206-
symstr(x) = Symbol(string(x))
204+
symstr(x) = Symbol(x isa AnalysisPoint ? x.name : string(x))
207205
unames = symstr.(inputs)
208206
fm(x) = convert(Matrix{Float64}, x)
209207
if nu > 0 && size(matrices.B, 2) == 2nu
@@ -276,25 +274,22 @@ function named_sensitivity_function(
276274
kwargs...,
277275
)
278276

279-
if isa(inputs, Symbol)
280-
nu = 1
281-
else
282-
inputs = map(inputs) do inp
283-
if inp isa ODESystem
284-
@variables u(t)
285-
if u Set(unknowns(inp))
286-
inp.u
287-
else
288-
error("Input $(inp.name) is an ODESystem and not a variable")
289-
end
277+
inputs = vcat(inputs)
278+
inputs = map(inputs) do inp
279+
if inp isa ODESystem
280+
@variables u(t)
281+
if u Set(unknowns(inp))
282+
inp.u
290283
else
291-
inp
284+
error("Input $(inp.name) is an ODESystem and not a variable")
292285
end
286+
else
287+
inp
293288
end
294-
nu = length(inputs)
295289
end
290+
nu = length(inputs)
296291
matrices, ssys = fun(sys, inputs, args...; kwargs...)
297-
symstr(x) = Symbol(string(x))
292+
symstr(x) = Symbol(x isa AnalysisPoint ? x.name : string(x))
298293
unames = symstr.(inputs)
299294
fm(x) = convert(Matrix{Float64}, x)
300295
if nu > 0 && size(matrices.B, 2) == 2nu

test/test_ODESystem.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,14 @@ eqs = [connect(r.output, F.input)
266266
connect(F.output, sys_inner.add.input1)]
267267
sys_outer = ODESystem(eqs, t, systems = [F, sys_inner, r], name = :outer)
268268

269-
matrices, _ = Blocks.get_sensitivity(sys_outer, [:inner_plant_input, :inner_plant_output])
269+
matrices, _ = Blocks.get_sensitivity(sys_outer, [sys_outer.inner.plant_input, sys_outer.inner.plant_output])
270270
S = ss(matrices...)
271271

272-
Sn = get_named_sensitivity(sys_outer, [:inner_plant_input, :inner_plant_output])
272+
Sn = get_named_sensitivity(sys_outer, [sys_outer.inner.plant_input, sys_outer.inner.plant_output])
273273

274274
@test S == Sn.sys
275275

276-
@test Sn.u == Sn.y == [:inner_plant_input, :inner_plant_output]
276+
@test Sn.u == Sn.y == [:outer₊inner₊plant_input, :outer₊inner₊plant_output] == [:outer₊inner₊plant_input, :outer₊inner₊plant_output]
277277

278278

279279
## Test connector names

test/test_batchlin.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ sol = solve(prob, Rodas5P(), abstol=1e-8, reltol=1e-8)
7272

7373
time = 0:0.1:8
7474
inputs, outputs = [duffing.u.u], [duffing.y.u]
75-
Ps2, ssys = trajectory_ss(closed_loop, :r, :y, sol; t=time)
75+
Ps2, ssys = trajectory_ss(closed_loop, closed_loop.r, closed_loop.y, sol; t=time)
7676
@test length(Ps2) == length(time)
7777
# bodeplot(Ps2)

0 commit comments

Comments
 (0)