99# specific unit tests will do that.
1010
1111import unittest
12+ from distutils .version import StrictVersion
13+
1214import numpy as np
15+ import pytest
16+ import scipy as sp
17+
1318from control .timeresp import *
1419from control .timeresp import _ideal_tfinal_and_dt , _default_time_vector
1520from control .statesp import *
@@ -29,11 +34,11 @@ def setUp(self):
2934 # Create some transfer functions
3035 self .siso_tf1 = TransferFunction ([1 ], [1 , 2 , 1 ])
3136 self .siso_tf2 = _convert_to_transfer_function (self .siso_ss1 )
32-
37+
3338 # tests for pole cancellation
34- self .pole_cancellation = TransferFunction ([1.067e+05 , 5.791e+04 ],
39+ self .pole_cancellation = TransferFunction ([1.067e+05 , 5.791e+04 ],
3540 [10.67 , 1.067e+05 , 5.791e+04 ])
36- self .no_pole_cancellation = TransferFunction ([1.881e+06 ],
41+ self .no_pole_cancellation = TransferFunction ([1.881e+06 ],
3742 [188.1 , 1.881e+06 ])
3843
3944 # Create MIMO system, contains ``siso_ss1`` twice
@@ -177,8 +182,8 @@ def test_step_info(self):
177182 # https://github.com/python-control/python-control/issues/440
178183 step_info_no_cancellation = step_info (self .no_pole_cancellation )
179184 step_info_cancellation = step_info (self .pole_cancellation )
180- for key in step_info_no_cancellation :
181- np .testing .assert_allclose (step_info_no_cancellation [key ],
185+ for key in step_info_no_cancellation :
186+ np .testing .assert_allclose (step_info_no_cancellation [key ],
182187 step_info_cancellation [key ], rtol = 1e-4 )
183188
184189 def test_impulse_response (self ):
@@ -218,6 +223,8 @@ def test_impulse_response(self):
218223 np .testing .assert_array_almost_equal (
219224 yy , np .vstack ((youttrue , np .zeros_like (youttrue ))), decimal = 4 )
220225
226+ @pytest .mark .skipif (StrictVersion (sp .__version__ ) < "1.3.0" ,
227+ reason = "requires SciPy 1.3.0 or greater" )
221228 def test_discrete_time_impulse (self ):
222229 # discrete time impulse sampled version should match cont time
223230 dt = 0.1
@@ -226,7 +233,7 @@ def test_discrete_time_impulse(self):
226233 sysdt = sys .sample (dt , 'impulse' )
227234 np .testing .assert_array_almost_equal (impulse_response (sys , t )[1 ],
228235 impulse_response (sysdt , t )[1 ])
229-
236+
230237 def test_initial_response (self ):
231238 # Test SISO system
232239 sys = self .siso_ss1
@@ -363,7 +370,7 @@ def test_step_robustness(self):
363370 "Unit test: https://github.com/python-control/python-control/issues/240"
364371 # Create 2 input, 2 output system
365372 num = [ [[0 ], [1 ]], [[1 ], [0 ]] ]
366-
373+
367374 den1 = [ [[1 ], [1 ,1 ]], [[1 ,4 ], [1 ]] ]
368375 sys1 = TransferFunction (num , den1 )
369376
@@ -381,47 +388,47 @@ def test_auto_generated_time_vector(self):
381388 ratio = 9.21034 * p # taken from code
382389 ratio2 = 25 * p
383390 np .testing .assert_array_almost_equal (
384- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , .5 ]))[0 ],
391+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , .5 ]))[0 ],
385392 (ratio / p ))
386393 np .testing .assert_array_almost_equal (
387- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , .5 ]).sample (.1 ))[0 ],
394+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , .5 ]).sample (.1 ))[0 ],
388395 (ratio2 / p ))
389396 # confirm a TF with poles at 0 and p simulates for ratio/p seconds
390397 np .testing .assert_array_almost_equal (
391- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , .5 , 0 ]))[0 ],
398+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , .5 , 0 ]))[0 ],
392399 (ratio2 / p ))
393400
394- # confirm a TF with a natural frequency of wn rad/s gets a
401+ # confirm a TF with a natural frequency of wn rad/s gets a
395402 # dt of 1/(ratio*wn)
396403 wn = 10
397404 ratio_dt = 1 / (0.025133 * ratio * wn )
398405 np .testing .assert_array_almost_equal (
399- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 0 , wn ** 2 ]))[1 ],
406+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 0 , wn ** 2 ]))[1 ],
400407 1 / (ratio_dt * ratio * wn ))
401408 wn = 100
402409 np .testing .assert_array_almost_equal (
403- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 0 , wn ** 2 ]))[1 ],
410+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 0 , wn ** 2 ]))[1 ],
404411 1 / (ratio_dt * ratio * wn ))
405412 zeta = .1
406413 np .testing .assert_array_almost_equal (
407- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]))[1 ],
414+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]))[1 ],
408415 1 / (ratio_dt * ratio * wn ))
409416 # but a smapled one keeps its dt
410417 np .testing .assert_array_almost_equal (
411- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]).sample (.1 ))[1 ],
418+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]).sample (.1 ))[1 ],
412419 .1 )
413420 np .testing .assert_array_almost_equal (
414- np .diff (initial_response (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]).sample (.1 ))[0 ][0 :2 ]),
421+ np .diff (initial_response (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]).sample (.1 ))[0 ][0 :2 ]),
415422 .1 )
416423 np .testing .assert_array_almost_equal (
417- _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]))[1 ],
424+ _ideal_tfinal_and_dt (TransferFunction (1 , [1 , 2 * zeta * wn , wn ** 2 ]))[1 ],
418425 1 / (ratio_dt * ratio * wn ))
419-
420-
426+
427+
421428 # TF with fast oscillations simulates only 5000 time steps even with long tfinal
422- self .assertEqual (5000 ,
429+ self .assertEqual (5000 ,
423430 len (_default_time_vector (TransferFunction (1 , [1 , 0 , wn ** 2 ]),tfinal = 100 )))
424-
431+
425432 sys = TransferFunction (1 , [1 , .5 , 0 ])
426433 sysdt = TransferFunction (1 , [1 , .5 , 0 ], .1 )
427434 # test impose number of time steps
@@ -430,16 +437,16 @@ def test_auto_generated_time_vector(self):
430437 self .assertNotEqual (15 , len (step_response (sysdt , T_num = 15 )[0 ]))
431438 # test impose final time
432439 np .testing .assert_array_almost_equal (
433- 100 ,
440+ 100 ,
434441 np .ceil (step_response (sys , 100 )[0 ][- 1 ]))
435442 np .testing .assert_array_almost_equal (
436- 100 ,
443+ 100 ,
437444 np .ceil (step_response (sysdt , 100 )[0 ][- 1 ]))
438445 np .testing .assert_array_almost_equal (
439- 100 ,
446+ 100 ,
440447 np .ceil (impulse_response (sys , 100 )[0 ][- 1 ]))
441448 np .testing .assert_array_almost_equal (
442- 100 ,
449+ 100 ,
443450 np .ceil (initial_response (sys , 100 )[0 ][- 1 ]))
444451
445452
@@ -490,7 +497,7 @@ def test_time_vector(self):
490497 np .testing .assert_array_equal (tout , Tin1 )
491498
492499 # MIMO forced response
493- tout , yout , xout = forced_response (self .mimo_dss1 , Tin1 ,
500+ tout , yout , xout = forced_response (self .mimo_dss1 , Tin1 ,
494501 (np .sin (Tin1 ), np .cos (Tin1 )),
495502 mimo_x0 )
496503 self .assertEqual (np .shape (tout ), np .shape (yout [0 ,:]))
0 commit comments