-
Notifications
You must be signed in to change notification settings - Fork 438
stability_margins doesn't find gain=1 crossover frequency correctly for DT systems #523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
If I am not mistaken, it follows from But the algorithm had a bug. Thanks for noticing and reporting. |
I see, Makes sense if we are restricting the root search to the unit circle, where 1/z = conj(z). And it has been a little while but I guess it must be that h(conj(z)) = conj(h(z)) |
fix #523: finding z for |H(z)|=1 computed the wrong polynomials
@bnagivator any ideas? I tried relaxing the tolerance but that didn't seem to help. |
Numerical issues. The coefficients of the numerator are significantly smaller than those of the denominator. python-control/control/margins.py Lines 159 to 172 in 92de12d
The result of My machine gives me a crossing frequency of 3.08 rad/s for |
I see. Looks like this may happen any time the nyquist frequency is maybe 3+ orders of magnitude faster than the slowest pole. What do you think about a stopgap solution to detect this by looking at the relative order of magnitudes of numerator and denominator polynomial and either give a warning or revert to the interpolating numerical solution via the FrequencyResponseData class? |
I was thinking to use the inaccurate but not completely wrong found crossing frequency as a starting point for a local numerical solve. That way we don't have to evaluate the whole frequency range again. |
Unfortunately I have another example where it is nowhere close (they invovle solutions to a class I am teaching so I will have to do some obfuscation before I can post them : ) |
Using an interpolating omega = ct.freqplot._default_frequency_range(sysd)
sysdfrd = ct.FRD(sysd(np.exp(1j*sysd.dt*omega)), omega, smooth=True)
ct.bode_plot(sysdfrd, omega=sysfrd.omega, margins=True); |
On option might be to include a |
(am hoping to have something working in place for 0.9 for the discrete-time controls class I'm teaching starting March 29. The students will appreciate a working DT margin calculation! : ) |
If we can get this sorted out before ~22 March, we can do a 0.9.0 release that week to make it easy for students to install. |
@murrayrm sure, a method keyword would make sense. What if I let that override things, but by default revert to the FRD method if it looks like the "old" method isn't going to give good numerical results? |
Seems fine by me to have the default be something that works well. You might consider setting up a benchmark file (in |
In any case there should be a check, whether the current results are accurate enough and give a warning if not. |
…margins_discrete
stability_margins doesn't find gain=1 crossover frequency correctly for DT systems, but it seems to mostly do so for CT systems. I think the probelm may be in how
margins.poly_z_mag1_crossing
is finding roots, but there were a few steps in that function I couldn't follow, e.g. why H(z)*H(1/z)=1 implies |H(z)| = 1.Example:
As an example of what it should look like, here is Matlab:
The text was updated successfully, but these errors were encountered: