[[2011a]]

#contents

*メンバー紹介 [#s79573c3]
***くまちゃん [#e0c68ca0]

***hiros [#t0a10068]

*コース[#o7b65f32]
#ref(map.JPG)
交差点がナナメだったりして、対策に苦労した。
*ハードウェア [#f69f9e3c]
**マシン解説 [#c5dc4b39]
#ref(machine.JPG)
これがマシン。どことなくアプ○ラス。この形にしたのは、以前の形が直角を曲がるのに不向きな形だった為。
特徴は、タイヤの間を縮める事で回転したときのずれを少なくした事。
#ref(front.JPG)
センサをタイヤのそばに置いて、制御のずれを減らした。
色々のせられる広いボディ。センサなどもつけやすい。
#ref(bottom.JPG)
タイヤが近いので小回りが利く。
*ソフトウェア [#x9bb2a61]
**くまちゃん [#g371cfff]
 #define THRESHOLD 40
 #define FIRST_TIME 1700
 #define SECOND_TIME 1500
 #define THIRD_TIME 1500
 #define FOURTH_TIME 1500
 #define FIFTH_TIME 1500
 #define TURN_TIME 0
 task main()
 {
	SetSensor(SENSOR_1,SENSOR_LIGHT);
	SetSensor(SENSOR_3,SENSOR_LIGHT);
	ClearTimer(0); 
	while (Timer(0) <= FIRST_TIME){
		if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)){
      	      		OnFwd(OUT_A+OUT_C); }
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){
			OnFwd(OUT_C); 
			Off(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);}
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);
			PlaySound(SOUND_CLICK) ;}
		
	}
	ClearTimer(1);
	while (FIRST_TIME < Timer(1) <= SECOND_TIME) {
		if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			Off(OUT_A+OUT_C);
			OnFwd(OUT_C);
			Wait(30);
			OnRev(OUT_A);
			Wait(30);}
   		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)){
      	      		OnFwd(OUT_A); 
			Off(OUT_C);}
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){
			OnFwd(OUT_C); 
			Off(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);
			PlaySound(SOUND_CLICK) ;}
	} 
	ClearTimer(2);
	while ( SECOND_TIME < Timer(2) <= THIRD_TIME ) {
		if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			Off(OUT_A+OUT_C);
			OnFwd(OUT_C);
			Wait(50);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)){
      	      		OnFwd(OUT_A); 
			Off(OUT_C);}
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){
			OnFwd(OUT_C); 
			Off(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);
			PlaySound(SOUND_CLICK) ;}
			}
	ClearTimer(3);
	while ( THIRD_TIME < Timer(3) <= FOURTH_TIME ) {
		if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			Off(OUT_A+OUT_C);
			OnFwd(OUT_A);
			Wait(30);
			OnRev(OUT_C);
			Wait(30);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)){
      	      		OnFwd(OUT_A); 
			Off(OUT_C);}
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){
			OnFwd(OUT_C); 
			Off(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);
			PlaySound(SOUND_CLICK) ;}
	ClearTimer(0); 
	while (FOURTH_TIME <= Timer(0) <= FIFTH_TIME){
		if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)){
      	      		OnFwd(OUT_C); }
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){
			OnFwd(OUT_C); 
			Off(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);}
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);
			PlaySound(SOUND_CLICK) ;}	
	}
	ClearTimer(3);	
	while ( Timer(3)<FIFTH_TIME ) {
		if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)){
      	      		OnFwd(OUT_A); 
			Off(OUT_C);}
		else if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){
			OnFwd(OUT_C); 
			Off(OUT_A);}
		else if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)){
			OnFwd(OUT_A); 
			Off(OUT_C);
			PlaySound(SOUND_CLICK) ;}
	}
 }

**hiros [#gfa35d61]
目標:
できるだけ短く書きたい、とにかくわかりやすくしたい。そして出来ればどの紙でやっても動くようにしたい。
***作戦(ロータリーなし) [#wbec58d9]
2つの光センサを使って、黒線を挟み、適時修正しながら進めていく。
まずはロータリーについては考えない事にした。
交差点に到達したら、まっすぐ先に進んでいくというプログラムを考えた。
交差点の判定は、「右も左も黒であれば、交差点」と考えた。

***コード [#ca6c9af8]
 #define isBlack <40
 #define isWhite >40
 #define R SENSOR_3
 #define L SENSOR_1
 #define RM OUT_C
 #define LM OUT_A
 #define LINE 8
 
 void go(){
 	OnFwd(RM+LM);
 }
 void tr(){
 	OnFwd(LM);
 	//Off(RM);
 	OnRev(RM);
 }
 void tl(){
 	OnFwd(RM);
 //	Off(LM);
 	OnRev(LM);
 }
 
 void move(){
 	if (L isWhite && R isWhite) go();
 	else if (L isWhite && R isBlack) tr();
 	else if (L isBlack && R isWhite) tl();
 	else if (L isBlack && R isBlack){
 /*	        PlaySound(SOUND_CLICK);
 		go();
 		Wait(LINE);
 	}
 }
 
 task main (){
 	SetSensor (R, SENSOR_LIGHT);
 	SetSensor (L, SENSOR_LIGHT);
 	while (1){
 		move();
 	}
 }
***作戦(ロータリーなし改) [#qc954620]
上のコードでは、直角な交差点ではまっすぐに進むが、私たちの交差点はかなり斜めで、「右も左も黒」、という判定になりにくい。よって、コードを新しく考える必要があった。このコードは寝ぼけていたのでアイディア自体がおかしいかもしれない。
まず、右か左のどちらが最初に黒(道)にあたったかを変数で覚えておいて、そのときに反対側(つまり回転の外側)が何回行われたかを格納しておき、その回数だけ反対側(内側)のモータを動かせば機体を道に対して平行に出来ると考えた。
***コード [#pf8e7b07]
 #define isBlack <40
 #define isWhite >40
 #define R SENSOR_3
 #define L SENSOR_1
 #define RM OUT_C
 #define LM OUT_A
 #define LINE 8
 
 void go(){
 	OnFwd(RM+LM);
 }
 void tr(){
 	OnFwd(LM);
 	OnRev(RM);
 }
 void tl(){
 	OnFwd(RM);
 	OnRev(LM);
 }
 
 int whichWay = 0; // if 1 then it found the way on its right first. (else if 2 then left first.)
 int rcount = 0; //L is rcount late.
 int lcount = 0; //R is lcount late.
 
 void move(){
 	if (L isWhite && R isWhite) go();
 	else if (L isWhite && R isBlack){
 		tr(); whichWay = 1;
 		rcount++; lcount = 0;
 	}
 	else if (L isBlack && R isWhite){
 		tl(); whichWay = 2;
 		lcount++; rcount = 0;
 	}
 	else if (L isBlack && R isBlack){
 		if (whichWay == 1) PlaySound(SOUND_CLICK);
 		if (whichWay == 2) PlaySound(SOUND_DOUBLE_BEEP);
 		while (1){
 			go();
 			if (L isWhite && R isWhite){
 				if (whichWay == 1) {
 						tl(); Wait (lcount);
 						go(); Wait (LINE);
 / /						if (L isWhite && R isWhite) break;
 				}else if (whichWay == 2){
 						tr(); Wait (rcount);
 						go(); Wait (LINE);
 / /						if (L isWhite && R isWhite) break;
 				}
 				break;
 			}
 		}
 	go();
 	Wait (LINE);
 	Off(RM+LM);
 	}
 }
 
 task main (){
 	SetSensor (R, SENSOR_LIGHT);
 	SetSensor (L, SENSOR_LIGHT);
 	while (1){
 		move();
 	}
 }

***作戦(ロータリーなし改改) [#w644155f]
上のコードは、交差点に入る前、機体が線に対して平行であればうまく行くが、現実的にはそれは難しいので、改良する必要があった。例えば、右が黒で、左は白であるとき、上のコードでは「右に道がある」ということになり、すぐ右に回転をしてしまう。これだと、斜めな交差点にさしかかると「右に回転ー>左に回転」の無限ループに陥って、その場から動かなくなってしまう。
なので、回転する前に判定を入れる事にした。
***コード [#zdd515b3]
***作戦(ロータリーあり) [#kbebd074]
ロータリーについて考えてみると、交差点との共通点である、「右も左も黒」という判定がある。
違いとしては、「前に道がない」ことなので、黒&黒となったときに、前に道があるかを探索して、もしなければもどり、右の道に進む。そのとき、「ロータリーである」と判定し、明らかな道がロータリー途中の道で、右にあったときにそれを一回とばす。
ちなみに、ここでハードウェアが大きく変わった。
***コード [#z0dc924d]
 #define isBlack <40
 #define isWhite >40
 #define R SENSOR_3
 #define L SENSOR_1
 #define RM OUT_A
 #define LM OUT_C
 #define LINE 15
 void go(){
 	OnFwd(RM+LM);
 }
 void tr(){
 	Off(LM + RM);
 	OnRev(RM);
 	OnFwd(LM);
 }
 void tl(){
 	Off(LM + RM);
 	OnRev(LM);
 	OnFwd(RM);
 }
 
 void gogo(){
 	if (R isWhite && L isWhite){ //road ahead
 		go();
 	} else if (R isBlack && L isWhite){ //road on right
 		tr();
 	} else if (R isWhite && L isBlack){ //road on left
 		tl();
 	} else if (R isBlack && L isBlack){ //rotary or intersection
 		// Cross line and look for road. If there was no road, then it must be the rotary.
 		go();
 		Wait (LINE);
 		// turn right a little, and if L isBlack then turn left to correct.
 		// else turn right so that it will find the way, and this should be the rotary.
 		tr();
 		Wait (5);
 		if (L isBlack) {
 			tl();
 			Wait (5);
 		} else { // R (W -> B -> W)
 			while (1){
 				if (R isBlack) break;
 				tr();
 			} while (1){
 				if (R isWhite || L isBlack) break;
 				tr();
 			}
 		}
 	}
 }
 
 task main (){
 	SetSensor (R, SENSOR_LIGHT);
 	SetSensor (L, SENSOR_LIGHT);
 	while (1){
 		gogo();
 	}
 }

***作戦(ロータリー改) [#eb1a9c52]
前回のコードは、何度も実行すれば何度か無事ゴールできた。ロータリーの処理をうっかり忘れていたので、多分まぐれだと思う。今回は、確実に自分の紙の上を走ればよしとした。よって、「黒&黒」になる回数をカウントして、ロータリーのところにあたったら左の道を通るようにした。そして、移動中に左ー>右のループに陥り動かなくなったときは前に進むように、bbbbという変数でコントロールする事にした。
#ref(markedmap.jpg)
上のピンクが黒黒判定の場所。青のところでループに陥る。
***コード [#ac6664c5]
 //言い換え
 #define isBlack <40
 #define isWhite >40
 #define R SENSOR_3
 #define L SENSOR_1
 #define RM OUT_A
 #define LM OUT_C
 //各秒数 線を越すための値と90度回転
 #define LINE 27
 #define TTIME 70
 //ターンするところ
 #define TURN_RIGHT1 3
 #define TURN_RIGHT2 5
 #define TURN_RIGHT3 8
 #define TURN_RIGHT4 10
 //とばすところ
 #define SKIP1 4
 #define SKIP2 9
 
 int bb = 0; //黒&黒のときの回数
 int bbbb = 0; //動かなくなったかを判定
 
 void go(){//前に進む
 	OnFwd(RM+LM);
 }
 void tr(){//右に回転
 	Off(LM + RM);
 	OnRev(RM);
 	OnFwd(LM);
 }
 void tl(){//左に回転
 	Off(LM + RM);
 	OnRev(LM);
 	OnFwd(RM);
 }
 
 void gogo(){//一連の動き
 	if (bbbb > 10) { //もし動かなかったら線は無視して前に進む
 		go();
 		Wait (LINE);
 		bbbb = 0;
 	}
 	if (R isWhite && L isWhite){ //road ahead
 		go();
 		bbbb = 0;
 	} else if (R isBlack && L isWhite){ //road on right
 		tr();
 		bbbb++;
 	} else if (R isWhite && L isBlack){ //road on left
 		tl();
 		bbbb++;
 	} else if (R isBlack && L isBlack){ //rotary or intersection
 		bb++;
 		PlaySound(SOUND_CLICK);
 		Off(RM+LM);
 		Wait (100);
 		if (bb == TURN_RIGHT1 || bb == TURN_RIGHT2 || bb == TURN_RIGHT3 || bb == TURN_RIGHT4){ //rotary
 			PlaySound(SOUND_UP);
 			go();
 			Wait (LINE);
 			tl();
 			Wait (TTIME);
 		} else if (bb == SKIP1 || bb == SKIP2){ //skip ロータリー内のスキップ
 			PlaySound(SOUND_LOW_BEEP);
 			go();
 			Wait (LINE);
 			tr();
 			Wait (40);
 		}
 		else { //skip 通常時の交差点
 			PlaySound(SOUND_DOWN);
 			go();
 			Wait (LINE);
 		}
 	}
 }
 
 task main (){
 	SetSensor (R, SENSOR_LIGHT);
 	SetSensor (L, SENSOR_LIGHT);
 	while (1){// 無限ループ
 		gogo();
 	}
 }


*感想 [#y22b0902]
**くまちゃん [#jd2fe435]
 ロータリーと急角度十字路の違いをプログラムするのが大変でした。
 プログラムで乗り越えようと思ったのですが、できなかったのでコースを5ブロックに分けてタイマーをセットして乗り切りました。

**hiros [#b3330aaa]
最後のロータリー改で一応クリアしたが、納得がいく結果にならなかった。これだと、線を変えたときいちいち調整する必要が出てきて、非常に面倒。満足が出来ない結果となった。あと、紙のでこぼこ具合がかなり影響してしまうのがつらかった。比較的短く書けたのはよかったかもしれない。

#comment

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