Skip to content
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

Frequency plot improvements #1011

Merged
merged 18 commits into from
Jun 29, 2024

Conversation

murrayrm
Copy link
Member

@murrayrm murrayrm commented Jun 16, 2024

This PR adds a number of improvements for frequency plots (Bode, Nyquist, etc). The changes are motivated by my experience in using python-control for a course, where I found a few things that were harder to do than they should have been.

Changes in this PR:

  • Allow label keyword in frequency response commands to override default label generation.

  • Fix bug in processing indent_radius keyword when nyquist_plot is passed a system (keyword was not getting sent through to nyquist_response).

  • Restore functionality that allows omega to be specified as a list of 2 elements (indicating a range) in all frequency response/plotting routines. This used to work for nyquist but got removed at some point. It now works for all frequency response commands.

    • Note: this could break some code if someone meant to evaluate the frequency response at exactly two frequencies. This case seems rare, but it can be fixed by passing the two elements as an array.
  • Fix up the ax keyword processing to allow arrays or lists + uniform processing in all freqplot routines.

  • Fix up rcParams processing (uniformity + remove unnecessary code). (This needs more work in a future pass to eliminate the rcParams keywords that are part of frequency plotting functions and to pull separate time and frequency plot parameters into a single place. There are some TODOs in the code marking what needs to be done.)

  • Added new suptitle() function to add titles that are better centered (on axes instead of figure). Using this for frequency domain plots for now; will update for time domain plots as well.

  • Set up frd as factory function with keywords, including setting the signal/system names. Calls to ct.FRD should how be replaces with ct.frd, though the former will still work.

  • Allow Bode and Nyquist plots for FRD systems with different omega vectors (Fix nyquist plotting from FrequencyResponseData #996) as well as mixtures of FRD and other LTI systems.

  • Added a notebook examples/cds110-bode_nyquist.ipynb that shows a lot of the new functionality in the context of frequency domain analysis.

  • Minor: changed the way that freq_label (frequency axis label) is implemented so that it can be more easily overriden (use fstring with '{units}' instead of '%' => can put in custom units).

For the most part these changes just make it easier to do things that were already possible. Example of some new code that makes use of these features (from examples/cds110-bode_nyquist.ipynb):

import control as ct
P = ct.tf([1], [1, 0.1, -1])  # normalized inverted pendulum
C = ct.tf([2, 10], [1])       # PD controller
L = P * C                     # Loop transfer function

# Bode and Nyquist plots
plt.figure(figsize=[7, 4])
ax1 = plt.subplot(2, 2, 1)
plt.title("Bode plot for L", size='medium')
ax2 = plt.subplot(2, 2, 3)
ct.bode_plot(
    [P, C, L], label=['P', 'C', 'L'], ax=[ax1, ax2],
    initial_phase=0)

ax3 = plt.subplot(1, 2, 2)
ct.nyquist_plot(L, ax=ax3)
plt.title("Nyquist plot for L", size='medium')

ct.suptitle("Loop analysis for inverted pendulum")
plt.tight_layout()

bode_nyquist

For the mixed FRD functionality (motivated by comments I made in #996), here's an example showing how Nyquist plots can be combined in ways that weren't possible before:

s = ct.tf('s')
sys = ct.tf(
    (0.02 * s**3 - 0.1 * s) / (s**4 + s**3 + s**2 + 0.25 * s + 0.04),
    name='tf')
sys1 = ct.frd(sys, np.logspace(-1, 1, 15), name='frd1')
sys2 = ct.frd(sys, np.logspace(-2, 2, 20), name='frd2')

ct.nyquist_plot([sys, sys1, sys2])
ct.suptitle("Mixed FRD, tf data")

frd_nyquist

@coveralls
Copy link

Coverage Status

coverage: 94.502% (+0.01%) from 94.49%
when pulling 4b3597f on murrayrm:freqresp_improvements-16Apr2024
into dbc998d on python-control:main.

@murrayrm murrayrm force-pushed the freqresp_improvements-16Apr2024 branch from 4b3597f to ffee41f Compare June 26, 2024 15:51
@coveralls
Copy link

Coverage Status

coverage: 94.535% (+0.01%) from 94.522%
when pulling ffee41f on murrayrm:freqresp_improvements-16Apr2024
into ad6b49e on python-control:main.

@slivingston slivingston self-requested a review June 27, 2024 16:11
@slivingston slivingston self-assigned this Jun 27, 2024
control/frdata.py Outdated Show resolved Hide resolved
fig.suptitle(title, **kwargs)

elif frame == 'axes':
# TODO: move common plotting params to 'ctrlplot'
Copy link
Member

Choose a reason for hiding this comment

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

This same TODO comment is already freqplot.py, and it is not clear what the comment means here (in ctrlplot). Should the TODO comment be deleted here in favor of the one in freqplot.py ?

Copy link
Member

Choose a reason for hiding this comment

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

Reading it again, I think this TODO comment is to be able to

rcParams = config._get_param('ctrlplot', 'rcParams', rcParams)

If so, then I understand the motivation, and OK to keep both TODO comments.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've got another PR coming that will address both TODOs. Doing things in stages so that everything is in (slightly) smaller chunks.

Copy link
Member

Choose a reason for hiding this comment

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

Awesome. I am almost done reviewing this one.

doc/plotting.rst Outdated Show resolved Hide resolved
doc/plotting.rst Outdated Show resolved Hide resolved
doc/plotting.rst Outdated Show resolved Hide resolved
doc/plotting.rst Outdated Show resolved Hide resolved
doc/plotting.rst Outdated Show resolved Hide resolved
doc/plotting.rst Outdated Show resolved Hide resolved
control/freqplot.py Outdated Show resolved Hide resolved
control/freqplot.py Outdated Show resolved Hide resolved
@coveralls
Copy link

Coverage Status

coverage: 94.518% (-0.004%) from 94.522%
when pulling 29f3713 on murrayrm:freqresp_improvements-16Apr2024
into ad6b49e on python-control:main.

@slivingston
Copy link
Member

Excellent improvements! I did not find any technical errors, but here are a few misprints in examples/cds110_bode-nyquist.ipynb:

  • "the way that basic" -> "the way basic"
  • The sentence that begins with "The system parameters are given by" should have \epsilon = 0.01, because the sentence continues with "and we assume that" on the next line.
  • "loop dynamicsof" -> "loop dynamics of"
  • "For how we just" -> "For now we just"
  • To get TeX rendering in section "Stability margins": $|1 - L(j\\omega) -> $|1 - L(j\\omega)$
  • "interpreation" -> "interpretation"

OK to leave it as-is, but one of the commit messages has a misprint: "reectoring/regularization of ax keyword processing" should have "refactoring".

After you consider/apply the above, it is ready to merge.

@murrayrm murrayrm force-pushed the freqresp_improvements-16Apr2024 branch from 29f3713 to 343df2c Compare June 29, 2024 18:27
@coveralls
Copy link

Coverage Status

coverage: 94.518% (+0.01%) from 94.506%
when pulling 343df2c on murrayrm:freqresp_improvements-16Apr2024
into e5394c4 on python-control:main.

@murrayrm murrayrm merged commit feeb56a into python-control:main Jun 29, 2024
23 checks passed
@murrayrm murrayrm deleted the freqresp_improvements-16Apr2024 branch June 29, 2024 18:40
@murrayrm murrayrm added this to the 0.10.1 milestone Jun 30, 2024
@murrayrm murrayrm mentioned this pull request Jun 30, 2024
5 tasks
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.

None yet

3 participants