2015b/MemberOnly 目次

はじめに

今回の課題のテーマは、「ボールを離れた場所から缶に当て、ボールを回収する」である。四人二組に分かれ、ボールを投げるロボットとボールを回収するロボットを作る。私は、ボールを缶にあてるロボットを作成した。

課題とルール

課題:点P、Qのボールをセンターラインを越えずに缶に当てる。缶に当たったボールを回収する。

2015b-mission3.png

ルール

  1. 競技時間はロボットAがSTART A地点のスタートラインを横切って、ロボットBがGOAL B地点のゴールラインに達するまで、あるいは審判が続行不能と判断するまで。
  2. ロボットAはSTART A地点から出発し、P地点におかれた赤いボールを拾って350mlのアルミ缶に当てる。その後、ロボットBがボールを回収する。引き続き青いボールについても同様の動作を繰り返す。ロボットBはボールを回収した後、最終的にGOAL Bまでボールを運ぶ。
  3. アルミ缶は中身が入っているものを使う
  4. ボールがアルミ缶に当たる前にロボットBがボールに触ってはいけない。
  5. ロボットAはセンターラインを超えては行けない。
  6. アルミ缶を5cm以上動かした場合は減点

投げて側ロボットの説明

これが製作したロボットである。

IMG_2697.jpg

ロボットの全体の動作・役割

超音波センサー

ボールと缶の位置を検知するのに使用する。今回の課題をクリアするために一番大切なものである。 捜索したい範囲を決め、その捜索した範囲内で1番近い障害物にロボットを向かせる。しかし、一つ注意点があり、超音波センサーはロボットの中心ではなく右側についてる。そのため、ボールを拾うためには少し右旋回をして、ボール・缶がロボットの中心に向くようにする必要がある。

IMG_2702-1.jpg

ボールをつかむ、投げる動作

ボールの位置を検知し近づいた後、ボールをつかむ、そして、缶の方向へ投げる。この動作をするのが下の部分である。オレンジ色の矢印方向に回すとボールをつかみ、青い矢印の方向に回すとボールを投げる。右の写真は実際につかんでいる時である。

IMG_2699-1.jpg IMG_2700-1.jpg

光センサー

二つ目のボールを見つける際にライントレースをするため使用する。

IMG_2696-1.jpg

受け手側のロボット

以下のロボットが相方のチームが作成した、ボールを受け取る側のロボットである。ここでは、ボールを取る時の動作だけ簡単に説明する。

IMG_2704-1.jpg

青いまるで囲まれたのが超音波センサーであり、ボールが通過したら、赤丸で囲まれた枠でとらえるというものである。連携の動作はブルートゥースで同期させてあるため、時間の制御で行うより正確性がある。

プログラムの説明

#define SPEED 50        // 速度 速50の定義
#define SPEED_SLOW 30           // 速度 遅30の定義
const float diameter = 5.45;  // タイヤの直径(僉
const float track = 10.35;      // タイヤのトレッド幅(僉
const float pi = 3.1415;        // 円周率
void fwdDist (float d){				//	dセンチ前進
	long angle;
	angle = d / (diameter * pi) * 360.0;
	RotateMotorEx(OUT_AC,SPEED_SLOW,angle,0,true,true);
}
void turnAng(long ang){				//	角度ang度の時計回りの旋回
	long angle ;
	angle = track/diameter*ang;
	RotateMotorEx(OUT_AC,SPEED_SLOW,angle,100,true,true);
}

以下のプログラムがボールを探すものである。今回の課題で一番大切なところである。 <一番近い障害物の探し方>

int searchDirection(long ang){			//	ボールを探してその方向を向き、ボールまでの距離を返す
	long angle, tacho_min;
	int d_min;

	d_min = 300;                            //    仮の最小値
	tacho_min = 0;

まず、角度を指定しその角度の半分を時計回りに旋回する。

	angle = (track / diameter) * ang;       //    角度からタイヤの回転を計算
	turnAng(ang / 2);                       //    指定された角度の半分を旋回
	ResetTachoCount(OUT_A);                 //    角度計測をリセット

その後、指定した角度分反時計回りに旋回する。旋回している時に超音波センサーを作動させ、検知した一番小さい値をd_minに代入する。一番小さい値、すなわちそれが、一番近い障害物である。

	OnFwdSync(OUT_AC,SPEED_SLOW,-100);      //    反時計回りに旋回
	while(MotorTachoCount(OUT_A) <= angle){
		if(SensorUS(S3) < d_min){
			d_min = SensorUS(S3);  //        仮の最小値を更新
			tacho_min = MotorTachoCount(OUT_A);
		}
	}

指定した角度を旋回したのち、”d_minに代入された場所=障害物の場所”にむかせるため時計回りに旋回させる。これにより、ロボットはボールの方向を向いたことになる。

	OnFwdSyncEx(OUT_AC,SPEED_SLOW,100,RESET_NONE);
	until(MotorTachoCount(OUT_A) <= tacho_min || SensorUS(S3) <= d_min);

	Wait(15);                               //微調整
	Off(OUT_AC);
	Wait(500);
	return d_min;
}
void searchDirection2(long ang){               // 缶を探してその方向を向く(以下 void search Direction(long ang) と説明同じ)
	long angle, tacho_min;    
	int d_min;
 
	d_min = 300;
	tacho_min = 0;

	angle = (track / diameter) * ang;
	turnAng(ang/2);
	ResetTachoCount(OUT_C);
  
	OnFwdSync(OUT_AC,SPEED_SLOW,-100);

	while(MotorTachoCount(OUT_C) >= angle*-1){
		if(SensorUS(S3) < d_min){
			d_min = SensorUS(S3);
			tacho_min = MotorTachoCount(OUT_C);
		}
	}

	OnFwdSyncEx(OUT_AC,SPEED_SLOW,100,RESET_NONE);
	until(MotorTachoCount(OUT_C) >= tacho_min || SensorUS(S3) <= d_min);
 
	Wait(15);
	Off(OUT_AC);
	Wait(500);
}
void line () {					   //	ライントレースのプログラム

	float d;
	int S = 0;                                 //   交差点の回数を計るための箱
	SetSensorLight(S2);
	long t_L = CurrentTick();
	while(S<3){
		while(CurrentTick() - t_L <= 170) {     //右旋回の時間が0.17以下の時ライントレースを繰り返す。
                                                        //0.17秒を超えた場合交差点と判断し、ループから脱出する。
			if (SENSOR_2 < 30) {
				OnFwd(OUT_C,30);
				OnRev(OUT_A,25);
			} else if (SENSOR_2 < 38) {
				OnFwd(OUT_C,30);
				Off(OUT_A);				
			} else if (SENSOR_2 < 52) {
				OnFwd(OUT_AC,30);
				t_L = CurrentTick();
			} else if (SENSOR_2 < 60) {
				OnFwd(OUT_A,30);
				Off(OUT_C);
				t_L = CurrentTick();
			} else {
				OnFwd(OUT_A,30);
				OnRev(OUT_C,25);
				t_L = CurrentTick();
			}

			Wait(1);
		}

		S++;
		if(S==1){				   //	交差点1回目(点P)を左折
			Off(OUT_AC);			   //	Q点のボールを狙う
			Wait(1000);
			RotateMotor(OUT_A,SPEED,210);
			OnFwdSync(OUT_AC,SPEED_SLOW,0);
			Wait(1000);
			d = searchDirection(120);          //   Q点2つ目のボールを狙う
			fwdDist(d - 8.0);                  //   8cm手前で止まる
			RotateMotor(OUT_C,SPEED_SLOW,150); //	拾う前微調整()

			RotateMotor(OUT_B,33,80);          //	アームを少し閉じる

			OnFwdSync(OUT_AC,SPEED,0);         //	ボール拾い
			Wait(450);
			RotateMotor(OUT_B,33,80);
			Off(OUT_AC);

			t_L = CurrentTick();
		} else if(S==2){		           //	交差点2回目でライントレースの処理を終了させる
			break;
		}
	}
}
task main(){

	SetSensorLowspeed(S3);                   //  超音波センサー(ポート3)
	SetSensorLight(S2);                       //  光センサー(ポート2)  

	int mail = 0;                             

	int d = searchDirection(120);	        //	ボール探し
	fwdDist(d - 8.0);

	RotateMotor(OUT_C,SPEED_SLOW,125);        //	拾う前微調整

	OnFwdSync(OUT_AC,SPEED,0);		  //	ボール拾い
	Wait(450);
	RotateMotor(OUT_B,33,80);                 //    ボールつかむ
	Off(OUT_AC);

	fwdDist(-5);                              //つかんだ後5cm後ろへ進む
       
       RotateMotor(OUT_C,SPEED_SLOW,-300);	  //	缶付近に移動(300度左旋回し1.8秒前進)
	OnFwdSync(OUT_AC,SPEED,0);
	Wait(1800);

	searchDirection2(90);			  //	角度合わせ

	RotateMotor(OUT_C,SPEED_SLOW,90);	  //	発射前微調整(超音波センサーが中心でなく右についているため)

ブルートゥースで受け取り側ロボットにメッセージを送る。(詳しい説明は”ブルートゥースの説明”でする)

	SendRemoteNumber(1,MAILBOX1,10);	  //	キャッチ側を移動させる

	while(mail != 20){		          //	キャッチ準備完了待ち
		Off(OUT_ABC);
		Wait(1);
		ReceiveRemoteNumber(MAILBOX1,false,mail);
	}
	OnFwd(OUT_B,-70);				//	ボール発射
	Wait(800);
	Off(OUT_B);

	turnAng(210);					//	210度旋回しライントレース準備のための移動
	OnFwd(OUT_AC,1);
	Wait(1);
	OnFwd(OUT_A,SPEED_SLOW);
	OnFwd(OUT_C,SPEED_SLOW - 3);
	until(SENSOR_2 < 40);
	Off(OUT_A);

	line();				        	//	ライントレース

       Off(OUT_ABC);

}

ブルートゥースの説明

上記 task main ()の中からブルートゥースのプログラムの部分のみ抜粋

投げて側が親、受け取り側が子となり、親がボールを発射するまでの用意が終わったのちに受け取り側のロボットが受け取る体制に入るようにした。これをすることで、投げる側のロボットが障害物の缶を検知する際に間違って受け取る側のロボットを検知しないようにするためである。(同時にスタートさせてしまうと受け取り側のロボットが近くに来てしまい間違って障害物として認知してしまう恐れがある)

以下は、プログラム内容

受け取り側にメッセージを送信し、投げて側はその場で待機する。この待機している時に受け取り側ロボットが、缶に近づき受け取る体制に入る。

SendRemoteNumber(1,MAILBOX1,10);	  //	キャッチ側を移動させる

	while(mail != 20){		          //	キャッチ準備完了待ち
		Off(OUT_ABC);
		Wait(1);

ここで、受け取る準備が出来次第、投げて側に以下のメッセージが送られてくる。  

ReceiveRemoteNumber(MAILBOX1,false,mail);

これを受け取り次第、投げて側は缶に向かってボールを投げる。

工夫点

1.投げる動作

ボールを投げる側のロボットはボールを”確実に”つかみ・遠くの缶に当てなくてはならない。正確さがとても要求される。そこで、確実につかみ真っすぐなげるために、2つ爪の機構にした。2つ爪にすることで、ボールが左右にこぼれず真っすぐつかむことができ、真っすぐなげることが出来る。

2.超音波センサーを使用すること。

時間・角度に頼りすぎると微調整が多くなったり、電池の消耗具合によって正確の精度を出すことが出来なくなってしまう。そこで、超音波センサーを使い対象物までの距離を測ることで、ボール・缶の位置を正確に知ることが出来る。

3.同期させる

ボール・缶を探す際、近くに受け取り側ロボットに来られてしまうと間違ってそのロボットを検知してしまう恐れがある。ブルートゥースを使い、別々に動作をさせることで誤認識を防ぐことが出来る。 また、なげる側と受け取る側のロボットの動作に正確性がでる。(個々のタイマー指定で制御を行うと電池の消耗加減等で、大きな誤差が出来てしまう。)

改善点

+ボールの位置を検知できない。

ボールが小さいため、探索中は遅く旋回させ、さらに一番長い直径に超音波センサーが当たらないと見つけることが出来ない。検知精度を高める手段としては、ボールまでの距離を縮める、もっと旋回を遅くする、が有効であると考えられる。

考察

全体の結果的には投げる側と受け取る側のロボットがしっかり連携を取りあい、課題を成功したのでよかっと思う。 投げる側のロボットの結果としては、スタートしたのちボールを検知することが出来ればそのあと、ボールをつかみ・投げ缶に正確にあてることが出来る。この制度が高められることはいいことだと思う。しかし、ボールが検知できない場合がやはり悔やまれる。もっと時間をかけて制度を高めたかった。

感想

最後の課題のこのロボコンで、角度センサー・光センサー・超音波センサー・同期、など学んだことを取り入れることができ、それぞれの役割を生かせたと思う。プログラムも当初に比べれば短く綺麗にまとめることが出来るようになったように感じる。しかし、まだ、ミスも多く打つのも遅いのでそこのところをもっと努力したい。


添付ファイル: fileIMG_2704-1.jpg 198件 [詳細] fileIMG_2699-1.jpg 206件 [詳細] fileIMG_2696-1.jpg 108件 [詳細] fileIMG_2700-1.jpg 140件 [詳細] fileIMG_2702-1.jpg 116件 [詳細] fileIMG_2697.jpg 153件 [詳細] file2015b-mission3.png 338件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-02-29 (月) 16:27:03