Skip to content
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
2 changes: 1 addition & 1 deletion src/hinfinity_design.jl
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ function _scalematrix(A::AbstractMatrix; method = :QR)
elseif method === :SVD
return _coordinatetransformsvd(A)
else
error("The method $method is not supported, use 'QR' or 'SVD' instad.")
error("The method $method is not supported, use `:QR` or `:SVD` instead.")
end
end

Expand Down
64 changes: 63 additions & 1 deletion src/named_systems2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ function Base.promote_rule(::Type{NamedStateSpace{TE, StateSpace{TE, T1}}}, ::Ty
NamedStateSpace{TE, StateSpace{TE, promote_type(T1,eltype(MT))}}
end

function Base.promote_rule(::Type{U}, ::Type{NamedStateSpace{T, S}}) where
{T, TF, U<:TransferFunction{<:Any, TF} , S<:AbstractStateSpace{T}}
inner = promote_type(U,S)
NamedStateSpace{T, inner}
end



function Base.convert(::Type{NamedStateSpace{T, S}}, s::U) where {T, S <: AbstractStateSpace, U <: AbstractStateSpace}
Expand All @@ -82,6 +88,11 @@ function Base.convert(::Type{NamedStateSpace{T, S}}, s::NamedStateSpace{T, U}) w
NamedStateSpace{T,typeof(sys)}(sys, s.x, s.u, s.y, s.name)
end

function Base.convert(::Type{NamedStateSpace{T, S}}, s::U) where {T, S <: AbstractStateSpace, U <: TransferFunction}
s2 = Base.convert(S, s)
named_ss(s2, x = gensym("x"), u = gensym("u"), y = gensym("y"))
end

# function Base.convert(::Type{TransferFunction{TE, S}}, s::U) where {TE, S, U <: NamedStateSpace{TE}}
# convert(TransferFunction{TE, S}, s.sys)
# end
Expand Down Expand Up @@ -288,6 +299,34 @@ function Base.:*(s1::NamedStateSpace{T, S}, s2::Number) where {T <: CS.TimeEvolu
)
end

function Base.:*(s1::AbstractMatrix, s2::NamedStateSpace{T, S}) where {T <: CS.TimeEvolution, S}
if isdiag(s1)
return NamedStateSpace{T,S}(
s1*s2.sys,
s2.x,
s2.u,
[Symbol(string(y)*"_scaled") for y in s2.y],
isempty(s2.name) ? "" : s2.name*"_scaled",
)
else
return *(promote(s1, s2)...)
end
end

function Base.:*(s1::NamedStateSpace{T, S}, s2::AbstractMatrix) where {T <: CS.TimeEvolution, S}
if isdiag(s2)
return NamedStateSpace{T,S}(
s1.sys*s2,
s1.x,
[Symbol(string(u)*"_scaled") for u in s1.u],
s1.y,
isempty(s1.name) ? "" : s1.name*"_scaled",
)
else
return *(promote(s1, s2)...)
end
end

function Base.:/(s::NamedStateSpace{T, S}, n::Number) where {T <: CS.TimeEvolution, S}
s*(1/n)
end
Expand Down Expand Up @@ -324,7 +363,9 @@ end
"""
measure(s::NamedStateSpace, names)

Return a system with specified states as measurement outputs.
Return a system with specified state variables as measurement outputs.

See also [`add_output`](@ref).
"""
function measure(s::NamedStateSpace, names)
inds = names2indices(names, s.x)
Expand Down Expand Up @@ -801,6 +842,27 @@ function CS.append(systems::NamedStateSpace...; kwargs...)
end


"""
add_output(sys::NamedStateSpace, C2::AbstractArray, D2 = 0; y)

Add outputs to `sys` corresponding to the output matrix `C2` and the feedthrough matrix `D2` to the system `sys`.

# Arguments:
- `y`: The names used for the new outputs. If not provided, the names will be generated automatically.

See also [`measure`](@ref) for a simpler way to output state variables.
"""
function CS.add_output(sys::NamedStateSpace, C2::AbstractArray, D2=0; y = [Symbol("y_$i") for i in (1:size(C2, 1)) .+ sys.ny])
T = promote_type(CS.numeric_type(sys), eltype(C2), eltype(D2))
A,B,C,D = ssdata(sys)
D3 = D2 == 0 ? zeros(T, size(C2, 1), sys.nu) : D2
x = sys.x
u = sys.u
y = [sys.y; y]
named_ss(ss(A, B, [C; C2], [D; D3]), sys.timeevol; x, u, y)
end


function CS.minreal(sys::NamedStateSpace, args...; kwargs...)
msys = minreal(sys.sys, args...; kwargs...)
named_ss(msys; sys.u, sys.y, sys.name)
Expand Down
25 changes: 25 additions & 0 deletions test/test_named_systems2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ end
G = measure(s1, :x)
@test G.C == ones(1, 1)
@test G.y == [:x]

@test add_output(s1, [0.2]) isa NamedStateSpace
@test add_output(s1, [0.2], y=[:hej]).y[2] === :hej

end

G1 = ss(1,1,1,0)
Expand Down Expand Up @@ -189,6 +193,27 @@ s2 = named_ss(G2, x = [:z], u = [:u1], y=[:y2])
G1 = named_ss(ssrand(1,1,1, Ts=1), "G1")
G2 = named_ss(ssrand(1,1,1, Ts=1), "G2")
gangoffourplot(G1, G2) # tests some convert methods for I to discrete


G1 = named_ss(ssrand(1,1,1), "G1")
# Scalars
@test_nowarn G1*1
@test_nowarn 1*G1

# Transfer function
@test (G1*tf(1, [1,1])).sys == (G1*ss(tf(1, [1,1]))).sys
@test (tf(1, [1,1])*G1).sys == (ss(tf(1, [1,1]))*G1).sys

# Matrix
@test (G1*ones(1,1)).sys == (G1*ss(ones(1,1))).sys
@test (ones(1,1)*G1).sys == (ss(ones(1,1))*G1).sys

# if the matrix is diagonal, the names are `u_scaled`
@test endswith(string((G1*ones(1,1)).u[]), "_scaled")

# If the matrix is not diagonal, the names are generic
G1 = named_ss(ssrand(1,2,1), "G1")
@test !endswith(string((G1*ones(2,2)).u[1]), "_scaled")
end


Expand Down
Loading