[[2017a/Member]]~
目次
#contents
*課題2 [#g1e40900]
&color(red){結論から言うと確実に最後までライントレースができるロボットとプログラムを作れませんでした。};
#ref(2017a/Mission2/2017a-mission2.png,70%,課題コース) 
指定されたコースのライントレースをする。自分はE地点直進コースを選びました。詳細は[[課題2>2017a/Mission2]]を参照。


*ロボットの説明 [#v307b7eb]
**全体図 [#pe51c239]
| &ref(2017a/Member/mattu/Mission2/robo_mission2_1.jpg,50%,ロボ画像1);&br;ロボットの全体像 | &ref(2017a/Member/mattu/Mission2/robo_mission2_2.jpg,50%,ロボ画像2);&br;左側面 | &ref(2017a/Member/mattu/Mission2/robo_mission2_3.jpg,50%,ロボ画像3);&br;裏側 |
| &ref(2017a/Member/mattu/Mission2/robo_mission2_4.jpg,50%,ロボ画像4);&br;正面 | &ref(2017a/Member/mattu/Mission2/robo_mission2_5.jpg,50%,ロボ画像5);&br;光センサー取り付け部分 | &ref(2017a/Member/mattu/Mission2/robo_mission2_6.jpg,50%,ロボ画像6);&br;光センサー取り付け部分 |
センサー部以外のロボット本体は説明書に載っているデフォルトのロボットを流用。センサー取り付け部分をタイヤの軸にできるだけ近づくような構造に改良しました。こうすることで半径の小さい急カーブを曲がりやすくなりました。

しかし固定部分の構造上光センサーの取り付け部分に若干の遊びがあり、センサーが動いてしまいます。これにより光センサーの値が少しずつ変わってしまうので失敗でした。

*プログラムについて [#l23a7ada]

**プログラム概要 [#yc67d727]
ラインの左側をトレースする方法のプログラムです。コーナーや角を曲がる回数は予めわかっているので、カウンターで曲がった回数を計測して曲がり角毎に曲がり方のプログラムを書く方法を選びました。途中でどうしても曲がり角と判定してしまう急カーブがあるのでその部分もカウンターのカウントに含めています。

最後のA地点でのSOUND_DOWNを書き忘れています。
***定義とサブルーチン [#k346f72a]
 #define THRESHOLD 45  //しきい値
 #define SPEED_H 30  
 #define SPEED_L 20
 #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
 #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_H, SPEED_H);  // 大きく右に曲がる
 #define STEP 1
 #define nMAX 210  // カーブ判定の最大値
 #define short_break Off(OUT_BC); Wait(1000);
 #define CROSS_TIME 200
 #define cross_line OnRL(SPEED_L,SPEED_L);Wait(CROSS_TIME);short_break;


***メイン [#r5d93972]
交差点と角の判定には黒色を測定した回数のカウンターを利用し、カウントがnMAXを超えると曲がり角があると判定します。

 task main()
 {
   SetSensorLight(S3);
   int nOnline=0;  // 黒になった回数のカウンター
   int n=0;  // 曲がり角と判定した回数のカウンター
 
   while (true) {
     while (nOnline < nMAX) {
       if (SENSOR_3 < THRESHOLD-10) {
         turn_left1;
         nOnline++;  // 左に大きく曲がった時カウンターを増やす。
       } else {
         if (SENSOR_3 < THRESHOLD-7) {
           turn_left0;
         } else if (SENSOR_3 < THRESHOLD+7) {
           go_forward;
         } else if (SENSOR_3 < THRESHOLD+10) {
           turn_right0;
         } else {
           turn_right1;
         }
         nOnline=0;  // 黒色の判定カウンターリセット
       }
       Wait(STEP);
     }
 
     if (n==0) {  // F地点
       PlaySound(SOUND_UP);
       turn_left1; Wait(700);
       n++;
       nOnline=0;
     }
 
     else if (n==1) {  // Q地点
       PlaySound(SOUND_DOWN);
       short_break;
       turn_left0; Wait(600);
       n++;
       nOnline=0;
     }
 
     else if (n==2) {  // R地点
       PlaySound(SOUND_UP);
       turn_right0; Wait(900);
       n++;
       nOnline=0;
     }
 
     else if (n==3) {  // S地点
       PlaySound(SOUND_UP);
       turn_left1; Wait(500);
       n++;
       nOnline=0;
     }
 
     else if (n==4) {  // G地点
       PlaySound(SOUND_UP);
       turn_left1; Wait(300);
       n++;
       nOnline=0;
     }
 
     else if (n==5) {  // GH間の左急カーブを曲がり角と判定してしまうため曲がり切るための修正
       turn_left1; Wait(1200); turn_left0; Wait(1200);
       n++;
       nOnline=0;
     }
 
     else if (n==6) {  // H地点
       PlaySound(SOUND_UP);
       turn_left1; Wait(300);
       n++;
       nOnline=0;
     }
 
     else if (n==7) {  // T地点(一回目)
       PlaySound(SOUND_DOWN);
       short_break;
       turn_right1;
       cross_line;
       n++;
       nOnline=0;
     } 
 
     else if (n==8) {  // T地点(二回目)
       PlaySound(SOUND_DOWN);
       short_break;
       turn_right1; Wait(nMAX*STEP);
       cross_line;
       n++;
       nOnline=0;
     }
 
     else if (n==9) {  // R地点
       PlaySound(SOUND_DOWN);
       n++;
       nOnline=0;
     }
 
     else if (n==10) {  // S地点
       PlaySound(SOUND_UP);
       turn_right0; Wait(900);
       n++;
       nOnline=0;
     }
 
     else if (n==11) {  // P地点
       PlaySound(SOUND_UP);
       n++;
       nOnline=0;
     }
 
     else if (n==12) {  // E地点
       PlaySound(SOUND_DOWN);
       short_break;
       turn_left1; Wait(100);
       n++;
       nOnline=0;
     }
   }
 }
 
*まとめ [#db133fd6]
**なぜ完成できなかったか反省点 [#a4d115a6]
・光センサーの取り付け方  

光センサーがしっかりと固定される構造を作っておくべきでした。ほんのわずかな数値の違いでもカーブの判定等で誤差が生じるので、プログラムの数値を変えなければなりませんでした。ロボットを作り終えプログラムを書き始めてから気づいたが、たいしたことはないだろうと放置していたのが間違いだった。

・直角に曲がる時のサブルーチンを作っておくべき  

E地点直進コースの場合は左向きに直角に曲がる場所がF、G、H地点の3か所あるので、直角に曲がる場合のサブルーチンを書いておくべきでした。そうしていればプログラムも見やすくなり、数値の調整も容易だったと思います。

・電池の消耗を考慮したプログラムを作る

電池を消耗するとモーターの出力が落ちてくるのでWaitを使って時間計測するプログラムだと、ロボットの動きにも差が生じるので数値を変える必要が出てきます。最適な数値を見つけるために何度も試運転しているとどんどん電池を消耗するので、使える部分ではRotateMotorを使うべきでした。

・コースの紙は丁寧に作る

コースを作る際に黒色のラインをマジックペンで塗りましたが、塗りムラがあったため何度か塗り直しをしました。色の濃さは光センサーの計測やプログラムの数値に直結するので、最初からキチンと作っておくべきでした。

**結果 [#m552c6ac]
最後までライントレースして完走できたのは数回しかありませんでした。製作にはそれなりの時間をかけましたがプログラムがあまりすっきり書けていないので、サブルーチンや定義を面倒くさがらずに作っておけば数値の調整も容易で試行回数を減らすことができたかもしれません。

**感想 [#q7207f09]
確実に毎回ライントレースができるロボットを完成させることができなかったので、悔いが残る結果で終わりでした。課題1と違ってモーターだけではなくセンサーも使用し、ロボット自身に判断させる必要が出てきたのでプログラミングがかなり難しくなったと思いました。ペアのパートナーとはコースが異なるとプログラムも全く違うので、今回の課題は自分の力でプログラムの問題を解決しなければならないことが多く大変でしたが、光センサーを使ったプログラミングはできることが増えるので楽しかったです。


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