From 96cc1245b92239e02af33e9190b83cc1f2bca74b Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sat, 30 Jan 2021 01:46:01 +0100 Subject: [PATCH 1/2] fix #523: finding z for |H(z)|=1 computed the wrong polynomials --- control/margins.py | 11 ++++++----- control/tests/margin_test.py | 24 +++++++++++++----------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/control/margins.py b/control/margins.py index 20da2a879..fc2a20d7c 100644 --- a/control/margins.py +++ b/control/margins.py @@ -156,13 +156,14 @@ def _poly_z_real_crossing(num, den, num_inv_zp, den_inv_zq, p_q, dt, epsw): return z, w -def _poly_z_mag1_crossing(num, den, num_inv, den_inv, p_q, dt, epsw): +def _poly_z_mag1_crossing(num, den, num_inv_zp, den_inv_zq, p_q, dt, epsw): # |H(z)| = 1, H(z)*H(1/z)=1, num(z)*num(1/z) == den(z)*den(1/z) - p1 = np.polymul(num, num_inv) - p2 = np.polymul(den, den_inv) + p1 = np.polymul(num, num_inv_zp) + p2 = np.polymul(den, den_inv_zq) if p_q < 0: + # * z**(-p_q) x = [1] + [0] * (-p_q) - p2 = np.polymul(p2, x) + p1 = np.polymul(p1, x) z = np.roots(np.polysub(p1, p2)) eps = np.finfo(float).eps**(1 / len(p2)) z, w = _z_filter(z, dt, eps) @@ -171,7 +172,7 @@ def _poly_z_mag1_crossing(num, den, num_inv, den_inv, p_q, dt, epsw): return z, w -def _poly_z_wstab(num, den, num_inv, den_inv, p_q, dt, epsw): +def _poly_z_wstab(num, den, num_inv_zp, den_inv_zq, p_q, dt, epsw): # Stability margin: Minimum distance to -1 # TODO: Find a way to solve for z or omega analytically with given diff --git a/control/tests/margin_test.py b/control/tests/margin_test.py index 4965bbe89..6f4c3e41a 100644 --- a/control/tests/margin_test.py +++ b/control/tests/margin_test.py @@ -336,17 +336,19 @@ def test_zmore_stability_margins(tsys_zmore): @pytest.mark.parametrize( 'cnum, cden, dt,' - 'ref,' - 'rtol', - [([2], [1, 3, 2, 0], 1e-2, # gh-465 - (2.9558, 32.8170, 0.43584, 1.4037, 0.74953, 0.97079), - 0.1 # very crude tolerance, because the gradients are not great - ), - ([2], [1, 3, 3, 1], .1, # 2/(s+1)**3 - [3.4927, 69.9996, 0.5763, 1.6283, 0.7631, 1.2019], - 1e-3)]) -def test_stability_margins_discrete(cnum, cden, dt, ref, rtol): + 'ref,', + [( # gh-465 + [2], [1, 3, 2, 0], 1e-2, + (2.9558, 32.390, 0.43584, 1.4037, 0.74951, 0.97079)), + ( # 2/(s+1)**3 + [2], [1, 3, 3, 1], .1, + [3.4927, 65.4212, 0.5763, 1.6283, 0.76625, 1.2019]), + ( # gh-523 + [1.1 * 4 * np.pi**2], [1, 2 * 0.2 * 2 * np.pi, 4 * np.pi**2], .05, + [2.3842, 18.161, 0.26953, 11.712, 8.7478, 9.1504]), + ]) +def test_stability_margins_discrete(cnum, cden, dt, ref): """Test stability_margins with discrete TF input""" tf = TransferFunction(cnum, cden).sample(dt) out = stability_margins(tf) - assert_allclose(out, ref, rtol=rtol) + assert_allclose(out, ref, rtol=1e-4) From 48a18d6218b9b17befdd5d84f6d0b612bdc34815 Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sat, 30 Jan 2021 01:54:09 +0100 Subject: [PATCH 2/2] revert the removal of rtol for discrete margin test: conda on python3.6 is not as precise --- control/tests/margin_test.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/control/tests/margin_test.py b/control/tests/margin_test.py index 6f4c3e41a..fbd79c60b 100644 --- a/control/tests/margin_test.py +++ b/control/tests/margin_test.py @@ -336,19 +336,23 @@ def test_zmore_stability_margins(tsys_zmore): @pytest.mark.parametrize( 'cnum, cden, dt,' - 'ref,', + 'ref,' + 'rtol', [( # gh-465 [2], [1, 3, 2, 0], 1e-2, - (2.9558, 32.390, 0.43584, 1.4037, 0.74951, 0.97079)), + [2.9558, 32.390, 0.43584, 1.4037, 0.74951, 0.97079], + 2e-3), # the gradient of the function reduces numerical precision ( # 2/(s+1)**3 [2], [1, 3, 3, 1], .1, - [3.4927, 65.4212, 0.5763, 1.6283, 0.76625, 1.2019]), + [3.4927, 65.4212, 0.5763, 1.6283, 0.76625, 1.2019], + 1e-4), ( # gh-523 [1.1 * 4 * np.pi**2], [1, 2 * 0.2 * 2 * np.pi, 4 * np.pi**2], .05, - [2.3842, 18.161, 0.26953, 11.712, 8.7478, 9.1504]), + [2.3842, 18.161, 0.26953, 11.712, 8.7478, 9.1504], + 1e-4), ]) -def test_stability_margins_discrete(cnum, cden, dt, ref): +def test_stability_margins_discrete(cnum, cden, dt, ref, rtol): """Test stability_margins with discrete TF input""" tf = TransferFunction(cnum, cden).sample(dt) out = stability_margins(tf) - assert_allclose(out, ref, rtol=1e-4) + assert_allclose(out, ref, rtol=rtol) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy