目次
上の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成する。
次のいずれかの経路を黒い線にそって動くロボットを作成する (他のメンバーとは別の経路になるようにする)。
Aスタート
E直進
F(SOUND_UP)
Q一時停止(SOUND_DOWN)&左折
R直進(SOUND_UP)
S左折(SOUND_UP)
G(SOUND_UP)
H(SOUND_UP)
T一時停止(SOUND_DOWN)&直進
T一時停止(SOUND_DOWN)&直進
R一時停止(SOUND_DOWN)&左折
S直進(SOUND_UP)
P左折(SOUND_UP)
E一時停止(SOUND_DOWN)&左折
A停止(SOUND_DOWN)
E右折(SOUND_UP)
P一時停止(SOUND_DOWN)&左折
Q(SOUND_UP)&直進
R(SOUND_UP)&左折
T一時停止(SOUND_DOWN)&直進
T一時停止(SOUND_DOWN)&直進
H(SOUND_UP)
G(SOUND_UP)
S一時停止(SOUND_DOWN)&左折
P直進(SOUND_UP)
Q左折(SOUND_UP)
F(SOUND_UP)
E直進
A停止(SOUND_DOWN)
なるべく速く正確に動くロボットになるように工夫すること。
一時停止の交差点および丁字路ではSOUND_DOWNを鳴らした後、1秒間停止すること。
直角コーナーおよび一時停止が不要は丁字路ではSOUND_UPを鳴らし、停止しないで進むこと。
ロボットはサイズは、幅15cm長さ18cm以内とする(高さは無制限)。
交差点、丁字路、直角コーナーについては、差し掛かった時点で判別するものとし、
予め設定した走行時間のみで判定したり、走行距離のみで判定してはならない。
ペアの友達と話し合って自分はE地点直進コースに決定した。
NXTの組み立てガイドに掲載されている通りのロボットを組み立て、光センサーを取り付けた。
進行方向右側の車輪をCスロット、左側の車輪をAスロットに接続し、光センサーを2スロットに取り付けた。
光センサーができるだけ地面に近くなるように取り付けた。
E~F,G~H地点の間にある急カーブを曲がり切ることが困難であるので、ロボットのタイヤを左右別々に動かすことでロボットの回転軸をずらして曲がり切ることができるようにプログラミングをする。
基本的に黒線左側をライントレースして行き、最大回数によって交差点を認識するが、G~H地点とT~T地点は右側をライントレースすることで交差点の誤認識を避ける。
#define WHITE 61 //域値を4つ用意。GLAYOはGLAYIより白い域に近い。 #define GLAYO 49 #define GLAYI 43 #define BLACK 33
光センサーを使用して実際に数値を確かめて域値を決定した。
#define GS OnFwd(OUT_AC,50); // 直進 #define curve_left OnFwd(OUT_A,-25);OnFwd(OUT_C,50); // 左旋回 #define turn_left OnFwd(OUT_A,25);OnFwd(OUT_C),50; // 左折 #define turn_right OnFwd(OUT_A,50);OnFwd(OUT_C,25); // 右折 #define curve_right OnFwd(OUT_A,50);OnFwd(OUT_C,-25); // 右旋回 #define tMAX 200 //最大回数
旋回時は左右のタイヤが前後逆に動くので、スピードのバランスを考えた。
#define corner curve_left;Wait(100);Off(OUT_AC);PlaySound(SOUND_UP);t0 = CurrentTick(); //F,G地点 #define crossA curve_left;Wait(100);Off(OUT_AC);PlaySound(SOUND_DOWN);t0 = CurrentTick(); //交差点通過時 #define crossB curve_right;Wait(100);Off(OUT_AC);PlaySound(SOUND_UP);t0 = CurrentTick(); //交差点通過時無視 #define fin curve_right;Wait(100);Off(OUT_AC); //ゴール
task LT() //左側ライントレース { SetSensorLight(S2); long t0=CurrentTick(); while (CurrentTick()-t0<tMAX) { if (SENSOR_2 <= BLACK ) { curve_left;t0 = CurrentTick(); } else if (SENSOR_2 <= GLAYI) { turn_left;0 = CurrentTick(); } else if (SENSOR_2 <= GLAYO) { GS;0 = CurrentTick(); } else if (SENSOR_2 <= WHITE) { turn_right;0 = CurrentTick(); } else { curve_right; } } } Off(OUT_AC);
task LTR() //右側ライントレース { SetSensorLight(S2); long t0=CurrentTick(); while (CurrentTick()-t0<tMAX) { if (SENSOR_2 <= BLACK ) { curve_right;0 = CurrentTick(); } else if (SENSOR_2 <= GLAYI) { turn_right;0 = CurrentTick(); } else if (SENSOR_2 <= GLAYO) { GS;0 = CurrentTick(); } else if (SENSOR_2 <= WHITE) { turn_left;0 = CurrentTick(); } else { curve_left; } } } Off(OUT_AC);
task main() { SetSensorLight(S2); //光センサー稼働 long t0 = CurrentTick(); //時間定義 LTL; //スタート~F地点 corner; //F地点 LTL; //F地点~Q地点 crossA; //Q地点 LTL; //Q地点~S地点 crossB; //S地点通過 LTL; S地点~G地点 corner; //G地点 LTR; //G~H地点 corner; //H地点 LTR; //H~T地点 crossA; //T地点 LTR; //T~T地点 crossA; //T地点 LTL; //T~R地点 crossA; ///R地点 LTL; //R~S地点 crossB; //S地点 LTL; //S~P地点 corner; //P地点 LTL; //P~E地点 corner; //E地点 LTL; //E~A地点 fin; //A地点 }
自分でプラグラミング時の定義、サブルーチンを考えないと上手くライントレースができないため非常に困難な課題であった。 最初は急カーブを交差点認識してしまい、左側ライントレースと右側ライントレースを上手に使い分けることに苦労した。 またタイマーの最大値を自分で発見することにもかなりの時間を割いた。
ちなみに課題とは無関係であるが、ロボットの音階を自分たちで計算して、半音を見つけることで好きな曲をロボットを走らせながら鳴らすことができてロボットの多機能さを実感した。