This notebook demonstrates how to determine the stability of a transfer function its poles.
Some materials developed in this notebook were inspired by https://github.com/jckantor/CBE30338
# Libraries you need for animations
%matplotlib notebook
%config InlineBackend.figure_formats = {'svg',} # svg makes the figures look nicer
import control
import numpy as np
import matplotlib.pylab as plt
import matplotlib.gridspec as gridspec
from ipywidgets.widgets.interaction import interact
import ipywidgets.widgets as widgets
# Create sub plots using gridspec
gs = gridspec.GridSpec(1, 2)
f = plt.figure(figsize=(10,5));
ax1 = plt.subplot(gs[0, 0]); # row 0, col 0
ax1.grid(True, which='both');
ax2 = plt.subplot(gs[0, 1]); # row 0, col 1
ax2.grid(True, which='both');
# Initialize the plots and set limits and labels, this gives us an empty plot as shown below
line1, = ax1.plot([], [], 'ro', ms=5);
line2, = ax2.plot([], [], 'b', lw=2);
ax1.set_ylim(-10,10)
ax1.set_xlim(-5,5)
ax2.set_ylim(-5,5)
ax2.set_xlim(0,100)
ax1.set_ylabel('$Im(z)$')
ax1.set_xlabel('$Re(z)$')
ax2.set_xlabel('Time')
def g(A, B, line1, line2):
T = np.linspace(0,100,1000)
sys = control.tf([1],[A,B])
poles = control.pole(sys)
t, u = control.step_response(sys,T=T)
line1.set_data(poles.real, poles.imag)
line2.set_data(t,u)
ax1.relim()
ax2.relim()
ax1.autoscale_view()
ax2.autoscale_view()
f.canvas.draw()
def plot_interactive():
def f(A, B):
g(A, B, line1, line2)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10, value=1)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=1)
interact(f, A=A_slider, B=B_slider,)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.
# Create sub plots using gridspec
# We'll create a 2x2 grid, with 2 subplots on row 1 and one longer subplot on row 2
gs = gridspec.GridSpec(1, 2)
f = plt.figure(figsize=(10,5));
ax1 = plt.subplot(gs[0, 0]); # row 0, col 0
ax1.grid(True, which='both');
ax2 = plt.subplot(gs[0, 1]); # row 0, col 1
ax2.grid(True, which='both');
# Initialize the plots and set limits and labels, this gives us an empty plot as shown below
line1, = ax1.plot([], [], 'ro', ms=5);
line2, = ax2.plot([], [], 'b', lw=2);
ax1.set_ylim(-10,10)
ax1.set_xlim(-5,5)
ax2.set_ylim(-5,5)
ax2.set_xlim(0,100)
ax1.set_ylabel('$Im(z)$')
ax1.set_xlabel('$Re(z)$')
ax2.set_xlabel('Time')
def g(A, B, C, line1, line2):
T = np.linspace(0,100,1000)
sys = control.tf([1],[A,B,C])
poles = control.pole(sys)
t, u = control.step_response(sys,T=T)
line1.set_data(poles.real, poles.imag)
line2.set_data(t,u)
ax1.relim()
ax2.relim()
ax1.autoscale_view()
ax2.autoscale_view()
f.canvas.draw()
def plot_interactive():
def f(A, B, C):
g(A, B, C, line1, line2)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10, value=1)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=1)
C_slider = widgets.FloatSlider(description='C', min=-10, max=10, value=1)
interact(f, A=A_slider, B=B_slider, C=C_slider)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.
# Create sub plots using gridspec
# We'll create a 2x2 grid, with 2 subplots on row 1 and one longer subplot on row 2
gs = gridspec.GridSpec(1, 2)
f = plt.figure(figsize=(10,5));
ax1 = plt.subplot(gs[0, 0]); # row 0, col 0
ax1.grid(True, which='both');
ax2 = plt.subplot(gs[0, 1]); # row 0, col 1
ax2.grid(True, which='both');
# Initialize the plots and set limits and labels, this gives us an empty plot as shown below
line1, = ax1.plot([], [], 'ro', ms=5);
line2, = ax2.plot([], [], 'b', lw=2);
ax1.set_ylim(-10,10)
ax1.set_xlim(-5,5)
ax2.set_ylim(-5,5)
ax2.set_xlim(0,100)
ax1.set_ylabel('$Im(z)$')
ax1.set_xlabel('$Re(z)$')
ax2.set_xlabel('Time')
def g(A, B, C, D, line1, line2):
T = np.linspace(0,100,1000)
sys = control.tf([1],[A,B,C,D])
poles = control.pole(sys)
t, u = control.step_response(sys,T=T)
line1.set_data(poles.real, poles.imag)
line2.set_data(t,u)
ax1.relim()
ax2.relim()
ax1.autoscale_view()
ax2.autoscale_view()
f.canvas.draw()
def plot_interactive():
def f(A, B, C, D):
g(A, B, C, D, line1, line2)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10, value=1)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=1)
C_slider = widgets.FloatSlider(description='C', min=-10, max=10, value=1)
D_slider = widgets.FloatSlider(description='D', min=-10, max=10, value=1)
interact(f, A=A_slider, B=B_slider, C=C_slider, D=D_slider)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.
# Create sub plots
gs = gridspec.GridSpec(2, 2)
f = plt.figure(figsize=(10,5))
ax1 = plt.subplot(gs[0, 0]) # row 0, col 0
ax1.grid(True, which='both')
ax2 = plt.subplot(gs[0, 1]) # row 0, col 1
ax2.grid(True, which='both')
ax3 = plt.subplot(gs[1, :]) # row 1, span all columns
line1, = ax1.semilogx([], [], 'b', lw=2)
line2, = ax2.semilogx([], [], 'b', lw=2)
line3, = ax3.plot([], [], 'r', lw=2)
ax1.set_ylabel('Magnitude')
ax2.set_ylabel('Phase')
ax3.set_xlabel('Time');
def g(A, B, line1, line2, line3):
T = np.linspace(0,100,1000)
L = control.tf([1],[A,B])
sys = L/(1+L)
mag, phase, omega = control.bode(L, Plot=False);
t, u = control.step_response(sys,
T=T)
line1.set_data(omega, mag)
line2.set_data(omega, phase)
line3.set_data(t,u)
ax1.relim()
ax2.relim()
ax3.relim()
ax1.autoscale_view()
ax2.autoscale_view()
ax3.autoscale_view()
f.canvas.draw()
def plot_interactive():
def f(A, B):
g(A, B, line1, line2, line3)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10 ,value=1)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=1)
interact(f, A=A_slider, B=B_slider)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.
# Create sub plots
gs = gridspec.GridSpec(2, 2)
f = plt.figure(figsize=(10,5))
ax1 = plt.subplot(gs[0, 0]) # row 0, col 0
ax1.grid(True, which='both')
ax2 = plt.subplot(gs[0, 1]) # row 0, col 1
ax2.grid(True, which='both')
ax3 = plt.subplot(gs[1, :]) # row 1, span all columns
line1, = ax1.semilogx([], [], 'b', lw=2)
line2, = ax2.semilogx([], [], 'b', lw=2)
line3, = ax3.plot([], [], 'r', lw=2)
ax1.set_ylabel('Magnitude')
ax2.set_ylabel('Phase')
ax3.set_xlabel('Time');
def g(A, B, C, line1, line2, line3):
T = np.linspace(0,100,1000)
L = control.tf([1],[A,B,C])
sys = L/(1+L)
mag, phase, omega = control.bode(L, Plot=False);
t, u = control.step_response(sys,
T=T)
line1.set_data(omega, mag)
line2.set_data(omega, phase)
line3.set_data(t,u)
ax1.relim()
ax2.relim()
ax3.relim()
ax1.autoscale_view()
ax2.autoscale_view()
ax3.autoscale_view()
f.canvas.draw()
def plot_interactive():
def f(A, B, C):
g(A, B, C, line1, line2, line3)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10 ,value=1)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=1)
C_slider = widgets.FloatSlider(description='C', min=-10, max=10, value=1)
interact(f, A=A_slider, B=B_slider, C=C_slider)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.
# Create sub plots
gs = gridspec.GridSpec(2, 2)
f = plt.figure(figsize=(10,5))
ax1 = plt.subplot(gs[0, 0]) # row 0, col 0
ax1.grid(True, which='both')
ax2 = plt.subplot(gs[0, 1]) # row 0, col 1
ax2.grid(True, which='both')
ax3 = plt.subplot(gs[1, :]) # row 1, span all columns
line1, = ax1.semilogx([], [], 'b', lw=2)
line2, = ax2.semilogx([], [], 'b', lw=2)
line3, = ax3.plot([], [], 'r', lw=2)
ax1.set_ylabel('Magnitude')
ax2.set_ylabel('Phase')
ax3.set_xlabel('Time');
def g(A, B, C, D, line1, line2, line3):
T = np.linspace(0,100,1000)
L = control.tf([1],[A,B,C])
sys = L/(1+L)
mag, phase, omega = control.bode(L, Plot=False);
t, u = control.step_response(sys,
T=T)
line1.set_data(omega, mag)
line2.set_data(omega, phase)
line3.set_data(t,u)
ax1.relim()
ax2.relim()
ax3.relim()
ax1.autoscale_view()
ax2.autoscale_view()
ax3.autoscale_view()
f.canvas.draw()
def plot_interactive():
def f(A, B, C, D):
g(A, B, C, D, line1, line2, line3)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10 ,value=1)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=1)
C_slider = widgets.FloatSlider(description='C', min=-10, max=10, value=1)
D_slider = widgets.FloatSlider(description='D', min=-10, max=10, value=1)
interact(f, A=A_slider, B=B_slider, C=C_slider, D=D_slider)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.
# Create sub plots
gs = gridspec.GridSpec(2, 2)
f = plt.figure(figsize=(10,5))
ax1 = plt.subplot(gs[0, 0]) # row 0, col 0
ax1.grid(True, which='both')
ax2 = plt.subplot(gs[0, 1]) # row 0, col 1
ax2.grid(True, which='both')
ax3 = plt.subplot(gs[1, :]) # row 1, span all columns
line1, = ax1.semilogx([], [], 'b', lw=2)
line2, = ax2.semilogx([], [], 'b', lw=2)
line3, = ax3.plot([], [], 'r', lw=2)
ax1.set_ylabel('Magnitude')
ax2.set_ylabel('Phase')
ax3.set_xlabel('Time');
def g(A, B, C, D, Kp, tauI, taud, line1, line2, line3):
T = np.linspace(0,100,1000)
G=control.tf([1],[A,B,C,D])
Gc=Kp*control.tf([tauI*taud,tauI,1],[tauI*1,0])
L = G*Gc
sys=L/(1+L)
mag, phase, omega = control.bode(L, Plot=False);
t, u = control.step_response(sys, T=T)
line1.set_data(omega, mag)
line2.set_data(omega, phase)
line3.set_data(t,u)
ax1.relim()
ax2.relim()
ax3.relim()
ax1.autoscale_view()
ax2.autoscale_view()
ax3.autoscale_view()
f.canvas.draw()
print ('Process TF: {}'.format(G))
print ('Controller TF: {}'.format(Gc))
print ('Open-Loop TF: {}'.format(L))
print ('Closed-Loop TF: {}'.format(sys))
def plot_interactive():
def f(A, B, C, D, Kp, tauI, taud,):
g(A, B, C, D, Kp, tauI, taud, line1, line2, line3)
A_slider = widgets.FloatSlider(description='A', min=-10, max=10 ,value=0)
B_slider = widgets.FloatSlider(description='B', min=-10, max=10, value=0)
C_slider = widgets.FloatSlider(description='C', min=-10, max=10, value=1)
D_slider = widgets.FloatSlider(description='D', min=-10, max=10, value=1)
Kp_slider = widgets.FloatSlider(description='Kp', min=0.0001, max=100, value=1)
tauI_slider = widgets.FloatSlider(description='τI', min=0.0001,max=100, value=1)
taud_slider = widgets.FloatSlider(description='τd', min=0.0001,max=100, value=1)
interact(f, A=A_slider, B=B_slider, C=C_slider, D=D_slider, Kp=Kp_slider, tauI=tauI_slider, taud=taud_slider)
plot_interactive()
Failed to display Jupyter Widget of type interactive
.
If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.
If you're reading this message in another frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.