#contents
*課題について [#f729ca33]

*ロボットの説明 [#h1a6f92b]
**ロボット全体 [#f4876158]

ベースはそのまま使用し、前方の光センサーを少しタイヤ近づけました。
#ref(2016a/Member/kurokouchi/Mission2/01.jpg,100%,01)

**ロボットの改良 [#yaaaca9a]

ロボットの後ろタイヤを外し、カーブを曲がりやすくしました。
#ref(2016a/Member/kurokouchi/Mission2/03.jpg,100%,01)

カーブを曲がりやすくしたことで短い区間でも機体の姿勢を戻すことが出来る様になりました。
*プログラムの説明 [#s30e530a]

#ref(2016a/Member/kurokouchi/Mission2/04.jpg,100%,01)
**基本的な定義 [#y54b4306]

しかし、機体が左右に細かく動くためタイヤが外れやすくなりました。また、交差点をカーブとして認識することが多いことなど安定性があまりないため上の機体の状態に戻しました。
***定数の定義 [#mc5e2d5a]

*プログラムの説明 [#s30e530a]
 #define CROSS_TIME 40
 #define BALANCE_TIME 40

- CROSS_TIME:交差点判別時間
~ 黒部分がCROSS_TIMEより続いたら交差点として判別する。
- BALANCE_TIME:姿勢制御用時間
~ 境界部分がBALANCE_TIMEより続いたら機体がまっすぐとして判別する。

***マクロの定義 [#ca9f59fc]

基本動作のマクロです。

 #define roll_left OnRev(OUT_A); OnFwd(OUT_C); //左回転
 #define turn_left OnFwd(OUT_C); Off(OUT_A); //左旋回
 #define go OnFwd(OUT_A); OnFwd(OUT_C); //前進
 #define turn_right OnFwd(OUT_A); Off(OUT_C); //右旋回
 #define roll_right OnFwd(OUT_A); OnRev(OUT_C); //右回転
 #define back OnRev(OUT_A); OnRev(OUT_C); Wait(200); Off(OUT_AC); //後進

交差点判別後のマクロです。

 #define top OnRev(OUT_C); OnFwd(OUT_A); Wait(CROSS_TIME); OnFwd(OUT_AC); Wait(10);
 #define left OnRev(OUT_A); OnFwd(OUT_C); Wait(20);
 #define right OnRev(OUT_C); OnFwd(OUT_A); Wait(80); OnFwd(OUT_AC); Wait(20);
 #define bottom OnRev(OUT_C); OnRev(OUT_AC); Wait(100); Off(OUT_AC);

- #define top:前進

#ref(2016a/Member/kurokouchi/Mission2/08.png,100%,01)

角度を戻してそのまま直進する。


- #define left:左折

#ref(2016a/Member/kurokouchi/Mission2/07.png,100%,01)

角度を戻してそのままライントレースさせる。


- #define right:右折

#ref(2016a/Member/kurokouchi/Mission2/09.png,100%,01)

角度を右寄りにして外側の線に機体を移動する。



**ライントレース [#y54b4306]
線の左側境界部分をトレースするプログラムです。

光センサーでの色判別は
今回の課題ではライントレースでの移動をスムーズにするために、左右の境界部分のライントレースプログラムを作成した。

- 白部分・・・・光センサーの値:52以降 
- 弱白部分・・・光センサーの値:50以降〜52以下 
- 境界部分・・・光センサーの値:42以降〜50以下 
- 弱黒部分・・・光センサーの値:38以降〜42以下 
- 黒部分・・・・光センサーの値:38未満 
***光センサーでの色判別について [#l08c4391]

とする。
- 白部分・・・・・光センサーの値:53以降 
- 弱白部分・・・光センサーの値:52以降〜53以下 
- 境界部分・・・光センサーの値:44以降〜52以下 
- 弱黒部分・・・光センサーの値:41以降〜44以下 
- 黒部分・・・・・光センサーの値:41未満 

タイマーについては
***タイマーについて [#t320a82e]

- FastTimer(0):交差点判別用のタイマー
~ 光センサーが黒部分の判定をしている時にカウントをして、0.3秒以上続いたら交差点として判別する。また、黒部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。
~ 光センサーが黒部分の判定をしている時にカウントをして、0.4秒以上続いたら交差点として判別する。また、黒部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。
- FastTimer(1):交差点誤判別防止用のタイマー
~ 小さなカーブを交差点として誤判別しないために指定秒数間交差点判別を行わないようにする。ここで、指定秒数を変数としてl_timeをグローバル変数として定義する。また、ライントレース開始時にClearTimer(1)でFastTimer(1)を初期化する。

とする。

***左境界部分のトレース [#d1357496]
 
  sub line_l(){
    int ch=0; //ループ脱出用変数
    ClearTimer(0); //交差点判別用のタイマー初期化
    ClearTimer(1); //交差点誤判別防止用のタイマー初期化
    while(ch==0) //chが0の時はループを続ける
    {
      if(SENSOR_2 > 52) //白部分 右回転
      if(SENSOR_2 > 53) //白部分 右回転
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する
        OnFwd(OUT_A);
        OnRev(OUT_C);
              roll_right;
      }
      else if(SENSOR_2 > 50) //弱白部分 右旋回
      else if(SENSOR_2 > 52) //弱白部分 右旋回
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する
        OnFwd(OUT_A);
        Off(OUT_C);
              turn_right;
      }
      else if(SENSOR_2 > 42) //境界部分 直進
      else if(SENSOR_2 > 44) //境界部分 直進
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,4); //直進部分では素早く進むために力を強めに設定する
        OnFwd(OUT_A);
        OnFwd(OUT_C);
              go;
      }
      else if(SENSOR_2 >38 ) //弱黒部分 左旋回
      else if(SENSOR_2 > 41) //弱黒部分 左旋回
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する
        OnFwd(OUT_C);;
        Off(OUT_A);
              turn_left;
      }
      else{ //黒部分 左回転
        SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する
        OnRev(OUT_A);
        OnFwd(OUT_C);
              roll_left;
      }
 
        if(FastTimer(0)>30&&FastTimer(1)>l_time){  //交差点判別
        if(FastTimer(0)>CROSS_TIME&&FastTimer(1)>l_time){  //交差点判別
         Off(OUT_AC); //車輪を止める
         PlaySound(SOUND_UP);  //音を鳴らす
         Wait(100);  //1秒待つ
         ch=1; //ループ脱出の為にchを1にする
       }
       Wait(1); //0.01秒待つ 
    }
  }

***右境界部分のトレース [#o8e077a8]

  sub line_r(){
    int ch=0; //ループ脱出用変数
    ClearTimer(0); //交差点判別用のタイマー初期化
    ClearTimer(1); //交差点誤判別防止用のタイマー初期化
    while(ch==0) //chが0の時はループを続ける
    {
      if(SENSOR_2 > 53) //白部分 左回転
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
              roll_left;
      }
      else if(SENSOR_2 > 52) //弱白部分 左旋回
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
              turn_left;
      }
      else if(SENSOR_2 > 44) //境界部分 直進
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
              go;
      }
      else if(SENSOR_2 > 41) //弱黒部分 右旋回
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
              turn_right;
      }
      else{ //黒部分 右回転
              roll_right;
      }
 
        if(FastTimer(0)>CROSS_TIME&&FastTimer(1)>l_time){  //交差点判別
         Off(OUT_AC); //車輪を止める
         PlaySound(SOUND_UP);  //音を鳴らす
         Wait(100);  //1秒待つ
         ch=1; //ループ脱出の為にchを1にする
       }
       Wait(1); //0.01秒待つ 
    }
  }

**交差点の判別 [#s1bbda60]
上記のライントレース用プログラム内の交差点判別部分について詳しく説明する。

      if(FastTimer(0)>30&&FastTimer(1)>l_time){  //交差点判別
      if(FastTimer(0)>CROSS_TIME&&FastTimer(1)>l_time){  //交差点判別
       Off(OUT_AC); //車輪を止める
       PlaySound(SOUND_UP);  //音を鳴らす
       Wait(100);  //1秒待つ
       ch=1; //ループ脱出の為にchを1にする
     }

交差点は黒部分が長く続いた時に交差点として判別するようにした。そこでタイマーを使い黒部分以外の時は以下の関数でタイマーを初期化するようにした。また交差点と判別したことが分かるように、判別したら音を鳴らすようにした。

  ClearTimer(0);

タイマーが0.3秒より長い時間が経過した時に交差点として判別する。
タイマーがCROSS_TIMEより長い時間が経過した時に交差点として判別する。CROSS_TIMEは40とする。

  if(FastTimer(0)>30)
  if(FastTimer(0)>CROSS_TIME)

しかし、上記のプログラムではカーブを交差点として誤判別してしまう事があるので、それを防ぐためにタイマーをもう一つ追加して次の指定秒数をカウントしなければ交差点と判別しないようにした。

  if(FastTimer(0)>30&&FastTimer(1)>l_time)
  if(FastTimer(0)>CROSS_TIME&&FastTimer(1)>l_time)

l_timeを上記の指定秒数として、メインプログラムで指定する。


**姿勢制御プログラム [#a7ef2032]
C,Dに置いたコップを正確に取るために、ラインを使い機体の姿勢をまっすぐにするプログラムを作成しました。

**交差点での処理 [#ve44873a]
***タイマーについて [#uae84032]

前進
- FastTimer(0):姿勢判別用のタイマー
~ 光センサーが境界部分の判定をしている時にカウントをして、タイマーがBALANCE_TIME以上になったら機体の姿勢をまっすぐとして判別する。また、境界部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。

#ref(2016a/Member/kurokouchi/Mission2/08.png,100%,01)
- FastTimer(1):ライントレース時間判別用のタイマー
~ ライントレースをする時間を指定しなければ、姿勢がまっすぐにならない場合ライントレースをし続けてしまい、C,Dに置いてあるコップをとることが出来なくなってしまうので追加しました。また、姿勢制御プログラム開始時にClearTimer(1)でFastTimer(1)を初期化する。

角度を戻してそのまま直進する。
***姿勢制御の方法 [#g5f4ea3c]

 sub top(){
   OnRev(OUT_C);
   OnFwd(OUT_A);
   Wait(40);
   OnFwd(OUT_AC);
   Wait(10);
 }
姿勢制御プログラムは、交差点判別プログラムを応用して作成しました。交差点判別プログラムとの違いは、黒部分の判定ではなく境界部分の判定であることです。

左折

#ref(2016a/Member/kurokouchi/Mission2/07.png,100%,01)
また、ラインの長さは限られているので、一定時間が経過しても姿勢がまっすぐにならなければ、一度処理を止めて後退してからまた姿勢制御プログラムを開始するようにしました。

角度を戻してそのままライントレースさせる。
***左境界部分での姿勢制御 [#la2de7ff]

 sub left(){
   OnRev(OUT_A);
   OnFwd(OUT_C);
   Wait(20);
 }
 sub balance_l(){
    int ch=0; //ループ脱出用変数
    ClearTimer(0); //姿勢判別用のタイマー初期化
    while(ch==0) //chが0の時はループを続ける
    {
          ClearTimer(1); //ライントレース時間判別用のタイマー初期化
          while(FastTimer(1)<200&&ch==0)
	  {
        if(SENSOR_2 > 53) //白部分 右回転
        {
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                roll_right;
        }
        else if(SENSOR_2 > 52) //弱白部分 右旋回
        {
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                turn_right;
        }
        else if(SENSOR_2 > 44) //境界部分 直進
        {
                go;
        }
        else if(SENSOR_2 > 41) //弱黒部分 左旋回
        {
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                turn_left;
        }
        else{ //黒部分 左回転
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                roll_left;
        }
 
          if(FastTimer(0)>BALANCE_TIME) //交差点判別
              {  
           Off(OUT_AC); //車輪を止める
           PlaySound(SOUND_UP);  //音を鳴らす
           Wait(100);  //1秒待つ
           ch=1; //ループ脱出の為にchを1にする
         }
         Wait(1); //0.01秒待つ 
      }
          if(ch==0)
          {
	    back; //後退
          }
    }
  }

右折
***右境界部分での姿勢制御 [#oa1e2b0b]

#ref(2016a/Member/kurokouchi/Mission2/09.png,100%,01)

角度を右寄りにして外側の線に機体を移動する。

 sub right(){
   OnRev(OUT_C);
   OnFwd(OUT_A);
   Wait(80);
 }

**特別な交差点の判別 [#a7ef2032]

#ref(2016a/Member/kurokouchi/Mission2/06.png,100%,01)

上の様な交差点判別するにはロボットの姿勢をすぐに戻さなければいけないが、機体の性能上判別が困難なため以下のプログラムを追加した。

  sub line_r(){
 sub balance_r(){
    int ch=0; //ループ脱出用変数
    ClearTimer(0); //交差点判別用のタイマー初期化
    ClearTimer(1); //交差点誤判別防止用のタイマー初期化
    ClearTimer(0); //姿勢判別用のタイマー初期化
    while(ch==0) //chが0の時はループを続ける
    {
      if(SENSOR_2 > 52) //白部分 左回転
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する
        OnFwd(OUT_C);
        OnRev(OUT_A);
          ClearTimer(1); //ライントレース時間判別用のタイマー初期化
          while(FastTimer(1)<200&&ch==0)
	  {
        if(SENSOR_2 > 53) //白部分 左回転
        {
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                roll_left;
        }
        else if(SENSOR_2 > 52) //弱白部分 左旋回
        {
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                turn_left;
        }
        else if(SENSOR_2 > 44) //境界部分 直進
        {
                go;
        }
        else if(SENSOR_2 > 41) //弱黒部分 右旋回
        {
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                turn_right;
        }
        else{ //黒部分 右回転
          ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化
                roll_right;
        }
 
          if(FastTimer(0)>BALANCE_TIME) //交差点判別
              {  
           Off(OUT_AC); //車輪を止める
           PlaySound(SOUND_UP);  //音を鳴らす
           Wait(100);  //1秒待つ
           ch=1; //ループ脱出の為にchを1にする
         }
         Wait(1); //0.01秒待つ 
      }
      else if(SENSOR_2 > 50) //弱白部分 左旋回
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する
        OnFwd(OUT_C);
        Off(OUT_A);
      }
      else if(SENSOR_2 > 42) //境界部分 直進
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,4); //直進部分では素早く進むために力を強めに設定する
        OnFwd(OUT_A);
        OnFwd(OUT_C);
      }
      else if(SENSOR_2 >38 ) //弱黒部分 右旋回
      {
        ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化
        SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する
        OnFwd(OUT_A);;
        Off(OUT_C);
      }
      else{ //黒部分 右回転
        SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する
        OnRev(OUT_C);
        OnFwd(OUT_A);
      }
 
        if(FastTimer(0)>30&&FastTimer(1)>l_time){  //交差点判別
         Off(OUT_AC); //車輪を止める
         PlaySound(SOUND_UP);  //音を鳴らす
         Wait(100);  //1秒待つ
         ch=1; //ループ脱出の為にchを1にする
       }
       Wait(1); //0.01秒待つ 
          if(ch==0)
          {
	    back; //後退
          }
    }
  }

これによってひとつ前の交差点から線の左側をトレースしていたものを右側をトレースさせるようにした。

**最後の交差点の判別 [#v23d196e]
ゴール地点の四角の中に入るために、最後の交差点を判別したら以下の処理を実行する。

 sub last(){
   OnRev(OUT_C); //姿勢をまっすぐにする
   OnFwd(OUT_A);
   Wait(40);
   OnFwd(OUT_AC); //前進
   Wait(200); //2秒間待つ
   Off(OUT_AC); //停止 
   ClearTimer(0); //交差点判別用のタイマー初期化(初期化しなくてもよいが最後なので一応初期化)
   ClearTimer(1); //交差点誤判別防止用のタイマー初期化(初期化しなくてもよいが最後なので一応初期化)
 }

**メインプログラム [#r51b8f1f]

 task main ()
 {
 
   SetSensor(SENSOR_2, SENSOR_LIGHT);
 
    l_time=300; //次の交差点までの秒数を3秒に設定
    line_l(); //左側境界部分をトレース
    left(); //S地点を左折
    line_l(); 
    left(); //P地点を左折
    line_l(); 
    top(); //Q地点を直進
    l_time=700; //交差点誤判別防止用秒数を7秒に設定
    line_l();
    top(); //Q地点を直進
    l_time=300; //交差点誤判別防止用秒数を3秒に設定
    line_l();
    right(); //R地点を右折
    line_r(); //右側境界部分をトレース
    left(); //P地点を左折
    l_time=700; //交差点誤判別防止用秒数を7秒に設定
    line_l();
    last(); 
 
 }


*課題結果 [#i72ce040]

課題コースはC地点 → S左折 → P左折 → Q直進 → Q直進 → R右折 → P左折 → A地点のコースです。
#ref(2016a/Member/kurokouchi/Mission2/05.png,100%,01)

C地点からA地点までのタイムは1分10秒でした。

*反省・感想 [#af5aefdb]
C地点からA地点までのタイムは1分10秒で到達タイムが1分切れなかったことが残念でした。しかし、到達率がほぼ10割で、安定性のあるプログラムが書けたことはよかったです。


今回の課題から光センサーを使い始めたので一つ一つの動作を時間指定しなくてよくなった部分があり電池の残量などによる動作の不安定さがなくなった分、プログラムが複雑になったと感じました。


また、機体の都合で増やした処理もあったのでロボット本体にもう少し工夫した方が良かったと思いました。次回の課題ではプログラムだけではなくロボットにも工夫したいです。


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