*目次 [#b782d0ee] #contents *課題について [#yf9b9e75] 課題については[[課題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(); }