Skip to content

Commit 813c937

Browse files
committed
fix step_info settling time calculation for constant signals
1 parent 6406868 commit 813c937

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

control/tests/timeresp_test.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
"""timeresp_test.py - test time response functions"""
22

33
from copy import copy
4+
from math import isclose
45

56
import numpy as np
67
import pytest
78
import scipy as sp
89

910
import control as ct
1011
from control import StateSpace, TransferFunction, c2d, isctime, ss2tf, tf2ss
11-
from control.exception import slycot_check, pandas_check
12+
from control.exception import pandas_check, slycot_check
1213
from control.tests.conftest import slycotonly
13-
from control.timeresp import (_default_time_vector, _ideal_tfinal_and_dt,
14-
forced_response, impulse_response,
15-
initial_response, step_info, step_response)
14+
from control.timeresp import _default_time_vector, _ideal_tfinal_and_dt, \
15+
forced_response, impulse_response, initial_response, step_info, \
16+
step_response
1617

1718

1819
class TSys:
@@ -1275,3 +1276,45 @@ def test_no_pandas():
12751276
# Convert to pandas
12761277
with pytest.raises(ImportError, match="pandas"):
12771278
df = resp.to_pandas()
1279+
1280+
1281+
# https://github.com/python-control/python-control/issues/1014
1282+
def test_step_info_nonstep():
1283+
# Pass a constant input
1284+
timepts = np.linspace(0, 10, endpoint=False)
1285+
y_const = np.ones_like(timepts)
1286+
1287+
# Constant value of 1
1288+
step_info = ct.step_info(y_const, timepts)
1289+
assert step_info['RiseTime'] == 0
1290+
assert step_info['SettlingTime'] == 0
1291+
assert step_info['SettlingMin'] == 1
1292+
assert step_info['SettlingMax'] == 1
1293+
assert step_info['Overshoot'] == 0
1294+
assert step_info['Undershoot'] == 0
1295+
assert step_info['Peak'] == 1
1296+
assert step_info['PeakTime'] == 0
1297+
assert step_info['SteadyStateValue'] == 1
1298+
1299+
# Constant value of -1
1300+
step_info = ct.step_info(-y_const, timepts)
1301+
assert step_info['RiseTime'] == 0
1302+
assert step_info['SettlingTime'] == 0
1303+
assert step_info['SettlingMin'] == -1
1304+
assert step_info['SettlingMax'] == -1
1305+
assert step_info['Overshoot'] == 0
1306+
assert step_info['Undershoot'] == 0
1307+
assert step_info['Peak'] == 1
1308+
assert step_info['PeakTime'] == 0
1309+
assert step_info['SteadyStateValue'] == -1
1310+
1311+
# Ramp from -1 to 1
1312+
step_info = ct.step_info(-1 + 2 * timepts/10, timepts)
1313+
assert step_info['RiseTime'] == 3.8
1314+
assert step_info['SettlingTime'] == 9.8
1315+
assert isclose(step_info['SettlingMin'], 0.88)
1316+
assert isclose(step_info['SettlingMax'], 0.96)
1317+
assert step_info['Overshoot'] == 0
1318+
assert step_info['Peak'] == 1
1319+
assert step_info['PeakTime'] == 0
1320+
assert isclose(step_info['SteadyStateValue'], 0.96)

control/timeresp.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,17 +1674,19 @@ def step_info(sysdata, T=None, T_num=None, yfinal=None, params=None,
16741674

16751675
if not np.isnan(InfValue) and not np.isinf(InfValue):
16761676
# RiseTime
1677-
tr_lower_index = np.where(
1677+
tr_lower_index = np.nonzero(
16781678
sgnInf * (yout - RiseTimeLimits[0] * InfValue) >= 0
16791679
)[0][0]
1680-
tr_upper_index = np.where(
1680+
tr_upper_index = np.nonzero(
16811681
sgnInf * (yout - RiseTimeLimits[1] * InfValue) >= 0
16821682
)[0][0]
16831683
rise_time = T[tr_upper_index] - T[tr_lower_index]
16841684

16851685
# SettlingTime
1686-
settled = np.where(
1687-
np.abs(yout/InfValue-1) >= SettlingTimeThreshold)[0][-1]+1
1686+
outside_threshold = np.nonzero(
1687+
np.abs(yout/InfValue - 1) >= SettlingTimeThreshold)[0]
1688+
settled = 0 if outside_threshold.size == 0 \
1689+
else outside_threshold[-1] + 1
16881690
# MIMO systems can have unsettled channels without infinite
16891691
# InfValue
16901692
if settled < len(T):

0 commit comments

Comments
 (0)