黒線に沿って走らせろ!

目次

メンバー

  • ぐっP……電気電子工学科。ロボットに語りかけている時は優しく見守ってやってください。きっと精神がまいっている時です。
  • 鍾馗……電気電子工学科。ロボットに無駄なものを付けては改悪している。

課題内容

次のような周回コース(黒い線)を動くロボットを作成せよ。

・通常の交差点が2箇所以上ある
・ロータリー型の交差点が1箇所以上ある (ロータリーでは反時計まわりに進む)
・直角に曲がるコーナーおよびそのコーナーをショートカットするコース(点線)が存在する
・急なヘアピンカーブが1箇所以上ある
・スタート地点に目印がある
・黒い線の幅は15〜20mm程度

センサー、モーターはいくつ使ってもよい。プログラムは次の2つを作成すること。

1.直角のコーナーを通る
2.直角のコーナーを通らない(近道する)

交差点を曲がる時には、光センサを有効に使うこと(ある地点からの距離や時間だけに頼らないこと)

との指令を受けて、私たちが開発したコースがこちらとなります。

なお、条件にある直角コーナーの進行は厳正なるじゃんけんの結果、ぐっP→通る鍾馗→近道となりました。

コース

交差点では直進、ロータリーでは条件通り反時計回りに進行します。

ちなみに、ロータリー内の硬貨は大きさ比較のために置いただけです。やや大きめの紙に描いてあることがわかっていただければ幸いです。

ロボットの紹介

案 案

上は全体像。他の班と比べて小型です。詳細は下記参照。

それと実はこれRCX真下の黒色レゴブロック一つ分は、撤去することができます。ですがRCXとくっつけることを考えると、長い平行に設置した2本のレゴブロックが一番食いつきやすく、外しやすかったので(要検証)、小型化よりも利便性をとりました。

ドライブベース

前と一緒

前回使用したロボットの流れを組む小型のユニットとなっております。ただし前回と同じようにスピードがそこそこ出ます。これはある意味デメリット。なぜなら細かい調整ができず、誤差が大きくなるからです。 ドライブベースの上にある二本の長いレゴブロックはこのロボットの竜骨と言ってもよい部分です。ここには光センサーを支え、尾輪を支え、RCX 本体をも支えてもらうので、外れないようにしっかりと接続してあります。

光センサーユニット

光センサーユニットは簡単なつくり

センサー部分が偏っているので一見左右非対称に見えますが、ブロックを左右対称につけるより、この方がずれが少ないです。ちなみにコースのラインの太さは約20ミリメートルです。

案 案

光センサーは簡単にドライブベースの竜骨にとっつけてあるだけです。適当……ではなく取り外しが容易でセンサー幅などが簡単に変えられるからです。

センサーは極力接地面に近づけてあります。検証はしていませんが、そのほうが外部からの影響が少ないと判断したからです。

回転センサーユニット

いらない子

左輪の回転数を計ることができるセンサーです。

回転センサーはもともと使う予定がなかったのでRCXを押し上げる形でとってつけてあります。本来なら駆動輪に直接取り付けるのがよかったのでしょうが、プログラムがある程度出来上がったころに追加した物なので、他のユニットに極力影響がないように取り付けたせいで、微妙に噛み具合が緩くなっています。たぶん若干の誤差が出ます改善しました。今はちゃんと計測できます。

ちなみにまったく使いません。死重量です。それなのになぜ取り付けたかと言うと、鍾馗のわがままです。曰く「センサー何個つけてもいいなら3つとも全部埋めようぜ」と言うことだそうです。残っているモーター一つでもっといらない物を作っていましたがさすがに本当に何も寄与しないのでお蔵入りさせました。

影の功労者

本体ではありませんが、プログラム制作に役立ったこちらの部品を載せておきます。

テスター

突き出たブロックの部分がちょうどセンサーとタイヤの接地面の位置になっているので、動かしたときのシミュレーションが簡単に行えます。

プログラムの紹介

トレースの基本

2つの光センサーを使ったトレース

基本的に右が黒なら右折、左が黒なら左折、両方白なら直進、という方法です。

上図は右折の方法で、右センサが「黒」と判断したら、左のタイヤは進めたまま右のタイヤだけをバックさせる、という動作を右センサが「白」と判断するまで行います。

2つの光センサーを使ったトレース

ひとつのセンサーでトレースするときは上図のように黒線の左(右)側をなぞるように進行させます。このときセンサーが黒なら左(右)折、白なら右(左)折で直進をすることはありません。

ぐっPのプログラム

あらかじめ通常のライントレースモードや、ロータリーモードなどを定義しておき、状況に応じて変化させるようなプログラムになっています。

  • 時間指定の部分
    #define LITTLE_TIME1_1 12        //旋回時間調整(1)を指定
    #define LITTLE_TIME2 1           //旋回時間調整(2)を指定
    #define LITTLE_TIME1_2 4         //旋回時間調整(3)を指定
    #define THRESHOLD 50             //センサーの閾値を指定
    #define BACK_TIME 5              //後退の時間を指定	
    #define HAIRPIN 120              //ヘアピンカーブモード(1回目)への移行時間を指定
    #define CROSS 250                //2回目の交差点でのモード変更の時の時間を指定
    #define ROTARY_IN_1 40           //ロータリーモード(1回目)への移行の時間を指定
    #define ROTARY_RIGHT 140         //ロータリー入口と出口の、右センサのみ有効な時間を指定
    #define ROTARY_LEFT 80           //ロータリー進行中の、左センサのみ有効な時間を指定
    #define RIGHT_ANGLE 80           //直角カーブ前の、近道を無視する時の時間を指定
    #define RIGHT_ANGLE_2 170        //直角を曲がる時と、近道終わりを無視する時の時間を指定
    #define END 25                   //終わりのラインを越えて、スタートラインに戻る時の時間を指定
    
    #define SE_L SENSOR_1            //短縮のため、センサー1(SENSOR_1)をセンサーレフト(SE_L)に
    #define SE_R SENSOR_3            //同上
  • 動作定義の部分
    int x = 0;                                                  //モード設定用の変数を定義
    int y = 0;                                                  //カウント用の変数を定義
    
    void go_straight()                                          //直進を定義
    {
    	OnFwd(OUT_AC);
    }
    
    void back()                                                 //後退(小)を定義
    {
    	OnRev(OUT_AC);
    	Wait(WAIT_TIME);
    }
    
    void back_2()                                               //後退(大)を定義
    {
    	back();
    	Wait(WAIT_TIME);
    	Wait(WAIT_TIME);
    }
    
    void turn_right_little()                                    //緩めの右旋回を定義
    {
    	OnFwd(OUT_A);OnRev(OUT_C);                                //左タイヤを直進させながら、右タイヤを次の場合分けに従い後退
    	if((x == 0)||(x == 1)||(x == 8)){                         //ヘアピン前、ヘアピンカーブ、直角カーブの時は
    		Wait(LITTLE_TIME1_1);                             //大きく後退
    	}else{	                                                  //その他の場合は
    		Wait(LITTLE_TIME1_2);                             //小さく後退
    	}
    	Off(OUT_C);Wait(LITTLE_TIME2);                            //右タイヤを旋回時間(2)秒停止させる
    }
    
    void turn_left_little()                                     //緩めの左旋回を定義(内容は右旋回の左右反対)
    {
    	OnFwd(OUT_C);OnRev(OUT_A);
    	if((x == 0)||(x == 1)||(x == 8)){
    		Wait(LITTLE_TIME1_1);
    	}else{
    		Wait(LITTLE_TIME1_2);
    	}
    	Off(OUT_A);Wait(LITTLE_TIME2);
    }
    
    void turn_hairpin()                                         //ヘアピンカーブの曲がり方を定義	
    {
    	back();                                                   //位置調整のためやや下がる
    	while(FastTimer(0) < HAIRPIN){                            //ヘアピンを曲がるまでの間、
    		if(SE_R >= THRESHOLD){                            //右センサが白なら進む
    			go_straight();
    		}else{                                            //右センサが黒なら右旋回
    			turn_right_little();
    		}		
    	}
    	PlaySound(SOUND_FAST_UP); x++;                            //xを+1する
    }
    
    void line_trace()                                           //ライントレースの方法を定義
    {
    	if((SE_L >= THRESHOLD)&&(SE_R < THRESHOLD)){              //右センサが黒で左センサが白なら、
    		turn_right_little();                              //右旋回
    	}else if((SE_L < THRESHOLD)&&(SE_R >= THRESHOLD)){        //右センサが白で左センサが黒なら、
    		turn_left_little();                               //左旋回
    	}else{                                                    //それ以外(両方白または両方黒)なら、
    		go_straight();                                    //直進
    	}
    }
    
    void line_trace_2()                                         //交差点でのライントレースの方法を定義
    {
    	if((SE_L >= THRESHOLD)&&(SE_R < THRESHOLD)){              //右センサが黒で左センサが白なら、
    		turn_right_little();                              //右旋回
    	}else if((SE_L < THRESHOLD)&&(SE_R >= THRESHOLD)){        //右センサが白で左センサが黒なら、
    		turn_left_little();                               //左旋回
    	}else if((SE_L < THRESHOLD)&&(SE_R < THRESHOLD)){         //両方黒なら、
    		go_straight();                                    //どちらかが白になるまで直進して、以下の場合分けに従う
    		until((SE_L >= THRESHOLD)||(SE_R >= THRESHOLD));
    		if(SE_L < THRESHOLD){                                  //左が黒(右が白)なら、
    			Off(OUT_C);OnFwd(OUT_A);                       //左が白になるまで、右タイヤだけ前進
    			until(SE_L >= THRESHOLD);
    		}else{                                                 //それ以外(逆に右が黒で左が白)なら、
    			Off(OUT_A);OnFwd(OUT_C);                       //右が黒になるまで、左タイヤだけ前進
    			until(SE_R >= THRESHOLD);	
    		}
    		y++; PlaySound(SOUND_CLICK);                      //yを+1する
    	}else{                                                    //それ以外(両方白)なら、
    		go_straight();                                    //直進
    	}
    }
    
    void rotary_right()                                         //ロータリー入り口での右折の方法を定義
    {
    	while(FastTimer(0) < ROTARY_RIGHT){                       //右折完了するまでの間、
    		if((SE_R < THRESHOLD)){                           //右センサが黒なら右旋回
    			turn_right_little();
    		}else{                                            //その他(右センサが白)なら直進
    			go_straight();
    		}
    	}
    }
    
    void rotary_left_0()                                        //ロータリーの左回りでの基礎動作(以下左基礎と表記)を定義
    {                                                                 //内容は上の左右反対
    	if((SE_L < THRESHOLD)){
    		turn_left_little();
    	}else{
    		go_straight();
    	}
    }
    
    void rotary_left()                                          //ロータリーでの左回りの方法を定義
    {
    	while(SE_R >= THRESHOLD){                                 //右センサが白の間(右センサが黒になるまで)、	
    		rotary_left_0();                                  //左基礎
    	}
    	y++; ClearTimer(0); PlaySound(SOUND_CLICK);               //yを+1する
    	while(FastTimer(0) < ROTARY_LEFT){                        //右センサがラインを横切るまで、
    		rotary_left_0();                                  //左基礎
    	}
    	while(SE_R >= THRESHOLD){                                 //右が白の間(右が黒になるまで)、
    		rotary_left_0();                                  //左基礎
    	}
    	Off(OUT_AC);Wait(END);
    	x++; ClearTimer(0); PlaySound(SOUND_FAST_UP);             //xを+1する
    	back_2();                                                 //位置調整のため後退
    }
    
    void right_angle()                                          //直角カーブ前の近道の無視の仕方を定義
    {
    	back_2();                                                 //位置調整のため後退
    	while(FastTimer(0) < RIGHT_ANGLE){                        //無視し終えるまでの間、
    		if(SE_R < THRESHOLD){                             //右センサが黒なら右旋回
    			turn_right_little();
    		}else{                                            //その他(右センサが白)なら直進
    			go_straight();
    		}
    	}
    }
  • メインの部分
    task main()
    {
    	SetPower(OUT_A,1);                                        //右タイヤのモーターの出力を1に設定(速度調節)
    	SetPower(OUT_C,1);                                        //同上
    	SetSensor(SE_L,SENSOR_LIGHT);                             //左センサが光センサであることを宣言
    	SetSensor(SE_R,SENSOR_LIGHT);                             //同上
    
    	int i;                                                    //forループのための関数宣言
    	for(i=0;i<=1;i++){                                        //以下のプログラムを2回ループさせる
    		x = 0;
    		ClearTimer(0);
    		while(x != 10){                                   //{}内のプログラムをx=10でない間(コースを1周するまで)ループさせる
    			if((FastTimer(0) >= HAIRPIN)&&(SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 0 && x == 0)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x++; y++; PlaySound(SOUND_FAST_UP);
                                                                           //ヘアピンカーブの始まりで両方黒になったとき、xとyを+1する
    			}else if((y == 3)&&(x == 2)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x++; PlaySound(SOUND_FAST_UP);
                                                                           //ロータリーに入る直前に、xを+1する
    			}else if((FastTimer(0) >= ROTARY_RIGHT)&&(y == 3)&&(x == 3)){
    				Off(OUT_AC);Wait(END);x++; PlaySound(SOUND_FAST_UP);
                                                                           //ロータリーに入った後、xを+1する
    			}else if((FastTimer(0) >= ROTARY_RIGHT)&&(y == 4)&&(x == 5)){
    				Off(OUT_AC);Wait(END);x++; PlaySound(SOUND_FAST_UP);
                                                                           //ロータリーを出た後に、xを+1する
    			}else if((SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 4 && x == 6)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x++; y++; PlaySound(SOUND_CLICK);
                                                                           //近道の始まりで両方黒になったとき、xとyを+1する
    			}else if((FastTimer(0) >= RIGHT_ANGLE)&&(y == 5)&&(x == 7)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x++; PlaySound(SOUND_FAST_UP);
                                                                           //近道を無視した後、xを+1する
    			}else if((FastTimer(0) >= RIGHT_ANGLE_2)&&(y == 5 && x == 8)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x = 6; PlaySound(SOUND_FAST_UP);
                                                                           //直角を曲がった後、xを6(ライントレースモード)にする
    			}else if((FastTimer(0) >= RIGHT_ANGLE_2)&&(SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 5 && x == 6)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x = 3; PlaySound(SOUND_FAST_UP);
                                                                           //ロータリーの入り口で両方黒になったら、xを3(ロータリーモード)にする
    			}else if((FastTimer(0) >= ROTARY_RIGHT)&&(y == 5)&&(x == 3)){
    				Off(OUT_AC);Wait(END);x++; PlaySound(SOUND_FAST_UP);
                                                                           //ロータリーに入った後、xを+1する
    			}else if((FastTimer(0) >= ROTARY_RIGHT)&&(y == 6)&&(x == 5)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x++; PlaySound(SOUND_FAST_UP);
                                                                           //ロータリーを出た後に、xを+1する
    			}else if((FastTimer(0) >= CROSS)&&(SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 6)&&(x == 6)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x = 2;
                                                                           //2つめの交差点を1回越えた後、xを2(交差点でのライントレースモード)にする
    			}else if((FastTimer(0) >= CROSS)&&(y == 7)&&(x == 2)){
    				Off(OUT_AC);Wait(END);x = 0; PlaySound(SOUND_FAST_UP);
                                                                           //2つ目の交差点を2回越えた後、xを0(ヘアピンカーブ準備モード)にする
    			}else if((SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 7)&&(x == 0)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); x++; y++; PlaySound(SOUND_FAST_UP);
                                                                           //ヘアピンカーブの始まりで両方黒になったとき、xとyを+1する
    			}else if((y == 8)&&(x == 2)){
    				x = 6;
                                                                           //ヘアピンカーブを越えた後、xを6(ライントレースモード)にする
    			}else if((SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 8)&&(x == 6)){
    				Off(OUT_AC);Wait(END);ClearTimer(0); y++; PlaySound(SOUND_CLICK);
                                                                           //コースの終わりで両方黒になったとき、yを+1する
    			}else if((FastTimer(0) >= END)&&(SE_L < THRESHOLD && SE_R < THRESHOLD)&&(y == 9)&&(x == 6)){
    				x = 9; PlaySound(SOUND_FAST_UP);
                                                                           //コースの始まりに戻ったとき、xを9(終了モード)にする	
    			}
    
    			if(x == 1){                                    //ヘアピンカーブモード
    				turn_hairpin();
    			}else if((x == 0)||(x == 6||x == 8)){          //ライントレースモード
                                                                           //0と8はそれぞれヘアピン準備モードと直角カーブモードで、旋回がきつくなっている
    				line_trace();
    			}else if(x == 2){                              //交差点でのライントレースモード
    				line_trace_2();
    			}else if((x == 3)||(x == 5)){                  //ロータリー出入りモード
    				rotary_right();
    			}else if(x == 4){                              //ロータリー進行モード
    				rotary_left();
    			}else if(x == 7){                              //直角カーブモード
    				right_angle();
    			}else{                                         //終了モード(xが10になり、whileループを抜ける)
    				Off(OUT_AC); y = 0; x++;
    			}	
    		}
    	}
    }

鍾馗のプログラム

状況(phase)によってその専用のプログラム(関数)を実行しています。そのせいでこのルート専用のプログラムになってしまいました。

基本的に「片側だけのセンサーだけでトレース&もう片方で次の状況にいつ移るかを計測」と「両方のセンサーを使ってトレース」の2種類で移動しています。ちなみに

一個のセンサーでトレースの特徴

  • 移動が遅い
  • トレースする時、いつも一定の軌道を描く
  • 片方のセンサーが余る→自由に使えるセンサーができる

二個のセンサーでトレースの特徴

  • 移動が早い
  • トレースするときふらふらする。軌道が毎回変わる

ロータリーや点線進入など問題がおきやすいところは一個の光センサートレースなので、最終的に安定的な結果を出すことができました。センサーの幅をある程度変えても問題なく進行できます。

ちなみに1週40秒強で移動します(電池の消耗具合によって変化)。

#define value 45		//明るさ1
#define Hvalue 50		//明るさ2
#define seL SENSOR_1		//SENSOR_1は長いのでセンサー左と言う意味を込めて略しています
#define seR SENSOR_3		//上参考
int phase;			//状況
int count;			//いろいろなカウント
int cross;			//交差点に侵入した回数を計測:交差点をそのまま直進する回数を直前で代入しています

void Rsen_trace(){								//右センサーのみでトレースする関数
 OnFwd(OUT_AC);if(seR < value){Off(OUT_C);OnFwd(OUT_A);}				//右センサーが黒線上なら右に
	else{Off(OUT_A);OnFwd(OUT_C);}							//右センサーが黒線外なら左に
	if(seL < value){phase++;}							//左センサーが反応したら次フェイズへ
}

void Lsen_trace(){								//左センサーのみでトレースする関数
	if(seL < value)	{Off(OUT_A);OnFwd(OUT_C);}					//左センサーが黒線上なら左に
	else		{Off(OUT_C);OnFwd(OUT_A);}					//左センサーが黒線外なら右に
	if(seR < value){								//ロータリー内でのフェイズ移行の時期を計測しています
		if(count < 2){OnFwd(OUT_AC);Wait(15);count++;}				//右センサーの反応が今まで1回以内ならば無視
		else{Off(OUT_AC);phase++;count = 1;}					//2回以上ならば次フェイズに移行。countを元に戻します
	}
}

void Dsen_trace(){								//2個のセンサーを使ってトレースする関数
	if(seL < value && seR > value){OnFwd(OUT_C);Off(OUT_A);}			//左:黒線上 右:黒線外	→ 左折
	if(seR < value && seL > value){OnFwd(OUT_A);Off(OUT_C);}			//右:黒線上 左:黒線外	→ 右折
	if(seL > value && seR > value){OnFwd(OUT_AC);} 					//両センサーが黒線外		→ 直進
		if(seL < value && seR < value) {					//両センサーが黒線上の時crossの値で行動を変化させます
		OnFwd(OUT_AC);Wait(30);PlaySound(SOUND_UP);				//直進:主に通常交差点の通過するときの行動です
			if(cross==0){Off(OUT_AC);phase++;}				//crossの値が既定値ならば次フェイズに移行します
			else{cross--;}							//そうでなければ淡々と数えます
		}
}

void hairpinLturn(){								//ヘアピン左ターンを行う関数
 PlaySound(SOUND_CLICK);OnFwd(OUT_AC);until(seL >= Hvalue);Off(OUT_AC);			//左センサーが黒線外に出るまで前進
 PlaySound(SOUND_CLICK);OnRev(OUT_A);OnFwd(OUT_C);					//超信地左旋回
 			     until(seL < value);until(seL >= Hvalue);Off(OUT_AC);	//左センサーが黒線上→黒線外になるまで待機
 PlaySound(SOUND_CLICK);OnFwd(OUT_C);Wait(15);until(seL >= Hvalue);Off(OUT_AC);		//左旋回 また黒線上に入る左センサーが黒線外になるまで待機
 PlaySound(SOUND_CLICK);phase++;							//次フェイズへ
}

void in_rotary(){								//ロータリーに入るときの関数
 PlaySound(SOUND_CLICK);OnRev(OUT_AC);Wait(20);Off(OUT_AC);				//ロータリーに入る前のDsen_trace()で進みすぎたのを戻す
 PlaySound(SOUND_CLICK);OnFwd(OUT_A);OnRev(OUT_C);Wait(50);				//超信地右旋回
 PlaySound(SOUND_CLICK);OnFwd(OUT_AC);until(seL < value);				//左センサーが黒線上になるまで前進
 PlaySound(SOUND_CLICK);Off(OUT_AC);phase++;						//次フェイズへ
}

void out_rotary(){								//ロータリーから出るときの関数
 PlaySound(SOUND_CLICK);OnFwd(OUT_AC);Wait(10);OnRev(OUT_C);Wait(10);			//少しだけ前進した後、超信地右旋回
 PlaySound(SOUND_CLICK);until(seL >= Hvalue);until(seL < value);Off(OUT_AC);		//左センサーが黒線外→黒線上になるまで待機した後停止。
 phase++;										//次フェイズへ
}

void in_shorterline(){								//近道(点線)に入る時の関数
 PlaySound(SOUND_CLICK);OnFwd(OUT_A);Wait(5);						//少しだけ前進
 PlaySound(SOUND_CLICK);until(seL >= Hvalue);until(seL < value);Off(OUT_AC);		//左センサーが黒線外→黒線上になるまで待機した後停止。
 PlaySound(SOUND_CLICK);OnFwd(OUT_C);Wait(5);Off(OUT_AC);				//(微調整)左旋回をちょっとだけ
 PlaySound(SOUND_DOWN);phase++;								//次フェイズへ
 }

void go_shorterline(){								//近道(点線)を進行する時の関数
 if(seL <= Hvalue && seR > value){OnFwd(OUT_C);until(seR < value);Off(OUT_AC);}		//左:黒線上 右:黒線外 → 右センサーが黒線上になるまで左旋回
 if(seR <= Hvalue && seL > value){OnFwd(OUT_A);until(seL < value);Off(OUT_AC);}		//右:黒線上 左:黒線外 → 左センサーが黒線上になるまで右旋回
 if(seL < value && seR < value){PlaySound(SOUND_DOWN);phase++;}				//両センサーが黒線上の時次フェイズへ
}
 
void out_shorterline(){								//近道(点線)から出る時の関数
 PlaySound(SOUND_CLICK);OnFwd(OUT_A);Wait(5);						//(微調整)右旋回
 PlaySound(SOUND_CLICK);until(seL >= Hvalue);until(seL < value);Off(OUT_AC);		//左センサーが黒線外→黒線上になるまで待機した後停止。
 PlaySound(SOUND_CLICK);OnFwd(OUT_AC);until(seR >= Hvalue)Off(OUT_AC);			//右センサーが黒線外になるまで前進
 PlaySound(SOUND_CLICK);phase++;							//次フェイズへ
}

task main(){
SetSensor(SENSOR_1,SENSOR_LIGHT);		//センサー1を光センサーと認識させる
SetSensor(SENSOR_3,SENSOR_LIGHT);		//センサー3を光センサーと認識させる
SetPower(OUT_A,6);				//出力調整
SetPower(OUT_C,6);				//出力調整

int i; 
for (i=1;i<=2;i++){				//2週させます
phase = 1;
count = 1;
while(phase!=19){				//phase==19で終了
 while(phase==1){Rsen_trace();}
 while(phase==2){hairpinLturn();}
 cross=2;					//次フェイズに使う。以下同じ
 while(phase==3){Dsen_trace();}
 while(phase==4){in_rotary();}
 while(phase==5){Lsen_trace();}
 while(phase==6){out_rotary();}
 count = 2;
 while(phase==7){Lsen_trace();}
 while(phase==8){in_shorterline();}
 while(phase==9){go_shorterline();}
 while(phase==10){out_shorterline();}
 cross = 0;
 while(phase==11){Dsen_trace();}
 while(phase==12){in_rotary();}
 while(phase==13){Lsen_trace();}
 while(phase==14){out_rotary();}
 cross = 1;
 while(phase==15){Dsen_trace();}
 while(phase==16){Rsen_trace();}
 while(phase==17){hairpinLturn();}
 cross = 0;
 while(phase==18){Dsen_trace();}
}
}

}

感想

ぐっPの反省・感想

今回の課題、「ライントレース」。ロボットがなぞるラインは敷かれているものの、それをなぞらせる指令を下す私たちがトレースできるラインはほとんど存在しない状況からのスタートだった。何が言いたいのかというと、今回の課題はプログラムにおける制御の割合が非常に大きいものであった、ということです。

このことは取りかかりの説明で言われていた上に、課題の特性上重々承知していたつもりでした。しかし、私のチームが製作したコースはデザイン性を重視した左右対称のものであったため、

「半分まで進めばあとは逆をたどっていけばよい」

「あとは最初からもう一回繰り返せば2周できる」

などという甘い考えのもとプログラムを書いてしまっていました。その結果、途中でプログラムを1から見直す必要が出てきたり、最終的にも安定した走行が出来ていない状態になってしまいました。何事にも油断大敵、全力で臨まなくてはならないことを思い知りました。そのせいで遅くまで作業する私に付き合ってくれた相方には頭が上がりませんm(_ _)m

次回からはいよいよ最後の課題です。まだわからぬチームの仲間とともに、素晴らしいロボットと動作を築き上げていきたいと思います。

鍾馗の反省 ――意味のない努力

何でこんなこと考えたのだろうか

「光センサーが45以下なら停止→光センサーが45以下なら○○○○○」のコンボが上図のようにうまくいかないことも考えて、「光センサーが45以下なら停止→光センサーが50以下なら○○○○○」となるように基本的にプログラムを書いています。valueとHvalueと光センサーの値に2つも定義しているのはそのためです。

しかしあとで確認したのですが1つの値(45)でまったく問題は出ませんでした。

慣性で前にずれることは会っても、後ろにずれることはない。考えてみれば当たり前のことでした。

鍾馗の反省 ――挑戦心が足りない!

プログラム構成第2案をさらします

基本的に左センサーのみでトレースします。右センサーが黒線上になるのは次の4通り(のはず)


案 案

このとき左側のセンサーは白と判断する

案 案

このとき左側のセンサーは黒と判断する


そのあと向こう側に伸びる線があるか否かを判断していけば、ロボットは今どのような状況にいるのかを判断できるのではないかと考えました。回転センサーを使えば結構うまくいくのではなどと考えていました

この方法で行けばコースがどのようなものであっても進めるでしょう。


ちなみに次の場合

案

たぶん左センサーのみでうまくいってくれんじゃないの(投げやり)

案

スタート位置で止まる必要なくね?(暴論)

案

点線は一箇所しかないのだから逆方向から進ませればいいや(妥協)

の3本でお送りします。

ちなみにこの案でやらなかった理由は、考え付いたときには第1案のものが完成していて 時間がなかったからです。やっつけで作ってみましたが、うまくいきませんでしたし。

と、言うか実は自班のヘアピンというか鋭角カーブは対応できないので、自班のコースが完走できないと言う根本的な問題がある。

最後に

このページやロボット、プログラムなどについて意見などがありましたら、今後の参考のためぜひコメントをお願いします。


このページに来てくれた人数 575 今見ている人数 1


添付ファイル: filetester.jpg 31件 [詳細] fileSENSOR_R.gif 38件 [詳細] file片側センサ.gif 35件 [詳細] filelinetrace.gif 24件 [詳細] file本体2.jpg 24件 [詳細] file本体.jpg 22件 [詳細] fileロボット絵.bmp 23件 [詳細] fileドライブベース1.jpg 26件 [詳細] file回転センサー1.jpg 24件 [詳細] file光センサー1.jpg 30件 [詳細] file反省7.gif 31件 [詳細] file反省6.gif 29件 [詳細] file反省5.gif 26件 [詳細] file反省4.gif 28件 [詳細] file反省3.gif 26件 [詳細] file反省2.gif 30件 [詳細] file反省1.gif 25件 [詳細] filerobotanime.gif 38件 [詳細] filesensor2.jpg 33件 [詳細] filesensor1.jpg 31件 [詳細] filecourse.jpg 37件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-12-20 (火) 16:57:23