2015b/Member

課題 ロボコン

課題内容

課題2で用いたマップを2枚用いて、ボールをバトン代わりにリレーを行うロボットを制作する。

目次

ルール

フィールド

2015b-mission3.png

これが今回のロボコンで用いるマップとなる。細かいルールは次節で述べることする。

基本ルール(要上図参照)

               ・競技時間はロボットAがSTART A地点のスタートラインを横切って、ロボットBがGOAL B地点のゴールラインに達するまで、あるいは審判が続行不能と判断するまで。

               ・ロボットAはSTART A地点から出発し、P地点におかれた赤いボールを拾って350mlのアルミ缶に当てる。

               ・その後、ロボットBがボールを回収する。

               ・引き続き青いボールについても同様の動作を繰り返す。

               ・ロボットBはボールを回収した後、最終的にGOAL Bまでボールを運ぶ。

               ・アルミ缶は中身が入っているものを使う。

               ・RISのチームはアルミ缶の上に灯台としてランタンを置く。

               ・ボールがアルミ缶に当たる前にロボットBがボールに触ってはいけない。

               ・ロボットAはセンターラインを超えては行けない。

               ・アルミ缶を5cm以上動かした場合は減点

以上が基本ルールである。これに、細かな技術点が付き得点を競っていく。

ロボット紹介

ロボットA(球を発射する側)

ロボットAは、ドライブベースのようにモータ二つからなる足回りと、一つの爪から構成される。

足回りはライントレースの際に利用した形が基礎となっている。

ロボットAの最も大きな特徴は前方にある爪である。この爪のようなパーツで、球をつかみ、蹴りだす動作までするのだ。

hanasu01_1.jpg

上図の爪のようなパーツは左タイヤについた回転センサと連動する。当初、球を見つけるために光センサを用いていたものの、光センサが球を認識するにはかなりたまに接近する必要があり、また少しでもずれるとセンサが認識しないことが多々あった。

したがって、タイヤが何回転したかによって球を回収させるようにした。ロボットの移動はライントレースで制御しているため、回転センサだと誤差が大きくなる王にも考えられたが、驚くことに光センサより精度はあがった。

球の回収方法は、まず指定の回数だけタイヤが回転したら爪パーツが上図では反時計回りをする。その後、指定の回数だけ進んだ後、ロボット上部に取り付けた光センサで缶の位置(ランタンの位置)を見定め(この方法については後述する)、爪に時計回りをさせることによって球を発射させる。

言葉だ毛ではわかりにくいと思われるので、下図を参照していただきたい。

回収する動作
A_kaishu.gif
放出する動作
A_keru.gif

ロボットB(球を回収するロボット)

ロボットは、ドライブベースのようなモータ二つからなる足回りと、4つのコンベアの一連から構成される。

足回りはAと同様のライントレースが行えるような形になっている。

ロボットBの最も大きな特徴は球を回収するために用いるコンベアである。 外観は下図である。

tsukamu06.jpg

当初、Aから放たれた球を光センサで探索しようとしたものの、光センサの測定範囲が極端に狭いことが分かったため、極力広範囲の球を回収できるような形にした。

広範囲をカバーし、且つ缶を倒すことがないようにするために端の方はゴム製の管のような細いパーツをつけた。これにより、無理なくコンベアの外側にある球をコンベアの方に誘導することができる。

tsukamu05_1.jpg

ロボットAのプログラム

次に、プログラムの方を説明する。定数やマクロについてを説明したのちに、サブルーチン、メイン関数と順々に説明を行う

ライントレース用

#define shiki 48//閾値
#define tomaru(t) Off(OUT_AC);Wait(t);//t秒間停止
#define FWD OnFwd(OUT_AC);//直進
#define BACK OnRev(OUT_AC);//後退
#define LEFT_t OnRev(OUT_A); OnFwd(OUT_C);//左旋回
#define LEFT Off(OUT_A); OnFwd(OUT_C);//左回転
#define RIGHT_t OnRev(OUT_C); OnFwd(OUT_A); //右旋回
#define RIGHT Off(OUT_C); OnFwd(OUT_A);//右回転
#define power(s) SetPower(OUT_A+OUT_C,s);//出力制御

ライントレース用の定数設定は課題2と同じであるため、説明はこの程度にしておく。

ロボコン独自の機構

この節では課題2では用いなかった機構についてを説明する。

#define open(t) OnFwd(OUT_B);Wait(t);//爪をt秒間開く回転動作を行う
#define close(t) OnRev(OUT_B);Wait(t);Off(OUT_B);//爪をt秒間閉じる回転動作を行う
#define stop_B Off(OUT_B);//爪を固定する
#define SUN 50//ランタンの輝度を表す定数
#define shoot power(2);open(15);Wait(10);close(15);//球をけりだす動作

これらを基にプログラムを組んだ。

trace_0 (スタート地点から赤い球を見つける迄)

次にライントレースを行うサブルーチンについてを説明していく。しかしながら、球をとってから投げるまでの動作はひとつながりでは無く、

ゝ紊鬚箸襪泙 球を発射するまで

とプログラムが別れていて、それが二つの球においてあるためライントレースのサブルーチンだけで4つ存在することを先に述べておく。図に示すと下図のようになる。

MAP_A.jpg

今回の節は「スタート地点から赤い球を見つける迄」のプログラムについてを説明する。

sub trace_0()
{
	power(2);//出力を2にする
	ClearSensor(SENSOR_1);//回転センサをリセットする
      /*ライントレース*/
	while(1){
		if (SENSOR_2 < shiki -7){
			LEFT_t;
		} else if (SENSOR_2 < shiki -4){
			LEFT;
		} else if (SENSOR_2 < shiki){
			FWD;
		} else if(SENSOR_2 < shiki +4){
			RIGHT;
		} else {
			RIGHT_t;
		} 

ここまでは課題2のライントレースと大体同じである。したがって、詳しい説明は省略する。

		if(SENSOR_1 > 335){//回転センサが335を越えたら
			power(3);
			close(50);//0.5秒だけ爪を閉じる
			ClearSensor(SENSOR_1);//回転センサをリセット
			break;//trace_0終了
		}
	}
}

これがtrace_0独自のプログラムとなる部分である。回転センサにより一定の回転が行われたと判断されたら球をつかむ動作を即座に行う。爪の回転数は多めに設定してあり、モータとギアに負荷をかけてしまうものの、確実につかみ離さないことがさせた。

trace_1(赤球を放す迄)

sub trace_1()
{
	ClearSensor(SENSOR_1);
	close(10);//0.1秒球を締める
	Off(OUT_B);//爪を固定する
	power(2);
    /*ライントレース*/
	while(1){
		if (SENSOR_2 < shiki -7){
			LEFT_t;
		} else if (SENSOR_2 < shiki -4){
			LEFT;
		} else if (SENSOR_2 < shiki){
			FWD;
		} else if(SENSOR_2 < shiki +4){
			RIGHT;
		} else {
			RIGHT_t;
		} 
		if(SENSOR_1 > 62){//回転センサが62以上の時作動
		tomaru(10);//停止させる
		break;//トレース終了
		}
	}
}

trace_0との違いは、SENSOR_1の上限と、ライントレースを開始する前に念のためもう一度爪を締めなおすことくらいである。その他はtrace_0と同じである。

trace_2(青球を掴む迄)

sub trace_2()
{
	power(1);
	ClearSensor(SENSOR_1);
	while(1){
		if (SENSOR_2 < shiki -7){
			RIGHT_t;
		} else if (SENSOR_2 < shiki -4){
			RIGHT;
		} else if (SENSOR_2 < shiki){
			FWD;
		} else if(SENSOR_2 < shiki +4){
			LEFT;
		} else {
			LEFT_t;
		} 
		if(SENSOR_1 > 44){
			power(3);
			close(50);
			ClearSensor(SENSOR_1);
			break;
		}
	}
}

trace_2は前述の二つと大体同じである。回転センサの上限が62であることとライントレースを線の右端で行うことが、前二つとの違いでなる。

trace_3(青球を放す迄)

sub trace_3()
{
	power(2);
	ClearSensor(SENSOR_1);
	while(1){
		close(1);//少しだけ爪を締める
		Off(OUT_B);
		if (SENSOR_2 < shiki -7){
			RIGHT_t;
		} else if (SENSOR_2 < shiki -4){
			RIGHT;
		} else if (SENSOR_2 < shiki){
			FWD;
		} else if(SENSOR_2 < shiki +4){
			LEFT;
		} else {
			LEFT_t;
		} 
		if(SENSOR_1 > 110){
			power(3);
			close(50);
			ClearSensor(SENSOR_1);
			break;
		}
	}
}

trace_3が他の3つと異なる点はライントレースを行うたびに爪を締めるところにある。今回trace_3で走行する区間は直角が二つ存在する。したがって普通にライントレースを行うと爪で挟んだはずの球が逃げてしまうのである。よって、毎度締め付けることで球が逃げるのを防いだ。

しかし、これはロボット本体に大きなダメージを与えることにつながってしまったため、爪を締めなくとも停止させる程度でもよかったかもしれないなと競技の後に反省をした。

光源探査

次に缶を見つける動作についての説明をする。NQCには超音波センサがないため缶の位置を探すために、缶の上におかれたランタンの光を基に探索を行い、球を衝突させた。

しかしながら、少しでもずれると球は缶の脇をすり抜けてしまう。したがって、今回は明るさの最大値を測定し、そこへ向かって球を放すことで缶の中心を狙う。

したがって、回転センサと光センサを連動させて最大値を特定する。以下、光の明るさの最大値を求め、その方向にロボットを向かせるプログラムである。

sub LIGHT()
{		
	PlaySound(SOUND_UP);//動作確認用
	int sun_MAX = 0;//明るさの最大値
	int sensor_MAX = 0;//明るさの最大値を示したときの回転センサの値
	close(20);//球が逃げないように、再度爪を締め付ける
	ClearSensor(SENSOR_1);//回転センサのリセット
	power(1);//出力1
	while(SENSOR_1 < 85){//SENSOR_1が85で大体1回転となる
		RIGHT_t;//右旋回
		if(SENSOR_3 > sun_MAX){//明るさの最大値の変更手続き
			sun_MAX = SENSOR_3;//現在地を最大値として記憶
			sensor_MAX = SENSOR_1//現在地の角度を記憶
		}
	}
	tomaru(10);//一回転終了後、一時停止
	LEFT_t;//左旋回
	until(SENSOR_1 < sensor_MAX);//角度が上で記憶した値になるまで
	tomaru(10);//停止
}

まず、現在地の明るさを測定する。つぎに時計回りで一回転をする。一回転する間で最も明るかった場所の角度を記憶させる。一回転を行った後に、最も明るかった所の角度まで戻る。

こうすることで、缶に球が当たる確率が上がる。

図にすると下図のようになる。

LIGHT.gif

main関数

いよいよmain関数の説明に入る。

task main()
{
	/*回転センサ*/
	SetSensor(SENSOR_1,SENSOR_ROTATION);
	/*トレース用センサ*/
	SetSensor(SENSOR_2,SENSOR_LIGHT);
	/*探索用センサ*/
	SetSensor(SENSOR_3,SENSOR_LIGHT);
       /*行動開始*/
	FWD;Wait(150);//スタートの枠からの脱出
	trace_0();//赤玉へ向かうトレース
	tomaru(50);//一時停止
	trace_1();//赤玉をホールドした状態
	LIGHT();//ランタンの探索
	shoot;//球を放す

ここまでは普通に、

''球を掴む位置まで進み、球を掴み、その状態のまま一定程度進み、缶を探索し、ボールを放す。''

という普通の流れである。

しかしながら、次の青色の球に向かうまでは少し工夫を凝らしている。

	tomaru(20);//0.2秒停止
	ClearSensor(SENSOR_1);//回転センサリセット
	RIGHT_t;//右旋回
	until(SENSOR_1 > 28);//回転センサが28以上になるまで回転をする。
	tomaru(10);//0.1秒停止

ココでは、ロボットAの車体を、缶の方向から右方の円のようになっている線に向かせている。 このことによって、円状になったコース上を反時計回りにライントレースをするのをしやすくさせている。

参考画像(再掲)

MAP_A.jpg
	ClearSensor(SENSOR_1);//回転センサをリセット
	FWD;//直進
	until(SENSOR_1 > 26);//回転数が26以上になるまで
	Off(OUT_B);//爪をふらつかせない
	FWD;//直進させる
	until(SENSOR_2 < 48);//黒い線にぶつかるまで
	open(7);//爪を開く
	Off(OUT_B);//爪を止める
	trace_2();//ライントレース

先ほど右下方を向かせた。しかしながら、青い球が置いてある場所を通らずに円状でライントレースをするには、今いる場所から強制的に脱出させ円状に乗せる必要がある。

まず、回転数が26以上になるまでタイヤを進める。このことにより、ロボットの車体はMAP上の空白の部分に移動できるようになっている。

次に、黒線を踏むまで強制的に直進させる。

そうすることにより、黒い線にたどり着いたロボットAは無事にライントレースを再開させることができる。

なお、誤差が生じやすく成功率がとても低い。しかし、コースの性質上NQCで青い球を最短経路で回収するにはこの方法が最適であるため行った次第である。

	tomaru(10);//0.1秒停止
	FWD;Wait(100);//1秒前進。
	trace_3();//ライントレース
	tomaru(10);//0.1秒停止
	LIGHT();//缶を探索
	shoot;//玉を放す
	trace_1();//ライントレース
}

基本的につかんで離す動作である。

途中で1秒間直進させるのは交差点から強制的に脱出させるためである。また、最後のライントレースはこのままではMAPの境界線部分での停止となるため、ロボットを適当な場所に移動させる必要があった。したがってライントレースをおこない、ロボットAを適当な場所に停止させた。

以上がロボットAの動きである。

ロボットB

ロボットBもロボットAと同様に先に定数等を述べ、サブルーチンを説明し、最後にmain関数の説明をする。

ライントレース用

#define CHECKCROSSTIME 25//交差点か否かを見定める時間
#define fwd(OUT) Off(OUT);OnFwd(OUT)//モータの正回転
#define rev(OUT) Off(OUT);OnRev(OUT)//モータの負回転
#define TURNLEFT fwd(OUT_AC)//左旋回
#define LEFT Off(OUT_C);fwd(OUT_A)//左回転
#define TURNRIGHT rev(OUT_AC)//右旋回
#define RIGHT Off(OUT_A);rev(OUT_C)//右回転
#define STRAIGHT rev(OUT_C);fwd(OUT_A)//直進
#define BACK fwd(OUT_C);rev(OUT_A)//後退
#define ISNOTCROSS FastTimer(0) <= CHECKCROSSTIME || FastTimer(1) <= startime//交差点か否かの条件文

ライントレースの時に用いられる定数

ロボコン独自の機構

#define RELEASE rev(OUT_B);//コンベアの逆回転
#define LOADING fwd(OUT_B);//コンベアの順回転

コンベアを順回転させることにより球を回収でき、逆回転させることで球を放出させることができる。

ライントレース

ロボットBもライントレースで移動を行う。ライントレースの方法はAと大体同じであるため省略。

sub trace(){
	ClearTimer(0);
	while(ISNOTCROSS){
		if(FastTimer(1) < startime){
			ClearTimer(0);
		}
		if(52 <= SENSOR_1){
			TURNRIGHT;
		}else if(50 <= SENSOR_1){
			RIGHT;
		}else if(41 <= SENSOR_1){
			STRAIGHT;
		}else if(39 <= SENSOR_1){
			LEFT;
		}else {
			TURNLEFT;
		}
		if(39 <= SENSOR_1) ClearTimer(0);
	}
	Off(OUT_AC);
	ClearTimer(0);
	Wait(100);
}

一部違うのは、ライントレースが行われる条件文である。この条件文は前述の定数である。つまり、ロボットBが交差点を判断した場合このライントレースは終了し、1秒間停止する。

交差点での対応

前節では交差点を判断するまでのプログラムを示した。つぎに交差点を判断した後のそれぞれの動作について説明をする。

まず直進について説明する。

/* 直進する */
sub go_straight(){
	STRAIGHT;//直進する
	Wait(30);//0.3秒
	ClearTimer(1);//タイマーリセット
}

直線の動作はいたってシンプルである。交差点を判断したらそのまま一定秒数直進させれば交差点を越え、直進ができる。

次に左折について説明する。

/* 左折する */
sub turn_left(){
	ClearTimer(1);//タイマーリセット
	ClearTimer(0);//タイマーリセット
}

ロボットBは線の左側でライントレースを行う。したがって、左折はライントレースを行い続ければいいだけなので、タイマーのリセットを行えば十分なのである。 今回右折はしなかった。

main関数

最後にmain関数の説明をする。

task main(){
	SetSensor(SENSOR_1,SENSOR_LIGHT);//光センサをセット
	ClearTimer(0);//タイマーをセット
	LOADING;//コンベアの順回転開始
	go_straight();//スタート地点からの脱出
	trace();//ライントレース
	go_straight();//直進
	Off(OUT_AC);//停止
	Wait(2300);//23秒停止。停止することでロボットAとの衝突をさける。
	ClearTimer(1);//タイマをセット
	startime=900;//変数設定。

ここで、今「startime」とあるが、これは交差点かどうかの判断をせずにライントレースをする時間のことである。

	trace();//ライントレース
	startime=300;//3秒間、交差点判断を無視
	go_straight();//直進
	trace();//ライントレース
	go_straight();//直進
	trace();//ライントレース
	go_straight();//直進
	startime=1400;//14秒間、交差点判断を無視
	trace();//ライントレース
	startime=300;//3秒間交差点判断を無視
	TURNRIGHT;//右旋回
	Wait(10);
	Off(OUT_AC);//停止
	RELEASE;//コンベアを逆回転して、球を排出。
	Wait(300);//3秒

これで一周が終了となる。競技中ではここまでの動作で一区切りとした。

しかしながら、ロボットBを担当したugwis君は万が一のための二周目をも用意していてくれた。流石である。残りの部分が二週目のプログラムである。ugwis君の頑張りをここに記しておく。

	BACK;
	Wait(100);//1秒後退
	TURNRIGHT;
	Wait(40);//0.4秒右旋回
	LOADING;//コンベア順回転開始
	ClearTimer(0);//タイマーリセット
	trace();//ライントレース
	turn_left();//左折
	startime=900;//9秒間、交差点判断を無視
	trace();//ライントレース
	startime=300;//3秒間、交差点判断を無視
	go_straight();//直進
	trace();//ライントレース
	go_straight();//直進
	trace();//ライントレース
	go_straight();//直進
	startime=1400;//14秒間、交差点判断を無視
	trace();//ライントレース
	startime=300;//3秒間、交差点判断を無視
	TURNRIGHT;
	Wait(10);//右旋回0.1秒
	Off(OUT_AC);//停止
	RELEASE;//コンベア逆回転により、球放出
	Wait(300);//3秒間逆回転
	go_straight();
	Wait(10);//直進0,1秒
	Off(OUT_ABC);//全動作停止
}

感想

テスト期間であったため、いつもより準備時間がとても短かった。そのため、木曜は夜更かしをしてロボット製作をし、翌金曜は午前中に集まり、授業開始まで4人で力を合わせやっていた。当時は非常に大変であったが今思うととても良い思い出である。また、最後の最後に4人で集まって協力し一つの目標に向かうことができたのは、かなり良い経験となった。

また、今回私はロボットAのプログラムを主に政策を進めた。したがって他の説明がおろそかになっているところが謀らずもないとは言いがたい。よってロボット本体についてはcst321君、sun16君の頁を、ロボットBnoプログラムについてはugwis君の頁を読んでいただくとより詳しいことが書いてあるはずなので、そちらを参照していただきたい。

最後までお世話になった皆さんとどこかで再開できる日を願って。

次会う日まで、お元気で。


添付ファイル: fileLIGHT.gif 122件 [詳細] fileMAP_A.jpg 111件 [詳細] filetsukamu05_1.jpg 114件 [詳細] filetsukamu06.jpg 139件 [詳細] fileA_keru.gif 109件 [詳細] fileA_kaishu.gif 111件 [詳細] filehanasu01_1.jpg 135件 [詳細] file2015b-mission3.png 121件 [詳細]

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