*目次 [#b782d0ee]
#contents


*課題について [#yf9b9e75]
課題については[[課題2>2017a/Mission2]]を参照。
課題については[[課題2>2017a/Mission2]]を参照。コースはE地点直進コース。


*ロボットについて [#m8075db9]
 今回の課題ではロボットの大きさ制限(幅15cm長さ18cm以内)があったため、説明書に載っている基本の形を少し改良して収まるようにした。その際、後輪の位置によって機体の角度が微妙に変わるため、光センサーを完全には固定せず、常に地面に接するようにした。地面に接することで、より正確なライン判断にもつながっている。

 また、今回も収納しやすいように分解を容易にできるようにし、ケースへの収納や機体の復元を簡単にしている。


*プログラムについて [#s4fe308e]
**ライントレース用サブルーチン [#m65ce6d9]
私のコースはE地点直進コースで、最初のE地点を判断する必要がないため、黒線の左側の境目をトレースするようにした。

黒線の値を測ると画像のようになったため、以下のようにしきい値を定義した。
 #define THRESHOLD 44
また、黒線の境目から大幅にそれた場合は両方のタイヤを回転させ、旋回するようにしたため、以下の5つの動きを定義した。モーターの速度はトレースの正確さを高めるために遅めに設定した。
 #define SPEED_1 20 // ライントレース用
 
 #define go_stright OnFwd(OUT_BC,SPEED_1);Wait(STEP);Off(OUT_BC); // 直進
 #define turn_right_1 OnFwd(OUT_C,SPEED_1);Wait(STEP);Off(OUT_C); // 右折
 #define turn_right_2 OnFwd(OUT_C,SPEED_1);OnRev(OUT_B,SPEED_1);Wait(STEP);Off(OUT_BC); // 右旋回
 #define turn_left_1 OnFwd(OUT_B,SPEED_1);Wait(STEP);Off(OUT_B); // 左折
 #define turn_left_2 OnFwd(OUT_B,SPEED_1);OnRev(OUT_C,SPEED_1);Wait(STEP);Off(OUT_BC); // 左旋回
次に、直角・交差点に差し掛かった時にはライントレースのサブルーチンから抜けるようにするために最も黒い値である「33」が、nMax回連続すれば、繰り返しが終わるようにした。

コースでの試運転を続けた結果、150回の連続が妥当だと判断したため、nMaxを以下のように定義した。
 #define nMax 150
前回の課題では使わなかったサブルーチンで以下のようなプログラムを組んだ。
 sub Line_tolesu_left() // 左側のライントレース用サブルーチン
 {
   SetSensorLight(S3);
   int n=0;
     while (n <= nMax) {
       if (SENSOR_3 < THRESHOLD-11) {
         turn_left_2;
         n++; // カウントを増やす
       } else {
         if (SENSOR_3 < THRESHOLD-6) {
           turn_left_1;
         } else if (SENSOR_3 < THRESHOLD+6) {
           go_stright;
         } else if (SENSOR_3 < THRESHOLD+11) {
           turn_right_1;
         } else {
           turn_right_2;
         }
         n=0; //回数リセット
       }
     }
     Off(OUT_BC);
 }

*プログラム全体 [#e6c91527]
ロボットに送信したプログラムは以下の通り
 #define THRESHOLD 44 // しきい値
 
 #define SPEED_1 20 // ライントレース用
 #define SPEED_2 30 // 交差点用
 #define STEP 1
 #define nMax 150
 
 #define go_stright OnFwd(OUT_BC,SPEED_1);Wait(STEP);Off(OUT_BC); // 直進
 #define turn_right_1 OnFwd(OUT_C,SPEED_1);Wait(STEP);Off(OUT_C); // 右折
 #define turn_right_2 OnFwd(OUT_C,SPEED_1);OnRev(OUT_B,SPEED_1);Wait(STEP);Off(OUT_BC); //  右旋回
 #define turn_left_1 OnFwd(OUT_B,SPEED_1);Wait(STEP);Off(OUT_B); // 左折
 #define turn_left_2 OnFwd(OUT_B,SPEED_1);OnRev(OUT_C,SPEED_1);Wait(STEP);Off(OUT_BC); // 左旋回
 
 float GetAngle(float d) // 距離dからタイヤの回転数を計算する関数
 {
   const float diameter = 2.7; // タイヤの半径
   const float pai=3.1415; // 円周率
   float ang = d/(2*diameter*pai)*360.0; // 角度を計算する
   return ang;
 }
 
 sub START() // 最初の四角の中から出るサブルーチン
 {
   int angleA = GetAngle(5); // 5.0cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleA); // 指定した角度でモータを回転
 }
 
 sub Line_tolesu_left() // 左側のライントレース用サブルーチン
 {
   SetSensorLight(S3);
   int n=0;
     while (n <= nMax) {
       if (SENSOR_3 < THRESHOLD-11) {
         turn_left_2;
         n++; // カウントを増やす
       } else {
         if (SENSOR_3 < THRESHOLD-6) {
           turn_left_1;
         } else if (SENSOR_3 < THRESHOLD+6) {
           go_stright;
         } else if (SENSOR_3 < THRESHOLD+11) {
           turn_right_1;
         } else {
           turn_right_2;
         }
         n=0; //回数リセット
       }
     }
     Off(OUT_BC);
 }
 
 sub Line_tolesu_right() // 右側のライントレース用サブルーチン
 {
   SetSensorLight(S3);
   int n=0;
     while (n <= nMax) {
       if (SENSOR_3 < THRESHOLD-11) {
         turn_right_2;
         n++;
       } else {
         if (SENSOR_3 < THRESHOLD-6) {
           turn_right_1;
         } else if (SENSOR_3 < THRESHOLD+6) {
           go_stright;
         } else if (SENSOR_3 < THRESHOLD+11) {
           turn_left_1;
         } else {
           turn_left_2;
         }
         n=0; //回数リセット
       }
     }
     Off(OUT_BC);
 }
 
 sub FGH() // F,G,H用サブルーチン
 {
   PlaySound(SOUND_UP);
   int angleB = GetAngle(1); // 1.0cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleB); // 指定した角度でモータを回転
   int angleC = GetAngle(8.79); // 8.79cm進むのに必要な回転角度
   RotateMotor(OUT_B,SPEED_2,angleC); // 指定した角度でモータを回転
   RotateMotor(OUT_C,SPEED_2,-angleC);
 }
 
 sub QR() // Q,2回目のR用サブルーチン
 {
   Wait(1000);
   PlaySound(SOUND_DOWN);
   int angleD = GetAngle(1); // 1.0cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleD); // 指定した角度でモータを回転
   int angleE = GetAngle(8.79); // 8.79cm進むのに必要な回転角度
   RotateMotor(OUT_B,SPEED_2,angleE); // 指定した角度でモータを回転
   RotateMotor(OUT_C,SPEED_2,-angleE);
 }
 
 sub RS() // R,2回目のS用サブルーチン
 {
   PlaySound(SOUND_UP);
   int angleF = GetAngle(4); // 4cm進むのに必要な回転角度
   RotateMotor(OUT_C,SPEED_2,angleF); // 指定した角度でモータを回転
 }
 
 sub SP() // S,P用サブルーチン
 {
   PlaySound(SOUND_UP);
   int angleG = GetAngle(10); // 10cm進むのに必要な回転角度
   RotateMotor(OUT_B,SPEED_2,angleG); // 指定した角度でモータを回転
 }
 
 sub Curve() // 急カーブ用サブルーチン
 {
   int angleH = GetAngle(3); // 3cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleH); // 指定した角度でモータを回転
 }
  
 sub T() // T用サブルーチン
 {
   Wait(1000);
   PlaySound(SOUND_DOWN);
   int angleI = GetAngle(2.5); // 2.5cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleI); // 指定した角度でモータを回転
 }
 
 sub E() // E用サブルーチン
 {
   Wait(1000);
   PlaySound(SOUND_DOWN);
   int angleJ = GetAngle(1); // 1cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleJ); // 指定した角度でモータを回転
   int angleK = GetAngle(8.79); // 8.79cm進むのに必要な回転角度
   RotateMotor(OUT_B,SPEED_2,angleK); // 指定した角度でモータを回転
   RotateMotor(OUT_C,SPEED_2,-angleK);
 }
 
 sub GOAL() // 最初の四角の中に入るサブルーチン
 {
   int angleL = GetAngle(1); // 1cm進むのに必要な回転角度
   RotateMotor(OUT_C,SPEED_2,angleL); // 指定した角度でモータを回転
   int angleM = GetAngle(17); // 17cm進むのに必要な回転角度
   RotateMotor(OUT_BC,SPEED_2,angleM); // 指定した角度でモータを回転
 }
 
 task main()
 {
   START();
   Line_tolesu_left();
   FGH();
   Line_tolesu_left();
   QR();
   Line_tolesu_left();
   RS();
   Line_tolesu_left();
   SP();
   Line_tolesu_left();
   FGH();
   Line_tolesu_left();
   Curve();
   Line_tolesu_right();
   Curve();
   Line_tolesu_left();
   FGH();
   Line_tolesu_left();
   T();
   Line_tolesu_left();
   T();
   Line_tolesu_left();
   QR();
   Line_tolesu_left();
   RS();
   Line_tolesu_left();
   SP();
   Line_tolesu_left();
   E();
   Line_tolesu_left();
   GOAL();
 }


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