Rigid Chips リファレンスマニュアル モデルデータ SCRIPT考察3-4


目次へ戻る

■SCRIPT考察3-4 「飛行機の製作:高度維持水平飛行アシスト制御」


◆考え方


ここでは、機体を水平状態に維持するためのアシスト機能の発展形として、高度維持水平飛行アシスト機能について紹介します。
ここでベースに用いる機体は、スクリプト考察3-3の完成形としています。
高度維持のためには機体を若干ピッチアップさせる必要があり、スクリプト考察3-3では補正項「+0.8」をピッチ制御式に追加しました。
この補正項を計算で求めることで、自動的に適正な補正がかかるようにします。

まず、「高度維持水平飛行する」ということを数値化します(対象となる制御量を決めます)。



上図は、飛行するコアを左(W)側より見たときの、コアの進行方向、仰角、コアのY,Z速度ベクトルの関係を表しています。
高度維持するためには、コアの進行方向(ワールド速度ベクトル)を水平にする必要があり、上図ではφ=0になるようにすることに相当します。
スクリプトでは、上図中に記載された計算式によってφの値を求め、これを0に近づけるようにエレベータを制御します。


◆実装


//plane
val{
	pitch(default=0,min=-10,max=10,step=1,disp=1)
	roll(default=0,min=-10,max=10,step=1,disp=1)
	yaw(default=0,min=-10,max=10,step=1,disp=1)
	jet(default=0,min=0,max=50000,step=0,disp=1)
	gear_angle(default=80,min=80,max=170,step=0,disp=1)
	gear_brake(default=0,min=0,max=200,step=0,disp=1)
}

key{
	0:pitch(step=-1)
	1:pitch(step= 1)
	2:roll(step= 0.5)
	3:roll(step=-0.5)
	4:yaw(step=-1)
	6:yaw(step= 1)
	5:jet(step= 50000)
	8:jet(step=-50000)
}

body{
	core(){
		n:frame(angle=-20){
			n:jet(angle=110,power=jet,effect=1){}
		}
		w:chip(){
			w:trim(angle=roll){
				w:chip(){}
			}
		}
		e:chip(){
			e:trim(angle=roll){
				e:chip(){}
			}
		}
		s:chip(){
			s:chip(){
				s:chip(){
					w:chip(angle=-90){
						s:chip(angle=-yaw){}
					}
					e:chip(angle=-90){
						s:chip(angle=yaw){}
					}
					s:chip(){
						w:trim(angle=pitch){}
						e:trim(angle=-pitch){}
					}
				}
			}
		}
		w:frame(angle=10){
			w:wheel(angle=gear_angle,brake=gear_brake){}
		}
		e:frame(angle=10){
			e:wheel(angle=gear_angle,brake=gear_brake){}
		}
	}
}

Lua{
prev=0 -- 補正項
function balancer()
-- 補正項の計算(積分) prev=prev-(_AX(0)-math.atan2(-_VY(0),-_VZ(0)))*0.5 prev=math.min(2,math.max(-2,prev)) -- 補正項のリミッタ
-- 水平飛行制御 ROLL=_EZ(0)*10+_WZ(0) PITCH=-_AX(0)*20-_WX(0)+prev end function gear_updown() if(_H(0)>=0) then GEAR_ANGLE=GEAR_ANGLE-5 -- ギアダウン GEAR_BRAKE=0 else GEAR_ANGLE=GEAR_ANGLE+5 -- ギアアップ GEAR_BRAKE=GEAR_BRAKE+10 end end function main() if(_KEY(7)>0) then -- Aキーを押しているとき水平維持制御 balancer() end gear_updown() -- 表示 out(0,"Up/Down:Pitch, Left/Right:Roll, Z/C:Yaw, X:Jet-On, D:Jet-Off") out(1,"x=",_X(0),", y=",_Y(0),", z=",_Z(0)) out(2,"ax=",math.deg(_AX(0)),", ay=",math.deg(_AY(0)),", ez=",math.deg(_EZ(0))) out(3,"vx=",_VX(0),", vy=",_VY(0),", vz=",_VZ(0)) out(4,"wx=",_WX(0),", wy=",_WY(0),", wz=",_WZ(0)) end }
まず補正項として変数「prev」を宣言します。
prev=0	-- 補正項
この変数は、フレームをまたがって値を保存しておく必要があるため、main()などの関数の外側でグローバル変数として宣言します。
スクリプト考察3-3で記述した補正項「+0.8」をprevに置き換え、関数balancerの中にprevの計算式を挿入します。
	prev=prev-(_AX(0)-math.atan2(-_VY(0),-_VZ(0)))*0.5
この式の中で「(_AX(0)-math.atan2(-_VY(0),-_VZ(0)))」の部分が、上図で示したφを求めている箇所です。
φ>0ならばprevの値を減らすことでエレベータをピッチアップさせる方向に動かします。
この結果、φの値が減少して0に近づきます。
φ<0ならばprevの値を増やすことでエレベータをピッチダウンさせる方向に動かします。
この結果、φの値が増大して0に近づきます。
φ=0ならばprevの値が変化しないので、エレベータの角度を現状維持します。
このようなprevの振る舞いの結果、機体の進行方向が水平に漸近して行くようになります。
なお、係数「0.5」は、やはり制御の効き(強さ)を表しています。
この値を大きくすれば、素早くφ=0に近づくようになりますが、勢いが強すぎて上下に振動するようになります。
逆に値が小さければ(0に近ければ)、振動は治まりますが、φ=0にゆっくりと近づいて行くようになります。
このあたりは、お好みで調整して下さい。

なお、以下の式は、補正項prevの絶対値が必要以上に大きくなり過ぎてしまわないようにするためのリミッタです。
	prev=math.min(2,math.max(-2,prev))	-- 補正項のリミッタ
今回用いた制御方式は、一般には「積分制御」などと呼ばれ、制御量が目標値からずれた状態が長時間続くと、そのズレ分が不必要に蓄積されていってしまうため、挙動が破綻するほどの大きな値になってしまう場合があります。
本モデルでは、高度維持水平飛行状態になったときのprevの安定値は、大体0.7〜0.8程度となるので、prevの変化する範囲は、-2〜+2の範囲に限定してやれば十分となります。
また、変数を上限値、下限値の範囲内で制御したい場合などには、math.min()とmath.max()の関数を組み合わせることで、このように1行で簡単に記述できることも覚えておくと便利かもしれません。

目次へ戻る