|
11 | 11 | import unittest |
12 | 12 | import numpy as np |
13 | 13 | from control.timeresp import * |
| 14 | +from control.timeresp import _ideal_tfinal_and_dt, _default_time_vector |
14 | 15 | from control.statesp import * |
15 | 16 | from control.xferfcn import TransferFunction, _convert_to_transfer_function |
16 | 17 | from control.dtime import c2d |
@@ -94,6 +95,7 @@ def test_step_response(self): |
94 | 95 | np.testing.assert_array_equal(Tc.shape, Td.shape) |
95 | 96 | np.testing.assert_array_equal(youtc.shape, youtd.shape) |
96 | 97 |
|
| 98 | + |
97 | 99 | # Recreate issue #374 ("Bug in step_response()") |
98 | 100 | def test_step_nostates(self): |
99 | 101 | # Continuous time, constant system |
@@ -346,10 +348,75 @@ def test_step_robustness(self): |
346 | 348 | sys2 = TransferFunction(num, den2) |
347 | 349 |
|
348 | 350 | # Compute step response from input 1 to output 1, 2 |
349 | | - t1, y1 = step_response(sys1, input=0) |
350 | | - t2, y2 = step_response(sys2, input=0) |
| 351 | + t1, y1 = step_response(sys1, input=0, T_num=100) |
| 352 | + t2, y2 = step_response(sys2, input=0, T_num=100) |
351 | 353 | np.testing.assert_array_almost_equal(y1, y2) |
352 | 354 |
|
| 355 | + def test_auto_generated_time_vector(self): |
| 356 | + # confirm a TF with a pole at p simulates for 7.0/p seconds |
| 357 | + p = 0.5 |
| 358 | + np.testing.assert_array_almost_equal( |
| 359 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, .5]))[0], |
| 360 | + (7/p)) |
| 361 | + np.testing.assert_array_almost_equal( |
| 362 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, .5]).sample(.1))[0], |
| 363 | + (7/p)) |
| 364 | + # confirm a TF with poles at 0 and p simulates for 7.0/p seconds |
| 365 | + np.testing.assert_array_almost_equal( |
| 366 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, .5, 0]))[0], |
| 367 | + (7/p)) |
| 368 | + # confirm a TF with a natural frequency of wn rad/s gets a |
| 369 | + # dt of 1/(7.0*wn) |
| 370 | + wn = 10 |
| 371 | + np.testing.assert_array_almost_equal( |
| 372 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, 0, wn**2]))[1], |
| 373 | + 1/(7.0*wn)) |
| 374 | + zeta = .1 |
| 375 | + np.testing.assert_array_almost_equal( |
| 376 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]))[1], |
| 377 | + 1/(7.0*wn)) |
| 378 | + # but a smapled one keeps its dt |
| 379 | + np.testing.assert_array_almost_equal( |
| 380 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]).sample(.1))[1], |
| 381 | + .1) |
| 382 | + np.testing.assert_array_almost_equal( |
| 383 | + np.diff(initial_response(TransferFunction(1, [1, 2*zeta*wn, wn**2]).sample(.1))[0][0:2]), |
| 384 | + .1) |
| 385 | + np.testing.assert_array_almost_equal( |
| 386 | + _ideal_tfinal_and_dt(TransferFunction(1, [1, 2*zeta*wn, wn**2]))[1], |
| 387 | + 1/(7.0*wn)) |
| 388 | + # TF with fast oscillations simulates only 5000 time steps even with long tfinal |
| 389 | + self.assertEqual(5000, |
| 390 | + len(_default_time_vector(TransferFunction(1, [1, 0, wn**2]),tfinal=100))) |
| 391 | + # and simulates for 7.0/dt time steps |
| 392 | + self.assertEqual( |
| 393 | + len(_default_time_vector(TransferFunction(1, [1, 0, wn**2]))), |
| 394 | + int(7.0/(1/(7.0*wn)))) |
| 395 | + |
| 396 | + sys = TransferFunction(1, [1, .5, 0]) |
| 397 | + sysdt = TransferFunction(1, [1, .5, 0], .1) |
| 398 | + # test impose number of time steps |
| 399 | + self.assertEqual(10, len(step_response(sys, T_num=10)[0])) |
| 400 | + self.assertEqual(10, len(step_response(sysdt, T_num=10)[0])) |
| 401 | + # test impose final time |
| 402 | + np.testing.assert_array_almost_equal( |
| 403 | + 100, |
| 404 | + step_response(sys, 100)[0][-1], |
| 405 | + decimal=.5) |
| 406 | + np.testing.assert_array_almost_equal( |
| 407 | + 100, |
| 408 | + step_response(sysdt, 100)[0][-1], |
| 409 | + decimal=.5) |
| 410 | + np.testing.assert_array_almost_equal( |
| 411 | + 100, |
| 412 | + impulse_response(sys, 100)[0][-1], |
| 413 | + decimal=.5) |
| 414 | + np.testing.assert_array_almost_equal( |
| 415 | + 100, |
| 416 | + initial_response(sys, 100)[0][-1], |
| 417 | + decimal=.5) |
| 418 | + |
| 419 | + |
353 | 420 | def test_time_vector(self): |
354 | 421 | "Unit test: https://github.com/python-control/python-control/issues/239" |
355 | 422 | # Discrete time simulations with specified time vectors |
|
0 commit comments