[[2019a/Member]]

*課題2 [#t1a8307b]
下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。
**ミッション [#h5996f83]
A地点を出発し、次の経路を黒い線にそって動くロボットを作成する。

A地点から出発 → B → C(直進) → D(一時停止の後、直進) → E → F → G(一時停止の後、右折) → H → I → J(右折) → K(左折) → L(ピンポン玉をつかむ) → K(直進) → M(一時停止) → シュート→ A地点に入る(ゴール)

交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止すること。

*ロボット [#y641683e]
組み立て説明書にある基本のロボットをベースに、光センサーと玉をつかむ部品を組み込んだ。実際に走らせたところ、パワーがなくカーブで止まってしまったので、左右のモーターにギアを組み込みトルクを上げた。

*プログラム [#oe67ef8b]
まず、線の左側の、白と黒の境界線をたどるプログラムを作った。黒、黒寄りのグレー、白寄りのグレー、白の閾値を定義し、黒なら左、グレーなら直進、白寄りのグレーなら少しだけ右、といったように進むようにした。
また、D地点のような交差点やK地点のような丁字路では、黒の値をとる時間が一定値以上になったときに交差点と判断し、直進や左折等をするようにした。
しかし、このシステムでは G→H→I→J 間で円の内側をたどるため交差点の判断をすることができず、また K→M 間の R=4 のカーブを曲がりきることができなかった。
そこで、G地点を超えたところから線の右側の境界線をたどるようにすることでどちらもクリアすることができた。
これで一通りミッションを遂行できるが、問題は左右の境界線それぞれのプログラムが必要になり、サブルーチンの量が倍になってしまうことだ。
試行錯誤の結果、左を1、右を-1とする方法を見つけた。

 #define left 1
 #define right -1
 #define BLACK      40
 #define GRAY_BLACK 45
 #define GRAY_WHITE 52
 #define WHITE      60
 #define short_brake Wait(1000);
 #define go(x)         OnRev(OUT_B,30*x); OnRev(OUT_C,-30*x);
 #define go_little(x)  OnRev(OUT_B,35*(x+1)/2); OnRev(OUT_C,35*(-1*x+1)/2);
 #define go_straight   OnRev(OUT_BC,35);


 sub follow_line(int a)
 {
   SetSensorLight(S3);
   long t0=CurrentTick();
   while(CurrentTick()-t0<150) {
     if (SENSOR_3 < BLACK) {
       go(a);
     } else if (SENSOR_3 < GRAY_BLACK) {
       go_little(a);    t0=CurrentTick();
     } else if (SENSOR_3 < GRAY_WHITE) {
       go_straight;     t0=CurrentTick();
     } else if (SENSOR_3 < WHITE) {
       go_little(-1*a); t0=CurrentTick();
     } else {
       go(-1*a);        t0=CurrentTick();
     }
   }
   Off(OUT_BC);
 }

 sub cross_line(int b)
 {
   go_little(-1*b);
   Wait(300);
   go_straight;
   Wait(300);
   Off(OUT_BC);
 }

 sub turn_left(int c)
 {
   go_little(left);
   Wait(800-100*c);
   go(left);
   Wait(800-100*c);
   Off(OUT_BC);
 }

 sub turn_right(int d)
 {
   go_little(right);
   Wait(800+100*d);
   go(right);
   Wait(800+100*d);
   Off(OUT_BC);
 }

 sub change_line(int e)
 {
   go(-1*e);
   Wait(750);
   Off(OUT_BC);
 }

 sub ball_catch()
 {
   go(left);
   Wait(1000);
   go_little(left);
   Wait(1200);
   go_straight;
   Wait(800);
   Off(OUT_BC);
   OnFwd(OUT_A,30);
   Wait(600);
   Off(OUT_A);
   go(left);
   Wait(1000);
 }

 sub shoot()
 {
   go(left);
   Wait(200);
   Off(OUT_BC);
   Wait(1000);
   OnRev(OUT_A,70);
   Wait(900);
   Off(OUT_A);
 }

 task main()
 {
  go_straight; Wait(500);   // A->B
  follow_line(left); short_brake; cross_line(left);   // B->C->D
  follow_line(left); short_brake; turn_right(left); change_line(left);   // D->E->F->G
  repeat(2){follow_line(right); cross_line(right);};   // G->H->I
  follow_line(right); turn_right(right);   // I->J
  follow_line(right);   // J->K
  ball_catch();   // K->L->ボールをつかむ
  follow_line(right); cross_line(right);   // L->K
  follow_line(right);   // K->M
  shoot();   // シュート
  go_straight; Wait(1500);   // M->A
 }

*まとめ [#l45d68f0]


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