制御工学、難しそう…そう思ってます?
実はたった一つの複素平面上の曲線で、システムが「安定か」「どれだけ余裕があるか」が一目瞭然になる魔法のようなツールがあるんです。
それがナイキスト線図。
「え、ぐるぐる回るあのグラフ?何が嬉しいの?」と思ったあなた、今日から見方が変わります。
しかも今回は、ブラウザで動く無料シミュレーターを使って、手を動かしながら理解できる内容にしました。
「ぐるぐる」が教えてくれること
ナイキスト線図の核心、一言で言うとこうです。
「(-1, 0)という点を、軌跡がどう扱うかで安定性が決まる」
簡単な例えで考えてみましょう。
あなたが自転車に乗っているとします。ハンドルをちょっと切ったとき、自転車が「戻ろうとする力」が強すぎるとガタガタ振動しますよね。逆に弱すぎるとフラフラして倒れそうになる。
この「ちょうどいい塩梅」を数値で表したのがゲイン余裕と位相余裕なんです。
ナイキスト線図は、この「ちょうどよさ」を一目で判断できる診断チャートのようなもの。
それでは、実際の数式とコードを見ながら深掘りしていきましょう。
数式で理解する
今回のシミュレーターで扱う開ループ伝達関数はこちらです。
L(s) = G(s)H(s) = K \frac{(s + z)}{(s + a)(s + b)}
- $K$: ゲイン(システム全体の増幅率)
- $z$: 零点(分子をゼロにする点)
- $a, b$: 極(分母をゼロにする点、システムの固有特性)
ここに $s = j\omega$(純虚数)を代入すると、周波数応答 $L(j\omega)$ が得られます。
そして、安定性を判定するためのナイキストの安定判別則がこちら。
Z = N + P
もしくは
Z = P - N
- $P$: 開ループ伝達関数の右半平面にある極の数(実部が正の極)
- $N$: ナイキスト軌跡が点 $(-1, 0)$ を反時計回りに囲む回数
- $Z$: 閉ループ系の不安定極の数
閉ループが安定 $\Leftrightarrow Z=0$
今回のシミュレーターでは $a,b > 0$ なので極は $s = -a, -b$ にあり、すべて左半平面 → $P = 0$ です。
つまり、$N = 0$((-1,0)を囲まない)なら安定というシンプルな判定ができるんです。
コードで実装する ★最重要★
シミュレーターのコアロジックをJavaScriptで再現してみましょう。ブラウザのコンソールでも動かせます。
/**
* ナイキスト線図の計算と安定余裕の算出
* 伝達関数: L(s) = K * (s + z) / ((s + a)(s + b))
*/
class NyquistCalculator {
constructor(K, z, a, b) {
this.K = K; // ゲイン
this.z = z; // 零点
this.a = a; // 極1
this.b = b; // 極2
}
// 周波数応答 L(jω) を計算
frequencyResponse(omega) {
const jw = { re: 0, im: omega };
// 分子: K * (jω + z)
const numerator = {
re: this.K * z,
im: this.K * omega
};
// 分母: (jω + a)(jω + b)
const denom1 = { re: a, im: omega };
const denom2 = { re: b, im: omega };
const denominator = {
re: denom1.re * denom2.re - denom1.im * denom2.im,
im: denom1.re * denom2.im + denom1.im * denom2.re
};
// 複素数の割り算
const denomMag2 = denominator.re ** 2 + denominator.im ** 2;
return {
re: (numerator.re * denominator.re + numerator.im * denominator.im) / denomMag2,
im: (numerator.im * denominator.re - numerator.re * denominator.im) / denomMag2
};
}
// ゲイン交差周波数(|L(jω)| = 1 となるω)を探索
findGainCrossover() {
let omega = 0.1;
for (let i = 0; i < 1000; i++) {
const L = this.frequencyResponse(omega);
const gain = Math.sqrt(L.re ** 2 + L.im ** 2);
if (Math.abs(gain - 1) < 0.001) return omega;
omega += 0.01;
}
return null;
}
// 位相交差周波数(∠L(jω) = -180° となるω)を探索
findPhaseCrossover() {
let omega = 0.1;
for (let i = 0; i < 1000; i++) {
const L = this.frequencyResponse(omega);
const phase = Math.atan2(L.im, L.re) * 180 / Math.PI;
if (Math.abs(phase + 180) < 1) return omega;
omega += 0.01;
}
return null;
}
// ゲイン余裕 [dB] を計算
gainMargin() {
const omegaPc = this.findPhaseCrossover();
if (!omegaPc) return Infinity;
const L = this.frequencyResponse(omegaPc);
const gain = Math.sqrt(L.re ** 2 + L.im ** 2);
return 20 * Math.log10(1 / gain);
}
// 位相余裕 [deg] を計算
phaseMargin() {
const omegaGc = this.findGainCrossover();
if (!omegaGc) return Infinity;
const L = this.frequencyResponse(omegaGc);
const phase = Math.atan2(L.im, L.re) * 180 / Math.PI;
return 180 + phase;
}
}
// 使用例: K=5, z=2, a=1, b=3
const sys = new NyquistCalculator(5, 2, 1, 3);
console.log(`ゲイン余裕: ${sys.gainMargin().toFixed(2)} dB`);
console.log(`位相余裕: ${sys.phaseMargin().toFixed(2)} deg`);
このコード、実はシミュレーターの計算をほぼそのまま再現しています。
ポイント:
- 周波数応答は複素数計算でゴリゴリ
- ゲイン交差周波数と位相交差周波数は数値探索(シミュレーターも同じ方式)
- ゲイン余裕 = $20\log_{10}(1/|L(j\omega_{pc})|)$
- 位相余裕 = $180^\circ + \angle L(j\omega_{gc})$
数値例で確かめる
具体的な値で計算してみましょう。
設定: $K = 5$, $z = 2$, $a = 1$, $b = 3$
ステップ1: 位相交差周波数 $\omega_{pc}$ を求める
コードで探索すると、$\omega_{pc} \approx 1.73$ [rad/s] と出ました。
このときの $L(j\omega_{pc})$ を計算:
L(j1.73) = 5 \cdot \frac{j1.73 + 2}{(j1.73 + 1)(j1.73 + 3)}
複素数計算の結果: $L(j1.73) \approx -0.33 + j0.00$
ステップ2: ゲイン余裕を計算
|L(j1.73)| = 0.33
GM = 20\log_{10}\left(\frac{1}{0.33}\right) = 20\log_{10}(3.03) \approx 9.63 \text{ [dB]}
ステップ3: ゲイン交差周波数 $\omega_{gc}$ を求める
コードで探索: $\omega_{gc} \approx 2.45$ [rad/s]
このときの位相:
\angle L(j2.45) \approx -144^\circ
ステップ4: 位相余裕を計算
PM = 180^\circ + (-144^\circ) = 36^\circ
結果:
- ゲイン余裕: 9.63 dB(正 → 安定)
- 位相余裕: 36°(正 → 安定)
実際にシミュレーターで同じ値を入れてみてください。ピッタリ一致するはずです。
シミュレーターで遊ぶ(実験3連発)
実験1: ゲインKを限界まで上げる
初期値: K=1, z=2, a=1, b=3
スライダーをゆっくり右に動かしてみましょう。
- K=5: 軌跡が(-1,0)に近づく(余裕減少)
- K=10: ゲイン余裕がほぼ0に
- K=15: 軌跡が(-1,0)を囲み始める → 不安定化!
なぜ?: Kを大きくすると軌跡が全体的に拡大。(-1,0)を囲む = 閉ループに不安定極が発生。
実験2: 零点zで位相を進める
設定: K=5, a=1, b=3 固定、zを変化
- z=0.5: 位相余裕 15°(危険水域)
- z=2: 位相余裕 36°(良好)
- z=5: 位相余裕 52°(かなり余裕あり)
零点を左に動かすと位相が進み、位相余裕が改善します。
実験3: 3次系で不安定デモ
プリセットから 「K / ((s+a)(s+b)(s+a+b))(3次・不安定化デモ)」 を選択。
高次の系は低次より安定性が劣化しやすい。スライダーでKを上げると、あっという間に不安定に。
実務教訓: むやみに高次にすると制御が難しくなる。シンプルが一番。
現場でハマるポイント
1. 「(-1,0)を囲まなければ絶対安定」は嘘
これは開ループが安定(P=0)の場合だけの話。
倒立振子のように元々不安定なプラント(P>0)を制御する場合、囲まなくても閉ループが不安定になることがあります。
本シミュレーターはP=0固定なので、その点は注意。
2. ゲイン余裕・位相余裕は「目安」
現場では「GM > 10dB, PM > 45°」が一つの目安ですが、絶対ではない。
- 外乱が多い環境 → もっと余裕を
- 応答性重視 → 多少余裕を削る
トレードオフを理解した上で調整する必要があります。
3. ボード線図との対応を見逃すな
シミュレーター右側のボード線図、実はこれ同じ情報を別の形で表現しているだけ。
- ボード線図の「ゲインが0dBになる周波数」の位相 → 位相余裕
- ボード線図の「位相が-180°になる周波数」のゲイン → ゲイン余裕
両方の図を同時に見ながらパラメータ調整すると、理解が一気に深まります。
まとめ
- ナイキスト線図は「(-1,0)をどう扱うか」で安定性を判定 — 囲めば不安定、囲まなければ安定(P=0の場合)
- ゲイン余裕・位相余裕は「どれだけ安全域があるか」の指標 — コードで簡単に計算できる
- シミュレーターで手を動かすのが最短ルート — 理論と実践のギャップを埋められる
制御工学、実は「ぐるぐる」を見るだけでかなりのことがわかります。
ぜひ今日から、このシミュレーターで遊びながらナイキスト線図をマスターしてください。
▶ ナイキスト線図・安定余裕 シミュレーター — ブラウザで即動作、登録不要
NovaSolverでは1,600以上の工学シミュレーターを無料公開中 👉 一覧はこちら