[[2015b/Member]]
目次
#contents

*はじめに [#h31c7b26]
第二回目の課題のテーマは、「自立型ロボットによるライントレース」である。線をトレースするロボットの作成、ラインを縦80x横110の紙に描く、先生から与えられるコースを走るプログラムの製作が今回の課題である。
今回の課題において注意すべき点は4つ、
  1.ラインは2cm幅
  2.ロボットに搭載できる光センサーは1つのみ
  3.交差点の判断はその場で1秒間停止
  4.なるべく速いタイムを目指す
である。
*ロボットの説明 [#s9e6fd2a]
今回使用したロボットはこちらである。

&ref(2015b/Member/A.T.9/Mission2/IMG_2649.jpg);

このロボットは、NXTのセットに付属されている組み立て図に記載されているものである。今回の課題においては、プログラムにこだわり課題を成功させようと考えたため、ロボットの改造はしなかった。

**ロボットの全体の動作・役割 [#r1df50a8]
モーター2つと光センサー1つを搭載した基本的なロボットである。黄色い丸で囲まれたところがモーターに直結されたタイヤで、右折・左折・直進の動作をするための部分である。ポートBの回転で左折、ポートCの回転で右折、両方の回転で直進をする。そして、水色の丸で囲まれた部分が光センサーであり、今回の課題において一番重要な部分である。

&ref(2015b/Member/A.T.9/Mission2/IMG_2651.jpg);

**光センサーの説明 [#m63eace0]
ライントレースはその言葉の通りラインをたどるのだが、たどるためには最低でも黒と白の二つを判断させる必要がある。それを判断するのが”光センサー”だ。黒、白、黒、白・・・を繰り返すことで線をたどることが出来る。しかし、線をたどることはできても今回の課題は、”速さ”も要求されている。そのため、黒白の交互だけでは直進という動作がなくかなり遅くなる。それを改善するため黒と白の間にもう一つしきい値を入れることで、直進という選択肢を入れることが出来る。私のプログラムで使うしきい値の範囲は、
 37より下は黒、56より上は白、37以上56以下は黒と白の中間値
としている。


*ラインについての説明 [#kb8897f6]
これがロボットにトレースさせるラインである。

&ref(2015b/Member/A.T.9/Mission2/2015b-mission2.jpg);

この課題での交差点は線と線が交わっているところを指し、直角に曲がっているだけのところは交差点としない。

**トレース順序 [#e4c48083]
 A地点からB地点へ
 A地点 → P直進 → Q直進 → Q右折 → P右折 → Q左折 → P左折 → B地点
が私の課題である。

**私たちが描いた実際のライン [#za5b3fc5]

&ref(2015b/Member/A.T.9/Mission2/IMG_2652.jpg);


*プログラムの説明 [#j455cebb]
今回作成したプログラムの大まかな戦略は、
 1.”交差点”と”90度のコーナー”の数を数え、その時の数に応じて直進や右左折を行わせる
 2.トレースする黒線の左側通行と右側通行を使い分け、交差点をしっかりと検知

&ref(2015b/Member/A.T.9/Mission2/2015b-mission21.jpg);
赤く塗られた部分のみ黒線の右側通行をする。それ以外は黒線の左側を通行する。

**定義 [#y32c31fe]
 #define go OnFwd(OUT_BC,30);                    //直進
 #define LEFT OnFwd(OUT_B,30);OnRev(OUT_C,29);   //左に転回
 #define RIGHT OnFwd(OUT_C,30);OnRev(OUT_B,25);  //右に転回
 #define B(b) OnFwd(OUT_B,b);                    //タイヤBの動き
 #define C(c) OnFwd(OUT_C,c);                    //タイヤCの動き
 #define OFF Off(OUT_BC);                        //BCを止める
 #define sound PlaySound(SOUND_CLICK); Wait(100);//1秒間音を出す

**サブルーチン [#m2e0b497]
 sub AAA() {
   sound;       
   OFF;
   Wait(1000);
 }
このサブルーチン「AAA」は、交差点時における動作”1秒間停止”と、交差点に差し掛かったことを人間に伝えるため”音をだす”の動作が含まれる。これにより後のプログラムが短くなる。

**メインルーチン [#w8742e85]
 task main ()
 {
 
  int T=0;             
  int S=0;
T,Sの箱を作る。これは、”交差点”、”90度のコーナー”を数えるのに必要となる箱である。Tは左側通行時、Sは右側通行時における交差点・90度コーナーを数える。
 
 SetSensorLight(S3);                      //ポート3の光センサー
  long t_L=CurrentTick();                 //ここで時間の区切り t_L を作る。
 
  while(true){
 
    while(CurrentTick()-t_L<=170){
  
      if(SENSOR_3<37){
        LEFT; 
      } else if (SENSOR_3<56) {
        go;
        t_L=CurrentTick();
      } else {
        RIGHT;
        t_L=CurrentTick();
       }
      Wait(1);
     }
上記の行が今回の一番重要なところである。この行により交差点と90のコーナーを検知することが出来る。左に曲がる動作の時、37より下のしきい値が0.17秒続いたとき交差点、90度のコーナーとして検知する。
    T++;  //交差点、90度のコーナーが検知されると、ループから出されTに1が加算される。

    if (T==3) { //T=3の時は二回目のQ地点通過のため、右折動作をさせる。
      AAA();
      C(30);
      B(-30);
      Wait(500);
      go;
      Wait(320);

    } else if (T==4) { //T=4の時は二回目のP地点通過のため、右折動作をさせる。
      AAA();
      C(40);
      B(-15);
      Wait(700);
 
       long t_Z=CurrentTick();           //P地点右折後 t_Z を作る
       while(CurrentTick()-t_Z<15000){   //15秒経過するまで、黒線の左側通行を行う。
        if(SENSOR_3<37){
          LEFT;
        }else if(SENSOR_3<56){
          go;
          t_L=CurrentTick();
        }else{
          RIGHT;
          t_L=CurrentTick();
         }
        Wait(1);
        }

      OFF;            //15秒経過したら上記の動作で右に車体を振る。
      Wait(300);
      C(30);
      Wait(500);
      OFF;
      Wait(300);

       while(S<=2){        
        long t_K=CurrentTick();
        while(CurrentTick()-t_K<=175){    //黒線の右側を通行する。
         if (SENSOR_3<37) {
           RIGHT;
         }else if (SENSOR_3<56) {
           go;
           t_K=CurrentTick();
         }else{
           LEFT;
           t_K=CurrentTick();
          }
        Wait(1);
        }

      S++;   //交差点、90度のコーナーが検知されると、ループから出されSに1が代入される。
      S++;   //交差点、90度のコーナーが検知されると、ループから出されSに1が加算される。

         if(S==3){   //S=3は三回目のQ地点の通過であるため、左折の動作をさせる
           OFF;
           Wait(1000);
           B(40);
           Wait(600);
           go;
           Wait(200);

         }else{      //S=1・S=2は90度コーナーの検知のため、交差点でない動作をさせる
           C(30);
           B(-25);
           Wait(300);
          }

         t_K=CurrentTick();
       }
 

    } else if (T==5) {  //T=5は三回目のP地点の通過であるため、左折の動作をさせる。
       AAA();
       B(30);
       Wait(250);
       OFF;

    } else if (T==6) {  //T=6は交差点ではないので、交差点でない動作をさせる。
      B(30);
      C(-20);
      Wait(600);

    } else if (T==7) {  //T=7でB地点を判断しゴールである。
      OFF;
      Wait(10000);

    } else {  //交差点において直進をさせる動作である。
                         T=1の時(P地点一回目の通過時)、T=2(Q地点一回目の通過時)
      AAA();
      C(30);
      B(-30);
      Wait(200);
      go;
      Wait(300);
      OFF;

    }
   t_L = CurrentTick();
 
  }
 }

*結果 [#ba08c3af]
このプログラムでA地点からB地点まで、課題通りにトレースさせることが出来たので、成功といえるだろう。
タイムは5回連続で行い、最速は1分10秒、平均1分22秒であった。
 
*工夫点 [#nafc3d0d]
 1.右側通行と左側通行を使い分けた点。
今回の課題の中で一番苦しめられたのはQ地点三回目の左折である。交差点の前の90度コーナーを曲がってからすぐに交差点があるため、左側通行をしていると車体が斜めのまま入ってしまう。斜めに入ると交差点として検知されない。しかし、このことを左側通行・右側通行を使い分けることで改善することが出来た。T==4がその事例である。
 2.プログラムの変更、追加が簡単にできる点。
カウント式のため、交差点・90度コーナーに差し掛かった時の数を数えればすぐに変更、追加が可能である。


*悪い点・改善点 [#n50397a0]
 動きの滑らかさ
今回しきい値を2つしか作れず、3つの動作のみとなり滑らかな動きとは言えなかった。本来ならしきい値を多く作るほど動きは滑らかになり、所要時間の短縮化につながる。しかし、紙による問題が大きくそれが出来なかった。紙を曲げてしまったこと・黒線の色にむらがあることにより、しきい値の範囲に影響がでてしまった。そのため、2つのしきい値となり、滑らかな動きでなくなってしまった。時間があるならば、紙面にまで配慮し時間短縮を試みたい。


*感想 [#zb5e7ca9]
はじめのうちは線を上手くたどらせることすらできず、課題が完成するか不安だったが、一つ一つの動作を細かく見ていくことで理解が深まっていき、トレースプログラムが完成出来た。今回のこのライントレースの課題で、if,else if,else,CurrentTick()の使い方の知識がかなり深まった。これらはほかにどのように使われ、応用されているのかを学びたい。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS