Skip to content

Commit d6c1cfe

Browse files
committed
handle RHP poles in margin
1 parent 79e4654 commit d6c1cfe

File tree

2 files changed

+35
-8
lines changed

2 files changed

+35
-8
lines changed

lib/ControlSystemsBase/src/analysis.jl

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,16 @@ end
4545

4646
function count_eigval_multiplicity(p, location, e=eps(maximum(abs, p, init=0.0))) # The init is to handle poor type inference with exotic number types
4747
n = length(p)
48-
n == 0 && return 0
48+
tol = zero(e)
49+
n == 0 && return (0, tol)
4950
for i = 1:n
5051
# if we count i poles within the circle assuming i integrators, we return i
51-
if count(p->abs(p-location) < (e^(1/i)), p) == i
52-
return i
52+
tol = e^(1/i)
53+
if count(p->abs(p-location) < tol, p) == i
54+
return (i, tol)
5355
end
5456
end
55-
0
57+
(0, tol)
5658
end
5759

5860
"""
@@ -65,7 +67,7 @@ See also [`integrator_excess`](@ref).
6567
function count_integrators(P::LTISystem)
6668
p = poles(P)
6769
location = iscontinuous(P) ? 0 : 1
68-
count_eigval_multiplicity(p, location)
70+
count_eigval_multiplicity(p, location)[1]
6971
end
7072

7173
"""
@@ -79,7 +81,18 @@ function integrator_excess(P::LTISystem)
7981
p = poles(P)
8082
z = tzeros(P)
8183
location = iscontinuous(P) ? 0 : 1
82-
count_eigval_multiplicity(p, location) - count_eigval_multiplicity(z, location)
84+
np, tolp = count_eigval_multiplicity(p, location)
85+
nz, tolz = count_eigval_multiplicity(z, location)
86+
np - nz
87+
end
88+
89+
function integrator_excess_with_tol(P::LTISystem)
90+
p = poles(P)
91+
z = tzeros(P)
92+
location = iscontinuous(P) ? 0 : 1
93+
np, tolp = count_eigval_multiplicity(p, location)
94+
nz, tolz = count_eigval_multiplicity(z, location)
95+
np - nz, p, z, tolp, tolz
8396
end
8497

8598

@@ -563,12 +576,14 @@ function sisomargin(sys::LTISystem, w::AbstractVector{<:Real}; full=false, allMa
563576
end
564577
end
565578
if adjust_phase_start && isrational(sys)
566-
intexcess = integrator_excess(sys)
579+
intexcess, p, z, tol = integrator_excess_with_tol(sys)
580+
n_unstable_poles = count(real(p) > tol for p in p)
567581
if intexcess != 0
568582
# Snap phase so that it starts at -90*intexcess
569583
nineties = round(Int, phase[1] / 90)
570584
adjust = ((90*(-intexcess-nineties)) ÷ 360) * 360
571-
pm = pm .+ adjust
585+
pm_unstable_adjust = n_unstable_poles*360 # count the number of unstable poles, and remove 360 for each. Be careful with poles that are counted as integrators
586+
pm = pm .+ adjust .- pm_unstable_adjust
572587
phase .+= adjust
573588
fullPhase = fullPhase .+ adjust
574589
end

lib/ControlSystemsBase/test/test_analysis.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,18 @@ marginplot(G)
303303
@test ωϕₘ[][] 3.484166418318219
304304
@test ϕₘ[][] 50.783187269018754
305305

306+
307+
## System with RHP poles and zeros but stable in closed loop
308+
temp = let
309+
tempA = [-83.25487376152321 26.76511464761918 -43.73380610734441 -27.90719213203418 -9.51838201282524 21.932907840445864; -15.234225958115879 -7.005196625072119 -18.09631269583633 -1.5182977493068577 -18.323658349439512 32.32164964342026; 0.0 23.7278286542071 -2.198121109985474 -17.293997884135962 19.215332126022005 -31.45685591523796; 0.0 0.0 -20.278223915399145 -9.092020460145815 -11.728147286799778 21.40857710364235; 0.0 0.0 0.0 -0.4760794287541981 -3.7362512320067136 5.668501934932698; 0.0 0.0 0.0 0.0 -2.469694372034253 3.7916178279085737]
310+
tempB = [9.65940730736899; 0.0; 0.0; 0.0; 0.0; 0.0;;]
311+
tempC = [0.0 4.9399258118993306 -5.6197700696954245 -4.845153904367337 0.28951168477387096 0.28822873250094244]
312+
tempD = [0.0;;]
313+
ss(tempA, tempB, tempC, tempD)
314+
end
315+
ωgₘ, gₘ, ωϕₘ, ϕₘ = margin(temp, allMargins=true)
316+
@test ϕₘ[][] 27.406506322937503
317+
306318
# RGA
307319
a = 10
308320
P = ss([0 a; -a 0], I(2), [1 a; -a 1], 0)

0 commit comments

Comments
 (0)