Skip to content

Commit e54a81b

Browse files
committed
Quiet down noisy MATLAB tests
Fixes python-control#31, suppressing warnings for converting from MIMO to SISO if the user has explicitly specified the input to use, in `step_response`, `initial_response`, and `impulse_response`. If a test should give a warning (such as an impulse response for a system with a direct feedthrough term), test that a warning was issued, but suppress the warning from the output of the test.
1 parent 6be2368 commit e54a81b

2 files changed

Lines changed: 52 additions & 27 deletions

File tree

control/tests/matlab_test.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import scipy as sp
1616
from control.matlab import *
1717
from control.frdata import FRD
18+
import warnings
1819

1920
# for running these through Matlab or Octave
2021
'''
@@ -133,11 +134,19 @@ def testPZmap(self):
133134
pzmap(self.siso_tf2, Plot=False);
134135

135136
def testStep(self):
136-
#Test SISO system
137-
sys = self.siso_ss1
138137
t = np.linspace(0, 1, 10)
138+
# Test transfer function
139+
yout, tout = step(self.siso_tf1, T=t)
140+
youttrue = np.array([0, 0.0057, 0.0213, 0.0446, 0.0739,
141+
0.1075, 0.1443, 0.1832, 0.2235, 0.2642])
142+
np.testing.assert_array_almost_equal(yout, youttrue, decimal=4)
143+
np.testing.assert_array_almost_equal(tout, t)
144+
145+
# Test SISO system with direct feedthrough
146+
sys = self.siso_ss1
139147
youttrue = np.array([9., 17.6457, 24.7072, 30.4855, 35.2234, 39.1165,
140148
42.3227, 44.9694, 47.1599, 48.9776])
149+
141150
yout, tout = step(sys, T=t)
142151
np.testing.assert_array_almost_equal(yout, youttrue, decimal=4)
143152
np.testing.assert_array_almost_equal(tout, t)
@@ -160,15 +169,26 @@ def testStep(self):
160169
np.testing.assert_array_almost_equal(y_11, youttrue, decimal=4)
161170

162171
def testImpulse(self):
163-
#Test SISO system
164-
sys = self.siso_ss1
165172
t = np.linspace(0, 1, 10)
166-
youttrue = np.array([86., 70.1808, 57.3753, 46.9975, 38.5766, 31.7344,
167-
26.1668, 21.6292, 17.9245, 14.8945])
168-
yout, tout = impulse(sys, T=t)
173+
# test transfer function
174+
yout, tout = impulse(self.siso_tf1, T=t)
175+
youttrue = np.array([0., 0.0994, 0.1779, 0.2388, 0.2850, 0.3188,
176+
0.3423, 0.3573, 0.3654, 0.3679])
169177
np.testing.assert_array_almost_equal(yout, youttrue, decimal=4)
170178
np.testing.assert_array_almost_equal(tout, t)
171179

180+
# produce a warning for a system with direct feedthrough
181+
with warnings.catch_warnings(record=True) as warn:
182+
#Test SISO system
183+
sys = self.siso_ss1
184+
youttrue = np.array([86., 70.1808, 57.3753, 46.9975, 38.5766, 31.7344,
185+
26.1668, 21.6292, 17.9245, 14.8945])
186+
yout, tout = impulse(sys, T=t)
187+
self.assertEqual(len(warn), 1)
188+
self.assertIn("direct feedthrough", str(warn[-1].message))
189+
np.testing.assert_array_almost_equal(yout, youttrue, decimal=4)
190+
np.testing.assert_array_almost_equal(tout, t)
191+
172192
#Test MIMO system, which contains ``siso_ss1`` twice
173193
sys = self.mimo_ss1
174194
y_00, _t = impulse(sys, T=t, input=0, output=0)
@@ -500,7 +520,7 @@ def testMinreal(self, verbose=False):
500520
# sys = ss(A, B, C, D)
501521

502522
sys = ss(A, B, C, D)
503-
sysr = minreal(sys)
523+
sysr = minreal(sys, verbose=verbose)
504524
self.assertEqual(sysr.states, 2)
505525
self.assertEqual(sysr.inputs, sys.inputs)
506526
self.assertEqual(sysr.outputs, sys.outputs)
@@ -509,12 +529,11 @@ def testMinreal(self, verbose=False):
509529

510530
s = tf([1, 0], [1])
511531
h = (s+1)*(s+2.00000000001)/(s+2)/(s**2+s+1)
512-
hm = minreal(h)
532+
hm = minreal(h, verbose=verbose)
513533
hr = (s+1)/(s**2+s+1)
514534
np.testing.assert_array_almost_equal(hm.num[0][0], hr.num[0][0])
515535
np.testing.assert_array_almost_equal(hm.den[0][0], hr.den[0][0])
516536

517-
@unittest.skip("skipping testSS2cont: not implemented for MIMO")
518537
def testSS2cont(self):
519538
sys = ss(
520539
np.mat("-3 4 2; -1 -3 0; 2 5 3"),
@@ -534,7 +553,7 @@ def testSS2cont(self):
534553
-0.304617775734327 0.075182622718853"""), sysd.B)
535554

536555

537-
@unittest.skip("skipping testCombi01: need to check/update margins")
556+
@unittest.skip("need to update margin command")
538557
def testCombi01(self):
539558
# test from a "real" case, combines tf, ss, connect and margin
540559
# this is a type 2 system, with phase starting at -180. The
@@ -586,6 +605,7 @@ def testCombi01(self):
586605
Hol = Hc*Hno*Hp
587606

588607
gm, pm, wg, wp = margin(Hol)
608+
# print("%f %f %f %f" % (gm, pm, wg, wp))
589609
self.assertAlmostEqual(gm, 3.32065569155)
590610
self.assertAlmostEqual(pm, 46.9740430224)
591611
self.assertAlmostEqual(wp, 0.0616288455466)

control/timeresp.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,25 @@ def f_dot(x, t):
388388

389389
return T, yout, xout
390390

391+
def _get_ss_simo(sys, input=None, output=None):
392+
"""Return a SISO or SIMO state-space version of sys
391393
392-
def step_response(sys, T=None, X0=0., input=0, output=None,
394+
If input is not specified, select first input and issue warning
395+
"""
396+
sys_ss = _convertToStateSpace(sys)
397+
if sys_ss.issiso():
398+
return sys_ss
399+
warn = False
400+
if input is None:
401+
# issue warning if input is not given
402+
warn = True
403+
input = 0
404+
if output is None:
405+
return _mimo2simo(sys_ss, input, warn_conversion=warn)
406+
else:
407+
return _mimo2siso(sys_ss, input, output, warn_conversion=warn)
408+
409+
def step_response(sys, T=None, X0=0., input=None, output=None,
393410
transpose=False, **keywords):
394411
# pylint: disable=W0622
395412
"""Step response of a linear system
@@ -450,11 +467,7 @@ def step_response(sys, T=None, X0=0., input=0, output=None,
450467
--------
451468
>>> T, yout = step_response(sys, T, X0)
452469
"""
453-
sys = _convertToStateSpace(sys)
454-
if output is None:
455-
sys = _mimo2simo(sys, input, warn_conversion=True)
456-
else:
457-
sys = _mimo2siso(sys, input, output, warn_conversion=True)
470+
sys = _get_ss_simo(sys, input, output)
458471
if T is None:
459472
if isctime(sys):
460473
T = _default_response_times(sys.A, 100)
@@ -532,11 +545,7 @@ def initial_response(sys, T=None, X0=0., input=0, output=None,
532545
--------
533546
>>> T, yout = initial_response(sys, T, X0)
534547
"""
535-
sys = _convertToStateSpace(sys)
536-
if output is None:
537-
sys = _mimo2simo(sys, input, warn_conversion=False)
538-
else:
539-
sys = _mimo2siso(sys, input, output, warn_conversion=False)
548+
sys = _get_ss_simo(sys, input, output)
540549

541550
# Create time and input vectors; checking is done in forced_response(...)
542551
# The initial vector X0 is created in forced_response(...) if necessary
@@ -610,11 +619,7 @@ def impulse_response(sys, T=None, X0=0., input=0, output=None,
610619
--------
611620
>>> T, yout = impulse_response(sys, T, X0)
612621
"""
613-
sys = _convertToStateSpace(sys)
614-
if output is None:
615-
sys = _mimo2simo(sys, input, warn_conversion=True)
616-
else:
617-
sys = _mimo2siso(sys, input, output, warn_conversion=True)
622+
sys = _get_ss_simo(sys, input, output)
618623

619624
# System has direct feedthrough, can't simulate impulse response numerically
620625
if np.any(sys.D != 0) and isctime(sys):

0 commit comments

Comments
 (0)