diff --git a/control/margins.py b/control/margins.py index 301baaf57..019c866be 100644 --- a/control/margins.py +++ b/control/margins.py @@ -81,11 +81,16 @@ def _poly_iw_sqr(pol_iw): def _poly_iw_real_crossing(num_iw, den_iw, epsw): # Return w where imag(H(iw)) == 0 + + # Compute the imaginary part of H = (num.r + j num.i)/(den.r + j den.i) test_w = np.polysub(np.polymul(num_iw.imag, den_iw.real), np.polymul(num_iw.real, den_iw.imag)) + + # Find the real-valued w > 0 where imag(H(iw)) = 0 w = np.roots(test_w) w = np.real(w[np.isreal(w)]) w = w[w >= epsw] + return w @@ -471,7 +476,7 @@ def phase_crossover_frequencies(sys): omega : ndarray 1d array of (non-negative) frequencies where Nyquist plot intersects the real axis - gain : ndarray + gains : ndarray 1d array of corresponding gains Examples @@ -493,13 +498,13 @@ def phase_crossover_frequencies(sys): omega = _poly_iw_real_crossing(num_iw, den_iw, 0.) # using real() to avoid rounding errors and results like 1+0j - gain = np.real(evalfr(sys, 1J * omega)) + gains = np.real(sys(omega * 1j, warn_infinite=False)) else: zargs = _poly_z_invz(sys) z, omega = _poly_z_real_crossing(*zargs, epsw=0.) - gain = np.real(evalfr(sys, z)) + gains = np.real(sys(z, warn_infinite=False)) - return omega, gain + return omega, gains def margin(*args): diff --git a/control/tests/margin_test.py b/control/tests/margin_test.py index 07e21114f..43cd68ae3 100644 --- a/control/tests/margin_test.py +++ b/control/tests/margin_test.py @@ -12,12 +12,9 @@ from numpy import inf, nan from numpy.testing import assert_allclose -from control.frdata import FrequencyResponseData -from control.margins import (margin, phase_crossover_frequencies, - stability_margins) -from control.statesp import StateSpace -from control.xferfcn import TransferFunction -from control.exception import ControlMIMONotImplemented +from control import ControlMIMONotImplemented, FrequencyResponseData, \ + StateSpace, TransferFunction, margin, phase_crossover_frequencies, \ + stability_margins s = TransferFunction.s @@ -111,7 +108,6 @@ def test_margin_3input(tsys): out = margin((mag, phase*180/np.pi, omega_)) assert_allclose(out, np.array(refout)[[0, 1, 3, 4]], atol=1.5e-3) - @pytest.mark.parametrize( 'tfargs, omega_ref, gain_ref', [(([1], [1, 2, 3, 4]), [1.7325, 0.], [-0.5, 0.25]), @@ -119,7 +115,10 @@ def test_margin_3input(tsys): (([2], [1, 3, 3, 1]), [1.732, 0.], [-0.25, 2.]), ((np.array([3, 11, 3]) * 1e-4, [1., -2.7145, 2.4562, -0.7408], .1), [1.6235, 0.], [-0.28598, 1.88889]), + (([200.0], [1.0, 21.0, 20.0, 0.0]), + [4.47213595, 0], [-0.47619048, inf]), ]) +@pytest.mark.filterwarnings("error") def test_phase_crossover_frequencies(tfargs, omega_ref, gain_ref): """Test phase_crossover_frequencies() function""" sys = TransferFunction(*tfargs)
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: