Skip to content

Commit 0fc9602

Browse files
committed
tweak computation of integrator excess
to handle new difficult test case
1 parent 16325db commit 0fc9602

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

lib/ControlSystemsBase/src/analysis.jl

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,22 @@ function poles(sys::TransferFunction{<:TimeEvolution,SisoZpk{T,TR}}) where {T, T
3838
end
3939

4040

41-
function count_eigval_multiplicity(p, location)
42-
T = float(real(eltype(p)))
41+
function count_eigval_multiplicity(p, location, e=eps(maximum(abs, p)))
4342
n = length(p)
4443
n == 0 && return 0
45-
maximum(1:n) do i
44+
for i = 1:n
4645
# if we count i poles within the circle assuming i integrators, we return i
47-
if count(p->abs(p-location) < (i+1)*(eps(T)^(1/i)), p) >= i
48-
i
49-
else
50-
0
46+
if count(p->abs(p-location) < (e^(1/i)), p) == i
47+
return i
5148
end
5249
end
50+
0
5351
end
5452

5553
"""
5654
count_integrators(P)
5755
58-
Count the number of poles in the origin by finding the maximum value of `n` for which the number of poles within a circle of radius `(n+1)*eps(numeric_type(sys))^(1/n)` arount the origin (1 in discrete time) equals `n`.
56+
Count the number of poles in the origin by finding the maximum value of `n` for which the number of poles within a circle of radius `eps(maximum(abs, p))^(1/n)` around the origin (1 in discrete time) equals `n`.
5957
6058
See also [`integrator_excess`](@ref).
6159
"""

lib/ControlSystemsBase/test/test_analysis.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,33 @@ P = tf(1,[5, 10.25, 6.25, 1])
250250
w_180, gm, w_c, pm = margin(50P)
251251
@test pm[] -35.1 rtol=1e-2
252252

253+
## Tricky case from https://www.reddit.com/r/ControlTheory/comments/1inhxsz/understanding_stability_in_highorder/
254+
s = tf("s")
255+
kpu = -10.593216768722073; kiu = -0.00063; t = 1000; tau = 180; a = 1/8.3738067325406132e-5;
256+
kpd = 15.92190277847431; kid = 0.000790960718241793;
257+
kpo = -10.39321676872207317; kio = -0.00063;
258+
kpb = kpd; kib = kid;
259+
260+
C1 = (kpu + kiu/s)*(1/(t*s + 1))
261+
C2 = (kpu + kiu/s)*(1/(t*s + 1))
262+
C3 = (kpo + kio/s)*(1/(t*s + 1))
263+
Cb = (kpb + kib/s)*(1/(t*s + 1))
264+
OL = (ss(Cb)*ss(C1)*ss(C2)*ss(C3)*exp(-3*tau*s))/((C1 - a*s)*(C2 - a*s)*(C3 - a*s));
265+
266+
wgm, gm, ωϕₘ, ϕₘ = margin(OL; full=true, allMargins=true)
267+
@test ϕₘ[][] -320 rtol=1e-2
268+
for wgm in wgm[]
269+
@test mod(rad2deg(angle(freqresp(OL, wgm)[])), 360)-180 0 atol=1e-1
270+
end
271+
272+
nint = ControlSystemsBase.count_integrators(pade(OL, 2))
273+
nintbig = ControlSystemsBase.count_integrators(big(1.0)*pade(OL, 2))
274+
@test nint == nintbig # This one is very tricky and tests the threshold value of the eigval counting
275+
276+
@test ControlSystemsBase.count_integrators(pade(OL, 3)) == nintbig
277+
@test ControlSystemsBase.count_integrators(pade(OL, 4)) == nintbig
278+
@test ControlSystemsBase.count_integrators(pade(OL, 10)) == nintbig
279+
253280
# RGA
254281
a = 10
255282
P = ss([0 a; -a 0], I(2), [1 a; -a 1], 0)

0 commit comments

Comments
 (0)