たけし備忘録

自分の好奇心の赴くままに勉強メモ LL系が大好き Python bash Julia C

伝達関数とブロック線図

伝達関数

伝達関数とは、システムへの入力を出力に変換する関数のこと言う。
通常、伝達関数ラプラス変換によって変換された複素関数で表示されます。

出力、入力を順に時間の関数として$y(t), u(t)$とすると、これらをラプラス変換した関数を$Y(s), U(s)$としてやれば伝達関数$G(s)$は

$$ G(s) = \frac{Y(s)}{U(s)} $$

と書く。
考え方として分かりやすい書き方だと

$$ Y(s) = G(s)U(s) $$

と書く。つまり伝達関数$G(s)$とは、入力$U(s)$を$G(s)$倍するような増幅装置のような役割となっています。

Python-Controlではpc.tf(num, den)メソッドを使って伝達関数を生成します。

import control as pc

num = [1, 2, 3]
den = [4, 5, 6, 7]
sys = pc.tf(num, den)

このとき伝達関数sysは次のようになります

     s^2 + 2 s + 3
-----------------------
4 s^3 + 5 s^2 + 6 s + 7

先に定義したnumとdenというリストと見比べればなんとなく察しが付きます。
つまりnum, denというリストを用いてpc.tf(num, den)と書くと一般に次のようになります。

ブロック線図

ブロック線図は、制御系の中で信号の伝達の様子を示す図です。フローチャートのようなものと思って貰えばおおよその理解は十分です。

ブロック線図は基本要素として以下の3つがあります。

(a) 直列

f:id:takeshiD:20160829170246p:plain

$$ Y(s) = G_{1}(s) G_{2}(s) U(s) $$

(b) 並列

f:id:takeshiD:20160829170249p:plain

$$ Y(s) = G_{1}(s) \pm G_{2}(s) U(s) $$

© フィードバック

f:id:takeshiD:20160829170253p:plain

$$ Y(s) = \frac{G_{1}(s)}{1 \mp G_{2}(s) G_{1}(s)} U(s) $$

Python-Controlにはブロック線図のそれぞれに対応する関数が用意されています。

$$ G_{1}(s) = \frac{1}{1+s} \ , \ G_{2}(s) = s $$ でそれぞれを見てみます。

直列

直列の場合は、pc.series(G1, G2)という形で行います。
直列は要するに積ですので、実は G1*G2 という形でも計算出来ます。

import control as pc

G1 = pc.tf([1], [1, 1])
G2 = pc.tf([1, 0], [1])

print pc.series(G1, G2)
print G1*G2

どちらも同じく

  s
-----
s + 1

という出力を得ます。

並列

並列の場合は、pc.parallel(G1, G2)という形で行います。
並列は和ですので、G1+G2 という形でも計算出来ます。

import control as pc

G1 = pc.tf([1], [1, 1])
G2 = pc.tf([1, 0], [1])

print pc.parallel(G1, G2)
print G1+G2

どちらも同じく

s^2 + s + 1
-----------
   s + 1

という出力を得ます。

フィードバック

フィードバックを行う場合は、pc.feedback(G1, G2)という形式で行います。
もしくはG1.feedback(G2)という形式でも行えます。

フィードバックをしない形式を開ループ系。フィードバックを行う形式を特に閉ループ系と呼びます。

フィードバックの場合、入力と出力のフィードバックを行う点(加算点)でプラスとマイナスのどちらかの符号を選びます。
通常、フィードバックと言ったらマイナスで加算を行います。 すなわち次のようなブロック線図でフィードバックをします。

f:id:takeshiD:20160829174952p:plain

このように、マイナスでフィードバックする形式を特にネガティブフィードバック(Negative Feedback:NFB)と呼びます。
Python-Controlでも通常フィードバックと言えば、暗黙でネガティブフィードバックとなっています。

import control as pc

G1 = pc.tf([1], [1, 1])
G2 = pc.tf([1, 0], [1])

print pc.feedback(G1, G2)
print G1.feedback(G2)

どちらも同じく

   1
-------
2 s + 1

という出力を得ます。

補足

なぜマイナスでフィードバックを行うのが通常なのか、というところに疑問が湧きます。
マイナスでフィードバックを行うと最終的な伝達関数

$$ \frac{G_{1}(s)}{1+G_{2}(s) G_{1}(s)} $$

となります。

ではプラスでフィードバックを行うとどうなるでしょうか?
次のような伝達関数となります。

$$ \frac{G_{1}(s)}{1 - G_{2}(s) G_{1}(s)} $$

分母の$G_{2}(s) G_{1}(s)$の符号がマイナスになっています。これは実は非常に都合の悪いことがあります。

なぜなら、基本的にまず$G_{2}(s) G_{1}(s)$は$s$についての関数であり、$s$によって値が変わります。
ではある特定の$s$で$G_{2}(s) G_{1}(s)=1$となってしまう場合を考えてみましょう。

$$ \frac{G_{1}(s)}{1+G_{2}(s) G_{1}(s)} $$

の場合は、$½$になるだけで特に問題はありません。

$$ \frac{G_{1}(s)}{1-G_{2}(s) G_{1}(s)} $$

の場合、無限に発散してしまいます。

このエントリーの冒頭で、「伝達関数$G(s)$とは、入力$U(s)$を$G(s)$倍するような増幅装置のような役割」と書きました。

伝達関数が無限に発散することはつまり、入力がどんな値であろうとも無限大の出力が出るということです。

制御工学、ひいては伝達関数は数学的な議論ではなく実際の機器を動かすために使用しますので無限の出力という非現実的なことを行ってしまうと、機器が壊れるだとか電気代が馬鹿みたいに取られるだとか、そういった不都合なことが多く起きます。

ですので基本的にはマイナスのフィードバックを取るのが通常です。

補足の補足

制御工学は出力を狙った値にピタッと止めて安定させる、というのが目的です。

ですが、少々特殊な場合のみあえてプラスのフィードバックを取ることがあります。
まずプラスのフィードバックを行うと、無限に発散します。
実はもっと条件を細かく取ることで、無限に発散させずに、出力を振動させることが出来ます。
このような出力を振動させるようなものを電気回路・電子回路の世界では発振回路と呼びます。

発振回路はデジタルが主流の現代では非常に重要な回路です。興味がある場合はぜひとも調べてみてください。意外といろんな種類があり、それぞれで特性や経済性が変わって面白いです。