Skip to content

This system broke step_info function test #598

Description

@juanodecc

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions