diff --git a/src/hinfinity_design.jl b/src/hinfinity_design.jl index 5eda925..697355d 100644 --- a/src/hinfinity_design.jl +++ b/src/hinfinity_design.jl @@ -193,7 +193,7 @@ function hinfsynthesize( else # Return and empty controller, empty gain γ @warn "No feasible γ found, returning an empty controller. Try increasing the interval from the default `interval = (0, 20)` or change the scaling method using `method = :SVD`" - K = ss(0.0) + K = ss(zeros(P.nu, P.ny)) γ = Inf end if hp @@ -201,6 +201,9 @@ function hinfsynthesize( mats = bf.(ssdata(K)) K = ss(mats..., K.timeevol) end + if P.sys isa NamedStateSpace + K = named_ss(K, u=P.y, y=P.u, x=Symbol.("K" .* string.(P.sys.x))) + end if check γactual = hinfnorm2(lft(P, K))[1]::T # NOTE: this check can erroneosly indicate numerical problems if Rtrans21 != 1. This may happen for method = :QR, in which case γactual ≈ γFeasible / Rtrans21 diff --git a/src/named_systems2.jl b/src/named_systems2.jl index 0252a5a..2f939db 100644 --- a/src/named_systems2.jl +++ b/src/named_systems2.jl @@ -945,57 +945,50 @@ function named_ss(sys::ExtendedStateSpace{T}, name=""; end -function partition(P::NamedStateSpace; u=nothing, y=nothing, - w = nothing, - z = nothing, - B1 = nothing, - B2 = nothing, - C1 = nothing, - C2 = nothing, - D11 = nothing, - D12 = nothing, - D21 = nothing, - D22 = nothing, +function partition(P::NamedStateSpace; u=Symbol[], y=Symbol[], + w = Symbol[], + z = Symbol[], + # B1 = nothing, + # B2 = nothing, + # C1 = nothing, + # C2 = nothing, + # D11 = nothing, + # D12 = nothing, + # D21 = nothing, + # D22 = nothing, ) - if w === nothing - inds = names2indices(u, P.u) - w = setdiff(1:P.nu, inds) - u = inds + if w === nothing || (w isa AbstractArray && isempty(w)) + w = setdiff(P.u, u) end - if z === nothing - inds = names2indices(y, P.y) - z = setdiff(1:P.ny, inds) - y = inds + if z === nothing || (z isa AbstractArray && isempty(z)) + z = setdiff(P.y, y) end - if u === nothing - inds = names2indices(w, P.u) - u = setdiff(1:P.nu, inds) - w = inds + if u === nothing || (u isa AbstractArray && isempty(u)) + u = setdiff(P.u, w) end - if y === nothing - inds = names2indices(z, P.y) - y = setdiff(1:P.ny, inds) - z = inds + if y === nothing || (y isa AbstractArray && isempty(y)) + y = setdiff(P.y, z) end - u = names2indices(identity.(u), P.u) - y = names2indices(identity.(y), P.y) - z = names2indices(identity.(z), P.y) - w = names2indices(identity.(w), P.u) - u = vcat(u) - y = vcat(y) - z = vcat(z) - w = vcat(w) - ss(P.A, - B1 === nothing ? P.B[:, w] : B1, - B2 === nothing ? P.B[:, u] : B2, - C1 === nothing ? P.C[z, :] : C1, - C2 === nothing ? P.C[y, :] : C2 , - D11 === nothing ? P.D[z, w] : D11, - D12 === nothing ? P.D[z, u] : D12, - D21 === nothing ? P.D[y, w] : D21, - D22 === nothing ? P.D[y, u] : D22, - P.timeevol - ) + # u = names2indices(identity.(u), P.u) + # y = names2indices(identity.(y), P.y) + # z = names2indices(identity.(z), P.y) + # w = names2indices(identity.(w), P.u) + # u = vcat(u) + # y = vcat(y) + # z = vcat(z) + # w = vcat(w) + # ss(P.A, + # B1 === nothing ? P.B[:, w] : B1, + # B2 === nothing ? P.B[:, u] : B2, + # C1 === nothing ? P.C[z, :] : C1, + # C2 === nothing ? P.C[y, :] : C2 , + # D11 === nothing ? P.D[z, w] : D11, + # D12 === nothing ? P.D[z, u] : D12, + # D21 === nothing ? P.D[y, w] : D21, + # D22 === nothing ? P.D[y, u] : D22, + # P.timeevol + # ) + ExtendedStateSpace(P, w, u, z, y) end function CS.c2d(s::NamedStateSpace{Continuous}, Ts::Real, method::Symbol = :zoh, args...; diff --git a/test/test_manual_hinf.jl b/test/test_manual_hinf.jl index b6cc26e..58a615a 100644 --- a/test/test_manual_hinf.jl +++ b/test/test_manual_hinf.jl @@ -1,4 +1,4 @@ -using RobustAndOptimalControl, ControlSystemsBase, Plots +using RobustAndOptimalControl, ControlSystemsBase, Plots, Test P = named_ss(ss(tf(1, [1, 0.1, 1])), :P) We = named_ss(makeweight(10, 1, 0.1), :We, u=:y, y=:e) # We care a lot about the error on low frequencies Wu = named_ss(0.01makeweight(1e-3, 10, 10), :Wu, u=:Wu, y=:uw) # Above ω=100, we want to limit the control effort @@ -30,7 +30,7 @@ G = connect([P,We,Wu,Wd,sumP,split_u], connections; z1, w1) Gsyn = partition(G, u = [:u], y = [:y]) # You can provide either u or w, and either y or z K, γ, info = hinfsynthesize(Gsyn, γrel=1.001, interval = (0.1, 20), transform=false) - +@test K.u == [:y] Gsyn2 = hinfpartition(P, We, Wu, []) K2, γ2 = hinfsynthesize(Gsyn2, γrel=1.001, interval = (0.1, 20), transform=false) diff --git a/test/test_named_systems2.jl b/test/test_named_systems2.jl index 9d94018..b0bb336 100644 --- a/test/test_named_systems2.jl +++ b/test/test_named_systems2.jl @@ -44,8 +44,8 @@ s3 = named_ss(G3, x = :x, u = :u, y=:y, z=:z, w=:w) @test length(s3.y) == 2 s3part = partition(s3, y=:y, z=:z, w=:w, u=:u) -@test s3part == G3 -@test performance_mapping(s3part) == s3[:z, :w].sys +@test s3part.sys.sys == G3.sys +@test performance_mapping(s3part).sys == s3[:z, :w].sys # Test prefix matching G4 = ControlSystemsBase.ssrand(1,2,3)