From 90c564c5893973ce1ea0aa8d8430e4a76636b75e Mon Sep 17 00:00:00 2001 From: bnavigator Date: Tue, 29 Dec 2020 05:32:34 +0100 Subject: [PATCH] skip impulse sampling for old scipy --- control/tests/timeresp_test.py | 59 +++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/control/tests/timeresp_test.py b/control/tests/timeresp_test.py index 2c195b888..8020d8078 100644 --- a/control/tests/timeresp_test.py +++ b/control/tests/timeresp_test.py @@ -9,7 +9,12 @@ # specific unit tests will do that. import unittest +from distutils.version import StrictVersion + import numpy as np +import pytest +import scipy as sp + from control.timeresp import * from control.timeresp import _ideal_tfinal_and_dt, _default_time_vector from control.statesp import * @@ -29,11 +34,11 @@ def setUp(self): # Create some transfer functions self.siso_tf1 = TransferFunction([1], [1, 2, 1]) self.siso_tf2 = _convert_to_transfer_function(self.siso_ss1) - + # tests for pole cancellation - self.pole_cancellation = TransferFunction([1.067e+05, 5.791e+04], + self.pole_cancellation = TransferFunction([1.067e+05, 5.791e+04], [10.67, 1.067e+05, 5.791e+04]) - self.no_pole_cancellation = TransferFunction([1.881e+06], + self.no_pole_cancellation = TransferFunction([1.881e+06], [188.1, 1.881e+06]) # Create MIMO system, contains ``siso_ss1`` twice @@ -177,8 +182,8 @@ def test_step_info(self): # https://github.com/python-control/python-control/issues/440 step_info_no_cancellation = step_info(self.no_pole_cancellation) step_info_cancellation = step_info(self.pole_cancellation) - for key in step_info_no_cancellation: - np.testing.assert_allclose(step_info_no_cancellation[key], + for key in step_info_no_cancellation: + np.testing.assert_allclose(step_info_no_cancellation[key], step_info_cancellation[key], rtol=1e-4) def test_impulse_response(self): @@ -218,6 +223,8 @@ def test_impulse_response(self): np.testing.assert_array_almost_equal( yy, np.vstack((youttrue, np.zeros_like(youttrue))), decimal=4) + @pytest.mark.skipif(StrictVersion(sp.__version__) < "1.3.0", + reason="requires SciPy 1.3.0 or greater") def test_discrete_time_impulse(self): # discrete time impulse sampled version should match cont time dt = 0.1 @@ -226,7 +233,7 @@ def test_discrete_time_impulse(self): sysdt = sys.sample(dt, 'impulse') np.testing.assert_array_almost_equal(impulse_response(sys, t)[1], impulse_response(sysdt, t)[1]) - + def test_initial_response(self): # Test SISO system sys = self.siso_ss1 @@ -363,7 +370,7 @@ def test_step_robustness(self): "Unit test: https://github.com/python-control/python-control/issues/240" # Create 2 input, 2 output system num = [ [[0], [1]], [[1], [0]] ] - + den1 = [ [[1], [1,1]], [[1,4], [1]] ] sys1 = TransferFunction(num, den1) @@ -381,47 +388,47 @@ def test_auto_generated_time_vector(self): ratio = 9.21034*p # taken from code ratio2 = 25*p np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, .5]))[0], + _ideal_tfinal_and_dt(TransferFunction(1, [1, .5]))[0], (ratio/p)) np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, .5]).sample(.1))[0], + _ideal_tfinal_and_dt(TransferFunction(1, [1, .5]).sample(.1))[0], (ratio2/p)) # confirm a TF with poles at 0 and p simulates for ratio/p seconds np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, .5, 0]))[0], + _ideal_tfinal_and_dt(TransferFunction(1, [1, .5, 0]))[0], (ratio2/p)) - # confirm a TF with a natural frequency of wn rad/s gets a + # confirm a TF with a natural frequency of wn rad/s gets a # dt of 1/(ratio*wn) wn = 10 ratio_dt = 1/(0.025133 * ratio * wn) np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, 0, wn**2]))[1], + _ideal_tfinal_and_dt(TransferFunction(1, [1, 0, wn**2]))[1], 1/(ratio_dt*ratio*wn)) wn = 100 np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, 0, wn**2]))[1], + _ideal_tfinal_and_dt(TransferFunction(1, [1, 0, wn**2]))[1], 1/(ratio_dt*ratio*wn)) zeta = .1 np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]))[1], + _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]))[1], 1/(ratio_dt*ratio*wn)) # but a smapled one keeps its dt np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]).sample(.1))[1], + _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]).sample(.1))[1], .1) np.testing.assert_array_almost_equal( - np.diff(initial_response(TransferFunction(1, [1, 2*zeta*wn, wn**2]).sample(.1))[0][0:2]), + np.diff(initial_response(TransferFunction(1, [1, 2*zeta*wn, wn**2]).sample(.1))[0][0:2]), .1) np.testing.assert_array_almost_equal( - _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]))[1], + _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]))[1], 1/(ratio_dt*ratio*wn)) - - + + # TF with fast oscillations simulates only 5000 time steps even with long tfinal - self.assertEqual(5000, + self.assertEqual(5000, len(_default_time_vector(TransferFunction(1, [1, 0, wn**2]),tfinal=100))) - + sys = TransferFunction(1, [1, .5, 0]) sysdt = TransferFunction(1, [1, .5, 0], .1) # test impose number of time steps @@ -430,16 +437,16 @@ def test_auto_generated_time_vector(self): self.assertNotEqual(15, len(step_response(sysdt, T_num=15)[0])) # test impose final time np.testing.assert_array_almost_equal( - 100, + 100, np.ceil(step_response(sys, 100)[0][-1])) np.testing.assert_array_almost_equal( - 100, + 100, np.ceil(step_response(sysdt, 100)[0][-1])) np.testing.assert_array_almost_equal( - 100, + 100, np.ceil(impulse_response(sys, 100)[0][-1])) np.testing.assert_array_almost_equal( - 100, + 100, np.ceil(initial_response(sys, 100)[0][-1])) @@ -490,7 +497,7 @@ def test_time_vector(self): np.testing.assert_array_equal(tout, Tin1) # MIMO forced response - tout, yout, xout = forced_response(self.mimo_dss1, Tin1, + tout, yout, xout = forced_response(self.mimo_dss1, Tin1, (np.sin(Tin1), np.cos(Tin1)), mimo_x0) self.assertEqual(np.shape(tout), np.shape(yout[0,:]))