#Pythonで学ぶ制御工学< 極・零点と振る舞い >
##はじめに
基本的な制御工学をPythonで実装し,復習も兼ねて制御工学への理解をより深めることが目的である.
その第12弾として「極・零点と振る舞い」を扱う.
##極と振る舞い
前回(https://qiita.com/Yuya-Shimizu/items/2c9acdb6fdc2ef7440e5 )で,システムの安定性について学び,伝達関数において,極の実部が負であるとき安定となると知った.今回は,もう少し詳細に極とシステムの振る舞いについて知る.また,零点と振る舞いについても後述する.
式から考えると,おおむねこんな感じである.続いて,前回示した安定領域を複素数平面で表現したものに実際に条件別に出力させた応答信号を配置した.以下にその図を示す.
少し見づらいが,先ほどの式から得られた特徴から見ていくと分かりやすい.まず,1次遅れ系のものは,すべて実軸上にあることが分かる.また,2次遅れ系において,$\zeta$を固定させて$\omega_n$を変化させたものが図の上方4つになるが,1次遅れ系も2次遅れ系も実部の大きさによって,応答速度が変化していることが分かる.残るは,図の下方3つだが,これらは2次遅れ系において,$\omega_n$を固定させて$\zeta$を変化させたものである.これらも先ほどの説明どおり,$\zeta=0$,すなわち虚軸上にあるものは,持続振動になっており,また**$\zeta$が小さいほど,虚部は大きくなり,より振動的になっている**ことが分かる.また,虚部が大きいほど振動周期も短くなる.
以下にそれぞれの条件に合わせた比較図を3つ示しておく.1つ目は1次遅れ系の時定数変化による振る舞いの違い.2つ目は2次遅れ系の固有角振動数の変化による振る舞いの違い.3つ目は2次遅れ系の減衰係数の変化による振る舞いの違いである.
図 1次遅れ系の時定数変化による振る舞いの違い
図 2次遅れ系の固有角振動数の変化による振る舞いの違い
図 2次遅れ系の減衰係数の変化による振る舞いの違い
なお,ここで示した応答信号を出力するプログラムのソースコードは最後に示す.
##零点と振る舞い
続いて,零点と振る舞いついて,図を使っての説明を以下に示す.
式でいうと,おおむねこんな感じである.続いて,それらの応答信号の振る舞いを次に示す.
$P_1$と$P_2$の応答を比べることで,説明にあったとおり,零点があるときの方が振動が大きくなっていることが分かる.また,$P_3$に注目すると,はじめに少し外れたところへ応答している.このことから,不安定零点であるとき,逆ぶれが生じていることが分かる.
##ソースコード
最後に,今回の図を作成するときに作ったプログラムのソースコードを示しておく.
#####ソースコード①:極と振る舞い(1次遅れ系)
"""
2021/03/05
@Yuya Shimizu
極と振る舞い(1次遅れ系)
"""
from control.matlab import *
import matplotlib.pyplot as plt
import numpy as np
from for_plot import * #自分で定義した関数をインポート
#定義した関数について (https://qiita.com/Yuya-Shimizu/items/f811317d733ee3f45623)
##1次遅れ系のステップ応答
K = 1 #ゲインの設定
T = (1, 0.2, -0.2, -1) #時定数の設定
y=[]
t=[]
for i in range(len(T)):
P = tf([0, K], [T[i], 1]) #1次遅れ系
yy, tt = step(P, np.arange(0, 5, 0.01)) #ステップ応答(0~5秒で,0.01刻み)
y.append(yy)
t.append(tt)
for i in range(len(T)):
fig, ax = plt.subplots()
ax.plot(t[i], y[i])
plot_set(ax, 't', 'y') #グリッドやラベルを与える関数(自作のfor_plotライブラリより)
plt.title(f"T={T[i]}, K={K}")
plt.show()
#1つの図にまとめる
fig, ax = plt.subplots()
LS = linestyle_generator() #線種を与える関数(自作のfor_plotライブラリより)
for i in range(len(T)):
ax.plot(t[i], y[i], ls=next(LS), label=f"T={T[i]}")
plot_set(ax, 't', 'y', 'best')
ax.set_ylim(-1.2, 1.2)
plt.title(f"T={T}, K={K}")
plt.show()
#####ソースコード②:極と振る舞い(2次遅れ系)
"""
2021/03/05
@Yuya Shimizu
極と振る舞い(2次遅れ系)
"""
from control.matlab import *
import matplotlib.pyplot as plt
import numpy as np
from for_plot import * #自分で定義した関数をインポート
#定義した関数について (https://qiita.com/Yuya-Shimizu/items/f811317d733ee3f45623)
##2次遅れ系のステップ応答(固有角振動数omega_nを変化させる)
zeta = 0.8
omega_n = (-1, -0.5, 0, 0.5, 1) #3種類の固有角振動数を用意
K = 1
y=[]
t=[]
for i in range(len(omega_n)):
P = tf([0, K*omega_n[i]**2], [1, 2*zeta*omega_n[i], omega_n[i]**2]) #2次遅れ系
yy, tt = step(P, np.arange(0, 5, 0.01)) #ステップ応答(0~5秒で,0.01刻み)
y.append(yy)
t.append(tt)
#図示
for i in range(len(omega_n)):
fig, ax = plt.subplots()
ax.plot(t[i], y[i])
plot_set(ax, 't', 'y') #グリッドやラベルを与える関数(自作のfor_plotライブラリより)
plt.title(f"$\zeta$={zeta}, $\omega_n$={omega_n[i]}, K={K}")
plt.show()
#図示の準備
fig, ax = plt.subplots()
LS = linestyle_generator() #線種を与える関数(自作のfor_plotライブラリより)
for i in range(len(omega_n)):
ax.plot(t[i], y[i], ls=next(LS), label=f"$\omega_n$={omega_n[i]}")
plot_set(ax, 't', 'y', 'best')
ax.set_ylim(0, 1.2)
plt.title(f"$\zeta$={zeta}, $\omega_n$={omega_n}, K={K}")
plt.show()
##2次遅れ系のステップ応答(減衰係数zetaを変化させる)
zeta = (0, 0.2, 0.8) #5種類の減衰係数を用意
omega_n = 5
K = 1
y=[]
t=[]
for i in range(len(zeta)):
P = tf([0, K*omega_n**2], [1, 2*zeta[i]*omega_n, omega_n**2]) #2次遅れ系
yy, tt = step(P, np.arange(0, 5, 0.01)) #ステップ応答(0~5秒で,0.01刻み)
y.append(yy)
t.append(tt)
#図示
for i in range(len(zeta)):
fig, ax = plt.subplots()
ax.plot(t[i], y[i])
plot_set(ax, 't', 'y') #グリッドやラベルを与える関数(自作のfor_plotライブラリより)
plt.title(f"$\zeta$={zeta[i]}, $\omega_n$={omega_n}, K={K}")
plt.show()
#図示の準備
fig, ax = plt.subplots()
LS = linestyle_generator() #線種を与える関数(自作のfor_plotライブラリより)
for i in range(len(zeta)):
ax.plot(t[i], y[i], ls=next(LS), label=f"$\zeta$={zeta[i]}")
plot_set(ax, 't', 'y', 'best')
plt.title(f"$\zeta$={zeta}, $\omega_n$={omega_n}, K={K}")
plt.show()
#####ソースコード③:零点と振る舞い
"""
2021/03/05
@Yuya Shimizu
零点と振る舞い
"""
from control.matlab import *
import matplotlib.pyplot as plt
import numpy as np
from for_plot import * #自分で定義した関数をインポート
#定義した関数について (https://qiita.com/Yuya-Shimizu/items/f811317d733ee3f45623)
##零点による振る舞いの変化
zeta = 0.3 #減衰係数
omega_n = 5 #固有角振動数
K = 1 #ゲイン
Np = [[0, K*omega_n**2], #P1 : 零点なし
[3, K*omega_n**2], #P2 : 安定零点
[-3, K*omega_n**2]] #P3 : 不安定零点
#図示の準備
fig, ax = plt.subplots()
LS = linestyle_generator() #線種を与える関数(自作のfor_plotライブラリより)
for i in range(len(Np)):
P = tf(Np[i], [1, 2*zeta*omega_n, omega_n**2])
y, t = step(P, np.arange(0, 5, 0.01)) #ステップ応答(0~5秒で,0.01刻み)
ax.plot(t, y, ls=next(LS), label=f"$P_{i+1}$")
plot_set(ax, 't', 'y', 'best')
plt.title(f"$\zeta$={zeta}, $\omega_n$={omega_n}, K={K}")
plt.show()
##感想
今回は,式からと図から極・零点と振る舞いについて学んだ.これらは,システムの振る舞いを理解するのに非常に重要な部分であると思う.
##参考文献
Pyhtonによる制御工学入門 南 祐樹 著 オーム社