Skip to content

Commit ebff125

Browse files
authored
Merge pull request #1106 from murrayrm/fix_phase_crossover-28Jan2025
Turn off warn_infinite for phase_crossover_frequencies() calculation
2 parents c29e73f + d9e44d2 commit ebff125

File tree

2 files changed

+15
-11
lines changed

2 files changed

+15
-11
lines changed

control/margins.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,16 @@ def _poly_iw_sqr(pol_iw):
8181

8282
def _poly_iw_real_crossing(num_iw, den_iw, epsw):
8383
# Return w where imag(H(iw)) == 0
84+
85+
# Compute the imaginary part of H = (num.r + j num.i)/(den.r + j den.i)
8486
test_w = np.polysub(np.polymul(num_iw.imag, den_iw.real),
8587
np.polymul(num_iw.real, den_iw.imag))
88+
89+
# Find the real-valued w > 0 where imag(H(iw)) = 0
8690
w = np.roots(test_w)
8791
w = np.real(w[np.isreal(w)])
8892
w = w[w >= epsw]
93+
8994
return w
9095

9196

@@ -471,7 +476,7 @@ def phase_crossover_frequencies(sys):
471476
omega : ndarray
472477
1d array of (non-negative) frequencies where Nyquist plot
473478
intersects the real axis
474-
gain : ndarray
479+
gains : ndarray
475480
1d array of corresponding gains
476481
477482
Examples
@@ -493,13 +498,13 @@ def phase_crossover_frequencies(sys):
493498
omega = _poly_iw_real_crossing(num_iw, den_iw, 0.)
494499

495500
# using real() to avoid rounding errors and results like 1+0j
496-
gain = np.real(evalfr(sys, 1J * omega))
501+
gains = np.real(sys(omega * 1j, warn_infinite=False))
497502
else:
498503
zargs = _poly_z_invz(sys)
499504
z, omega = _poly_z_real_crossing(*zargs, epsw=0.)
500-
gain = np.real(evalfr(sys, z))
505+
gains = np.real(sys(z, warn_infinite=False))
501506

502-
return omega, gain
507+
return omega, gains
503508

504509

505510
def margin(*args):

control/tests/margin_test.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@
1212
from numpy import inf, nan
1313
from numpy.testing import assert_allclose
1414

15-
from control.frdata import FrequencyResponseData
16-
from control.margins import (margin, phase_crossover_frequencies,
17-
stability_margins)
18-
from control.statesp import StateSpace
19-
from control.xferfcn import TransferFunction
20-
from control.exception import ControlMIMONotImplemented
15+
from control import ControlMIMONotImplemented, FrequencyResponseData, \
16+
StateSpace, TransferFunction, margin, phase_crossover_frequencies, \
17+
stability_margins
2118

2219
s = TransferFunction.s
2320

@@ -111,15 +108,17 @@ def test_margin_3input(tsys):
111108
out = margin((mag, phase*180/np.pi, omega_))
112109
assert_allclose(out, np.array(refout)[[0, 1, 3, 4]], atol=1.5e-3)
113110

114-
115111
@pytest.mark.parametrize(
116112
'tfargs, omega_ref, gain_ref',
117113
[(([1], [1, 2, 3, 4]), [1.7325, 0.], [-0.5, 0.25]),
118114
(([1], [1, 1]), [0.], [1.]),
119115
(([2], [1, 3, 3, 1]), [1.732, 0.], [-0.25, 2.]),
120116
((np.array([3, 11, 3]) * 1e-4, [1., -2.7145, 2.4562, -0.7408], .1),
121117
[1.6235, 0.], [-0.28598, 1.88889]),
118+
(([200.0], [1.0, 21.0, 20.0, 0.0]),
119+
[4.47213595, 0], [-0.47619048, inf]),
122120
])
121+
@pytest.mark.filterwarnings("error")
123122
def test_phase_crossover_frequencies(tfargs, omega_ref, gain_ref):
124123
"""Test phase_crossover_frequencies() function"""
125124
sys = TransferFunction(*tfargs)

0 commit comments

Comments
 (0)