W10_FrequencyResponse
English translation
!pip install controlCollecting control Downloading control-0.10.0-py3-none-any.whl (513 kB) [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m513.9/513.9 kB[0m [31m5.5 MB/s[0m eta [36m0:00:00[0m [?25hRequirement already satisfied: numpy>=1.23 in /usr/local/lib/python3.10/dist-packages (from control) (1.25.2) Requirement already satisfied: scipy>=1.8 in /usr/local/lib/python3.10/dist-packages (from control) (1.11.4) Requirement already satisfied: matplotlib>=3.6 in /usr/local/lib/python3.10/dist-packages (from control) (3.7.1) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (1.2.1) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (4.51.0) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (1.4.5) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (24.0) Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (9.4.0) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (3.1.2) Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.6->control) (2.8.2) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib>=3.6->control) (1.16.0) Installing collected packages: control Successfully installed control-0.10.0
import numpy as np
import control as ctl
import matplotlib.pyplot as plt
Plotting a Nyquist plot (polar plot)
s=ctl.tf([1, 0], [1])
G_1 = 0.25/(s-0.5)
G_1.name='G_1'
G_2 = 0.5/(s-0.5)
G_2.name='G_2'
G_3 = 1.0/(s-0.5)
G_3.name='G_3'
fig1 = ctl.nyquist_plot(G_1)
fig2 = ctl.nyquist_plot(G_2)
fig3 = ctl.nyquist_plot(G_3)
plt.show()<Figure size 640x480 with 1 Axes>
Plotting a Bode plot
s = ctl.tf([1,0],[1])
G = 1/(s**2+0.5*s+1)
G.name='G(s)'
out = ctl.bode(G)<Figure size 640x480 with 2 Axes>
Examining frequency response in the time domain
omega = 2 # 0.1 ~ 10
t = np.arange(0,100,0.1)
u = np.sin(omega*t)
t,y = ctl.forced_response(G, t, u)
input = plt.plot(t,u)
output = plt.plot(t,y)
plt.xlabel('Time')
plt.legend(['input','output'])
plt.axis([0, 100, -3, 3])
plt.show()<Figure size 640x480 with 1 Axes>
current_omega = ctl.bode(G,omega,'ks')
overall = ctl.bode(G,np.arange(0.1,10,0.1))
plt.show()<Figure size 640x480 with 2 Axes>
Checking bandwidth (cut-off frequency)
ctl.bandwidth(G)1.4839084518312828
ctl.bandwidth(G, -10)2.0000000000008864
Plotting a more complex Bode plot
G_dc = ctl.tf([5],[1])
G_dc.name = 'DC'
G_p1 = 1/s
G_p1.name = 'Pole1'
G_p2 = 1/(0.5*s+1)
G_p2.name = 'Pole2'
G_p34 = 1/(s**2/2500+s*0.6/50+1)
G_p34.name = 'Pole3&4'
G_z1 = 0.1*s+1
G_z1.name = 'Zero1'
G_all = G_dc*G_p1*G_p2*G_p34*G_z1
G_all.name = 'All'
G_list = [G_dc, G_p1, G_p2, G_p34, G_z1, G_all]
out = ctl.bode(G_list, plot_phase=False)
<Figure size 640x480 with 1 Axes>
for sys in G_list:
print(sys.name, ctl.bandwidth(sys))DC inf Pole1 nan Pole2 1.9952566902229083 Pole3&4 72.6529421994053 Zero1 inf All nan