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

Time response plots #920

Merged
merged 12 commits into from
Jul 13, 2023
Merged

Conversation

murrayrm
Copy link
Member

@murrayrm murrayrm commented Jul 3, 2023

This PR implements time response plots for the various simulation routines in python-control via a new function time_response_plot() and via the plot() method on the TimeResponseData class. This is aligned with the new plotting paradigm in #645.

Examples (from the user documentation):

Input/output time responses are produced using one of several python-control functions: forced_response, impulse_response, initial_response(), input_output_response(), and step_response(). Each of these return a TimeResponseData object, which contains the time, input, state, and output vectors associated with the simulation. Time response data can be plotted with the time_response_plot() function, which is also available as the plot() method. For example, the step response for a two-input, two-output can be plotted using the commands:

sys_mimo = ct.tf2ss(
    [[[1], [0.1]], [[0.2], [1]]],
    [[[1, 0.6, 1], [1, 1, 1]], [[1, 0.4, 1], [1, 2, 1]]], name="MIMO")
response = step_response(sys)
response.plot()

which produces the following plot:

timeplot-mimo_step-default

The TimeResponseData object can also be used to access the data from the simulation:

time, outputs, inputs = response.time, response.outputs, response.inputs
fig, axs = plt.subplots(2, 2)
for i in range(2):
    for j in range(2):
        axs[i, j].plot(time, outputs[i, j])

A number of options are available in the plot method to customize the appearance of input output data. For data produced by the impulse_response() and step_response() commands, the inputs are not shown. This behavior can be changed using the plot_inputs keyword. It is also possible to combine multiple lines onto a single graph, using either the overlay_signals keyword (which puts all outputs out a single graph and all inputs on a single graph) or the overlay_traces keyword, which puts different traces (e.g., corresponding to step inputs in different channels) on the same graph, with appropriate labeling via a legend on selected axes.

For example, using plot_input=True and overlay_signals=True yields the following plot:

ct.step_response(sys_mimo).plot(
  plot_inputs=True, overlay_signals=True,
  title="Step response for 2x2 MIMO system " +
  "[plot_inputs, overlay_signals]")

timeplot-mimo_step-pi_cs

Input/output response plots created with either the forced_response() or the input_output_response() functions include the input signals by default. These can be plotted on separate axes, but also “overlaid” on the output axes (useful when the input and output signals are being compared to each other). The following plot shows the use of plot_inputs=’overlay’ as well as the ability to reposition the legends using the legend_map keyword:

timepts = np.linspace(0, 10, 100)
U = np.vstack([np.sin(timepts), np.cos(2*timepts)])
ct.input_output_response(sys_mimo, timepts, U).plot(
    plot_inputs='overlay',
    legend_map=np.array([['lower right'], ['lower right']]),
    title="I/O response for 2x2 MIMO system " +
    "[plot_inputs='overlay', legend_map]")

timeplot-mimo_ioresp-ov_lm

Another option that is available is to use the transpose keyword so that instead of plotting the outputs on the top and inputs on the bottom, the inputs are plotted on the left and outputs on the right, as shown in the following figure:

U1 = np.vstack([np.sin(timepts), np.cos(2*timepts)])
resp1 = ct.input_output_response(sys_mimo, timepts, U1)

U2 = np.vstack([np.cos(2*timepts), np.sin(timepts)])
resp2 = ct.input_output_response(sys_mimo, timepts, U2)

ct.combine_traces(
    [resp1, resp2], trace_labels=["Scenario #1", "Scenario #2"]).plot(
        transpose=True,
        title="I/O responses for 2x2 MIMO system, multiple traces "
        "[transpose]")

timeplot-mimo_ioresp-mt_tr

This figure also illustrates the ability to create “multi-trace” plots using the combine_traces() function.

Additional customization is possible using theinput_props, output_props and trace_props keywords to set complementary line colors and styles for various signals and traces:

out = ct.step_response(sys_mimo).plot(
    plot_inputs='overlay', overlay_signals=True, overlay_traces=True,
    output_props=[{'color': c} for c in ['blue', 'orange']],
    input_props=[{'color': c} for c in ['red', 'green']],
    trace_props=[{'linestyle': s} for s in ['-', '--']])

timeplot-mimo_step-linestyle

@murrayrm murrayrm marked this pull request as draft July 3, 2023 01:23
@coveralls
Copy link

coveralls commented Jul 3, 2023

Coverage Status

coverage: 94.968% (+0.1%) from 94.849% when pulling bab5071 on murrayrm:time_plots-20Jun2023 into a8658e4 on python-control:main.

@murrayrm murrayrm marked this pull request as ready for review July 10, 2023 04:36
@sawyerbfuller
Copy link
Contributor

Looks pretty comprehensive and pretty good to me. I particuarly like that this makes it much quicker to plot the inputs and outputs of a mimo system.

@murrayrm murrayrm merged commit 42c6fb1 into python-control:main Jul 13, 2023
14 checks passed
@murrayrm murrayrm added this to the 0.10.0 milestone Mar 31, 2024
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