2018a/Member

目次

課題2

下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。

コース

黒線の幅は20mm。図の中の寸法の単位はcmで、黒線についてはその真ん中からの距離である。

2018a-mission2.png

ミッション

次のコースで黒い線に沿って動き、350mlの空き缶(黄色で表示)を移動させるロボットを製作せよ。

選択したコース

   Aをスタート
   Bを右折
   Jで一時停止の後、Yの空き缶をキャッチしてJに戻る
   JからKに向かい、Kを直進
   Lを直進
   Iを左折
   Hで一時停止の後、左折
   Gで一時停止の後、右折
   Fで一時停止の後、右折
   Eを直進
   Dで一時停止の後、空き缶をXに置いてDに戻り、Cに向かう
   Cで一時停止の後、直進
   Bを直進
   Aで停止

(一時停止の指定がある場所は、1秒間停止する)

ロボットの説明

全体の構造

普通のどの方向にも動けるロボットを少し改良して小型化し、左右のタイヤの間に光センサーを取り付け、黒いラインに沿って動けるようにした。

ロボットの右上の部分に3つ目のモーターをつけ、缶を運ぶための枠を上げたり下げたりできるようにした。

下の写真がロボット全体の写真である。

IMG_0068.JPG

動力(タイヤ)部分

モーター二つを平行に取り付け、その間に光センサーを取り付けた。光センサーはタイヤに近づけすぎても明るさは正確に測れず、遠ざけすぎてもできないので、明るさをより精密に観測できかつ、正確なライントレースが可能となるような位置に光センサーを持ってくるのは大変だった。

プログラム上でBが左のタイヤのモーター、Aが右のタイヤのモーターである。

IMG_0085.JPG

缶を移動させる部分

ロボットの前方右上の部分にモーターを取り付け、四角形の枠が上がったり下がったりできるような形にした。ただ右側にモーターを置いてしまったことで、ロボット全体の左右のバランスが悪くなってしまった。

プログラム上でこのモーターはAとしている。

缶.jpg

メインプログラムへの準備

今回のプログラムでは、条件式が満たされるまでプログラムを続ける関数を用いて、交差点を判断して止まることができるプログラムを作成した。条件には時間や明るさを観測する回数などを用いた。

プログラムの制作の前に、今回は光センサーを用いてライントレースするので、白い部分と線の部分それぞれの明るさを測定した。

\のない白部分(プログラム上のWHITE)の明るさ:48

∪の縁の外側付近(プログラム上のWB)の明るさ:45

線の縁の真上(プログラム上のBLACKWH)の明るさ:42

だの縁の内側付近(プログラム上のBLACK)の明るさ:34

ダの真上の明るさ:32

図1.jpg

この測定結果と関数を用いてプログラムを作る。

ライントレースの方法

プログラム製作の前に光センサーの明るさの値を用いてライントレースする方法を説明する。

図2.jpg

上の図のように線の左側をライントレースする場合、明るさの値が大きくなった(白の部分に近づいた)場合は線のほうに曲がり、明るさの値が小さくなった(線の中央に近づいた)場合は逆に外側に曲がるようにする。より外側またはより内側に行き過ぎてしまった場合は、より素早く旋回できるようにする(図の,筬ァ砲叛騎里砲覆襦このようにすることで、黒い線の左側沿いをトレースして進むことができるようになる。

交差点を判断する方法

上のライントレースのみの命令で続けると、交差点を認識せずに曲がってしまい直進などをすることができない。

そこで、交差点を認識するためにwhile関数を用いて、明るさが33より小さい値を一定回数観測するとその命令を終了するという式を作った。これにより、一定時間右旋回をし続けると交差点だと認識して止まることができるようになる。具体的な式は後のプログラムの説明を参照。

観測された値やその他の命令の定義

観測した明るさの値やトレースするときの旋回などの定義を行う。

#define BLACK 34
#define BLACKWH  42
#define WB 45
#define WHITE 48
#define SPEED_H 40
#define SPEED_L 35
#define OnRL(speed_R,speed_L) OnFwd(OUT_B,speed_R);OnFwd(OUT_C,speed_L);
#define go_forward  OnRL(SPEED_H, SPEED_H);
#define turn_left1  OnRL(SPEED_L, -SPEED_L);  // 左旋回
#define turn_left0  OnRL(SPEED_L, 0);         // 左折
#define turn_right0 OnRL(0, SPEED_L);         // 右折
#define turn_right1 OnRL(-SPEED_L, SPEED_L);  // 右旋回

指定された時間黒い線の右側に沿って進むプログラム

sub Rine_Trace(int Move_time) //Move_timeに入れた時間だけ黒い線の右側をライントレースする
{
    long tb=CurrentTick(); //時間をリセット
    while(CurrentTick()-tb<=Move_time){ 
        if(SENSOR_3>WHITE){
        turn_left1;
      } else if(SENSOR_3>WB){
        turn_left0;
      } else if(SENSOR_3>BLACKWH){
        go_forward;
      } else if(SENSOR_3>BLACK){
        turn_right0;
      } else {
        turn_right1;
       }
    }
   Off(OUT_BC);
}

指定された時間黒い線の左側に沿って進むプログラム

sub Line_Trace(int Move_time)  //Move_timeに入れた時間だけ黒い線の左側をライントレースする
{
    long tb=CurrentTick();
    while(CurrentTick()-tb<=Move_time){
        if(SENSOR_3>WHITE){
        turn_right1;
      } else if(SENSOR_3>WB){
        turn_right0;
      } else if(SENSOR_3>BLACKWH){
        go_forward;
      } else if(SENSOR_3>BLACK){
        turn_left0;
      } else {
        turn_left1;
       }
    }
   Off(OUT_BC);
}

交差点を認識するまで黒い線の右側に沿って進むプログラム

光センサーの明るさの値がBLACKよりも小さな値を観測する場合が200回以上続くまで(交差点を認識するまで)黒い線の右側をライントレースする。以下、用いたプログラム

sub R_line_trace()  
{
  int n=0;
  while(n<=200){
     if(SENSOR_3>WHITE){
        turn_left1;
        n=0;     //nの値をリセット
      } else if(SENSOR_3>WB){
        turn_left0;
        n=0;     //nの値をリセット
      } else if(SENSOR_3>BLACKWH){
        go_forward;
        n=0;     //nの値をリセット
      } else if(SENSOR_3>BLACK){
        turn_right0;
        n=0;     //nの値をリセット
      } else {
        turn_right1;
        n++;          //このときのみnの値を保存したままwhileの式に戻る
       }
     }
   Off(OUT_BC);
   Wait(1000);
}

交差点を認識するまで黒い線の左側に沿って進むプログラム

光センサーの明るさの値がBLACKよりも小さな値を観測する場合が200回以上続くまで黒い線の左側をライントレースする。以下、用いたプログラム

sub L_line_trace()
{
  int n=0;
  while(n<=200){
     if(SENSOR_3>WHITE){
        turn_right1;
        n=0;
      } else if(SENSOR_3>WB){
        turn_right0;
        n=0;
      } else if(SENSOR_3>BLACKWH){
        go_forward;
        n=0;
      } else if(SENSOR_3>BLACK){
        turn_left0;
        n=0;
      } else {
        turn_left1;
        n++;
       }
    }
  Off(OUT_BC);
  Wait(1000);
}

交差点で止まったあとロボットを直進・右折・左折させるプログラム

交差点を認識後、ある明るさを観測するまでタイヤを動かすという命令を行うことにより、それぞれのタイヤのスピードを変えることで左折、右折、直進を簡単にできる。交差点認識時にはロボットは黒い線の一番暗い所にいるので、明るいところに移動するようにすれば一時停止と同時に曲がったりすることができる。

黒い部分から白い部分に移行する(光センサーの値がblightに入れた数値以上になる)まで動作し続ける。

sub BK_to_WT(int blight,int B_speed,int C_speed) 
{
   while (SENSOR_3<blight){
       OnFwd(OUT_B,B_speed); 
       OnFwd(OUT_C,C_speed); 
    }
   Off(OUT_BC);
}

缶をおいた場所から黒い線上に戻るためのプログラム

途中で缶を取りに行ったり置きに行ったりするため、ロボットが完全に白い部分に言ったのちに黒い線上に戻らなければならなくなる。そこで、明るさの値が小さくなるまで動き続けるようにするプログラムを用いれば、簡単に線上に戻ることができる。

白い部分から黒い部分に移行する(光センサーの値がblightに入れた数値以下になる)まで動作し続ける。

sub WT_to_BK(int blight,int B_speed,int C_speed) 
{
   while (SENSOR_3>blight){
       OnFwd(OUT_B,B_speed); 
       OnFwd(OUT_C,C_speed); 
    }
   Off(OUT_BC);
}

メインプログラム

task main()
{
    SetSensorLight(S3);     //3番ポートに光センサーを定義
    BK_to_WT(34,40,40);     //¬世襪気34になるまで左右のモーターを40%で動かす
    WT_to_BK(48,40,40);     //L世襪気48になるまで左右のモーターを40%で動かす
    Rine_Trace(3000);      //だの右側を3秒間ライントレースする
    R_line_trace();       //ジ鮑硬世鯒Ъ韻垢襪泙農の右側をライントレースする。
    BK_to_WT(48,40,-10);     //μ世襪気48になるまで左40%、右10%後ろ向きでモーターを動かす
    RotateMotor(OUT_A,-40,100); //Пο咾離癲璽拭Aを40%後ろ向きに100°回転する
    Off(OUT_A);         //Aのモーターの電源を切る
    WT_to_BK(42,0,-40);     //明るさが42になるまで右40%後ろ向きでモーターを動かす
    Rine_Trace(6000);      //線の右側を6秒間ライントレースする
    BK_to_WT(48,60,20);          //明るさが48になるまで左60%右20%でモーターを動かす」
    L_line_trace();       //交差点を認識するまで線の左側をライントレースする
    Line_Trace(1000);      //線の左側を1秒間ライントレースする
    L_line_trace();       //交差点を認識するまで線の左側をライントレースする
    Line_Trace(20000);      //線の左側を20秒間ライントレースする
    L_line_trace();              //宛鮑硬世鯒Ъ韻垢襪泙農の左側をライントレースする
    BK_to_WT(47,-25,40);     //洩世襪気47になるまで左25%後ろ向き右40%でモーターを動かす
    Line_Trace(1500);      //伽の左側を1.5秒間ライントレースする
    L_line_trace();       //蓋鮑硬世鯒Ъ韻垢襪泙農の左側をライントレースする
    BK_to_WT(48,-30,60);     //缶世襪気48になるまで左30%後ろ向き右60%でモーターを動かす
    Line_Trace(7000);            //21線の左側を7秒間ライントレースする
    BK_to_WT(48,20,60);     //22明るさが48になるまで左20%右60%でモーターを動かす
    R_line_trace();              //23交差点を認識するまで線の右側をライントレースする
    BK_to_WT(48,60,-30);         //24明るさが48になるまで左60%右30%後ろ向きでモーターを動かす
    RotateMotor(OUT_A,40,100);  //25右腕のモーターAを40%で100°回転させる
    Off(OUT_A);         //26モーターAの電源を切る
    WT_to_BK(34,-60,30);     //27明るさが34になるまで左60%後ろ向き右30%でモーターを動かす
    BK_to_WT(48,-60,30);         //28明るさが48になるまで左60%後ろ向き右30%でモーターを動かす
    Rine_Trace(10000);           //29線の右側を10秒間ライントレースする
    R_line_trace();       //30交差点を認識するまで線の右側をライントレースする
    BK_to_WT(48,60,30);          //31明るさが48になるまで左60%右30%でモーターを動かす
    Rine_Trace(7000);      //32線の右側を7秒間ライントレースする
    R_line_trace();              //33交差点を認識するまで線の右側をライントレースする
    BK_to_WT(48,40,40);          //34明るさが48になるまで左40%右40%でモーターを動かす
}                                //終
図3.jpg

課題2の反省・感想

どうしてもコース通りに行ってくれることがなく理論的には完成していてもトラブルが多かった。最終的には何とかゴールまでたどり着いたが、とても大変だった。明るさはやはり日によって変わってしまうので、毎回明るさを調節しなければならないのも大変だった。ロボット自体はすごくコンパクトにできていてよかった。プログラムに関しては、光センサーを積極的に用いてでき、急カーブや交差点の判断、直進・左折・右折などうまくできるように作れたので良かった。次回はもう少しサブルーチンを用いてできるだけメインプログラムを少なくできるようにしたい。


添付ファイル: file図3.jpg [詳細] file図2.jpg 1件 [詳細] file図1.jpg 6件 [詳細] file缶.jpg 1件 [詳細] fileIMG_0085.JPG 3件 [詳細] fileIMG_0068.JPG 1件 [詳細] fileIMG_0069.JPG 1件 [詳細] file2018a-mission2.png 2件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-07-19 (木) 19:06:01 (149d)