[[2019a/Member]] 目次 #contents *課題について [#n09c5be2] 次のようなコースを作成し、ライントレースをします。 #ref(2019a-mission2.png) 進む順番 A地点から出発 → B → C(直進) → D(一時停止の後、直進) → E → F → G(一時停止の後、右折) → H → I → J(右折) → K(左折) → L(ピンポン玉をつかむ) → K(直進) → M(一時停止) → シュート→ A地点に入る(ゴール) 交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止します。 *ロボットの本体の説明 [#qee10873] #ref(IMG_4777.JPG) 全体図 二輪駆動で移動します。 タイヤの少し前にラインセンサが付いており、モーターが回り、ロボットが移動したときに、適度にラインセンサが動き、地面の状況を調べることができます。 #ref(IMG_4779a.jpg) ボールをつかむためのアーム フェースギアを用い、モーターの回転軸を90度回転させることで、ボールをつかむためのアームを製作しました。 #ref(IMG_4783.JPG) アームのつかむ部分が重なっており、ボールをしっかりとつかむことができます。 *プログラムの説明 [#nf96d142] #ref(2019a-mission21.png) BからJ地点までは、ラインの左側を進みます。 KとM地点の間にある急なカーブが、ラインの左側を進むと回りきることができなかったので、ラインの右側をトレースすることにしました。 #ref(2019a-mission2-1.png) 次の5つのライントレースをするプログラムを組み合わせて、このコースをクリアすることにました。 ・ラインの左側を進み、交差点を直進するプログラム。 ・ラインの左側を進み、交差点で停止するプログラム。 ・ラインの右側を進み、交差点を直進するプログラム。 ・ラインの右側を進み、交差点で停止するプログラム。 ・ラインの右側を進み、白が続いたときに止まるプログラム。 基本的には、交差点を直進するプログラムと交差点で止まるプログラムがセットで組み合わせます。 ライントレースをしている時間を計測するために変数Bを用います。 ライントレースをしている間はBの値が増え続けます。 一定の値になり、一定の時間が経過したことがわかると、交差点を直進するプログラムから交差点で停止するプログラムに変わります。 交差点で停止すると、そのときにBの値が0になり、また次のセットが始まります。 図の緑の直線のところで、交差点を直進するプログラムから交差点で止まるプログラムになり、緑の丸のところでロボットは一時停止します。 while(B<4000){ cross_line(); } while(B>=4000){ stop_corner(); } #ref(a.png) ラインセンサの値は、黒のときが30くらいで、白のときが60くらいです。 そのため、白と黒の境の値をを40として、図のように、白のときは右に進み、黒のときは左に進みます。 交差点では、黒の上を進む時間が長い(左に進む時間が長い)ので、それを変数Aを用いて判断しました。 左に進んでいるときは、Aの値が増え続け、右に進むとAは0になります。 Aの値が一定の値(400)以上になったときに、交差点にいると判断して、1秒間停止します。 ライントレースの基本的なプログラミング(ラインの左側を進む) void stop_corner(){ SetSensorLight(S1); while(A<400){ if(SENSOR_1<40){ hidari; A=A+1; B=B+1; }else{ migi; B=B+1; A=0; } } tomaru; Wait(1000); B=0; }//交差点で止まるライントレース(ラインの左側を進む) ラインの右側を進むときのプログラムは、左に進むのと右に進むのが逆になります。 また、ボールを取るところでは、白が続いたらAの値が増え、その値が800になったら止まるようにしました。 交差点を直進するプログラムはただ単にライントレースします。 void cross_line(){ SetSensorLight(S1); if(SENSOR_1<40){ hidari; B=B+1; }else{ migi; B=B+1; } }//交差点を直進するライントレース(ラインの左側を進む) プログラムの全体 #define zenshin OnFwd(OUT_BC,50); //前進 #define migikaiten OnFwd(OUT_B,-70);OnFwd(OUT_C,40); //右回転 #define hidarikaiten OnFwd(OUT_B,40);OnFwd(OUT_C,-70); //左回転 #define migi OnFwd(OUT_C,40);Off(OUT_B);//右に進む #define hidari OnFwd(OUT_B,40);Off(OUT_C); //左に進む #define tomaru Off(OUT_BC); //ストップ long A=0;//交差点で止まるための時間を計測する変数 long B=0;//ライントレースしている時間を計測する変数 void stop_corner(){ SetSensorLight(S1); while(A<400){ if(SENSOR_1<40){ hidari; A=A+1; B=B+1; }else{ migi; B=B+1; A=0; } } tomaru; Wait(1000); B=0; }//交差点で止まるライントレース(ラインの左側を進む) void cross_line(){ SetSensorLight(S1); if(SENSOR_1<40){ hidari; B=B+1; }else{ migi; B=B+1; } }//交差点を直進するライントレース(ラインの左側を進む) void re_stop_corner(){ SetSensorLight(S1); while(A<400){ if(SENSOR_1>40){ hidari; A=0; B=B+1; }else{ migi; A=A+1; B=B+1; } } tomaru; Wait(1000); B=0; }//交差点で止まるライントレース(ラインの右側を進む) void re_cross_line(){ SetSensorLight(S1); if(SENSOR_1>40){ hidari; B=B+1; }else{ migi; B=B+1; } }//交差点を直進するライントレース(ラインの右側を進む) void stop_ball(){ SetSensorLight(S1); while(A<800){ if(SENSOR_1<40){ hidari; A=0; B=B+1; }else{ migi; B=B+1; A=A+1; } } tomaru; Wait(1000); B=0; }//ボールがあるところで白が続くと止まる(ラインの右側を進む) void stop_corner1(){ SetSensorLight(S1); while(A<400){ if(SENSOR_1<40){ hidari; A=A+1; B=B+1; }else{ migi; B=B+1; A=0; } } tomaru; Wait(1000); B=5000; }//交差点で止まるライントレース(ラインの左側を進む) task main() { while(B<4000){ cross_line(); } while(B>=4000){ stop_corner(); }//Dの交差点で一時停止する migi; Wait(100); tomaru; Wait(200);//交差点で止まったとき、機体の向きを調整する動作 while(B<5000){ cross_line(); } while(B>=5000){ stop_corner(); } migikaiten; Wait(300); tomaru; Wait(100); zenshin; Wait(200); tomaru; Wait(100);//円の部分での、ライン上にのるための動作 while(B<3000){ cross_line(); } while(B>=3000){ stop_corner(); }//円の終わり zenshin; Wait(900); tomaru; Wait(100);//円の終わりでの機体の向きの調整 while(B<4000){ stop_corner1(); } B=0;//交差点が止まるプログラムが単独で出てくるところ hidarikaiten; Wait(200); tomaru; Wait(100);//ロボットの向きの調整 while(B<2000){ re_cross_line(); } while(B>=2000){ stop_ball(); } //ボールのところ 白が続くと止まる OnFwd(OUT_A,-50); Wait(600); Off(OUT_A); Wait(100);//ボールを取る hidarikaiten; Wait(1000); tomaru; Wait(100); zenshin; Wait(400); tomaru; Wait(100);//ボールをとった後、ライン上に復帰する動作 while(B<10000){ re_cross_line();//ラインの右側を進む } while(B>=10000){ re_stop_corner(); }//ラインの右側を進み、ゴールの前で止まる OnFwd(OUT_A,50); Wait(600);//ボールを下ろす Off(OUT_A); Wait(100); zenshin; Wait(100); tomaru; Wait(100);//シュートする } *難しかったところ [#pa440e94] 基本的に5つのライントレースするプログラムを組み合わせているのですが、1回だけ交差点で止まるプログラムが単独出てきています。そのときは、交差点で止まったときにBを0にするのではなく、Bに大きな数(今回は5000)を代入してから、Bを0にしています。ただ単にBを0にしただけでは、プログラムが切り替わらなかったので、苦戦しました。 void stop_corner1(){ SetSensorLight(S1); while(A<400){ if(SENSOR_1<40){ hidari; A=A+1; B=B+1; }else{ migi; B=B+1; A=0; } } tomaru; Wait(1000); B=5000; }//交差点で止まるライントレース(ラインの左側を進む) while(B<4000){ stop_corner1(); } B=0; また、はじめ、条件ループの中に無条件ループを入れてしまい、プログラムが切り替わらなかったこともあり、大変でした。