From 9c87a5bdea1d1089db81ad51bc8815a94aa5517a Mon Sep 17 00:00:00 2001 From: Sawyer Fuller Date: Thu, 4 Mar 2021 10:20:07 -0800 Subject: [PATCH 1/2] fixed bug in calculation of pct overshoot that neglects not strictly proper transfer functions. --- control/tests/sisotool_test.py | 12 ++++-------- control/tests/timeresp_test.py | 2 +- control/timeresp.py | 4 ++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/control/tests/sisotool_test.py b/control/tests/sisotool_test.py index c626b8add..b4478f678 100644 --- a/control/tests/sisotool_test.py +++ b/control/tests/sisotool_test.py @@ -67,12 +67,9 @@ def test_sisotool(self, sys): initial_point_2, 4) # Check the step response before moving the point - # new array needed because change in compute step response default time step_response_original = np.array( - [0. , 0.0069, 0.0448, 0.124 , 0.2427, 0.3933, 0.5653, 0.7473, - 0.928 , 1.0969]) - #old: np.array([0., 0.0217, 0.1281, 0.3237, 0.5797, 0.8566, 1.116, - # 1.3261, 1.4659, 1.526]) + [0. , 0.0366, 0.2032, 0.4857, 0.82 , 1.1358, 1.3762, 1.507 , + 1.5206, 1.4326]) assert_array_almost_equal( ax_step.lines[0].get_data()[1][:10], step_response_original, 4) @@ -115,10 +112,9 @@ def test_sisotool(self, sys): bode_mag_moved, 4) # Check if the step response has changed - # new array needed because change in compute step response default time step_response_moved = np.array( - [0., 0.0072, 0.0516, 0.1554, 0.3281, 0.5681, 0.8646, 1.1987, - 1.5452, 1.875]) + [0. , 0.0415, 0.2687, 0.7248, 1.3367, 1.9505, 2.3765, 2.4469, + 2.0738, 1.2926]) assert_array_almost_equal( ax_step.lines[0].get_data()[1][:10], step_response_moved, 4) diff --git a/control/tests/timeresp_test.py b/control/tests/timeresp_test.py index 751cd35b0..1436977c7 100644 --- a/control/tests/timeresp_test.py +++ b/control/tests/timeresp_test.py @@ -522,7 +522,7 @@ def test_step_robustness(self): @pytest.mark.parametrize( "tfsys, tfinal", - [(TransferFunction(1, [1, .5]), 9.21034), # pole at 0.5 + [(TransferFunction(1, [1, .5]), 17.034386), # pole at 0.5 (TransferFunction(1, [1, .5]).sample(.1), 25), # discrete pole at 0.5 (TransferFunction(1, [1, .5, 0]), 25)]) # poles at 0.5 and 0 def test_auto_generated_time_vector_tfinal(self, tfsys, tfinal): diff --git a/control/timeresp.py b/control/timeresp.py index 9ccf24bf3..774fa489b 100644 --- a/control/timeresp.py +++ b/control/timeresp.py @@ -814,7 +814,7 @@ def step_info(sys, T=None, T_num=None, SettlingTimeThreshold=0.02, 'SettlingTime': SettlingTime, 'SettlingMin': yout[tr_upper_index:].min(), 'SettlingMax': yout.max(), - 'Overshoot': 100. * (yout.max() - InfValue) / (InfValue - yout[0]), + 'Overshoot': 100. * (yout.max() - InfValue) / InfValue, 'Undershoot': yout.min(), # not very confident about this 'Peak': yout[PeakIndex], 'PeakTime': T[PeakIndex], @@ -1124,7 +1124,7 @@ def _ideal_tfinal_and_dt(sys, is_step=True): default_dt = 0.1 total_cycles = 5 # number of cycles for oscillating modes pts_per_cycle = 25 # Number of points divide a period of oscillation - log_decay_percent = np.log(100) # Factor of reduction for real pole decays + log_decay_percent = np.log(5000) # Factor of reduction for real pole decays if sys._isstatic(): tfinal = default_tfinal From b36d0532f147c07a9e6d3bc7bb6a5978f83021ba Mon Sep 17 00:00:00 2001 From: Sawyer Fuller Date: Thu, 4 Mar 2021 11:22:53 -0800 Subject: [PATCH 2/2] slight adjustment of decay time in step response --- control/tests/sisotool_test.py | 8 ++++---- control/tests/timeresp_test.py | 6 +++++- control/timeresp.py | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/control/tests/sisotool_test.py b/control/tests/sisotool_test.py index b4478f678..6df2493cb 100644 --- a/control/tests/sisotool_test.py +++ b/control/tests/sisotool_test.py @@ -68,8 +68,8 @@ def test_sisotool(self, sys): # Check the step response before moving the point step_response_original = np.array( - [0. , 0.0366, 0.2032, 0.4857, 0.82 , 1.1358, 1.3762, 1.507 , - 1.5206, 1.4326]) + [0. , 0.021 , 0.124 , 0.3146, 0.5653, 0.8385, 1.0969, 1.3095, + 1.4549, 1.5231]) assert_array_almost_equal( ax_step.lines[0].get_data()[1][:10], step_response_original, 4) @@ -113,8 +113,8 @@ def test_sisotool(self, sys): # Check if the step response has changed step_response_moved = np.array( - [0. , 0.0415, 0.2687, 0.7248, 1.3367, 1.9505, 2.3765, 2.4469, - 2.0738, 1.2926]) + [0. , 0.023 , 0.1554, 0.4401, 0.8646, 1.3722, 1.875 , 2.2709, + 2.4633, 2.3827]) assert_array_almost_equal( ax_step.lines[0].get_data()[1][:10], step_response_moved, 4) diff --git a/control/tests/timeresp_test.py b/control/tests/timeresp_test.py index 1436977c7..37fcff763 100644 --- a/control/tests/timeresp_test.py +++ b/control/tests/timeresp_test.py @@ -310,6 +310,10 @@ def test_step_pole_cancellation(self, pole_cancellation, step_info_no_cancellation = step_info(no_pole_cancellation) step_info_cancellation = step_info(pole_cancellation) for key in step_info_no_cancellation: + if key == 'Overshoot': + # skip this test because these systems have no overshoot + # => very sensitive to parameters + continue np.testing.assert_allclose(step_info_no_cancellation[key], step_info_cancellation[key], rtol=1e-4) @@ -522,7 +526,7 @@ def test_step_robustness(self): @pytest.mark.parametrize( "tfsys, tfinal", - [(TransferFunction(1, [1, .5]), 17.034386), # pole at 0.5 + [(TransferFunction(1, [1, .5]), 13.81551), # pole at 0.5 (TransferFunction(1, [1, .5]).sample(.1), 25), # discrete pole at 0.5 (TransferFunction(1, [1, .5, 0]), 25)]) # poles at 0.5 and 0 def test_auto_generated_time_vector_tfinal(self, tfsys, tfinal): diff --git a/control/timeresp.py b/control/timeresp.py index 774fa489b..3df225de9 100644 --- a/control/timeresp.py +++ b/control/timeresp.py @@ -792,7 +792,7 @@ def step_info(sys, T=None, T_num=None, SettlingTimeThreshold=0.02, T, yout = step_response(sys, T) # Steady state value - InfValue = yout[-1] + InfValue = sys.dcgain() # RiseTime tr_lower_index = (np.where(yout >= RiseTimeLimits[0] * InfValue)[0])[0] @@ -1124,7 +1124,7 @@ def _ideal_tfinal_and_dt(sys, is_step=True): default_dt = 0.1 total_cycles = 5 # number of cycles for oscillating modes pts_per_cycle = 25 # Number of points divide a period of oscillation - log_decay_percent = np.log(5000) # Factor of reduction for real pole decays + log_decay_percent = np.log(1000) # Factor of reduction for real pole decays if sys._isstatic(): tfinal = default_tfinal