From 636c1ffea595963f6046c215afc7da75d2e3e888 Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson Date: Sun, 17 Nov 2024 06:51:06 +0100 Subject: [PATCH 1/2] rename `w1,z1` args to `external_inputs, external_outputs` --- docs/src/hinf_connection.md | 8 ++++---- examples/complicated_feedback.jl | 6 +++--- examples/flexible_servo.jl | 6 +++--- src/named_systems2.jl | 15 +++++++++------ 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/docs/src/hinf_connection.md b/docs/src/hinf_connection.md index 1ff73bf3..8a9757fb 100644 --- a/docs/src/hinf_connection.md +++ b/docs/src/hinf_connection.md @@ -80,10 +80,10 @@ nothing # hide When we specify the external inputs and outputs to [`connect`](@ref), we include $y$ and $u$ since they are external from the view of `connect`: ```@example hinfcon -w1 = [ # External inputs +external_inputs = [ :do, :u ] -z1 = [ # External outputs +external_outputs = [ :e, :uw, :y ] nothing # hide @@ -91,7 +91,7 @@ nothing # hide We are now ready to form the system we want to minimize the norm of ```@example hinfcon -G = connect([P,We,Wu,Wd,sumP,split_u], connections; z1, w1) +G = connect([P,We,Wu,Wd,sumP,split_u], connections; external_outputs, external_inputs) ``` At this stage, it's good practice to check that the poles, inputs and outputs of $G$ looks correct, it's easy to forget some signal.. @@ -108,7 +108,7 @@ we also check the equivalences we know should hold system_mapping(Gsyn) == P.sys ``` ```@example hinfcon -G[:uw, :u].sys == Wu.sys +sminreal(G[:uw, :u].sys) == Wu.sys ``` These will not be identical, the realization might differ, but they should represent the same system ```@example hinfcon diff --git a/examples/complicated_feedback.jl b/examples/complicated_feedback.jl index ed097f68..a29338fd 100644 --- a/examples/complicated_feedback.jl +++ b/examples/complicated_feedback.jl @@ -1,7 +1,7 @@ #= This example illustrates how named systems can be used to form complicated feedback interconnections. =# -using RobustAndOptimalControl, ControlSystemsBase +using RobustAndOptimalControl, ControlSystemsBase, Test, LinearAlgebra const ROC = RobustAndOptimalControl w = exp10.(LinRange(-2, 2, 300)) F = named_ss(ssrand(1, 1, 2, proper=true), x=:xF, u=:uF, y=:yF) @@ -40,9 +40,9 @@ connections = [ :uC => :uC :yR => :yR ] -w1 = [:uF] +external_inputs = [:uF] -G = ROC.connect([F, R, C, P, addP, addC], connections; w1) +G = ROC.connect([F, R, C, P, addP, addC], connections; external_inputs) @test sminreal(G[:yF, :uF].sys) ≈ F.sys diff --git a/examples/flexible_servo.jl b/examples/flexible_servo.jl index 0475c585..aa238d94 100644 --- a/examples/flexible_servo.jl +++ b/examples/flexible_servo.jl @@ -40,13 +40,13 @@ function flexible_servo_loop(; :qm => :y :e => :e ] - w1 = [:r] # r is an external input - G = connect([P, K, sumE], connections; w1) + external_inputs = [:r] # r is an external input + G = connect([P, K, sumE], connections; external_inputs) # Alternative calling convention: # u1 = [:u, :y, :e] # inputs # y1 = [:Cu, :qm, :e] # outputs - # G = connect([P, K, sumE]; u1, y1, w1) + # G = connect([P, K, sumE]; u1, y1, external_inputs) (; P, K, G) end diff --git a/src/named_systems2.jl b/src/named_systems2.jl index 174e7019..b889c94f 100644 --- a/src/named_systems2.jl +++ b/src/named_systems2.jl @@ -407,10 +407,13 @@ end ControlSystemsBase.feedback(s1::NamedStateSpace{T}, s2::AbstractStateSpace{T}; kwargs...) where {T <: CS.TimeEvolution} = feedback(s1, named_ss(s2); kwargs...) -function connect(systems; u1::Vector{Symbol}, y1::Vector{Symbol}, w1, z1 = (:), verbose = true, unique = true, kwargs...) +function connect(systems; u1::Vector{Symbol}, y1::Vector{Symbol}, external_inputs = nothing, w1 = nothing, external_outputs = (:), z1 = nothing, verbose = true, unique = true, kwargs...) full = append(systems...; unique) @assert length(y1) == length(u1) + z1 = something(external_outputs, z1) + w1 = something(external_inputs, w1) + w1 === nothing && error("The keyword argument `external_inputs` must be provided") if unique @check_unique u1 "Connected inputs not unique. If you want to connect several signals to the same input, use a summation node, e.g., named_ss(ss([1 1]), u=[:u1, :u2], y=:usum)" @check_unique full.u "system inputs" "To allow connecting a single input signal to several inputs with the same name, pass `unique = false`." @@ -439,7 +442,7 @@ end """ - connect(systems, connections; w1, z1 = (:), verbose = true, unique = true, kwargs...) + connect(systems, connections; external_inputs, external_outputs = (:), verbose = true, unique = true, kwargs...) Create block connections using named inputs and outputs. @@ -448,8 +451,8 @@ Addition and subtraction nodes are achieved by creating a linear combination nod # Arguments: - `systems`: A vector of named systems to be connected - `connections`: a vector of pairs output => input, where each pair maps an output to an input. Each output must appear as an output in one of `systems`, and similarly each input must appear as an input in one of `systems`. All inputs must have unique names and so must all outputs, but an input may have the same name as an output. In the example below the connection `:uP => :uP` connects the output `:uP` of the `addP` block to `P`'s input `:uP` -- `w1`: external signals to be used as inputs in the constructed system. Use `(:)` to indicate all signals -- `z1`: outputs of the constructed system. Use `(:)` to indicate all signals +- `external_inputs`: external signals to be used as inputs in the constructed system. Use `(:)` to indicate all signals +- `external_outputs`: outputs of the constructed system. Use `(:)` to indicate all signals - `verbose`: Issue warnings for signals that have no connection - `unique`: If `true`, all input names must be unique. If `false`, a single external input signal may be connected to multiple input ports with the same name. @@ -489,9 +492,9 @@ connections = [ :uC => :uC :yR => :yR ] -w1 = [:uF] # External inputs +external_inputs = [:uF] # External inputs -G = connect([F, R, C, P, addP, addC], connections; w1) +G = connect([F, R, C, P, addP, addC], connections; external_inputs) ``` If an external input is to be connected to multiple points, use a `splitter` to split up the signal into a set of unique names which are then used in the connections. From a808394a011bbf2d143f71b0d53e02c8a93c30ea Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson Date: Sun, 17 Nov 2024 08:20:10 +0100 Subject: [PATCH 2/2] change order --- src/named_systems2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/named_systems2.jl b/src/named_systems2.jl index b889c94f..d621d6df 100644 --- a/src/named_systems2.jl +++ b/src/named_systems2.jl @@ -411,7 +411,7 @@ function connect(systems; u1::Vector{Symbol}, y1::Vector{Symbol}, external_input full = append(systems...; unique) @assert length(y1) == length(u1) - z1 = something(external_outputs, z1) + z1 = something(z1, external_outputs) w1 = something(external_inputs, w1) w1 === nothing && error("The keyword argument `external_inputs` must be provided") if unique