Skip to content

Commit b9dad5e

Browse files
authored
fix computation of default response time for constant systems (#383)
* fix computation of default response time for constant systems * add single function to compute response times
1 parent 6b24bb4 commit b9dad5e

2 files changed

Lines changed: 37 additions & 27 deletions

File tree

control/tests/timeresp_test.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,21 @@ def test_step_response(self):
9494
np.testing.assert_array_equal(Tc.shape, Td.shape)
9595
np.testing.assert_array_equal(youtc.shape, youtd.shape)
9696

97+
# Recreate issue #374 ("Bug in step_response()")
98+
def test_step_nostates(self):
99+
# Continuous time, constant system
100+
sys = TransferFunction([1], [1])
101+
t, y = step_response(sys)
102+
np.testing.assert_array_equal(y, np.ones(len(t)))
103+
104+
# Discrete time, constant system
105+
sys = TransferFunction([1], [1], 1)
106+
t, y = step_response(sys)
107+
np.testing.assert_array_equal(y, np.ones(len(t)))
108+
97109
def test_step_info(self):
98110
# From matlab docs:
99-
sys = TransferFunction([1,5,5],[1,1.65,5,6.5,2])
111+
sys = TransferFunction([1, 5, 5], [1, 1.65, 5, 6.5, 2])
100112
Strue = {
101113
'RiseTime': 3.8456,
102114
'SettlingTime': 27.9762,

control/timeresp.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,7 @@ def step_response(sys, T=None, X0=0., input=None, output=None,
512512
"""
513513
sys = _get_ss_simo(sys, input, output)
514514
if T is None:
515-
if isctime(sys):
516-
T = _default_response_times(sys.A, 100)
517-
else:
518-
# For discrete time, use integers
519-
tvec = _default_response_times(sys.A, 100)
520-
T = range(int(np.ceil(max(tvec))))
521-
515+
T = _get_response_times(sys, N=100)
522516
U = np.ones_like(T)
523517

524518
T, yout, xout = forced_response(sys, T, U, X0, transpose=transpose,
@@ -573,12 +567,7 @@ def step_info(sys, T=None, SettlingTimeThreshold=0.02,
573567
'''
574568
sys = _get_ss_simo(sys)
575569
if T is None:
576-
if isctime(sys):
577-
T = _default_response_times(sys.A, 1000)
578-
else:
579-
# For discrete time, use integers
580-
tvec = _default_response_times(sys.A, 1000)
581-
T = range(int(np.ceil(max(tvec))))
570+
T = _get_response_times(sys, N=1000)
582571

583572
T, yout = step_response(sys, T)
584573

@@ -697,12 +686,8 @@ def initial_response(sys, T=None, X0=0., input=0, output=None,
697686
# Create time and input vectors; checking is done in forced_response(...)
698687
# The initial vector X0 is created in forced_response(...) if necessary
699688
if T is None:
700-
if isctime(sys):
701-
T = _default_response_times(sys.A, 1000)
702-
else:
703-
# For discrete time, use integers
704-
tvec = _default_response_times(sys.A, 1000)
705-
T = range(int(np.ceil(max(tvec))))
689+
# TODO: default step size inconsistent with step/impulse_response()
690+
T = _get_response_times(sys, N=1000)
706691
U = np.zeros_like(T)
707692

708693
T, yout, _xout = forced_response(sys, T, U, X0, transpose=transpose,
@@ -801,13 +786,7 @@ def impulse_response(sys, T=None, X0=0., input=0, output=None,
801786

802787
# Compute T and U, no checks necessary, they will be checked in lsim
803788
if T is None:
804-
if isctime(sys):
805-
T = _default_response_times(sys.A, 100)
806-
else:
807-
# For discrete time, use integers
808-
tvec = _default_response_times(sys.A, 100)
809-
T = range(int(np.ceil(max(tvec))))
810-
789+
T = _get_response_times(sys, N=100)
811790
U = np.zeros_like(T)
812791

813792
# Compute new X0 that contains the impulse
@@ -828,3 +807,22 @@ def impulse_response(sys, T=None, X0=0., input=0, output=None,
828807
return T, yout, _xout
829808

830809
return T, yout
810+
811+
812+
# Utility function to get response times
813+
def _get_response_times(sys, N=100):
814+
if isctime(sys):
815+
if sys.A.shape == (0, 0):
816+
# No dynamics; use the unit time interval
817+
T = np.linspace(0, 1, N, endpoint=False)
818+
else:
819+
T = _default_response_times(sys.A, N)
820+
else:
821+
# For discrete time, use integers
822+
if sys.A.shape == (0, 0):
823+
# No dynamics; use N time steps
824+
T = range(N)
825+
else:
826+
tvec = _default_response_times(sys.A, N)
827+
T = range(int(np.ceil(max(tvec))))
828+
return T

0 commit comments

Comments
 (0)