Visualization

the visualizations rely on CairoMakie.jl.

poles and zeros of a transfer function

g = (s + 2) / (s^2 + 1/4)
viz_poles_and_zeros(g)

response of a system to an input

g = 4 / (4 * s ^ 2 + 0.8 * s + 1)
U = 1 / s
Y = g * U
data = simulate(Y, 50.0)
viz_response(data, title="SO underdamped step response")

Nyquist diagram

g = 1 / (s^2 + s + 1)
nyquist_diagram(g)

Bode plot

g = 3 / (s + 1)
bode_plot(g, log10_ω_min=-4.0, log10_ω_max=4.0, nb_pts=300)

the range of frequencies presented is determined by log10_ω_min and log10_ω_max. the resolution of the Bode plot is determined by nb_pts.

see gain_phase_margins to compute the gain and phase margins and the critical and gain crossover frequencies.

Root locus plot

g_ol = 4 / (s + 3) / (s + 2) / (s + 1)
root_locus(g_ol)

modifying the figures

all visualization functions return a Figure object from CairoMakie.jl that can be further modified. for example:

g_ol = 4 / (s + 3) / (s + 2) / (s + 1)
fig = root_locus(g_ol)
ax = current_axis(fig)
xlims!(ax, -15, 5)
ax.xlabel = "real numbers"

cool plot theme

the custom plot theme can be invoked in CairoMakie.jl for other plots via:

using Controlz, CairoMakie
set_theme!(cool_theme)

more, CairoMakie.jl offers other themes here.

detailed docs

Controlz.viz_responseFunction
viz_response(data, 
             title="", xlabel="time, t", 
             ylabel="output, y*(t)",
             savename=nothing)

plot data[:, :output] vs. data[:, :t] to visualize the response of a system to an input. typically the data frame, data, is returned from simulate.

Arguments

  • data::DataFrame: data frame of time series data, containing a :t column for times and :output column for the outputs.
  • title::String: title of plot
  • xlabel::String: x-label
  • ylabel::String: y-label
  • savename::Union{Nothing, String}: filename to save as a figure in .png format.

Returns

CairoMakie.jl Figure object. this will display in a Pluto.jl notebook.

CairoMakie.jl commands can be invoked after viz_response to make further changes to the figure panel by e.g.:

fig = viz_response(data)
ax = current_axis(fig)
ax.xlabel = "new xlabel"
xlims!(ax, 0, 15)

Example

g = 4 / (4 * s ^ 2 + 0.8 * s + 1)
U = 1 / s
Y = g * U
data = simulate(Y, 50.0)
fig = viz_response(data)
source
Controlz.viz_poles_and_zerosFunction
viz_poles_and_zeros(g, savename=nothing, title::String="poles and zeros")

plot the zeros and poles of the transfer function g in the complex plane.

returns a CairoMakie.jl Figure object for further modification.

source
Controlz.nyquist_diagramFunction
nyquist_diagram(tf, nb_pts=500, ω_max=10.0, savename=nothing)

plot the Nyquist diagram for a transfer function tf to visualize its frequency response. s=-1 is plotted as a red +. nb_pts changes the resolution. ω_max gives maximum frequency considered.

returns a CairoMakie.jl Figure object for further modification.

source
Controlz.bode_plotFunction
axs = bode_plot(tf, log10_ω_min=-4.0, log10_ω_max=4.0, nb_pts=300)

draw the Bode plot of a transfer function tf to visualize its frequency response. returns the two axes of the plot for further tuning via matplotlib commands.

adjust the range of frequencies that the Bode plot presents with log10_ω_min and log10_ω_max.

increase the resolution of the Bode plot with nb_pts.

returns a CairoMakie.jl Figure object for further modification.

source
Controlz.root_locusFunction
root_locus(g_ol, max_mag_Kc=10.0, nb_pts=500, savename=nothing, legend_pos=:rt)

visualize the root locus plot of an open-loop transfer function g_ol.

Arguments

  • g_ol::TransferFunction: the open-loop transfer function of the closed loop system
  • max_mag_Kc::Float64=10.0: the maximum magnitude by which the gain of g_ol is scaled in order to see the roots traversing the plane
  • nb_pts::Int=500: the number of gains to explore. increase for higher resolution.
  • legend_pos::Symbol: Makie command for where to place legend

returns

a CairoMakie.jl Figure object for further modification.

source
Controlz.mk_gifFunction
mk_gif(data, title="", xlabel="time, t", 
             ylabel="output, y(t)",
             savename="response")

make a .gif of the process response. data is a data frame with two columns, :t and :output, likely returned from simulate. accepts same arguments as viz_response. ImageMagick must be installed to create the .gif. the .gif is saved as a file savename.

Arguments

  • data::DataFrame: data frame of time series data, containing a :t column for times and :output column for the outputs.
  • title::String: title of plot
  • xlabel::String: x-label
  • ylabel::String: y-label
  • savename::String: filename to save as a .gif. .gif extension automatically appended if not provided.
source