Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix non-commutative multiplication of named systems #62

Merged
merged 4 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/glover_mcfarlane.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,11 @@ Skogestad gives the following general advice:
of methods available including normalization with respect to the magnitude of
the maximum or average value of the signal in question. If one is to go straight to a design the following variation has
proved useful in practice:
(a) The outputs are scaled such that equal magnitudes of cross-coupling into each
- The outputs are scaled such that equal magnitudes of cross-coupling into each
of the outputs is equally undesirable.
(b) Each input is scaled by a given percentage (say 10%) of its expected range
- Each input is scaled by a given percentage (say 10%) of its expected range
of operation. That is, the inputs are scaled to reflect the relative actuator
capabilities. An example of this type of scaling is given in the aero-engine
case study of Chapter 12.
capabilities.
2. Order the inputs and outputs so that the plant is as diagonal as possible. The
relative gain array [`rga`](@ref) can be useful here. The purpose of this pseudo-diagonalization
is to ease the design of the pre- and post-compensators which, for simplicity, will
Expand Down
24 changes: 21 additions & 3 deletions src/named_systems2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,17 @@ function Base.:*(s1::Number, s2::NamedStateSpace{T, S}) where {T <: CS.TimeEvolu
)
end

function Base.:*(s1::NamedStateSpace{T, S}, s2::Number) where {T <: CS.TimeEvolution, S}
return NamedStateSpace{T,S}(
s1.sys*s2,
s1.x,
[Symbol(string(u)*"_scaled") for u in s1.u],
s1.y,
)
end

function Base.:/(s::NamedStateSpace{T, S}, n::Number) where {T <: CS.TimeEvolution, S}
(1/n)*s
s*(1/n)
end
##

Expand Down Expand Up @@ -354,6 +363,8 @@ Addition and subtraction nodes are achieved by creating a linear combination nod
- `z1`: outputs (can overlap with `y1`)
- `verbose`: Issue warnings for signals that have no connection

Note: Positive feedback is used, controllers that are intended to be connected with negative feedback must thus be negated.

Example:
The following complicated feedback interconnection

Expand Down Expand Up @@ -404,9 +415,9 @@ function connect(systems; u1::Vector{Symbol}, y1::Vector{Symbol}, w1::Vector{Sym

if verbose
leftover_inputs = setdiff(full.u, [u1; w1])
isempty(leftover_inputs) || @warn("The following inputs were unconnected $leftover_inputs")
isempty(leftover_inputs) || @warn("The following inputs were unconnected $leftover_inputs, ignore this warning if you rely on prefix matching")
leftover_outputs = setdiff(full.y, z1 == (:) ? y1 : [y1; z1])
isempty(leftover_outputs) || @warn("The following outputs were unconnected $leftover_outputs")
isempty(leftover_outputs) || @warn("The following outputs were unconnected $leftover_outputs, ignore this warning if you rely on prefix matching")
end


Expand Down Expand Up @@ -657,4 +668,11 @@ for fun in [:baltrunc, :balreal]
msys, rest... = CS.$(fun)(sys.sys, args...; kwargs...)
named_ss(msys; sys.u, sys.y), rest...
end
end

for fun in [:baltrunc2, :baltrunc_coprime]
@eval function $(fun)(sys::NamedStateSpace, args...; kwargs...)
msys, rest... = $(fun)(sys.sys, args...; kwargs...)
named_ss(msys; sys.u, sys.y), rest...
end
end
15 changes: 14 additions & 1 deletion src/reduction.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using ControlSystemsBase: ssdata

"""
sysr, hs = frequency_weighted_reduction(G, Wo, Wi; residual=true)
sysr, hs = frequency_weighted_reduction(G, Wo, Wi, r=nothing; residual=true)

Find Gr such that ||Wₒ(G-Gr)Wᵢ||∞ is minimized.
For a realtive reduction, set Wo = inv(G) and Wi = I.
Expand All @@ -16,6 +16,19 @@ Ref: Andras Varga and Brian D.O. Anderson, "Accuracy enhancing methods for the f
https://elib.dlr.de/11746/1/varga_cdc01p2.pdf

Note: This function only handles exponentially stable models. To reduce unstable and marginally stable models, decompose the system into stable and unstable parts using [`stab_unstab`](@ref), reduce the stable part and then add the unstable part back.

# Example:
The following example performs reduction with a frequency focus between frequencies `w1` and `w2`.
```julia
using DSP
w1 = 1e-4
w2 = 1e-1
wmax = 1
fc = DSP.analogfilter(DSP.Bandpass(w1, w2, fs=wmax), DSP.Butterworth(2))
tfc = DSP.PolynomialRatio(fc)
W = tf(DSP.coefb(tfc), DSP.coefa(tfc))
rsys, hs = frequency_weighted_reduction(sys, W, 1)
```
"""
function frequency_weighted_reduction(G, Wo, Wi, r=nothing; residual=true, atol=sqrt(eps()), rtol=1e-3)
iscontinuous(G) || error("Discrete systems not supported yet.")
Expand Down
17 changes: 12 additions & 5 deletions test/test_named_systems2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,18 @@ s2 = named_ss(G2, x = [:z], u = [:u2], y=[:y2])
@test s12.C == G12.C
@test s12.D == G12.D

G3 = 2*G2
@test ss(G3) == 2*ss(G2)

G3 = G2/2.0
@test ss(G3) == ss(G2)/2.0
G3 = 2*s2
@test ss(G3) == 2*ss(s2)
@test G3.u == s2.u
@test G3.y != s2.y

G3 = s2*2
@test ss(G3) == ss(s2)*2
@test G3.u != s2.u
@test G3.y == s2.y

G3 = s2/2.0
@test ss(G3) == ss(s2)/2.0

@test_throws ArgumentError s1*s1
end
Expand Down