Skip to content

Commit 96cc124

Browse files
committed
fix python-control#523: finding z for |H(z)|=1 computed the wrong polynomials
1 parent 6d51358 commit 96cc124

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

control/margins.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,14 @@ def _poly_z_real_crossing(num, den, num_inv_zp, den_inv_zq, p_q, dt, epsw):
156156
return z, w
157157

158158

159-
def _poly_z_mag1_crossing(num, den, num_inv, den_inv, p_q, dt, epsw):
159+
def _poly_z_mag1_crossing(num, den, num_inv_zp, den_inv_zq, p_q, dt, epsw):
160160
# |H(z)| = 1, H(z)*H(1/z)=1, num(z)*num(1/z) == den(z)*den(1/z)
161-
p1 = np.polymul(num, num_inv)
162-
p2 = np.polymul(den, den_inv)
161+
p1 = np.polymul(num, num_inv_zp)
162+
p2 = np.polymul(den, den_inv_zq)
163163
if p_q < 0:
164+
# * z**(-p_q)
164165
x = [1] + [0] * (-p_q)
165-
p2 = np.polymul(p2, x)
166+
p1 = np.polymul(p1, x)
166167
z = np.roots(np.polysub(p1, p2))
167168
eps = np.finfo(float).eps**(1 / len(p2))
168169
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):
171172
return z, w
172173

173174

174-
def _poly_z_wstab(num, den, num_inv, den_inv, p_q, dt, epsw):
175+
def _poly_z_wstab(num, den, num_inv_zp, den_inv_zq, p_q, dt, epsw):
175176
# Stability margin: Minimum distance to -1
176177

177178
# TODO: Find a way to solve for z or omega analytically with given

control/tests/margin_test.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,19 @@ def test_zmore_stability_margins(tsys_zmore):
336336

337337
@pytest.mark.parametrize(
338338
'cnum, cden, dt,'
339-
'ref,'
340-
'rtol',
341-
[([2], [1, 3, 2, 0], 1e-2, # gh-465
342-
(2.9558, 32.8170, 0.43584, 1.4037, 0.74953, 0.97079),
343-
0.1 # very crude tolerance, because the gradients are not great
344-
),
345-
([2], [1, 3, 3, 1], .1, # 2/(s+1)**3
346-
[3.4927, 69.9996, 0.5763, 1.6283, 0.7631, 1.2019],
347-
1e-3)])
348-
def test_stability_margins_discrete(cnum, cden, dt, ref, rtol):
339+
'ref,',
340+
[( # gh-465
341+
[2], [1, 3, 2, 0], 1e-2,
342+
(2.9558, 32.390, 0.43584, 1.4037, 0.74951, 0.97079)),
343+
( # 2/(s+1)**3
344+
[2], [1, 3, 3, 1], .1,
345+
[3.4927, 65.4212, 0.5763, 1.6283, 0.76625, 1.2019]),
346+
( # gh-523
347+
[1.1 * 4 * np.pi**2], [1, 2 * 0.2 * 2 * np.pi, 4 * np.pi**2], .05,
348+
[2.3842, 18.161, 0.26953, 11.712, 8.7478, 9.1504]),
349+
])
350+
def test_stability_margins_discrete(cnum, cden, dt, ref):
349351
"""Test stability_margins with discrete TF input"""
350352
tf = TransferFunction(cnum, cden).sample(dt)
351353
out = stability_margins(tf)
352-
assert_allclose(out, ref, rtol=rtol)
354+
assert_allclose(out, ref, rtol=1e-4)

0 commit comments

Comments
 (0)