diff --git a/lib/ControlSystemsBase/src/connections.jl b/lib/ControlSystemsBase/src/connections.jl index 3c0a85405..cd50828e3 100644 --- a/lib/ControlSystemsBase/src/connections.jl +++ b/lib/ControlSystemsBase/src/connections.jl @@ -259,7 +259,8 @@ feedback(P1::TransferFunction, P2::TransferFunction; pos_feedback::Bool = false) function feedback(G1::TransferFunction{<:TimeEvolution,<:SisoRational}, G2::TransferFunction{<:TimeEvolution,<:SisoRational}; pos_feedback::Bool = false) if !issiso(G1) || !issiso(G2) - error("MIMO TransferFunction feedback isn't implemented.") + @warn("MIMO TransferFunction feedback isn't implemented yet, converting to a state-space object and back. Consider converting your transfer functions to state-space form using `ss` as soon as possible.") + return tf(feedback(ss(G1), ss(G2); pos_feedback)) end G1num = numpoly(G1)[] G1den = denpoly(G1)[] @@ -274,7 +275,8 @@ end #Efficient implementations function feedback(L::TransferFunction{<:TimeEvolution,T}) where T<:SisoRational if size(L) != (1,1) - error("MIMO TransferFunction feedback isn't implemented, use L/(1+L)") + @warn("MIMO TransferFunction feedback isn't implemented yet, converting to a state-space object and back. Consider converting your transfer functions to state-space form using `ss` as soon as possible.") + return tf(feedback(ss(L))) end P = numpoly(L) Q = denpoly(L) @@ -283,7 +285,8 @@ end function feedback(L::TransferFunction{TE, T}) where {TE<:TimeEvolution, T<:SisoZpk} if size(L) != (1,1) - error("MIMO TransferFunction feedback isn't implemented, use L/(1+L)") + @warn("MIMO TransferFunction feedback isn't implemented yet, converting to a state-space object and back. Consider converting your transfer functions to state-space form using `ss` as soon as possible.") + return tf(feedback(ss(L))) end #Extract polynomials and create P/(P+Q) k = L.matrix[1].k diff --git a/lib/ControlSystemsBase/src/types/TransferFunction.jl b/lib/ControlSystemsBase/src/types/TransferFunction.jl index 37ddeee5b..c84779560 100644 --- a/lib/ControlSystemsBase/src/types/TransferFunction.jl +++ b/lib/ControlSystemsBase/src/types/TransferFunction.jl @@ -227,12 +227,22 @@ function /(n::Number, G::TransferFunction) matrix = fill(entry, 1, 1) return TransferFunction(matrix, G.timeevol) else - error("MIMO TransferFunction inversion isn't implemented yet") + error("MIMO TransferFunction inversion isn't implemented yet, consider converting your transfer functions to state-space form using `ss`") end end /(G::TransferFunction, n::Number) = G*(1/n) -/(G1::TransferFunction, G2::TransferFunction) = G1*(1/G2) Base.:(/)(sys1::LTISystem, sys2::TransferFunction) = *(promote(sys1, ss(1/sys2))...) # This special case is needed to properly handle improper inverse transfer function (1/s) +function /(f1::TransferFunction, f2::TransferFunction) + if issiso(f2) + T = numeric_type(f2) + One = one(1/one(T)) # This gymatics is to ensure that we get floats out of integer system division. We will always get floats for ss division in the branch below, so this is required for type stability + f1*(One/f2) + else + @warn "MIMO TransferFunction inversion isn't implemented yet, converting to state-space object and back. Consider converting your transfer functions to state-space form using `ss` as soon as possible." + tf(ss(f1) / ss(f2)) + end +end + ##################################################################### diff --git a/lib/ControlSystemsBase/test/test_transferfunction.jl b/lib/ControlSystemsBase/test/test_transferfunction.jl index eee3bdec8..e421e7f9b 100644 --- a/lib/ControlSystemsBase/test/test_transferfunction.jl +++ b/lib/ControlSystemsBase/test/test_transferfunction.jl @@ -271,4 +271,22 @@ if VERSION >= v"1.8.0-rc1" @test @test_logs (:warn, r"deprecated") tf(1).Ts == 0 end +# Test MIMO TransferFunction feedback behavior +@test_logs (:warn, r"MIMO TransferFunction feedback isn't implemented yet") feedback(C_222) +@test_logs (:warn, r"MIMO TransferFunction feedback isn't implemented yet") feedback(C_222, C_222) +# Test that feedback returns state-space for MIMO +fb_result = @test_logs (:warn, r"MIMO TransferFunction feedback isn't implemented yet") feedback(C_222) +@test fb_result isa TransferFunction +fb_result2 = @test_logs (:warn, r"MIMO TransferFunction feedback isn't implemented yet") feedback(C_222, C_222) +@test fb_result2 isa TransferFunction + +# Test MIMO TransferFunction division behavior +Ci_222 = tf(ssrand(2,2,2)) +# Test that division returns state-space for MIMO +div_result = @test_logs (:warn, r"MIMO TransferFunction inversion isn't implemented yet") C_222 / Ci_222 +@test div_result isa TransferFunction + +# Test improved error messages in MIMO TransferFunction inversion +@test_throws ErrorException("MIMO TransferFunction inversion isn't implemented yet, consider converting your transfer functions to state-space form using `ss`") 1 / Ci_222 + end