*Mission1レポート [#q946f150] 目次一覧 #contents **課題の内容 [#mission_intro] 図のようなコースを各自で作成した上で、次のような動作をするロボットを作成せよ。 +スタート地点から出発し、スタート地点外のすぐ近くに置かれたピンポン玉をつかむ。 +ピンポン玉をつかんだら速やかにスタート地点の境界の黒線に戻り、そこから黒線に沿って動いてゴール地点を目指す。ただしT字路では、直進、右折、左折を正しく判断させること。また、曲線部中央の障害物に接触しないようにすること。 +ゴール地点に到達したら、ゴールエリア外からピンポン玉をゴールにシュートする。 ただし、どうしてもエリア外からのシュートが難しい場合は、エリア内からシュートした後、エリアから出てもよい。 RIGHT:([[2012b/Mission]]より抜粋) #ref(./2012b-mission1.png,50%,Mission1_field) **ロボットの紹介 [#robot_intro] **プログラムの紹介 [#program_intro] ***概要 [#program_gaiyou] 今回私は上の図の左側からスタートするプログラムを担当しました。 私が作成したライントレースのプログラムでは、コース外へ延びる線との交差点においてうまく交差点だと認識してくれなかったので、交差点を避けて進むプログラムを作成することにしました。 プログラムの全体の流れとしては +ピンポン球を回収 +四角の枠から脱出し、そこからラインの右端をトレース +スタートから約10秒後にラインを横断し、その後はラインの左端をトレース +ラインを横断した地点から3番目の左急カーブ(ゴールゾーンの黒枠との丁字路)に差し掛かったらシュート +勝利のファンファーレを奏でる といった様になります。 ***作成したプログラムとその詳しい説明 [#program] #define SPEED_H 45 #define SPEED_L 35 #define SPEED_LL 20 #define THRESHOULD 47 モーターの稼働スピード及び閾値を定義。 より正確にラインをトレースするためにスピードを3段階設けました。 また、コースの黒線が若干白っぽいので閾値は高めに設定しました。 #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL); #define go_forward OnRL(SPEED_H,SPEED_H); #define turn_left1 OnRL(SPEED_L,-SPEED_L); #define turn_left0 OnRL(SPEED_L,-SPEED_LL); #define turn_right0 OnRL(-SPEED_LL,SPEED_L); #define turn_right1 OnRL(-SPEED_L,SPEED_L); #define STEP 1 #define nMAX 140 #define short_break Off(OUT_BC);Wait(1000); #define CROSS_TIME 400 #define cross_line OnRL(SPEED_H,0);Wait(CROSS_TIME); #define shoot OnRL(-SPEED_H,SPEED_H);Wait(1000);Off(OUT_BC);OnRL(SPEED_H,SPEED_H);Wait(600);Off(OUT_BC);OnFwd(OUT_A,100);Wait(250);Off(OUT_A); #define E 329.5 #define Fs 370 #define G 392 #define A 440 #define As 466 #define B 494 #define C 523.5 #define D 587 sub fanfare() { repeat(3) { PlayTone(D,100);Wait(140); } PlayTone(D,400);Wait(470); PlayTone(As,400);Wait(470); PlayTone(C,400);Wait(470); PlayTone(D,100);Wait(300); PlayTone(C,100);Wait(150); PlayTone(D,1000);Wait(1400); while (true) { PlayTone(A,400);Wait(450); PlayTone(G,400);Wait(450); PlayTone(A,400);Wait(450); PlayTone(G,100);Wait(230); PlayTone(C,400);Wait(450); PlayTone(C,100);Wait(230); PlayTone(B,400);Wait(450); PlayTone(C,100);Wait(230); PlayTone(B,400);Wait(450); PlayTone(B,100);Wait(230); PlayTone(A,400);Wait(450); PlayTone(G,400);Wait(450); PlayTone(Fs,400);Wait(450); PlayTone(G,180);Wait(230); PlayTone(E,1600);Wait(2000); PlayTone(A,400);Wait(450); PlayTone(G,400);Wait(450); PlayTone(A,400);Wait(450); PlayTone(G,100);Wait(230); PlayTone(C,400);Wait(450); PlayTone(C,100);Wait(230); PlayTone(B,400);Wait(450); PlayTone(C,100);Wait(230); PlayTone(B,400);Wait(450); PlayTone(B,100);Wait(230); PlayTone(A,400);Wait(450); PlayTone(G,400);Wait(450); PlayTone(A,400);Wait(450); PlayTone(C,180);Wait(230); PlayTone(D,1600);Wait(2000); } } 音階を定義し、ファンファーレのサブルーチンを用意。 task main() { SetSensorLight(S1); int nOnline=0; //ライン上にどれだけいたかをカウントする変数を用意 int nCurve=0; //左急カーブの回数をカウントする変数を用意 long t0 = CurrentTick(); //タイマーを用意 OnRL(-SPEED_L,SPEED_H); Wait(300); Off(OUT_BC); OnRev(OUT_A,30); Wait(500); Off(OUT_A); OnRL(2*SPEED_H,SPEED_H); Wait(250); Off(OUT_BC); ここの一連のプログラムで、ピンポン球を回収してスタートゾーンの枠から脱出します。 while (CurrentTick() - t0 < 10000) { if(SENSOR_1 < THRESHOULD - 13) { turn_right1; } else { if (SENSOR_1 < THRESHOULD - 7){ turn_right0; } else if (SENSOR_1 < THRESHOULD + 7){ go_forward; } else if (SENSOR_1 < THRESHOULD + 15){ turn_left0; } else { turn_left1; } Wait(STEP); } } この部分はスタートから10秒間の、ラインの右端をトレースするためのプログラムです。 閾値からの差によって曲がり方を選択しながら進んで行きます。 if (CurrentTick() - t0 == 10000) { cross_line; t0 = CurrentTick(); スタートから10秒経過したら、ラインを横断して左側へ移ります。 while (nCurve < 2) { if(SENSOR_1 < THRESHOULD - 13) { turn_left1; nOnline++; if (nOnline == nMAX) { nCurve++; nOnline=0; PlaySound(SOUND_CLICK); Off(OUT_BC); Wait(300); OnRL(SPEED_H,-SPEED_H); Wait(500); } } else { if (SENSOR_1 < THRESHOULD - 7){ turn_left0; } else if (SENSOR_1 < THRESHOULD + 7){ go_forward; } else if (SENSOR_1 < THRESHOULD + 15){ turn_right0; } else { turn_right1; } nOnline=0; } Wait(STEP); } } ラインの左側に移った後は、ラインの左端をトレースするように先ほどとは逆方向に曲がるようプログラミングします。 また、ラインの横断後左急カーブの回数が2回未満の時は、左急カーブに差し掛かったらカーブのカウンタを+1して旋回し、センサをライン上から外します。これは、1回のカーブでカウンタが2回以上プラスされるのを防ぐためです。 while (nCurve >= 2) { while (nOnline < nMAX) { if(SENSOR_1 < THRESHOULD - 13) { turn_left1; nOnline++; } else { if (SENSOR_1 < THRESHOULD - 7){ turn_left0; } else if (SENSOR_1 < THRESHOULD + 7){ go_forward; } else if (SENSOR_1 < THRESHOULD + 15){ turn_right0; } else { turn_right1; } nOnline=0; } Wait(STEP); } short_break; PlaySound(SOUND_LOW_BEEP); shoot; PlaySound(SOUND_FAST_UP); Wait(1000); OnRL(SPEED_H,SPEED_H); Wait(15000); Off(OUT_BC); Wait(1000); fanfare(); } } } 左急カーブを2つ通り過ぎた後は、その後の3つ目の左急カーブでピンポン球をゴールにシュートします。シュート後はゴールの枠内から脱出し、勝利のファンファーレを奏でます。 **感想・反省等 [#kansou]