Expand Up @@ -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 * Expand All @@ -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 Expand Down Expand Up @@ -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): Expand Down Expand Up @@ -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 Expand All @@ -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 Expand Down Expand Up @@ -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) Expand All @@ -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 Expand All @@ -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])) Expand Down Expand Up @@ -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,:])) Expand Down