Merge pull request #482 from bnavigator/skip-impulse-test · python-control/python-control@26206dc
@@ -9,7 +9,12 @@
99# specific unit tests will do that.
10101111import 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
3035self.siso_tf1 = TransferFunction([1], [1, 2, 1])
3136self.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])
38433944# 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
178183step_info_no_cancellation = step_info(self.no_pole_cancellation)
179184step_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],
182187step_info_cancellation[key], rtol=1e-4)
183188184189def test_impulse_response(self):
@@ -218,6 +223,8 @@ def test_impulse_response(self):
218223np.testing.assert_array_almost_equal(
219224yy, np.vstack((youttrue, np.zeros_like(youttrue))), decimal=4)
220225226+@pytest.mark.skipif(StrictVersion(sp.__version__) < "1.3.0",
227+ reason="requires SciPy 1.3.0 or greater")
221228def test_discrete_time_impulse(self):
222229# discrete time impulse sampled version should match cont time
223230dt = 0.1
@@ -226,7 +233,7 @@ def test_discrete_time_impulse(self):
226233sysdt = sys.sample(dt, 'impulse')
227234np.testing.assert_array_almost_equal(impulse_response(sys, t)[1],
228235impulse_response(sysdt, t)[1])
229-236+230237def test_initial_response(self):
231238# Test SISO system
232239sys = 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
365372num = [ [[0], [1]], [[1], [0]] ]
366-373+367374den1 = [ [[1], [1,1]], [[1,4], [1]] ]
368375sys1 = TransferFunction(num, den1)
369376@@ -381,47 +388,47 @@ def test_auto_generated_time_vector(self):
381388ratio = 9.21034*p # taken from code
382389ratio2 = 25*p
383390np.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))
386393np.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
390397np.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))
393400394-# 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)
396403wn = 10
397404ratio_dt = 1/(0.025133 * ratio * wn)
398405np.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],
4004071/(ratio_dt*ratio*wn))
401408wn = 100
402409np.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],
4044111/(ratio_dt*ratio*wn))
405412zeta = .1
406413np.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],
4084151/(ratio_dt*ratio*wn))
409416# but a smapled one keeps its dt
410417np.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)
413420np.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)
416423np.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],
4184251/(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,
423430len(_default_time_vector(TransferFunction(1, [1, 0, wn**2]),tfinal=100)))
424-431+425432sys = TransferFunction(1, [1, .5, 0])
426433sysdt = TransferFunction(1, [1, .5, 0], .1)
427434# test impose number of time steps
@@ -430,16 +437,16 @@ def test_auto_generated_time_vector(self):
430437self.assertNotEqual(15, len(step_response(sysdt, T_num=15)[0]))
431438# test impose final time
432439np.testing.assert_array_almost_equal(
433-100,
440+100,
434441np.ceil(step_response(sys, 100)[0][-1]))
435442np.testing.assert_array_almost_equal(
436-100,
443+100,
437444np.ceil(step_response(sysdt, 100)[0][-1]))
438445np.testing.assert_array_almost_equal(
439-100,
446+100,
440447np.ceil(impulse_response(sys, 100)[0][-1]))
441448np.testing.assert_array_almost_equal(
442-100,
449+100,
443450np.ceil(initial_response(sys, 100)[0][-1]))
444451445452@@ -490,7 +497,7 @@ def test_time_vector(self):
490497np.testing.assert_array_equal(tout, Tin1)
491498492499# 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)),
495502mimo_x0)
496503self.assertEqual(np.shape(tout), np.shape(yout[0,:]))