RigidChipsにおけるLuaによる制御の解説、より実用的で実践的な制御を解説します。
ON/OFF制御
トイレタンク
誰でも思いつく、シンプルな制御。
身近な例ではトイレの水タンクで、水を流した後タンクに水を入れ続け、一定より水位が上がると浮きが栓を押し、水を止めるという奴です。
制御対象
はトイレのタンク、
入力
はトイレタンクに入れる水、
出力
はトイレタンクの水位で、
「トイレタンクに入れる水」をほどよく調整して「トイレタンクの水位」を一定に保つことが
目的
です。
表で動作を表現するとこんな感じです。
対象 | 入力 | 出力 |
タンク | 水道 | 水位 |
- | 出す | 一定以下 |
- | 止める | 一定以上 |
Basicの速度制御
RigidChips的な例ではお手元のBasicをご覧ください。これを
10[m/s]
(36[km/h])になるように速度制御してみましょう。
「入力」は勿論WheelのPower変数Engine、速度は-_VZ(0)[m/s](前進でマイナスになるので)になります。
このとき-_VZ(0)を
出力値
、10を
目標値
と呼びます。
対象 | 入力 | 出力 |
Basic | Engine | -_VZ(0) |
- | -2500 | -_VZ(0)<10 |
- | 0 | -_VZ(0)>=10 |
これをプログラム的に表現するなら、
-_VZ(0)が10以下なら、Engineは-2500
そうでなければ、Engineは0
これをLuaにするなら、このような文になります。
if -_VZ(0)<10 then
ENGINE = -2500
else
ENGINE = 0
end
out(0,-_VZ(0))
手元のBasicは10[m/s]を保って走っているでしょうか。
このBasicは、毎フレーム自分の速度を調べ、10[m/s]より速いか遅いか調べます。
読み込まれた直後は速度は10[m/s]以下なので、変数Engineには-2500が代入されます。
そしてWheelが回り、地面との摩擦でBasicは加速し、また速度を調べ、10[m/s]以下なら更に加速します。
10[m/s]に達すると変数Engineは0になり、Basicは加速も減速もせず10[m/s]を保ちます。
速度がまた10[m/s]を下回れば変数Engineは再び-2500になり、Basicは再加速します。
速度の状況によって変数を変える
わけです。出力によって入力を変えることを
フィードバック
と言います。
このページで紹介している制御は全て入力が出力によって変化する
フィードバック制御
です。
P制御
スイッチ制御はごく簡単に書けますが、汎用性や実用性に欠けます。
そこで次はP制御(比例制御)について解説します。
P制御とは、出力値と目標値の差のことを
偏差
と呼び、入力を偏差に
比例
させるものです。
Basicの速度制御
例は引き続きBasicです。
入力値 | 出力値 | 目標値 | 偏差 |
Engine | -_VZ(0) | 10 | -_VZ(0)-10 |
これの偏差と入力値を 比例 させるわけですから、Luaで書くと
ENGINE = (-_VZ(0)-10)*500
out(0,-_VZ(0))
この動作を表にすると
入力値 | 出力値 | 目標値 | 偏差 |
-2500 | 0 | 10 | 10 |
-2500 | 2 | 10 | 8 |
-2500 | 4 | 10 | 6 |
-2000 | 6 | 10 | 4 |
-1000 | 8 | 10 | 2 |
0 | 10 | 10 | 0 |
1000 | 12 | 10 | -2 |
2000 | 14 | 10 | -4 |
2500 | 16 | 10 | -6 |
2500 | 18 | 10 | -8 |
2500 | 20 | 10 | -10 |
変数Engineの最大・最小値が2500と-2500なので、その値よりは動きません。
このP制御だと、出力値が目標値を通り越したとき、出力値もプラス(後進)になり、Basicを減速させようとします。
このような単純な構文で滑らかな動作とプラスとマイナスどちらにも対応できるのがP制御の魅力です。
また、このLuaでの
*500
の部分を
P係数
(比例係数)と呼びます。
これを変えると挙動がどう変わるか試してみてください。
しかしこのP制御にも弱点があり、Basicが坂道に差し掛かったとき、速度は10[m/s]よりも落ち、制御し切れません。
この坂道などで入力とは関係なく出力が変動する要因のことをを
外乱
と言います。
坂道での偏差の増大はP係数を大きくすることで緩和されますが、根本的な解決にはなりません。
なぜなら、偏差がゼロの理想的なBasicの状態では偏差ゼロ=入力値ゼロになり、重力の影響を避けられません。
坂道という外乱がある状態で偏差をゼロにするには、入力値はある程度必要なのです。
しかしこれをP制御では表現できません。どうしたものか・・・