[[2013b/Member]]

#contents

*コースと攻略方法 [#y2bdf8ae]

●コースについて
**コースについて [#a95be814]

&ref(2013b/Member/Redcicudu/Mission1/らいん1.jpg,39.9KB,何とも苦労したコースである);

コースは写真の通りである。今回は空き缶をコース上に配置し、それをどかしてもとに位置に戻しつつゴールを目指さなくてはならない。このコースの特徴を以下に示す。

+交差点は合計4回通過しなくてはならない。
+急なカーブや直角なカーブがあり、プログラムによっては交差点と誤認をしてしまう。
+輪っか状になっている部分が二つあり、こちらもプログラムによっては交差点と誤認してしまう。
+空き缶は交差点から10センチ以上離して設置しなくてはならない。

以上が主な特徴である。

●攻略方法
**攻略方法 [#xf054f62]

まず、私のプログラムはテキストの例を参考に作られているため、急なカーブや直角のカーブを見分けることができない。そこで、交差点を渡った回数を数え、その回数ごとにトレースする方法を切り替えることでこのコースを攻略することにした。

*ロボットについて [#vb01f325]

&ref(2013b/Member/Redcicudu/Mission1/ろぼ.jpg,40.7KB,いいロボだろう?);
&ref(2013b/Member/Redcicudu/Mission1/ろぼ4.jpg,36.4KB,いいロボだろう?);

ロボットは写真の通り少し背高ノッポになってしまった。それはできる限り縦と横に広がってしまわないように配慮したからだ。縦と横に広いとセンサーを上手くつけられなかったり、旋回するのに余計タイヤを回さなくてはならなくなってしまった、という経験を生かしているつもりである。また、重心を中心にするという目的もある。
ロボットは写真の通り少し背高ノッポになってしまった。それはできる限り縦と横に広がってしまわないように配慮したからだ。縦と横に広いとセンサーを上手くつけられなかったり、旋回するのに余計タイヤを回さなくてはならなくなってしまった、という経験を生かしているつもりである。また、重心を中心に寄せるという目的もある。また、初期のものから若干の改良を加えており強度的に問題のないパーツを極力外すことで軽量化を行っている。一応パーツは減ったもののセンサーの位置やアームの動作は初期のものとなんら変わりない。

&ref(2013b/Member/Redcicudu/Mission1/ろぼ2.jpg,38.8KB,みどころですよ!);
&ref(2013b/Member/Redcicudu/Mission1/ろぼ3.jpg,70.8KB,みどころですよ!);

アームは両側からはさむ形にした。広げきっているときはできるだけ邪魔にならないように胴体に近くなるように調整した。アーム用のモーターの回転軸が後方にあるため、長いリンケージロッドを利用しているのが特徴である。ロッドの接合部分はなかなか工夫したポイントの一つだ。
アームは両側からはさむ形にした。広げきっているときはできるだけ邪魔にならないように胴体に近くなるように調整した。アーム用のモーターの回転軸が後方にあるため、長いリンケージロッドを利用しているのが特徴である。リンケージロッドを使用することによって、ギヤを使用するときとは違いモーターの動きがダイレクトに伝わるし、ギヤをマウントするためのパーツを新たにつける必要もないので構造の簡略化と軽量化に寄与している。ロッドの接合部分は三次元的な動作に対応しており、なかなか工夫したポイントの一つでもある。

*プログラムについて [#q17d2328]

このプログラムはテキストのプログラムを参考にしている。私がプログラムに不慣れであったためにとんでもなく長いプログラムになってしまった。そこでいくつかに区切って説明をする。
このプログラムはテキストのプログラムを参考にしている。私がプログラムに不慣れであったためにとんでもなく長いプログラムになってしまった。そこで定義やサブルーチンごとに区切って説明していく。

●各種定義
 #define BB 30 //閾値
**定義 [#k9562d8d]

主にモーター関係のものが多い、ついでなのでカウンターの設定も一緒にしておいた。
 #define BB 30 //黒線の上なのかを識別するための閾値(しきいち)、この値を元に五段階の動作  を行うようにした
 #define BW 38
 #define WB 52
 #define WW 45
  
 #define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_B,speedL); //出力を入力すればモ ーターを動かせるように定義
 #define FWD OnRL(25,25); //前進をFWDとして定義
 
 #define HA 40 //モーターの出力
 #define HB 43
 #define LA 20
 #define LB 23
 #define T_LEFT1 OnRL(30,0); //左折  サブルーチンCROSS_1,2,4,5,6,7で使用
 #define T_RIGHT1 OnRL(-10,20); //右折
 #define Q_LEFT1 OnRL(25,-15); //左旋回
 #define Q_RIGHT1 OnRL(-15,15); //右旋回 
 
 #define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_B,speedL);
 #define FWD OnRL(HA,HB); //前進
 #define T_LEFT OnRL(LA,0); //左折
 #define T_RIGHT OnRL(0,LB); //右折
 #define Q_LEFT OnRL(LA,-LB); //左旋回
 #define Q_RIGHT OnRL(-LA,LB); //右旋回
 #define T_LEFT2 OnRL(20,0); //左折 サブルーチンCROSS_3で使用
 #define T_RIGHT2 OnRL(8,25); //右折
 #define Q_LEFT2 OnRL(20,-20); //左旋回
 #define Q_RIGHT2 OnRL(0,25); //右旋回
 
 #define STEP 5 //一回の判断で行う動作の長さ
 #define nMAX 40 //カウンタの最大値
 #define SB Off(OUT_AB);Wait(1000); //小休止
 #define CT 350 //交差点通過にかける時間
 #define STEP 5 //一回判断で行う動作の長さ
 #define nMAX 30 //交差点識別用カウンターの最大値、ある動きをこの数値以上行った時を交差点 として識別
 
 #define cross_line OnFwd(OUT_A,HA);OnFwd(OUT_B,HB);Wait(CT);SB; //交差点通過の動作
 #define cross_line RotateMotorEx(OUT_AB,speed_ab,75,0,true,true); //交差点通過の動作
 
 #define RMC(speed_c,-rad_c) RotateMotor(OUT_C,speed_c,rad_c);
 #define RMC(speed_c,-rad_c) RotateMotor(OUT_C,speed_c,rad_c); //アームの動きを定義
 #define speed_c 25 //アームの出力
 #define rad_c 150 //アームの動作範囲
 #define ARM1 RMC(speed_c,rad_c); //空き缶をつかむ
 #define ARM2 RMC(speed_c,-rad_c); //空き缶をはなす
 #define speed_ab 30 //モーターの出力
 #define rad_c 140 //アームの動作範囲
 #define ARM1 RMC(speed_c,rad_c); //アームが空き缶をつかむ動作をARM1として定義
 #define ARM2 RMC(speed_c,-rad_c); //アームが空き缶をはなす動作をARM2として定義
 #define speed_ab 30 //サブルーチンCATCH_CANの時のモーターの出力
 
 	int nOnline=0; //カウンタの変数を設定、0とする。	
 	int Online2=0;
 	int Online3=0;
 	int Online4=0;
 	int Online5=0;
 	int Online6=0;
 	int Online7=0;
ここでは各種動作や値の定義を行っている。ついでなのでカウンタ変数の設定も含めておいた。アームの動作は精密に行いたかったのでサーボモータとしての機能を利用した。おかげで無理な動作でアームが破損するというとは無かった。
 	int Online1=0; //交差点識別用カウンター、ある動作を数えるためのカウンターであり動作はサブルーチンによって異なる	
 	int Online2=0; //交差点を渡った回数を数えるカウンター、Online2~7まですべて同じ用途
 	int Online3=0; //  
 	int Online4=0; // 
 	int Online5=0; // 
 	int Online6=0; //
 	int Online7=0; // 
 	int OnRightangle=0; //ゴール付近のT字路を通過した回数を数えるカウンター、  OnRightangle1と2は同じ用途
 	int OnRightangle2=0; //
このプログラムは交差点の識別やサブルーチンの切り替えタイミングを計るためにカウンターを利用している、ある動作を行った回数を記録するすることであらかじめ与えておいた数値を超える回数を記録したら次の動作やサブルーチンに移行するように設定してある。

●サブルーチンその1
 sub CROSS_1()

**空き缶を掴むサブルーチン [#r3b5894d]
 sub CATCH_CAN() //空き缶をつかむ一連の動作のサブルーチン
 {
 
 	while(nOnline<nMAX){
  	RotateMotorEx(OUT_AB,speed_ab,70,0,true,true); //掴む位置まで移動
 
 	if(SENSOR_1<BB){		
  	ARM1; //缶を掴む
 
 	Q_RIGHT;
 	Off(OUT_C); //小休止、すぐに回頭すると微妙に位置がズレてしまうため
 
 	Wait(500);
 
  	RotateMotorEx(OUT_AB,speed_ab,240,0,true,true); //回頭位置まで移動
   
 
 	RotateMotorEx(OUT_AB,speed_ab,145,-100,true,true); //90度回頭
 
 	Off(OUT_AB); //小休止
 
 	Wait(500);
 
 	RotateMotorEx(OUT_AB,speed_ab,330,0,true,true); //回頭位置まで移動(その2) 
 
 	Off(OUT_AB); //小休止
 
 	Wait(500);
 
 	RotateMotorEx(OUT_AB,speed_ab,360,100,true,true); //180度回頭
 
 	ARM2; //缶を離す
 
 	Off(OUT_C); //小休止
 
 	Wait(500);
 
 	RotateMotorEx(OUT_AB,-speed_ab,200,0,true,true); //缶から離れる
 
 	RotateMotorEx(OUT_AB,speed_ab,410,100,true,true); //回頭して前を向く
 
 } 
私の場合は空き缶を直角カーブ上においたので空き缶をもとに戻す際に90度回頭しなければならなかったので、比較的正確に動作させることができるようにサーボモーターの機能を利用した。

**CROSS_1 [#r0d304e9]
 sub CROSS_1() //はじめのT字路を通過するためのサブルーチン
 {
 
 	while(OnRightangle<1){ //T字路を通過したらサブルーチンCROSS_2へ移行するように設定
 
 		while(Online1<nMAX){ //右旋回(Q_RIGHT1)をnMAX回以上行ったら交差点とみな し、通過するように設定
 
 		if(SENSOR_1<BB){ //黒線上では右旋回を行う
 
 		Q_RIGHT1;
 	
 	nOnline++;
 		Online1++; //右旋回の回数をカウント
 
 	} else {
 		} else {
 
 	if(SENSOR_1<BW){
 		if(SENSOR_1<BW){ //黒線よりのところでは右折を行う
 	
 	T_RIGHT;
 		T_RIGHT1;
 	
 	} else if(SENSOR_1<WB){	
 		} else if(SENSOR_1<WB){ //黒線と紙面の中間ではまっすぐ前進する
 	
 	FWD;
 		FWD;
 	
 	} else if(SENSOR_1<WW){
 		} else if(SENSOR_1<WW){ //紙面よりのところでは左折を行う
 	
 	T_LEFT;
 		T_LEFT1;
 
 	} else {
 		} else { //紙面上では左旋回を行う
 
 	Q_LEFT;
 		Q_LEFT1;
 
 	}
 		}
 
 	nOnline=0;
 		Online1=0; //カウンターをリセット
 		
 	}
 		}
 
 	Wait(STEP);
 		Wait(STEP); //左折や右折などを一回行うごとの長さ
 
 		}
 
 	RotateMotorEx(OUT_AB,speed_ab,50,0,true,true); //T字路を通過
 	RotateMotorEx(OUT_AB,speed_ab,180,100,true,true); //T字路を通過
 	OnRightangle++; //T字路を通過した回数をカウント
 	Online1=0; //カウンタをリセット
 	}
 } 	
このサブルーチンは進行方向から見て黒線の右側のふちに沿って走るプログラムである。簡単に説明すると、センサーの値が黒線の真っただ中を示したなら右へ、黒線の外なら左へ、その中間なら前進するというプログラムである。
ちなみに「nOnline」は、「右へ行く動作を何回行ったか」をカウントしている。その数が初めに定義した「nMAX」回より多くなったらこのサブルーチンを一旦停止するように設定してある。
 	
 }	
普通にライントレースさせたのではT字路を上手く曲がることができなかったので専用のサブルーチンを作った。以降のライントレースに関するサブルーチンは類似する点が多いので各命令に関する説明を少し省略してある。このサブルーチンにおいても90度回頭する動作を要求されるのでサーボモーターの機能を利用した。また、プログラムの説明を呼んでいただけると分かると思うがライントレースといってもこのプログラムは黒線そのものをたどるのではなく、黒い線の「縁」をトレースしていくのである。

●サブルーチンその2
 sub CROSS_2() //黒線の左の縁に沿って動く、前のものとは逆になってる。
**CROSS_2 [#w228b187]
 sub CROSS_2() //一回目の交差点を渡るまでのサブルーチン
 {
 
 	while(Online3<40){
 	while(Online2<1){ //交差点を一回渡ったらサブルーチンCROSS_3へ移行するように設定
 
 	if(SENSOR_1<BB){		
 		while(Online1<nMAX){
 
 	Q_LEFT;
 		if(SENSOR_1<BB){		
 
 		Q_RIGHT1;
 	
 	Online3++;
 		Online1++; //カウントするのは右旋回
 
 	} else {
 		} else {
 
 	if(SENSOR_1<BW){
 		if(SENSOR_1<BW){
 	
 	T_LEFT;
 		T_RIGHT1;
 	
 	} else if(SENSOR_1<WB){	
 		} else if(SENSOR_1<WB){	
 	
 	FWD;
 		FWD;
 	
 	} else if(SENSOR_1<WW){
 		} else if(SENSOR_1<WW){
 	
 	T_RIGHT;
 		T_LEFT1;
 
 	} else {
 		} else {
 
 	Q_RIGHT;
 		Q_LEFT1;
 
 	}
 		}
 
 	nOnline=0;
 		Online1=0;
 		
 	}
 		}
 
 	Wait(STEP);
 		Wait(STEP);
 
 		}	
 
 	cross_line; //交差点を渡る
 	Online2++; //交差点を渡った回数をカウント
 	Online1=0; //カウンタをリセット
 	}
 } 	
こちらのサブルーチンは左側のふちに沿って進むようにしてある。つまりその1とは左右が逆になっているのだ。あとはカウンターの変数を混同してしまわないように別のものにしてある。
 
 } 
基本的にCROSS_1と変わりがない、カウンターの数値が上限を越すとT字路を曲がる動作の代わりに交差点を渡る動作が行われる。

●サブルーチンその3
 sub CROSS_3()
 
**CROSS_3 [#ibd9b9f3]
 sub CROSS_3() //輪っかになっているところを動くサブルーチン、黒線の左の縁に沿って動くので前のものとは逆になってる
 {
 
 	while(Online6<50){
 	while(Online3<1){ //交差点を一回渡ったらサブルーチンCROSS_4へ移行するように設定
 
 	if(SENSOR_1<BB){		
 		while(Online1<nMAX){
 
 	Q_RIGHT;
 		if(SENSOR_1<BB){ //黒線上では左旋回を行う	
 
 	} else if(SENSOR_1<BW){
 		Q_LEFT2;
 	
 	T_RIGHT;
 		Online1++; //今回は動きが逆になるので左旋回の回数をカウントする
 
 		} else {
 
 		if(SENSOR_1<BW){ //黒線よりのところでは左折を行う
 	
 	} else if(SENSOR_1<WB){	
 		T_LEFT2;
 	
 	FWD;
 
 	Online6++;
 		} else if(SENSOR_1<WB){ //黒線と紙面の中間ではまっすぐ前進する
 	
 	} else {
 
 	if(SENSOR_1<WW){
 		FWD;
 	
 	T_LEFT;
 		} else if(SENSOR_1<WW){ //紙面よりのところでは右折を行う
 	
 		T_RIGHT2;
 
 	} else {
 		} else { //紙面上では右旋回を行う
 
 	Q_LEFT;
 		Q_RIGHT2;
 
 	}
 		}
 
 	Online6=0;
 		Online1=0;
 		
 	}
 		}
 
 	Wait(STEP);
 		Wait(STEP);
 
 		}
 
 	cross_line;
 	Online3++;
 	Online1=0;
 	}
 
 } 	
こちらは空き缶を掴む直前のライントレースである。その1と違うのはカウントするのは「何回前進したか」をカウントしている。このサブルーチンが終わった後にさらに前進し、空き缶を掴むのである。
輪っかを動くサブルーチン。輪っかの内側をトレースしてしまうとカウンターが動作を余計にカウントしてしまい交差点と誤認してしまう。そこで輪っかの外側をトレースするようにサブルーチンを作った。

●サブルーチンその4
 sub CATCH_CAN()
**CROSS_4 [#y3dfe5b8]
 sub CROSS_4()
 {
 
 	RotateMotorEx(OUT_AB,speed_ab,90,0,true,true); //掴む位置まで移動
 	while(Online4<1){ //交差点を1回渡ったら、CROSS_5へ移行するように設定
 
 	ARM1; //缶を掴む
 		while(Online1<nMAX){
 
 	Off(OUT_C); //小休止
 		if(SENSOR_1<BB){		
 
 	Wait(500);
 		Q_RIGHT1;
 	
 		Online1++;
 
 	RotateMotorEx(OUT_AB,speed_ab,240,0,true,true); //回頭位置まで移動
 		} else {
 
 	RotateMotorEx(OUT_AB,speed_ab,180,-100,true,true); //90度回頭
 		if(SENSOR_1<BW){
 	
 		T_RIGHT1;
 	
 		} else if(SENSOR_1<WB){	
 	
 		FWD;
 	
 		} else if(SENSOR_1<WW){
 	
 		T_LEFT1;
 
 	Off(OUT_AB);
 		} else {
 
 	Wait(500);
 		Q_LEFT1;
 
 	RotateMotorEx(OUT_AB,speed_ab,500,0,true,true); //回頭位置まで移動(その2) 
 		}
 
 	Off(OUT_AB);
 		Online1=0;
 		
 		}
 
 	Wait(500);
 		Wait(STEP);
 
 	RotateMotorEx(OUT_AB,speed_ab,410,100,true,true); //180度回頭
 		}
 
 	ARM2; //缶を離す
 	cross_line;
 	Online4++;
 	Online1=0;
 	}
 
 	Off(OUT_C);
 }
こちらはCROSS_2とほとんど同じなので説明は割愛。 

**CROSS_5 [#h97ef058]
 sub CROSS_5() //このサブルーチンで交差点を識別するためにカウントするのは右折(T_RIGHT1) の動作
 {
 
 	Wait(500);
 	while(Online5<1){ //交差点を渡ったらCROSS_6へ移行するように設定
 
 	RotateMotorEx(OUT_AB,-speed_ab,100,0,true,true); //缶から離れる
 		while(Online1<nMAX){
 
 	RotateMotorEx(OUT_AB,speed_ab,410,100,true,true); //回頭して前を向く
 		if(SENSOR_1<BB){		
 
 }  
これは空き缶を掴むための一連の動作なのだが、空き缶を直角カーブ上に配置したので方向転換が少し面倒である。今回は電池の消費具合に左右されにくいようにサーボモーターの機能を利用した。
 		Q_RIGHT1;
 
 		} else if(SENSOR_1<BW){
 	
 		T_RIGHT1;
 
 		Online1++; //右折の回数をカウントする
 	
 		} else {
 
 		if(SENSOR_1<WB){	
 
 		FWD;
 	
 		} else if(SENSOR_1<WW){
 		
 		T_LEFT1;
 
 		} else {
 
 		Q_LEFT1;
 
 		}
 
 		Online1=0;
 		
 		}
 
 		Wait(STEP);
 
 		}
 
 	cross_line;
 	Online5++;
 	Online1=0;
 	}
 	
 }	
このサブルーチンもほとんどはCROSS_2と同じなのだが一つ違う点はカウントする動作は「右折」の動作であるということ。このサブルーチンが向かう先の交差点はコースの関係上完全な90度の交差点ではない、そのため右旋回の動作を交差点で行ってくれないので右折の動作をカウントすることで解決した。

●メインタスク
 task main()
**CROSS_6 [#m37fa7b3]
 sub CROSS_6() //空き缶をつかむ直前のライントレース、前進を行った回数をカウントして空き缶を掴むサブルーチンへと移行する
 {
 
 	SetSensorLight(S1); //光センサーを設定
 	while(Online6<1){ //空き缶を動かした後はCROSS_7へ移行するように設定
 
 	SetSensorLowspeed(S2); //超音波センサーを設定
 		while(Online7<180){ //前進を180回行ったら超音波センサーで空き缶を探すよう  に設定
 
 	long t0=CurrentTick();
 		if(SENSOR_1<BB){
 
 	while(CurrentTick()-t0<=8000){ //最初の8秒間は交差点を認識させない、スタートのT字路を交差点と誤認するため
 		Q_RIGHT1;
 
 		CROSS_1();
 		} else if(SENSOR_1<BW){
 	
 		T_RIGHT1;
 	
 		} else if(SENSOR_1<WB){
 	
 		FWD;
 
 	}
 		Online7++; //前進した回数をカウントする
 	
 		} else {
 
 	while(Online2<1){ //交差点を一回渡ったらトレースする縁を切り替える
 		if(SENSOR_1<WW){
 	
 		T_LEFT1;
 
 		CROSS_1();
 		} else {
 
 	SB;
 	T_LEFT;Wait(nMAX*STEP); //方向修正
 	cross_line; //交差点を渡る
 	Online2++; //交差点を渡った回数を追加
 	nOnline=0; //カウンタをリセット
 		Q_LEFT1;
 
 		}
 
 		Online7=0;
 		
 		}
 
 		Wait(STEP);
 
 		}
 	
 	OnFwdSync(OUT_AB,20,0); //空き缶を感知するまで前進
 	until(SensorUS(S2)<=15); //空き缶を15cm手前以内に感知したらサブルーチンCATCH_CANへ 移行
 	CATCH_CAN(); //空き缶をつかむ一連の動作のサブルーチン
 	Online6++;
 	Online1=0;
 	}
 
 	OnFwd(OUT_A,50); //反対の縁をトレースするので反対側へ移動
 }	
空き缶を掴む直前のライントレース、あるいは掴む動作とライントレースとの切り替えのためのサブルーチンといってもいい、超音波センサーでしっかりと空き缶を捉え尚且つアームでがっちりと掴むためにはライントレースと超音波センサーで探知する動作をスムーズに切り替える必要があったあったためこのサブルーチンでは「前進」の動作をカウントして探知の動作へと切り替えている。

**CROSS_7 [#vf7e9cc1]
 sub CROSS_7() //ゴール手前のT字路を通過するためのサブルーチン
 {
 
 	Wait(800);
 	while(OnRightangle2<1){ //直角を通過
 
 	while(Online4<1){ //交差点を一回渡ったらトレースする縁を切り替える(その2)
 		while(Online1<nMAX){
 
 		CROSS_2();
 		if(SENSOR_1<BB){		
 
 	SB;
 	T_LEFT;Wait(nMAX*STEP); //方向修正(その2)
 	cross_line;
 	Online4++; //交差点を渡った回数を追加(その2)
 	Online3=0; //カウンタをリセット(その2)
 	}
 		Q_RIGHT1;
 	
 		Online1++;
 
 	OnFwd(OUT_B,50); //またトレースする縁が変わるので反対側へ移動
 		} else {
 
 	Wait(900);
 		if(SENSOR_1<BW){
 	
 		T_RIGHT1;
 	
 		} else if(SENSOR_1<WB){	
 	
 		FWD;
 	
 		} else if(SENSOR_1<WW){
 	
 		T_LEFT1;
 
 	while(Online5<2){ //交差点を二回渡ったら、交差点を認識しないようにする
 		} else {
 
 		CROSS_1();
 		Q_LEFT1;
 
 	SB;
 	T_LEFT;Wait(nMAX*STEP);
 	cross_line;
 	Online5++;
 	nOnline=0;
 	}
 		}
 
 	while(Online7<1){ //空き缶の目前までライントレース
 		Online1=0;
 		
 		}
 
 		CROSS_3();
 		Wait(STEP);
 
 	SB;
 	FWD; //空き缶を感知するまで前進
 	until(SensorUS(S2)<=10);
 	CATCH_CAN(); //空き缶をつかむ一連の動作
 	Online7++;
 	nOnline=0;
 		}
 	
 
 	RotateMotorEx(OUT_AB,speed_ab,40,0,true,true); //T字路を通過
 	RotateMotorEx(OUT_AB,speed_ab,180,100,true,true); //T字路を通過
 	OnRightangle2++; //T字路を通過した回数をカウント
 	Online1=0; //カウンタをリセット
 	}
 
 	CROSS_1(); //再びライントレースを行いゴールを目指す
 }
こちらは基本的にCROSS_1と同じサブルーチンなので説明を割愛する。

**メインタスク [#qf4e8c29]

ここで今までのサブルーチンを利用して一連の動作をすべてつなげている。
 task main()
 {
 
 	SetSensorLight(S1); //光センサーを設定
 
 	SetSensorLowspeed(S2); //超音波センサーを設定
 
 	CROSS_1(); //T字路まで
 
 	CROSS_2(); //輪っかの直前
 
 	OnFwd(OUT_A,50); //反対の縁をトレースするので反対側へ移動
 
 	Wait(500);
 
 	CROSS_3(); //輪っかを進む
 
 	OnFwd(OUT_B,50); //またトレースする縁が変わるので反対側へ移動
 
 	Wait(600);
 
 	CROSS_4(); //短い直線を進む
 
 	CROSS_5(); //2つ目の輪っかを進む
 
 	CROSS_6(); //空き缶の直前までトレース
 
 	CROSS_7(); //ゴールのT字路まで
 	
 	CROSS_2(); //ゴールを目指す
 
 } 
これがメインタスクである。多分文字ばかり読んでいても分かりにくいと思うので写真を加工して簡単な図を作成してみた。

&ref(2013b/Member/Redcicudu/Mission1/らいん2.jpg,49.9KB,おわかりいただけただろうか?);
&ref(2013b/Member/Redcicudu/Mission1/らいん3.jpg,48.9KB,おわかりいただけただろうか?);

上の図において赤い線はサブルーチンその1を、青はその2を、緑はその3を、黄色はその4を実行する領域を表している。この図において注目していただきたい点はどの領域でどのサブルーチンを使用しているかではない。すべてコースの曲線に対して常に外回りに進むようになっているのだ。こうすることによって、交差点以外ではカウンターが作動してしまうことを防ぐことができたのである。また、直角の上に空き缶を置いたのは直線が続いているところが多く、スムーズに空き缶を掴む動作に移行できるからである。
上の図において赤い線はCROSS_1、オレンジの線はCROSS_2、黄色い線はCROSS_3、緑の線はCROSS_4、青い線はCROSS_5、紫の線はCROSS_6、茶色の線はCROSS_7、ピンクの線は空き缶を探知するまでの動作となっている。この図のように輪っかになっている部分は内側とトレースせず、外側をトレースするようにできている。そうすることで交差点と急なカーブを誤認する事なくゴールを目指すことができるのだ。

*考察 [#m2fc770a]

*まとめ [#m2fc770a]
**制作した感想 [#ia7f26e3]
プログラムに関しては考え方自体はシンプルで、自分なりに「交差点」という難敵を克服したしつもりである。しかし、プログラムに不慣れであったためにとてつもなく長くなってしまった。もっと定義の仕方やサブルーチンの使い方を考え直そうと思った。
また、超音波センサーが思った以上の曲者で、視野が狭いうえに動きながら検知を行うとスムーズに次の動作へ移れなったりとなかなか手を焼かされてしまった。こちらの改善もまだまだ必要だと感じた。
また、超音波センサーが思った以上の曲者で、視野が狭いうえに動きながら検知を行うとスムーズに次の動作へ移れなったりとなかなか手を焼いた。こちらの改善もまだまだ必要だと感じた。
ロボットの製作はほとんど自分が自由勝手にやらせてもらった。講義に出席するたびにカタチの違うロボットのプログラムを行う羽目になった相方のpianoman君にはとても申し訳ないと思っている。それでもロボット自体に関しては自分なりにベストを尽くせたと考えている。

**実際に動かしてみて [#v0e10f43]
皆の前で発表する前に何回も調整を施したにもかかわらず、はじめのT字路をうまく認識してくれなかったり、普段は確実につかめていた空き缶を掴むことができなかった。たまたま私が目眩(?)を起こしてしまったせいでアームの中に空き缶を入れることができたが、よりにもよって本番でセンサーが精度よく空き缶を感知するとは思わなかった。(超音波センサーは思ったより精度がお粗末なのでそれを加味した値を設定していた)ロボコンなどで本番になってロボットがトラブルを起こしてしまうのは「本番」の魔物せいだと思った。



**改善点 [#oa9f0040]
改善点を挙げるとするならば、
+プログラムを見やすくシンプルにする。
+超音波センサーによる検知の精度を向上させる、もしくはそれ以外の方法で空き缶を検知する。
+ロボットをよりコンパクトに、低重心に、かつ部品点数を少なくする。
+もっと愛情を込めて作る

以上の三つを改善すればよりよいロボットに生まれ変わると思う。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS