「実践制御3」の編集履歴(バックアップ)一覧はこちら

実践制御3 - (2012/08/23 (木) 16:02:05) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

RigidChipsではプログラミング言語Luaを使ってモデルに複雑な動きをさせたり、制御したりすることができます。~ ホイールの制御、航空機の制御、ミサイルの制御といろいろありますが、ここではその制御について&bold(){Luaで}解説します。 *制御概論 「制御」とは「入力と出力を持つシステムにおいてその出力を自由に変化させること」です。~ 真面目にやると制御工学とか言ってちゃんとした学問になるっぽいけど、ここではRigidChipsでモデルが思い通りに動けばいいやというぐらいでやっていきます。~ 制御工学の授業とかではアホみたいに抽象的な制御を扱うらしいので、RigidChipsでの具体的な制御を知っているとその筋に進む人は有利・・・かもしれない。~ ~ さて、制御の大体の要素は、「&bold(){制御対象}」と「&bold(){入力}」と「&bold(){出力}」です。~ 飛行機の速度制御を例にすると、飛行機が制御対象、エンジンのPowerが入力、速度が出力に当たります。~ 「エンジンのPower」をうまく操作して、「飛行機」の「速度」を一定に保つのが速度制御と言うわけです。~ では、制御の方法の具体例を見てみましょう。~ *ON/OFF制御 **トイレタンク 誰でも思いつく、シンプルな制御。~ 身近な例ではトイレの水タンクで、水を流した後タンクに水を入れ続け、一定より水位が上がると浮きが栓を押し、水を止めるという奴です。~ &bold(){制御対象}はトイレのタンク、&bold(){入力}はトイレタンクに入れる水、&bold(){出力}はトイレタンクの水位で、~ 「トイレタンクに入れる水」をほどよく調整して「トイレタンクの水位」を一定に保つことが&bold(){目的}です。~ 表で動作を表現するとこんな感じです。~ |対象|入力|出力| |タンク|水道|水位| |-|出す|一定以下| |-|止める|一定以上| ~ #co(){{ 上の例でトイレ君は、どのようにしてちょうどいい量の水をタンクにためるのでしょうか。 トイレ君はまず最初に、タンク内に水がどのくらいたまっているかを調べます。 このときに水の量が少ないと思ったら、タンクの中に水を入れて、水位を上げます。 そして、もう一回水の量がたまったかを確認します。まだまだ足りないと思ったら、もっと水を出して、 水の量を増やしていきます。この作業をずっとずっと繰り返して、ようやく水が十分たまったと思ったら、 水をストップします。 やっていることはこれだけです。簡単でしょう? 要するに、&bold(){たまった水の量(出力)を確認しながら、水を出すか止めるか(入力)を決める}わけです。これが、ON/OFF制御です。 }} **Basicの速度制御 RigidChips的な例ではお手元のBasicをご覧ください。これを&bold(){10[m/s]}(36[km/h])になるように速度制御してみましょう。~ 「入力」は勿論WheelのPower変数Engine、速度は-_VZ(0)[m/s](前進でマイナスになるので)になります。~ このとき-_VZ(0)を&bold(){出力値}、10を&bold(){目標値}と呼びます。 |対象|入力|出力| |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~ &space(8)ENGINE = -2500~ else~ &space(8)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は再加速します。~ &bold(){速度の状況によって変数を変える}わけです。出力によって入力を変えることを&bold(){フィードバック}と言います。~ このページで紹介している制御は全て入力が出力によって変化する&bold(){フィードバック制御}です。~ *P制御 スイッチ制御はごく簡単に書けますが、汎用性や実用性に欠けます。~ そこで次はP制御(比例制御)について解説します。~ P制御とは、出力値と目標値の差のことを&bold(){偏差}と呼び、入力を偏差に&bold(){比例}させるものです。 **Basicの速度制御 例は引き続きBasicです。~ |入力値|出力値|目標値|偏差| |Engine|-_VZ(0)|10|-_VZ(0)-10| これの偏差と入力値を&bold(){比例}させるわけですから、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での&bold(){*500}の部分を&bold(){P係数}(比例係数)と呼びます。~ これを変えると挙動がどう変わるか試してみてください。~ しかしこのP制御にも弱点があり、Basicが坂道に差し掛かったとき、速度は10[m/s]よりも落ち、制御し切れません。~ この坂道などで入力とは関係なく出力が変動する要因のことをを&bold(){外乱}と言います。~ 坂道での偏差の増大はP係数を大きくすることで緩和されますが、根本的な解決にはなりません。~ なぜなら、偏差がゼロの理想的なBasicの状態では偏差ゼロ=入力値ゼロになり、重力の影響を避けられません。~ 坂道という外乱がある状態で偏差をゼロにするには、入力値はある程度必要なのです。~ しかしこれをP制御では表現できません。どうしたものか・・・
RigidChipsではプログラミング言語Luaを使ってモデルに複雑な動きをさせたり、制御したりすることができます。~ ホイールの制御、航空機の制御、ミサイルの制御といろいろありますが、ここではその制御について&bold(){Luaで}解説します。 #contents() *制御概論 「制御」とは「入力と出力を持つシステムにおいてその出力を自由に変化させること」です。~ 真面目にやると制御工学とか言ってちゃんとした学問になるっぽいけど、ここではRigidChipsでモデルが思い通りに動けばいいやというぐらいでやっていきます。~ 制御工学の授業とかではアホみたいに抽象的な制御を扱うらしいので、RigidChipsでの具体的な制御を知っているとその筋に進む人は有利・・・かもしれない。~ ~ さて、制御の大体の要素は、「&bold(){制御対象}」と「&bold(){入力}」と「&bold(){出力}」です。~ 飛行機の速度制御を例にすると、飛行機が制御対象、エンジンのPowerが入力、速度が出力に当たります。~ 「エンジンのPower」をうまく操作して、「飛行機」の「速度」を一定に保つのが速度制御と言うわけです。~ では、制御の方法の具体例を見てみましょう。~ *ON/OFF制御 **トイレタンク 誰でも思いつく、シンプルな制御。~ 身近な例ではトイレの水タンクで、水を流した後タンクに水を入れ続け、一定より水位が上がると浮きが栓を押し、水を止めるという奴です。~ &bold(){制御対象}はトイレのタンク、&bold(){入力}はトイレタンクに入れる水、&bold(){出力}はトイレタンクの水位で、~ 「トイレタンクに入れる水」をほどよく調整して「トイレタンクの水位」を一定に保つことが&bold(){目的}です。~ 表で動作を表現するとこんな感じです。~ |対象|入力|出力| |タンク|水道|水位| |-|出す|一定以下| |-|止める|一定以上| ~ #co(){{ 上の例でトイレ君は、どのようにしてちょうどいい量の水をタンクにためるのでしょうか。 トイレ君はまず最初に、タンク内に水がどのくらいたまっているかを調べます。 このときに水の量が少ないと思ったら、タンクの中に水を入れて、水位を上げます。 そして、もう一回水の量がたまったかを確認します。まだまだ足りないと思ったら、もっと水を出して、 水の量を増やしていきます。この作業をずっとずっと繰り返して、ようやく水が十分たまったと思ったら、 水をストップします。 やっていることはこれだけです。簡単でしょう? 要するに、&bold(){たまった水の量(出力)を確認しながら、水を出すか止めるか(入力)を決める}わけです。これが、ON/OFF制御です。 }} **Basicの速度制御 RigidChips的な例ではお手元のBasicをご覧ください。これを&bold(){10[m/s]}(36[km/h])になるように速度制御してみましょう。~ 「入力」は勿論WheelのPower変数Engine、速度は-_VZ(0)[m/s](前進でマイナスになるので)になります。~ このとき-_VZ(0)を&bold(){出力値}、10を&bold(){目標値}と呼びます。 |対象|入力|出力| |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~ &space(8)ENGINE = -2500~ else~ &space(8)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は再加速します。~ &bold(){速度の状況によって変数を変える}わけです。出力によって入力を変えることを&bold(){フィードバック}と言います。~ このページで紹介している制御は全て入力が出力によって変化する&bold(){フィードバック制御}です。~ *P制御 スイッチ制御はごく簡単に書けますが、汎用性や実用性に欠けます。~ そこで次はP制御(比例制御)について解説します。~ P制御とは、出力値と目標値の差のことを&bold(){偏差}と呼び、入力を偏差に&bold(){比例}させるものです。 **Basicの速度制御 例は引き続きBasicです。~ |入力値|出力値|目標値|偏差| |Engine|-_VZ(0)|10|-_VZ(0)-10| これの偏差と入力値を&bold(){比例}させるわけですから、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での&bold(){*500}の部分を&bold(){P係数}(比例係数)と呼びます。~ これを変えると挙動がどう変わるか試してみてください。~ しかしこのP制御にも弱点があり、Basicが坂道に差し掛かったとき、速度は10[m/s]よりも落ち、制御し切れません。~ この坂道などで入力とは関係なく出力が変動する要因のことをを&bold(){外乱}と言います。~ 坂道での偏差の増大はP係数を大きくすることで緩和されますが、根本的な解決にはなりません。~ なぜなら、偏差がゼロの理想的なBasicの状態では偏差ゼロ=入力値ゼロになり、重力の影響を避けられません。~ 坂道という外乱がある状態で偏差をゼロにするには、入力値はある程度必要なのです。~ しかしこれをP制御では表現できません。どうしたものか・・・

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー