2009b

課題2:黒い線に沿って動くロボット

作成者:ゆうたろう,PuKKu

 作成したコースを1周するロボットを製作する。交差点以外のコース上に500mlの空の紙パックを3個以上おき、紙パックにぶつかった時には次のような動作するプログラムを作成する。

  1. 紙パックをコース上に戻して再びコースに戻って進む(ゆうたろう)
  2. 紙パックを次の交差点まで運んで行き、その交差点に紙パックを残してさらにコースに沿って進む(PuKKu)

ただし、

  • 速さと正確さを追求すること
  • コースを1周したら自動的に止まること
  • 交差点では一時停止すること
    (2009b/練習問題より抜粋)

目次

ロボットの作成

方針

 今回は、特に「確実さ」に重点を置き、そしてより「速い」ロボットを目指して製作することにした。

ライントレース

右図

 ライントレースを確実にそして速く行うために、右図の例のように光センサー2個を黒線の外側になるように設置する。そして、黒い線に光センサーが反応すると黒い線が中央になるように向きを変え、ラインを見失わないように進むことができるようにする。また、2つの光センサーの幅をなるべく狭くするようにし、線から外れていることを早めに検出できるようにする。

イメージ図

紙パックの運搬

右図

 より容易に紙パックを運ぶことを考えたが、紙パックを逃がしてしまう可能性があった。そこで、紙パックを持つと目的の場所まで確実に運ぶことができるように、紙パックを逃がすことがないように右図のように四方を囲む方式を採用することにする。そして、紙パックは下図のアニメーションのような方法で捉えて運ぶようにする。

下図
イメージ図

作成過程

台車の作成

 今回は、左右に動くのが基本の動作となるので、最初の授業で作ったドライブベースを基にして上に乗るものが安定するように改良を加えた。また、2つの光センサーの幅を狭くするために、右図のように位置を変更した。

左図  右図
左図                            右図

光センサー

右図

 ライントレースが確実にできるように、光センサー2つの幅がなるべく小さくなるようにした。そして、なるべく地面に近づくようにして、線を正確にとらえられるようにした。

アーム

右図

 初めは、ギアだけを組み合わせて動かそうとしたが、アームの重さに耐えられずに動き出してしまった。そのため、ウォームギアを使用して、アームの重さでアームが動き出してしまわないようにした。

左図

 また、紙パックの四方を囲むようにして、運ぶときに逃がしてしまわないようにした。そして、なるべく確実に捉えることができるよう四角形の横の長さを少し長くした。

バンパー

 当初は、それぞれの図の左側の図のようにしていた。だが、実際に動かしてみると反応するときとしないときがあった。そのために思考錯誤をしてタッチセンサーの設置する場所から考え直し、組み立てガイドのバンパーを参考にしてそれぞれの図の右側の図のように改良を行った。この方式だと、きちんと紙パックを認識することができた。また、なるべく正面に紙パックがいるとき以外は反応しないようにするために、試作品に比べて、完成では、バンパーの直線部分を短くした。そして、紙パックを支えるために、と思って付けたバンパーの上の方の部分は、正面に紙パックがないときでも反応しやすくなるため外した。図1は、正面から見た様子であり、図2はタッチセンサーの様子を写した図である。

図1   図2
図1                      図2

試作品

左図

 この左図は、初期の状態である。これだと、バンパーが紙パックに反応することができたりできなかったりすることがあり、確実に運ぶことができなかった。

完成

 これが、完成品である。バンパーの反応は万全になった。一応、課題を行うことができるようになった。

左図  右図

工夫した点、苦労した点

  • ウォームギアを使用して、アームを動かすようにし、アームが自らの重さで動き出さないようにした点。
  • アームを動かす速度をウォームギアの使用で、適当な速さにすることができた点。
  • 光センサーの2つの幅を狭くすることで、黒い線を正確にとらえられるようにした点。
  • 紙パックを認識するバンパーをどのようにすれば、軽い紙パックを前に押し出すことなく認識できるかどうか考えながら作成した点。
  • コードをロボットの作業に支障が出ないようにコードを通すところを考えて配置した点。
  • 紙パックの四方を囲むことで運ぶ途中で障害物のない限り、確実に目的の場所に運ぶことができる点。
  • それぞれのパーツをどのようにして台車に乗せると良いのか考えた点。

問題点など

  • 紙パックの設置位置によって、バンパーが反応してアームが動き出したときに紙パックが枠の中にきちんと入ることができないと、その紙パックは、動かすことができない点。
  • バンパーが前に出ているため、カーブなどに紙パックが置かれると紙パックの正面を本体が向いていないのにバンパーが反応する点。
  • 紙パックを運ぶ際、下に段差などの障害物があると紙パックが倒れてしまう点。

A2の作成したコース

 このコースを走行する。

A2のコース

〜このコースについて〜
 マリオサーキット2,3(SFC版のマリオカート)を参考にして作った。このコースの欠点としては交差点直前のラインが曲がりくねってるため、マシンがときどき交差点から外れてしまうのと直線が少ないので箱をうまく配置しないと箱をうまくキャッチできない点である。

プログラム

1(ゆうたろう)

#define RUN_TIME  750         //プログラムの稼働時間

task main()
{
	SetSensor(SENSOR_1,SENSOR_LIGHT);   //光センサ1(左)をセット
	SetSensor(SENSOR_2,SENSOR_TOUCH);   //タッチセンサ2をセット
	SetSensor(SENSOR_3,SENSOR_LIGHT);   //光センサ3(右)をセット

	ClearTimer(0);

	while(Timer(0) <= RUN_TIME)
	{
		if(SENSOR_1 <  40)                  //光センサ1(左)が反応 
		{
			OnFwd(OUT_C);
			OnRev(OUT_A);
			Wait(4);
		}                                   //左へ方向修正
		else if(SENSOR_3 <40)               //光センサ3(右)が反応
		{
			OnFwd(OUT_A);
			OnRev(OUT_C);
			Wait(4);
		}                                   //右へ方向修正
		else
		{
			OnFwd(OUT_A+OUT_C);
			Wait(4);
		}                                   //方向修正の必要がない時は前進


		if(SENSOR_2 == 1)            //牛乳パックがあたったとき
		{
			Off(OUT_A+OUT_C);
			OnFwd(OUT_B);
			Wait(170);
			Off(OUT_B);                         //アームを下げる
			OnFwd(OUT_A);
			OnRev(OUT_C);
			Wait(200);                          //牛乳パックを反対方向へ
			OnRev(OUT_A+OUT_C);
			Wait(30);
			Off(OUT_A+OUT_C);                   //位置調整
			OnRev(OUT_B);
			Wait(170);
			Off(OUT_B);                         //アームを上げる
			OnRev(OUT_A+OUT_C);
			Wait(30);                           //位置調整
			OnFwd(OUT_C);
			OnRev(OUT_A);
			Wait(200);                          //方向を反転
			OnFwd(OUT_C);
			Wait(30);                           //位置調整
		}


		if((SENSOR_1 < 40) && (SENSOR_3 < 40))    //光センサ1と3がが両方反応した時
		{
			Off(OUT_A+OUT_C);
			Wait(30);                                 //一時停止
			OnFwd(OUT_A+OUT_C);
			Wait(50);                                 //前進
		}
	}
	Off(OUT_A+OUT_C);
}
箱の配置と進行ルート←箱の配置と進行ルート
交差点ではいちいち停止し、箱があればどけて進む。ご苦労なことである。

工夫した点、問題点など

〜工夫した点〜

これで成功率が飛躍的に向上

 バンパーを改良し、タッチセンサが反応するようにした。
 より成功率を上げるために交差点で二度止まるようにした。

 また牛乳パックは時計回りで回転し、どける。
反対方向へよける

パックを進行方向の反対にどかした後、進行方向へ向き直る時そのまま回転するとマシンがパックにあたってしまうので、向き直る前に少し位置をずらしてから向き直るようにした。これにより、マシンがパックに当たらなくなった。

〜問題点〜
 マクロなどを使わなかったためにプログラムがけっこうややこしくなってしまった。やりようによっては、もうちょいすっきりさせることができたような気もする。

2(PuKKu)

#define THRESHOLD 40					//閾値
#define REST 5						//少しの間動かす
#define ON_AC SetOutput(OUT_A+OUT_C,OUT_ON);		//モーターAとCに電源を入れる
#define FLOAT_AC SetOutput(OUT_A+OUT_C,OUT_FLOAT);	//モーターAとCをFloatで止める
#define FWD_AC SetDirection(OUT_A+OUT_C,OUT_FWD);	//モーターAとCを前進させる
#define FWD_A SetDirection(OUT_A,OUT_FWD);		//モーターAを前進させる
#define FWD_C SetDirection(OUT_C,OUT_FWD);		//モーターCを前進させる
#define REV_AC SetDirection(OUT_A+OUT_C,OUT_REV);	//モーターAとCを後退させる
#define REV_A SetDirection(OUT_A,OUT_REV);		//モーターAを後退させる
#define REV_C SetDirection(OUT_C,OUT_REV);		//モーターCを後退させる
#define ARM_DOWN OnFwd(OUT_B);Wait(180);Off(OUT_B);	//アームを下ろす



task line_trace(){					//ライントレース
	ON_AC;						//モーターAとCに電源を入れる
	while(true){
		if(SENSOR_3<THRESHOLD){			//センサー3(右)が暗いとき
			FWD_A;				//右に曲がろうとする
 			REV_C;
			Wait(REST);
 		}else if(SENSOR_1<THRESHOLD){		//センサー1(左)が暗いとき
			FWD_C;				//左に曲がろうとする
			REV_A;
			Wait(REST);
		}else {					//その他
			FWD_AC;				//前進をする
			Wait(REST);
		}
	}
}

sub arm_up(){						//アームを上げる
	OnRev(OUT_B);Wait(180);
	Off(OUT_B);
	REV_AC;						//後退をする
	ON_AC;
	Wait(50);
	FLOAT_AC;
}

sub turn(){						//ターンをする(左回り)
	int turn=0;					//ターンができたかできなかったか
	int time2=0;					//時間を記録
	while(turn==0){
		REV_A;FWD_C;
		ON_AC;
		ClearTimer(1);
		Wait(70);
		until(FastTimer(1)>300 || (SENSOR_1<THRESHOLD));
		time2=FastTimer(1);
		until(SENSOR_3<THRESHOLD);		//センサー3(右)が黒くなるまで
		FLOAT_AC;
		if(time2>300){				//3秒以上回ったら少し前へ進む
			start line_trace;
			Wait(50);
			stop line_trace;FLOAT_AC;
			time2=0;
		}else{					//その他(ターン終了へ)
			turn=1;
		}
	}
}

task main(){
	SetSensor(SENSOR_1,SENSOR_LIGHT);		//光センサー1(左)
	SetSensor(SENSOR_2,SENSOR_TOUCH);		//タッチセンサー
	SetSensor(SENSOR_3,SENSOR_LIGHT);		//光センサー3(右)
	int i=0;					//運んだ回数
	int get=0;					//紙パックを持っているかいないか
	int time=0;					//時間を記録
	
	
	start line_trace;				//ライントレース、スタート
	while(i<=3){					//紙パックを3回運ぶ
		if((SENSOR_2==1) && (get==0)){		//紙パックを持っていなくて、タッチセンサーが反応したら
			if(i==3){			//3回運んでいたら
				i++;			//終了へ
			}
			Wait(30);
			stop line_trace;FLOAT_AC;	//少し進んで止まる
			ARM_DOWN;			//アームを下ろす
			get=1;				//紙パックを持ちました
			
							//運ぶべきものか、置き去るべきものかの判断へ
			REV_A;FWD_C;			//左に少し曲がって、センサー1(左)が暗くなるか確認へ
			ON_AC;
			Wait(30);
			ClearTimer(0);
			FWD_A;
			until((FastTimer(0)>80) || (SENSOR_1<THRESHOLD));
			time=FastTimer(0);
			if(FastTimer(0)>80){		//暗くならなかったら(運ぶべきもの)
				REV_AC;Wait(time);	//元の場所へ戻る
				FWD_A;Wait(50);
				FLOAT_AC;
				start line_trace;	//ライントレース再開
			}else if(SENSOR_1<THRESHOLD){	//暗くなったら(置き去るべきもの)
				REV_AC;Wait(time);	//元の場所へ戻る
				FWD_A;
				Wait(50);
				FLOAT_AC;
				start line_trace;	//ライントレースを少しだけ再開
				Wait(200);
				stop line_trace;FLOAT_AC;
				turn();			//ターンをする
				start line_trace;	//再びライントレースをし、コースにきちんと入る
				Wait(80);
				stop line_trace;
				REV_AC;			//後退をする(ターンをした辺りへ戻る)
				Wait(50);
				FLOAT_AC;
				arm_up();		//アームを上げる
				get=0;			//紙パックを離しました
				turn();			//ターンをして元の向きへ
				start line_trace;	//ライントレースを再開
			}
		}else if((SENSOR_1<THRESHOLD) && (SENSOR_3<THRESHOLD)){//センサー1(左)とセンサー3(右)が共に暗くなったら
			stop line_trace;FLOAT_AC;		//交差点だから停止
			if(i<=2){				//運んだ回数が2回以下だったら
				Wait(50);			//一時停止
				FWD_AC;				//前進
				ON_AC;
				if(get==1){			//紙パックを持っていたら
					Wait(50);
					until((SENSOR_1<THRESHOLD) && (SENSOR_3<THRESHOLD));
					//センサー1(左)とセンサー3(右)が共に暗くなったときよりもう少し前へ
					Wait(50);
					start line_trace;	//ライントレースをして、ラインへ戻りながら進む
					Wait(100);
					stop line_trace;FLOAT_AC;
					turn();			//ターンをする
					start line_trace;	//ライントレースをして、ラインの上に戻る
					Wait(80);
					stop line_trace;
					REV_AC;			//後退する(ターンをした辺りへ戻る)
					Wait(50);
					FLOAT_AC;
					arm_up();		//アームを上げる
					get=0;			//紙パックを離しました
					turn();			//ターンをする
					start line_trace;	//ライントレースを再開
					i++;			//運んだ回数をプラス1
				}else{				//紙パックを持っていなかったら
					Wait(100);		//一時停止
					start line_trace;	//ライントレース再開
				}
			}
		}
	}
	stop line_trace;FLOAT_AC;				//ライントレース終了
}

プログラムの作成と課題の解決策について

右図

 私の課題は、紙パックを交差点へ運ぶというものである。右図には、具体的にこのロボットがどの方向へ進み、紙パックがどの辺りに設置してあるかを示してある。一見、交差点に運ぶだけのように思うが、このコースに注目をすると、紙パックを交差点まで運んでも、次に交差点を通るときにこの紙パックが邪魔になってしまうのだ。つまり、この課題を行う上での以下の2つの点が特に大変であった。これらについて、私なりに考えた解決策を示してみる。

  • 交差点に置いてある紙パックかどうか判断させる点。
  • どのようにして、紙パックを避けるのかという点。

〜交差点に置いてある紙パックかどうか判断させる点〜

左図

 交差点を見てみると、必ずT字型の交差点であることを知らせる印が進行方向から見て左側にある。つまり、1回紙パックを持ったあとに左斜めに進んでT字型の印があるかどうかを判断させて、交差点であるかどうかを決めていくことが一番良い方法だと私は思った(プログラムでは「//運ぶべきものか、置き去るべきものかの判断へ」から)。左図の,らの順番でロボットは動き、交差点にあるかどうか判断する。初めは、紙パックに触る回数で、奇数回が運ぶというようにしようと思ったが、実はそれができないところが一か所あったので断念をした。

〜どのようにして、紙パックを避けるのかという点〜

右図

 この点についてはとても悩んだ。紙パックの周りを通る方法や、最後に交差点を通るまで紙パックを持ち続ける方法など。その中で、確実にライントレースを再び行うことができるものは、コース上からあまり離れないターンをする方法だと思った。そこで、もう一度紙パックを持って少し動いてから、回転し元の位置に戻すようにした。こうすることによって、ライントレースだけは確実に行うことができるようになった(プログラムでは「sub turn()」が主であるが、この説明の部分は「//暗くなったら(置き去るべきもの)」から)。右図は「//暗くなったら(置き去るべきもの)」の「//ライントレースを少しだけ再開」からの部分の軌跡を示したものである。 銑い僚臠屬貌阿い討い。い終えたときに紙パックを離す。

その他の工夫した点や問題点など

  • 紙パックがバンパーに当たっても、少し間をおいて紙パックを捉えるようにしたことで以前より失敗する確率が低くなった点。
  • 「turn()」を有効に使うために交差点で紙パックを置くときにも使えるようにした点。
  • コース上から離れないようにするために、ライントレースをしてコース上に戻るようにした点。
  • 交差点に紙パックを置くときに、黒い線が途切れているために半回転したことが分からなくなり、かつ前に出すぎておいてしまうために、もう一度進行方向を向かせて、少し前に出てから、もう一度回転をさせる点。
  • ターンをする度、紙パックを持っているとアームが本体より前に出ているために、他の紙パックを動かしてしまう点。
  • ターンをすることで、画用紙の周りに紙パックが出てしまうと、ときによっては紙パックが倒れてしまう点。

感想

〜ゆうたろう〜
 PuKKuの力無しではこの課題こなせなかったかもしれぬ。だが、マシン製作に少しくらいは貢献したはずだ。今回の課題の出来は上々だ。

〜PuKKu〜
 今回は、ゆうたろうと一緒に集まって製作する時間があまりとれなくて大変だった。それに加えて、ダウンしてしまい時間がギリギリになってしまったことは大きなダメージであった。ロボットの作成では、バンパーについてもう少し考えておくべきだった。でも、なんとかできて形が良かった。
 また、プログラムでは課題をどのような方法で解決していくか考えるのが大変だった。でも、面白かった。

コメント

コメントをどうぞ

  • ロボットの説明、プログラムの説明ともに、写真や図を使用してわかりやすくできていて、とてもよいです。プログラムについては、if部分をインデントして見やすくしてください。また、パックが軽すぎて反応しづらい場合、センサー部分を改良することで反応しやすくすることができないか考えてみてください(今回は工夫しなくても反応する範囲かもしれませんが)。 -- こさか? 2009-12-11 (金) 15:32:20
  • ロボットもプログラムもいろいろと工夫しているようですし、その説明も詳しくてとてもよいです。一つ目のプログラムでは閾値に直接数値を書いていますが、変数を使った方が後でまとめて調節できます。また、whileから抜け出す方法として、変数を設定しなくともbreakもあります。他にも、細かいことですが、変数をマクロ内で定義すると、呼び出すたびに何回も定義することになるので、変数を定義する場所にも注意できたらより無駄がなくなると思います。プログラムがごちゃごちゃしてしまったら、フローチャートなどを書いて整理しなおすと良いかもしれません。図や写真をフルに活用しているし、問題を明確にしてそれに対してどう解決するかがきちんと書かれていた点は素晴らしかったと思います-- FI? 2009-12-20 (日) 16:41:36


添付ファイル: fileturn21301.gif 109件 [詳細] filekousaten501.gif 107件 [詳細] filecourse_trans.jpg 260件 [詳細] filecourse_zoom.jpg 201件 [詳細] filecourse_2.jpg 182件 [詳細] fileturn.jpg 201件 [詳細] fileIMG_017531.jpg 202件 [詳細] fileIMG_01752.jpg 211件 [詳細] filecourse_11.jpg 117件 [詳細] filebanper20.jpg 229件 [詳細] filebanper10.jpg 187件 [詳細] fileIMG_01631.jpg 213件 [詳細] fileIMG_01701.jpg 174件 [詳細] fileIMG_01692.jpg 180件 [詳細] fileIMG_01212.jpg 212件 [詳細] fileIMG_01672.jpg 193件 [詳細] filearm_anime3.gif 214件 [詳細] fileIMG_01461.jpg 206件 [詳細] fileIMG_01061.jpg 196件 [詳細] fileIMG_01101.jpg 204件 [詳細] fileIMG_01111.jpg 197件 [詳細] fileIMG_01301.jpg 204件 [詳細] filelinetrace.jpg 173件 [詳細]

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