Skip to content

Commit b59fba9

Browse files
committed
2 fixes. 1st fix: the m_nr branch which is meant to handle negative reals takes the -1 root and uses the p_nr case causes t_emp to become infinite due to ln|p|=0 causing a division by zero and a RuntimeWarning. FIX exclude |p|=1 so they use the m_w case which uses cycle counting formula which is appropriate for unit circle poles.
2nd fix: The m_int case used p.real -1 <sqrt_eps instead of np.abs (p.real-1)<sqrt_eps. Without abs any pole with Re(p) < 1 were matched rather than just poles near +1 causing stable poles like 0.95 to be discarded as discrete integrators. I updated the corresponding test to have the expected value to match the correct result. Fixes #1204.
1 parent 146ccee commit b59fba9

2 files changed

Lines changed: 4 additions & 4 deletions

File tree

control/tests/timeresp_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -818,14 +818,14 @@ def test_step_robustness(self):
818818
@pytest.mark.parametrize(
819819
"tfsys, tfinal",
820820
[(TransferFunction(1, [1, .5]), 13.81551), # pole at 0.5
821-
(TransferFunction(1, [1, .5]).sample(.1), 25), # discrete pole at 0.5
821+
(TransferFunction(1, [1, .5]).sample(.1), 13.81551), # discrete pole at 0.5
822822
(TransferFunction(1, [1, .5, 0]), 25)]) # poles at 0.5 and 0
823823
def test_auto_generated_time_vector_tfinal(self, tfsys, tfinal):
824824
"""Confirm a TF with a pole at p simulates for tfinal seconds"""
825825
ideal_tfinal, ideal_dt = _ideal_tfinal_and_dt(tfsys)
826826
np.testing.assert_allclose(ideal_tfinal, tfinal, rtol=1e-4)
827827
T = _default_time_vector(tfsys)
828-
np.testing.assert_allclose(T[-1], tfinal, atol=0.5*ideal_dt)
828+
np.testing.assert_allclose(T[-1], tfinal, atol=ideal_dt)
829829

830830
@pytest.mark.parametrize("wn, zeta", [(10, 0), (100, 0), (100, .1)])
831831
def test_auto_generated_time_vector_dt_cont1(self, wn, zeta):

control/timeresp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,13 +2172,13 @@ def _ideal_tfinal_and_dt(sys, is_step=True):
21722172
m_z = np.abs(p) < sqrt_eps
21732173
p = p[~m_z]
21742174
# Negative reals- treated as oscillatory mode
2175-
m_nr = (p.real < 0) & (np.abs(p.imag) < sqrt_eps)
2175+
m_nr = (p.real < 0) & (np.abs(p.imag) < sqrt_eps)&(np.abs(p.real+1)>sqrt_eps)
21762176
p_nr, p = p[m_nr], p[~m_nr]
21772177
if p_nr.size > 0:
21782178
t_emp = np.max(log_decay_percent / np.abs((np.log(p_nr)/dt).real))
21792179
tfinal = max(tfinal, t_emp)
21802180
# discrete integrators
2181-
m_int = (p.real - 1 < sqrt_eps) & (np.abs(p.imag) < sqrt_eps)
2181+
m_int = (np.abs(p.real - 1) < sqrt_eps) & (np.abs(p.imag) < sqrt_eps)
21822182
p_int, p = p[m_int], p[~m_int]
21832183
# pure oscillatory modes
21842184
m_w = (np.abs(np.abs(p) - 1) < sqrt_eps)

0 commit comments

Comments
 (0)