目次
決められたコース上をライントレースするロボット、およびプログラミングを作成する。
矢印の通りに進み、「!」のマークの場所で一時停止をする。
デフォルトのロボットをそのまま流用し、光センサーをアーム部を取り付けた。 デフォルトロボットの拡張性の良さを利用し少し無理をしたアームや光センサーの取り付けをした。
↓実際のロボットの写真
紙コップを取得し運ぶための機構である。 できるだけ大きなアームを実現しようとしたが、今回の場合それが仇となりアーム内でコップの位置が安定しないという事案が発生した。もう少しプログラミングとともに洗練することでとてもマシになる部分なので改良が望まれる部分であった。
地面に垂直に取り付けた 紙コップが光センサーの邪魔をしないようにバリアがついている できるだけセンサーを地面につけるように努力をした、、、と言いたいがほぼデフォルトのロボットの流用なのであまりオリジナリティはない。
最初に、今回のプログラミングで頻出されるプログラミングコードを定義した
#define turn_left1 OnFwd(OUT_A,50 * x); OnRev(OUT_C,20 * x); //急な左折 #define turn_left2 OnFwd(OUT_A,60 * x); OnFwd(OUT_C,40 * x); //緩やかに左折 #define turn_left3 OnRev(OUT_C,30 * x); OnFwd(OUT_A,35 * x); //超信地左旋回 #define go_forward OnFwd(OUT_AC,50 * x); //前進 #define go_back OnRev(OUT_AC,50 * x); //後進 #define turn_right2 OnFwd(OUT_A,40 * x); OnFwd(OUT_C,60 * x); //急な右折 #define turn_right1 OnRev(OUT_A,20 * x); OnFwd(OUT_C,50 * x); //緩やかに右折 #define turn_right3 OnRev(OUT_A,35 * x); OnFwd(OUT_C,30 * x); //超信地右旋回 #define turn_right4 OnFwd(OUT_C,30 * x); //信地右旋回 #define DO 523 //音の高さ(適当である) #define x 0.9 //モーター出力のかけ数 #define z 1.0 //モーター駆動時間へのかけ数 #define AD OnRev(OUT_B,30 * x); Wait(800); Off(OUT_B); //アーム部を下げる (コップをとる) #define AU OnFwd(OUT_B,30 * x); Wait(800); Off(OUT_B); //アーム部を上げる(コップを置く)
また、今回サブルーチンとして「(左・右)に沿ってライントレースを行い、次の交差点に到着したら停止して音を鳴らす」という2つのものを作成した。
右に沿ってライントレースするサブルーチン
sub IKK() { int BP = 0; while (BP < 160){ if (SENSOR_2 < 45) { turn_right1; BP++; }else{ if (SENSOR_2 < 49 ) { turn_right2; } else if (SENSOR_2 < 56 ) { go_forward; } else if (SENSOR_2 < 58) { turn_left2; } else { turn_left1; } BP = 0; } Wait(1); } Off(OUT_AC); PlayTone(DO,100); Wait(100); Wait(10); BP = 0; }
左に沿ってライントレースするサブルーチン
sub DKK() { int BP = 0; while (BP < 200){ if (SENSOR_2 < 45) { turn_left1; BP++; }else{ if (SENSOR_2 < 49 ) { turn_left2; } else if (SENSOR_2 < 56 ) { go_forward; } else if (SENSOR_2 < 57) { turn_right2; } else { turn_right1; } BP = 0; } Wait(1); } Off(OUT_AC); PlayTone(DO,100); Wait(100); BP = 0; }
今回、サブルーチンの核となっている交差点を判別するプログラミングだが、BPという変数を使用し、連続して黒い線上にいる時間を計測、BPがある一定の値を超えると交差点と判別しそこでサブルーチンを停止するという仕組みをとっている。
task main() { while (SENSOR_2 > 45) { go_forward; } go_forward; Wait(600); turn_right3; Wait(300); while (SENSOR_2 > 45) { turn_left3; }
Aの枠線まで直進した後、一定量直進しさらに右を向いた後に線が見つかるまで左に回転する
SetSensorLight(S2); IKK(); turn_left2; //B Wait(300 * z); IKK(); turn_right4; //C Wait(1900 * z); while (SENSOR_2 > 45) { turn_left3; }
右側に沿ってライントレースをする
IKK(); go_forward; //F Wait(200 * z); while (SENSOR_2 > 45) { turn_left3; } IKK(); turn_right4; Wait(1700 * z); //急カーブ while (SENSOR_2 > 45) { turn_right4; } turn_right4; Wait(100); while (SENSOR_2 < 45) { turn_right4; } IKK(); Wait(1000); //E go_forward; Wait(300 * z); turn_right3; Wait(100 * z); while (SENSOR_2 > 45) { turn_right3; } turn_right3; Wait(100 * z); while (SENSOR_2 < 45) { turn_right3; }
右に沿って動くと、Fの後の2つ目のカーブを交差点として認識するので、それを利用した。
IKK(); turn_left3; //R Wait(300 * z); go_forward; Wait(210); while (SENSOR_2 > 45) { turn_left3; } turn_left3; Wait(80 * z); while (SENSOR_2 < 45) { turn_left3; } turn_left3; Wait(600 * z); go_forward; Wait(300 * z); DKK(); //P
R部での交差点認識が鬼門となった。また、R地点でで右沿いのライントレースから左沿いのライントレースにシフトしている。 円をトレースするときは内周より外周で回ったほうが都合がいいためだ。
turn_right3; Wait(1750 * z); //coppu1 go_forward; Wait(150); Off(OUT_AC); AD; Off(OUT_B); go_back; Wait(150); turn_left3; Wait(1950 * z); turn_right3; Wait(200 * z); go_forward; Wait(500 * z); while (SENSOR_2 > 45) { turn_right3; } Off(OUT_ABC); PlayTone(DO,100); Wait(100); PlayTone(DO,100); Wait(100); Wait(3000);
右を向きX地点にあるコップを取得し原点回帰する
DKK(); Wait(1000); //Q→S turn_right3; Wait(400); go_forward; Wait(300); while (SENSOR_2 > 45) { turn_left3; }
S地点にて、円Yを回るときはコップを置く関係上外周を回るほうがいいため、左沿いから右沿いにシフトするための行動をとった。
IKK(); Wait(1000); //S2度目 turn_left3; Wait(3000 * z); //koppu2 go_forward; Wait(500); Off(OUT_AC); AU; go_back; Wait(500); turn_right3; Wait(2500 * z); Off(OUT_ABC); Wait(1000); turn_left3; Wait(100); go_forward; Wait(600); while (SENSOR_2 > 45) { turn_left3; }
二度目に地点Sに差し掛かった時に後ろを向きYにコップを置いて、回帰する。
IKK(); Wait(1000); //F OnFwd(OUT_A,20); OnRev(OUT_C,60); Wait(200 * z); OnFwd(OUT_A,60); OnRev(OUT_C,1); Wait(800 * z); DKK(); Wait(1000); //C OnFwd(OUT_C,40); Wait(1700 * z); OnRev(OUT_A,30); OnRev(OUT_C,30); Wait(1700 * z); DKK(); turn_right3; Wait(200 * z); OnFwd(OUT_C,50); OnFwd(OUT_A,50); //D,ゴールへ Wait(300 * z); }
F地点で右沿いから左沿いのライントレースへと変化させている。 このほうがF地点で超信地旋回する際によりコースとロボットの向きが水平になり、ライントースの安定性が増す。
ライントレース自体は完璧であったが、コップの運送において大きな失敗をしてしまい、本番では一発で成功させることができたなった。
上の通り、ライントレースのみでの成功率はほぼ100%であった。が、コップの取得についてプログラミングの作成が難しく、試行ごとのズレも大きく明確な打開策がないまま本番を迎えてしまった。 次回の課題でその打開策が見つかるように努力したい。