Skip to content

Commit 96e44fe

Browse files
committed
unit tests for infinite frequency response values, warnings
1 parent b67eb7d commit 96e44fe

3 files changed

Lines changed: 74 additions & 3 deletions

File tree

control/lti.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,8 +644,9 @@ def dcgain(sys):
644644
Returns
645645
-------
646646
gain : ndarray
647-
The zero-frequency gain, or np.nan if the system has a pole
648-
at the origin
647+
The zero-frequency gain, or np.inf if the system has a pole at the
648+
origin, np.nan if there is a pole/zero cancellation at the origin.
649+
649650
"""
650651
return sys.dcgain()
651652

control/tests/freqresp_test.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,73 @@ def test_phase_wrap(TF, wrap_phase, min_phase, max_phase):
364364
mag, phase, omega = ctrl.bode(TF, wrap_phase=wrap_phase)
365365
assert(min(phase) >= min_phase)
366366
assert(max(phase) <= max_phase)
367+
368+
369+
def test_freqresp_warn_infinite():
370+
"""Test evaluation of transfer functions at the origin"""
371+
sys_finite = ctrl.tf([1], [1, 0.01])
372+
sys_infinite = ctrl.tf([1], [1, 0.01, 0])
373+
374+
# Transfer function with finite zero frequency gain
375+
np.testing.assert_almost_equal(sys_finite(0), 100)
376+
np.testing.assert_almost_equal(sys_finite(0, warn_infinite=False), 100)
377+
np.testing.assert_almost_equal(sys_finite(0, warn_infinite=True), 100)
378+
379+
# Transfer function with infinite zero frequency gain
380+
with pytest.warns(RuntimeWarning, match="divide by zero"):
381+
np.testing.assert_almost_equal(sys_infinite(0), np.inf)
382+
with pytest.warns(RuntimeWarning, match="divide by zero"):
383+
np.testing.assert_almost_equal(
384+
sys_infinite(0, warn_infinite=True), np.inf)
385+
np.testing.assert_almost_equal(sys_infinite(0, warn_infinite=False), np.inf)
386+
387+
# Switch to state space
388+
sys_finite = ctrl.tf2ss(sys_finite)
389+
sys_infinite = ctrl.tf2ss(sys_infinite)
390+
391+
# State space system with finite zero frequency gain
392+
np.testing.assert_almost_equal(sys_finite(0), 100)
393+
np.testing.assert_almost_equal(sys_finite(0, warn_infinite=False), 100)
394+
np.testing.assert_almost_equal(sys_finite(0, warn_infinite=True), 100)
395+
396+
# State space system with infinite zero frequency gain
397+
with pytest.warns(RuntimeWarning, match="not finite"):
398+
np.testing.assert_almost_equal(sys_infinite(0), np.inf)
399+
with pytest.warns(RuntimeWarning, match="not finite"):
400+
np.testing.assert_almost_equal(sys_infinite(0), np.inf)
401+
np.testing.assert_almost_equal(sys_infinite(0, warn_infinite=True), np.inf)
402+
np.testing.assert_almost_equal(sys_infinite(0, warn_infinite=False), np.inf)
403+
404+
405+
def test_dcgain_consistency():
406+
"""Test to make sure that DC gain is consistently evaluated"""
407+
# Set up transfer function with pole at the origin
408+
sys_tf = ctrl.tf([1], [1, 0])
409+
assert 0 in sys_tf.pole()
410+
411+
# Set up state space system with pole at the origin
412+
sys_ss = ctrl.tf2ss(sys_tf)
413+
assert 0 in sys_ss.pole()
414+
415+
# Evaluation
416+
np.testing.assert_equal(sys_tf(0), np.inf + 0j)
417+
np.testing.assert_equal(sys_ss(0), np.inf + 0j)
418+
np.testing.assert_equal(sys_tf.dcgain(), np.inf + 0j)
419+
np.testing.assert_equal(sys_ss.dcgain(), np.inf + 0j)
420+
421+
# Set up transfer function with pole, zero at the origin
422+
sys_tf = ctrl.tf([1, 0], [1, 0])
423+
assert 0 in sys_tf.pole()
424+
assert 0 in sys_tf.zero()
425+
426+
sys_ss = ctrl.tf2ss(ctrl.tf([1, 0], [1, 1])) * \
427+
ctrl.tf2ss(ctrl.tf([1], [1, 0]))
428+
assert 0 in sys_ss.pole()
429+
assert 0 in sys_ss.zero()
430+
431+
# Pole and zero at the origin should give nan for the response
432+
np.testing.assert_equal(sys_tf(0), np.nan)
433+
np.testing.assert_equal(sys_tf.dcgain(), np.nan)
434+
# TODO: state space cases not yet working
435+
# np.testing.assert_equal(sys_ss(0), np.nan)
436+
# np.testing.assert_equal(sys_ss.dcgain(), np.nan)

control/tests/statesp_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ def test_dc_gain_discr(self):
523523
@pytest.mark.parametrize("dt", [None, 0, 1, True],
524524
ids=["dtNone", "c", "dt1", "dtTrue"])
525525
def test_dc_gain_integrator(self, outputs, inputs, dt):
526-
"""DC gain when eigenvalue at DC returns appropriately sized array of nan.
526+
"""DC gain w/ pole at origin returns appropriately sized array of inf.
527527
528528
the SISO case is also tested in test_dc_gain_{cont,discr}
529529
time systems (dt=0)

0 commit comments

Comments
 (0)