Repository navigation
This system broke step_info function test #598
Copy link
Copy link
Closed
Description
The SettlingMin or SettlingMax or/and Peak values calculus depend on span time selección when the system is asymptotic system:
step_info test broke with this test (In this case Fail SettingMax):
@pytest.fixture
def siso_tf_peak1(self):
# Peak_value = Undershoot = y_final(y(t=inf))
# step info time values depend on time vector discretization
# use T=linspace(0,50,10000)
T = TSys(TransferFunction([-1, 1],[1, 1]))
T.step_info = {
'RiseTime': 2.2002,
'SettlingTime': 4.6104,
'SettlingMin': 0.9004,
'SettlingMax': 0.9999,
'Overshoot': 0,
'Undershoot': 100.0,
'Peak': 1.0,
'PeakTime': 0.0,
'SteadyStateValue': 1.0}
return T
the problem is with SettlingMax using T by deafault
========================================================================== FAILURES ===========================================================================
__________________________________________________ TestTimeresp.test_step_info[siso_tf_peak1-ltisys-yfinal] ___________________________________________________
self = <control.tests.timeresp_test.TestTimeresp object at 0x7f443b7aebb0>, tsystem = TransferFunction(array([-1, 1]), array([1, 1])), systype = 'ltisys'
time_2d = False, yfinal = True
@pytest.mark.parametrize(
"yfinal", [True, False], ids=["yfinal", "no yfinal"])
@pytest.mark.parametrize(
"systype, time_2d",
[("ltisys", False),
("time response", False),
("time response", True),
],
ids=["ltisys", "time response (n,)", "time response (1,n)"])
@pytest.mark.parametrize(
"tsystem",
["siso_tf_step_matlab",
"siso_ss_step_matlab",
"siso_tf_kpos",
"siso_tf_kneg",
"siso_tf_type1",
"siso_tf_peak1"],
indirect=["tsystem"])
def test_step_info(self, tsystem, systype, time_2d, yfinal):
"""Test step info for SISO systems."""
step_info_kwargs = tsystem.kwargs.get('step_info', {})
if systype == "time response":
# simulate long enough for steady state value
tfinal = 3 * tsystem.step_info['SettlingTime']
if np.isnan(tfinal):
pytest.skip("test system does not settle")
t, y = step_response(tsystem.sys, T=tfinal, T_num=5000)
sysdata = y
step_info_kwargs['T'] = t[np.newaxis, :] if time_2d else t
else:
sysdata = tsystem.sys
if yfinal:
step_info_kwargs['yfinal'] = tsystem.step_info['SteadyStateValue']
info = step_info(sysdata, **step_info_kwargs)
> self.assert_step_info_match(tsystem.sys, info, tsystem.step_info)
control/tests/timeresp_test.py:509:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <control.tests.timeresp_test.TestTimeresp object at 0x7f443b7aebb0>, sys = TransferFunction(array([-1, 1]), array([1, 1]))
info = {'Overshoot': 0, 'Peak': 1.0, 'PeakTime': 0.0, 'RiseTime': 2.1630344812974367, ...}
info_ref = {'Overshoot': 0, 'Peak': 1.0, 'PeakTime': 0.0, 'RiseTime': 2.2002, ...}
def assert_step_info_match(self, sys, info, info_ref):
"""Assert reasonable step_info accuracy."""
if sys.isdtime(strict=True):
dt = sys.dt
else:
_, dt = _ideal_tfinal_and_dt(sys, is_step=True)
for k in ['RiseTime', 'SettlingTime', 'PeakTime']:
np.testing.assert_allclose(info[k], info_ref[k], atol=dt,
err_msg=f"{k} does not match")
for k in ['Overshoot', 'Undershoot', 'Peak', 'SteadyStateValue']:
np.testing.assert_allclose(info[k], info_ref[k], rtol=5e-3,
err_msg=f"{k} does not match")
# steep gradient right after RiseTime
absrefinf = np.abs(info_ref['SteadyStateValue'])
if info_ref['RiseTime'] > 0:
y_next_sample_max = 0.8*absrefinf/info_ref['RiseTime']*dt
else:
y_next_sample_max = 0
for k in ['SettlingMin', 'SettlingMax']:
if (np.abs(info_ref[k]) - 0.9 * absrefinf) > y_next_sample_max:
# local min/max peak well after signal has risen
> np.testing.assert_allclose(info[k], info_ref[k], rtol=1e-3)
E AssertionError:
E Not equal to tolerance rtol=0.001, atol=0
E
E Mismatched elements: 1 / 1 (100%)
E Max absolute difference: 0.0019
E Max relative difference: 0.00190019
E x: array(0.998)
E y: array(0.9999)
control/tests/timeresp_test.py:471: AssertionError
_________________________________________________ TestTimeresp.test_step_info[siso_tf_peak1-ltisys-no yfinal] _________________________________________________
self = <control.tests.timeresp_test.TestTimeresp object at 0x7f44b0132df0>, tsystem = TransferFunction(array([-1, 1]), array([1, 1])), systype = 'ltisys'
time_2d = False, yfinal = False
@pytest.mark.parametrize(
"yfinal", [True, False], ids=["yfinal", "no yfinal"])
@pytest.mark.parametrize(
"systype, time_2d",
[("ltisys", False),
("time response", False),
("time response", True),
],
ids=["ltisys", "time response (n,)", "time response (1,n)"])
@pytest.mark.parametrize(
"tsystem",
["siso_tf_step_matlab",
"siso_ss_step_matlab",
"siso_tf_kpos",
"siso_tf_kneg",
"siso_tf_type1",
"siso_tf_peak1"],
indirect=["tsystem"])
def test_step_info(self, tsystem, systype, time_2d, yfinal):
"""Test step info for SISO systems."""
step_info_kwargs = tsystem.kwargs.get('step_info', {})
if systype == "time response":
# simulate long enough for steady state value
tfinal = 3 * tsystem.step_info['SettlingTime']
if np.isnan(tfinal):
pytest.skip("test system does not settle")
t, y = step_response(tsystem.sys, T=tfinal, T_num=5000)
sysdata = y
step_info_kwargs['T'] = t[np.newaxis, :] if time_2d else t
else:
sysdata = tsystem.sys
if yfinal:
step_info_kwargs['yfinal'] = tsystem.step_info['SteadyStateValue']
info = step_info(sysdata, **step_info_kwargs)
> self.assert_step_info_match(tsystem.sys, info, tsystem.step_info)
control/tests/timeresp_test.py:509:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <control.tests.timeresp_test.TestTimeresp object at 0x7f44b0132df0>, sys = TransferFunction(array([-1, 1]), array([1, 1]))
info = {'Overshoot': 0, 'Peak': 1.0, 'PeakTime': 0.0, 'RiseTime': 2.1630344812974367, ...}
info_ref = {'Overshoot': 0, 'Peak': 1.0, 'PeakTime': 0.0, 'RiseTime': 2.2002, ...}
def assert_step_info_match(self, sys, info, info_ref):
"""Assert reasonable step_info accuracy."""
if sys.isdtime(strict=True):
dt = sys.dt
else:
_, dt = _ideal_tfinal_and_dt(sys, is_step=True)
for k in ['RiseTime', 'SettlingTime', 'PeakTime']:
np.testing.assert_allclose(info[k], info_ref[k], atol=dt,
err_msg=f"{k} does not match")
for k in ['Overshoot', 'Undershoot', 'Peak', 'SteadyStateValue']:
np.testing.assert_allclose(info[k], info_ref[k], rtol=5e-3,
err_msg=f"{k} does not match")
# steep gradient right after RiseTime
absrefinf = np.abs(info_ref['SteadyStateValue'])
if info_ref['RiseTime'] > 0:
y_next_sample_max = 0.8*absrefinf/info_ref['RiseTime']*dt
else:
y_next_sample_max = 0
for k in ['SettlingMin', 'SettlingMax']:
if (np.abs(info_ref[k]) - 0.9 * absrefinf) > y_next_sample_max:
# local min/max peak well after signal has risen
> np.testing.assert_allclose(info[k], info_ref[k], rtol=1e-3)
E AssertionError:
E Not equal to tolerance rtol=0.001, atol=0
E
E Mismatched elements: 1 / 1 (100%)
E Max absolute difference: 0.0019
E Max relative difference: 0.00190019
E x: array(0.998)
E y: array(0.9999)
control/tests/timeresp_test.py:471: AssertionError
====================================================================== warnings summary =======================================================================
control/tests/rlocus_test.py:79
/home/jpp/github_repos/my_python_control/python-control/control/tests/rlocus_test.py:79: PytestUnknownMarkWarning: Unknown pytest.mark.timeout - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
@pytest.mark.timeout(2)
-- Docs: https://docs.pytest.org/en/stable/warnings.html
=================================================================== short test summary info ===================================================================
SKIPPED [1] control/tests/matlab2_test.py:204: skipping test_check_convert_shape, need to update test
SKIPPED [1] control/tests/matlab2_test.py:275: need to update test
SKIPPED [4] control/tests/timeresp_test.py:498: test system does not settle
SKIPPED [6] control/tests/timeresp_test.py:880: No continuous forced_response without time vector.
SKIPPED [1] control/tests/type_conversion_test.py:162: future test; conversions not yet fully implemented
SKIPPED [2] control/tests/xferfcn_test.py:742: .__matmul__ not implemented
XFAIL control/tests/lti_test.py::TestLTI::test_timebaseEqual_deprecated[None-True-True]
returns false
XFAIL control/tests/optimal_test.py::test_discrete_lqr
reason: discrete LQR not implemented
XFAIL control/tests/statefbk_test.py::TestStatefbk::testLQR_warning
warning not implemented
FAILED control/tests/timeresp_test.py::TestTimeresp::test_step_info[siso_tf_peak1-ltisys-yfinal] - AssertionError:
FAILED control/tests/timeresp_test.py::TestTimeresp::test_step_info[siso_tf_peak1-ltisys-no yfinal] - AssertionError:
========================================= 2 failed, 2483 passed, 15 skipped, 3 xfailed, 1 warning in 93.49s (0:01:33) =========================================
(control-dev) jpp@jpp-linux:~/github_repos/my_python_control/python-control$ /home/jpp/miniconda3/envs/control-dev/bin/python /home/jpp/github_repos/my_python_control/python-control/examples/step_info_example2.py
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
bnavigator commentedon Mar 30, 2021
Please be more precise when refering to variables. The calculation of
SettlingMaxis not using T. Neither theT=TSys()from the fixture nor theTparameter insidestep_info(). It is using the values ofyoutonly, not taking into accountInfValue.juanodecc commentedon Mar 30, 2021
the system is asymptotic... need more simulation time or relax the tolerance... because the SettlingMax is equal to yout[-1] in this case... similarly, the we have the same problem with SettlingMin for step_info(-siso_tf_peak1).