Skip to content

Fix negative real handling and improve pole matching logic#1216

Open
UbeenII wants to merge 6 commits into
python-control:mainfrom
UbeenII:fix-impulse-response-negative-real-pole
Open

Fix negative real handling and improve pole matching logic#1216
UbeenII wants to merge 6 commits into
python-control:mainfrom
UbeenII:fix-impulse-response-negative-real-pole

Conversation

@UbeenII

@UbeenII UbeenII commented May 15, 2026

Copy link
Copy Markdown

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.

Relaxed the T[-1] tolerance from 0.5 *ideal_dt to ideal_dt because discrete-time vectors must land on integer multiples of dt, so T[-1] can overshoot ideal_tfinal by up to one full sample period.

Fixes #1204.

@slivingston slivingston left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments:

  • Why are the commits associated with a GitHub user different from the user who is opening this PR? (Neither user account has a real name, so authorship is unclear.)
  • A change that results in _ideal_tfinal_and_dt() returning a different tfinal is not ideal because it will change behavior of several public functions, e.g., impule_response when timepts arg is not given.
  • Ideally, when fixing a bug, you have a test that reproduces it; i.e., a regression test.

@UbeenII UbeenII force-pushed the fix-impulse-response-negative-real-pole branch from b59fba9 to d037196 Compare May 16, 2026 21:15
…eals 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 python-control#1204.
@UbeenII UbeenII force-pushed the fix-impulse-response-negative-real-pole branch from d037196 to 8821978 Compare May 16, 2026 22:22
@UbeenII

UbeenII commented May 16, 2026

Copy link
Copy Markdown
Author

Sorry this is my first time contributing. I have fixed the dual author problem and I think GitHub now reflects the correct account now. I added an additional test to this case: test_discrete_time_negative_one_settling for #1204. The test creates a system with a pole at z=-1 and verifies that impulse_response no longer raises a RuntimeWarning. I have also reverted the m_int change to what it was originally.

@UbeenII UbeenII force-pushed the fix-impulse-response-negative-real-pole branch 2 times, most recently from ad376f0 to 8821978 Compare May 16, 2026 23:41
@UbeenII UbeenII requested a review from slivingston June 7, 2026 14:36
@UbeenII

UbeenII commented Jun 7, 2026

Copy link
Copy Markdown
Author

I realised the previous failure on the CI was due to an accidental change I made to one of the tests ( changing 13.8 to 25) I've restored it to the original main branch value (13.81551) and verified that the entire suite passes cleanly locally now. Ready for review whenever you get a chance

@slivingston

Copy link
Copy Markdown
Member

Thanks; I will review it tomorrow.

@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 94.736%. remained the same — UbeenII:fix-impulse-response-negative-real-pole into python-control:main

@slivingston slivingston left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I will merge this after you consider my formatting comments.

Comment thread control/tests/timeresp_test.py Outdated
Comment thread control/tests/timeresp_test.py Outdated
Comment thread control/tests/timeresp_test.py Outdated
Comment thread control/timeresp.py Outdated
Comment thread control/timeresp.py Outdated
UbeenII and others added 4 commits June 9, 2026 09:18
Co-authored-by: Scott C. Livingston <scott@rerobots.net>
Co-authored-by: Scott C. Livingston <scott@rerobots.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RuntimeWarning in impulse_response for discrete-time systems with negative real poles

3 participants