8000 Merge pull request #575 from bnavigator/add-frd-margin-test · basicmachines/python-control@2500199 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2500199

Browse files
authored
Merge pull request python-control#575 from bnavigator/add-frd-margin-test
Ease cutoff between poly and frd method for stability margins
2 parents b41574f + 52d8fc3 commit 2500199

File tree

2 files changed

+30
-29
lines changed

2 files changed

+30
-29
lines changed

control/margins.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def _likely_numerical_inaccuracy(sys):
218218
# * z**(-p_q)
219219
x = [1] + [0] * (-p_q)
220220
p1 = np.polymul(p1, x)
221-
return np.linalg.norm(p1) < 1e-3 * np.linalg.norm(p2)
221+
return np.linalg.norm(p1) < 1e-4 * np.linalg.norm(p2)
222222

223223
# Took the framework for the old function by
224224
# Sawyer B. Fuller <minster@uw.edu>, removed a lot of the innards
@@ -337,7 +337,8 @@ def stability_margins(sysdata, returnall=False, epsw=0.0, method='best'):
337337
if isinstance(sys, xferfcn.TransferFunction) and not sys.isctime():
338338
if _likely_numerical_inaccuracy(sys):
339339
warn("stability_margins: Falling back to 'frd' method "
340-
"because of chance of numerical inaccuracy in 'poly' method.")
340+
"because of chance of numerical inaccuracy in 'poly' method.",
341+
stacklevel=2)
341342
omega_sys = freqplot._default_frequency_range(sys)
342343
omega_sys = omega_sys[omega_sys < np.pi / sys.dt]
343344
sys = frdata.FRD(sys, omega_sys, smooth=True)

control/tests/margin_test.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -336,41 +336,41 @@ def test_zmore_stability_margins(tsys_zmore):
336336
@pytest.mark.parametrize(
337337
'cnum, cden, dt,'
338338
'ref,'
339-
'rtol',
339+
'rtol, poly_is_inaccurate',
340340
[( # gh-465
341341
[2], [1, 3, 2, 0], 1e-2,
342-
[2.9558, 32.390, 0.43584, 1.4037, 0.74951, 0.97079],
343-
2e-3), # the gradient of the function reduces numerical precision
342+
[ 2.955761, 32.398492, 0.429535, 1.403725, 0.749367, 0.923898],
343+
1e-5, True),
344344
( # 2/(s+1)**3
345345
[2], [1, 3, 3, 1], .1,
346346
[3.4927, 65.4212, 0.5763, 1.6283, 0.76625, 1.2019],
347-
1e-4),
348-
( # gh-523
347+
1e-4, True),
348+
( # gh-523 a
349349
[1.1 * 4 * np.pi**2], [1, 2 * 0.2 * 2 * np.pi, 4 * np.pi**2], .05,
350350
[2.3842, 18.161, 0.26953, 11.712, 8.7478, 9.1504],
351-
1e-4),
351+
1e-4, False),
352+
( # gh-523 b
353+
# H1 = w1**2 / (z**2 + 2*zt*w1 * z + w1**2)
354+
# H2 = w2**2 / (z**2 + 2*zt*w2 * z + w2**2)
355+
# H = H1 * H2
356+
# w1 = 1, w2 = 100, zt = 0.5
357+
[5e4], [1., 101., 10101., 10100., 10000.], 1e-3,
358+
[18.8766, 26.3564, 0.406841, 9.76358, 2.32933, 2.55986],
359+
1e-5, True),
352360
])
353-
def test_stability_margins_discrete(cnum, cden, dt, ref, rtol):
361+
@pytest.mark.filterwarnings("error")
362+
def test_stability_margins_discrete(cnum, cden, dt,
363+
ref,
364+
rtol, poly_is_inaccurate):
354365
"""Test stability_margins with discrete TF input"""
355366
tf = TransferFunction(cnum, cden).sample(dt)
356-
out = stability_margins(tf, method='poly')
367+
if poly_is_inaccurate:
368+
with pytest.warns(UserWarning, match="numerical inaccuracy in 'poly'"):
369+
out = stability_margins(tf)
370+
# cover the explicit frd branch and make sure it yields the same
371+
# results as the fallback mechanism
372+
out_frd = stability_margins(tf, method='frd')
373+
assert_allclose(out, out_frd)
374+
else:
375+
out = stability_margins(tf)
357376
assert_allclose(out, ref, rtol=rtol)
358-
359-
360-
def test_stability_margins_methods():
361-
# the following system gives slightly inaccurate result for DT systems
362-
# because of numerical issues
363-
omegan = 1
364-
zeta = 0.5
365-
resonance = TransferFunction(omegan**2, [1, 2*zeta*omegan, omegan**2])
366-
omegan2 = 100
367-
resonance2 = TransferFunction(omegan2**2, [1, 2*zeta*omegan2, omegan2**2])
368-
sys = 5 * resonance * resonance2
369-
sysd = sys.sample(0.001, 'zoh')
370-
"""Test stability_margins() function with different methods"""
371-
out = stability_margins(sysd, method='best')
372-
# confirm getting reasonable results using FRD method
373-
assert_allclose(
374-
(18.876634740386308, 26.356358386241055, 0.40684127995261044,
375-
9.763585494645046, 2.3293357226374805, 2.55985695034263),
376-
stability_margins(sysd, method='frd'), rtol=1e-5)

0 commit comments

Comments
 (0)
0