- 追加された行はこの色です。
- 削除された行はこの色です。
*目次 [#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();
}