Skip to content

Commit a9fa17f

Browse files
committed
return named systems
1 parent 9c1ce5c commit a9fa17f

File tree

2 files changed

+14
-7
lines changed

2 files changed

+14
-7
lines changed

docs/src/batch_linearization.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,11 @@ using Test
226226

227227
However, if we only open at `y` we get controller linearizations that _still contain the closed loop through the scheduling connection_ `v`. We can verify this by looking at what variables are present in the input-output map
228228
```@example BATCHLIN
229-
Cy = named_ss(controllersy[end], x=Symbol.(unknowns(ssy)))
230-
sminreal(Cy).x
229+
sminreal(controllersy[end]).x
231230
```
232231
notice how the state of the plant is included in the controller, this is an indication that we didn't fully isolate the controller during the linearizaiton. If we do the same thing for the controller with the loop opened at `u`, we see that the state of the plant is not included in the controller:
233232
```@example BATCHLIN
234-
Cu = named_ss(controllersu[end], x=Symbol.(unknowns(ssu)))
235-
sminreal(Cu).x
233+
sminreal(controllersu[end]).x
236234
```
237235
The call to `sminreal` is important here, it removes the states that are not needed to represent the input-output map of the system. The state of the full model, including the plant state, is present in the linearization before this call.
238236

src/ode_system.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ function ControlSystemsBase.ss(
5454
named_ss(sys, inputs, outputs; kwargs...).sys # just discard the names
5555
end
5656

57+
symstr(x) = Symbol(x isa AnalysisPoint ? x.name : string(x))
58+
5759

5860
"""
5961
RobustAndOptimalControl.named_ss(sys::ModelingToolkit.AbstractSystem, inputs, outputs; descriptor=true, kwargs...)
@@ -105,7 +107,6 @@ function RobustAndOptimalControl.named_ss(
105107
end
106108
end
107109
matrices, ssys, xpt = ModelingToolkit.linearize(sys, inputs, outputs; kwargs...)
108-
symstr(x) = Symbol(x isa AnalysisPoint ? x.name : string(x))
109110
unames = symstr.(inputs)
110111
if nu > 0 && size(matrices.B, 2) == 2nu
111112
# This indicates that input derivatives are present
@@ -437,7 +438,11 @@ function trajectory_ss(sys, inputs, outputs, sol; t = _max_100(sol.t), allow_inp
437438

438439
# TODO: The value of the output (or input) of the input analysis points should be mapped to the perturbation vars
439440
perturbation_vars = ModelingToolkit.inputs(ssys)
440-
# @show original_inputs = reduce(vcat, unnamespace(ap) for ap in vcat(inputs)) # assuming all inputs are analysis points for now
441+
# original_inputs = reduce(vcat, unnamespace(ap) for ap in vcat(inputs)) # assuming all inputs are analysis points for now
442+
443+
input_names = reduce(vcat, getproperty.(ap.outputs, :u) for ap in vcat(inputs))
444+
output_names = reduce(vcat, ap.input.u for ap in vcat(outputs))
445+
441446
op_nothing = Dict(unknowns(sys) .=> nothing) # Remove all defaults present in the original system
442447
defs = ModelingToolkit.defaults(sys)
443448
ops = map(t) do ti
@@ -464,7 +469,11 @@ function trajectory_ss(sys, inputs, outputs, sol; t = _max_100(sol.t), allow_inp
464469
end
465470
lins = first.(lins_ops)
466471
resolved_ops = last.(lins_ops)
467-
(; linsystems = [ss(l...) for l in lins], ssys, ops, resolved_ops)
472+
named_linsystems = map(lins) do l
473+
# Convert to a NamedStateSpace with the same names as the original system
474+
named_ss(ss(l.A, l.B, l.C, l.D); name = string(Base.nameof(sys)), x = symstr.(unknowns(ssys)), u = symstr.(input_names), y = symstr.(output_names))
475+
end
476+
(; linsystems = named_linsystems, ssys, ops, resolved_ops)
468477
end
469478

470479
"_max_100(t) = length(t) > 100 ? range(extrema(t)..., 100) : t"

0 commit comments

Comments
 (0)