下の図のようなコースを書くチームで作成し、「ミッション」を遂行するためのロボットを作成せよ。
黒い線にそって動くロボットを作成する。
交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止すること。
二つのコースがあり、私は
A地点から出発 → B → C(直進) → D(一時停止の後、直進) → E → F → G(一時停止の後、右折) → H → I → J(右折) → K(左折) → L(ピンポン玉をつかむ) → K(直進) → M(一時停止) → シュート→ A地点に入る(ゴール)
というコースを選んだ。
下の図で青→緑の矢印の順で動き、緑の矢印はピンポン玉を運んでいる。
ピンポン玉をつかむ機構を取り付けたことで、RISの本体を後ろに下げることになったが、RISを横向きに取り付けることでロボットのバランスをとった。
光センサーはタイヤのすぐ前に設置した。センサーをタイヤに近づけることで、ロボットが、正確にライントレースするようにした。
タイヤを4つではなく、3つにすることで、旋回しやすく動きやすくした。摩擦を少なくするために、ゴムを外したホイールのみを取り付けた。車軸を固定しなことで、さらに摩擦を減らすことができ、スムーズに動くようになった。
アームはピンポン玉を挟むような形にした。
異なる方向にアームが回転し、動くようにするために、ギアの配置を工夫した。 また、コンパクトに見えるように、ギアを上下に配置し、アームの位置の調整のため、二つ並んだギアの下にグレーのパーツをかませた。
また、前回同様、アームの開き具合の微調節のために、青いパーツを取り付けて、簡単に閉じたり開いたりできるようにした。
コースの関係上右側のふちをライントレースするようにした。 光センサーの下の明るさを値として検知して、検出された値によって決められた動作を行わせることで、ライントレースをする。
私たちは、以下のように5段階に値を決めた。
以下が、その値で行う動作である。
ライントレースをしていて交差点に進入すると、黒が一定時間続く。これを利用し、黒が一定時間続いたら停止するプログラムを作った。
普通の交差点と、円形交差点では、下の図のように黒の部分を走る距離が変わる。そのためグローバル変数を使って、連続して黒になっている時間を計り、普通の交差点では0.20秒黒は続いたら、円形交差点では、0.15秒黒が続いたら停止するようにプログラムを作成した。
上で説明した動作を行うために以下のマクロを定義した。
int t;
#define kuro 41 //真っ黒 #define kurohai 43 //黒 #define hai 46 //灰 #define shirohai 48 //白
#define go_ahead OnFwd(OUT_AC); //直進 #define turn_left SetPower(OUT_AC,3);Off(OUT_A);OnFwd(OUT_C); //左曲がり #define turn_right SetPower(OUT_AC,3);Off(OUT_C);OnFwd(OUT_A); //右曲がり #define Uturn_left SetPower(OUT_AC,3);OnRev(OUT_A);OnFwd(OUT_C); //左旋回 #define Uturn_right SetPower(OUT_AC,3);OnRev(OUT_C);OnFwd(OUT_A); //右旋回
#define kyukei Wait(100); //1秒停止
#define STEP 1
下にライントレースに使用したサブルーチンを示す。
円形交差点と普通の交差点では、前者のほうが走行距離が短くなり、交差点と認識しないという問題が発生したため、グローバル変数tを使い、黒が連続して続く時間を計り、値を円形交差点ではt=15、普通の交差点ではt=20と変化させて対応した。
sub follow_line1() { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); //タイマー0をリセット while(FastTimer(0)<t) //タイマーの値がt未満の間繰り返す { if(SENSOR_2<kuro) { Uturn_right; //真っ黒なら右旋回せよ } else if(SENSOR_2<kurohai) { turn_right;ClearTimer(0); //黒なら右に曲がれ } else if(SENSOR_2<hai) { go_ahead;ClearTimer(0); //灰なら直進せよ } else if(SENSOR_2<shirohai) { turn_left;ClearTimer(0); //白なら左に曲がれ } else { Uturn_left;ClearTimer(0); //真っ白なら左旋回せよ } Wait(STEP); } Off(OUT_AC); //止まれ kyukei; //一秒停止 }
グローバル変数tで指定した時間だけ止まることなくライントレースを続けるためのプログラムで、半径の小さいカーブなどで、交差点と誤認識することの防止などのために作成した。
sub follow_line2() { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); //タイマー0をリセットする while(FastTimer(0)<t) //タイマーの値がt未満の間繰り返す { if(SENSOR_2<kuro) { Uturn_right; //真っ黒なら右旋回せよ } else if(SENSOR_2<kurohai) { turn_right; //黒なら右に曲がれ } else if(SENSOR_2<hai) { go_ahead; //灰なら直進せよ } else if(SENSOR_2<shirohai) { turn_left; //白なら左に曲がれ } else { Uturn_left; //真っ白なら左旋回せよ } Wait(STEP); } Off(OUT_AC); //止まれ }
交差点を認識し、停止している車体に交差点を直進させるためのプログラムで、動きは上の通りである。
sub cross_line() { SetSensor(SENSOR_2,SENSOR_LIGHT); while(SENSOR_2<hai) { go_ahead; //黒ければ直進せよ } Off(OUT_AC); kyukei; //一時停止 while(SENSOR_2>hai) { Uturn_left; //白ければ左旋回せよ } Off(OUT_AC); kyukei; //一時停止 }
交差点を右折するためのプログラムで、白になるまで右旋回し、止まるようになっている。
sub kousaten_turn_right() { SetSensor(SENSOR_2,SENSOR_LIGHT); while(SENSOR_2<shirohai) { Uturn_right; //黒ければ右旋回せよ } Off(OUT_AC); //止まれ kyukei; //一秒停止 }
交差点を左折するためのプログラムで、黒ければ直進し、白くなったら止まり、その後、また黒くなるまで左旋回するようになっている。
sub kousaten_turn_left() { SetSensor(SENSOR_2,SENSOR_LIGHT); while(SENSOR_2<hai) { go_ahead; //黒ければ直進せよ } Off(OUT_AC); kyukei; while(SENSOR_2>hai) { Uturn_left; //白ければ左旋回せよ } Off(OUT_AC); //止まれ kyukei; //一秒停止 }
モーターの回転速度ゆっくりにするために、SetPowerを使用した。
sub pinpon_catch() { SetPower(OUT_B,1); OnRev(OUT_B); Wait(30); //アームを閉じる Off(OUT_B); //止まる kyukei; //一時停止 }
ピンポン玉を放す前、交差点を認識して止まるようなプログラムになっているため、止まった際に少し右を向いているので、それを修正するためのプログラムを書き込んだ。
また、ピンポン玉をシュートするために、少し下がるようにした。
sub shoot() { OnFwd(OUT_C); Wait(20); //左に曲がる Off(OUT_C); Wait(100); SetPower(OUT_B,1); OnFwd(OUT_B); Wait(20); //アームを開く Off(OUT_B); Wait(100); OnRev(OUT_AC); Wait(31); //後ろに下がる Off(OUT_AC); }
task main() { OnFwd(OUT_AC); //スタート Wait(80); Off(OUT_AC); kyukei; t=20;follow_line1(); //AからCへ移動 cross_line(); //CのT字路を直進する t=20;follow_line1(); //CからDへ移動 cross_line(); //Dの交差点を直進する t=20;follow_line1(); //DからEへ移動 kousaten_turn_right(); //Eを右折する t=100;follow_line2(); //EからFへ移動 t=20;follow_line1(); kousaten_turn_right(); //Fを右折する t=50;follow_line2(); //FからGへ移動 t=15;follow_line1();
円形交差点を交差点として誤認識しないように、0.9秒間は止まらないようにした。
kousaten_turn_right(); //Gを右折する t=90;follow_line2(); // GからHへ移動 t=15;follow_line1(); cross_line(); //Hを直進 t=90;follow_line2(); // HからIへ移動 t=15;follow_line1(); cross_line(); //Iを直進 t=90;follow_line2(); // IからJへ移動 t=15;follow_line1(); kousaten_turn_right(); //Jを右折する
交差点を左折してからピンポン球をつかむまでに進む秒数を計り、グローバル関数tをt=125として定めた。
t=70;follow_line2(); // JからKへ移動 t=15;follow_line1(); kousaten_turn_left(); //Kを左折する t=125;follow_line2(); //KからLからへ移動 kyukei; //一秒停止 pinpon_catch(); //ピンポン玉をつかむ
半径の小さい道があったため、交差点を誤認識しないようにするため時間制御のライントレースのプログラムを途中まで使用した。
t=20;follow_line1(); LからKへ移動 cross_line(); //KのT字路を直進する t=1000;follow_line2(); t=20;follow_line1(); //KからMまで移動
最初、ピンポン玉をはなした後、ロボットを前進させてシュートしていた、あまりにも勢いがないため、 ピンポン球をシュートするために、ピンポン球をはなした後、少し下がり、アームを閉じる力を利用してピンポン球をはじき出すように改良した。
シュートの手順は以下の通り。 1.向きを直した後
2.アームを開く
3.後ろに下がる
この写真では下がりすぎだが、ピンポン玉をはじくために少し後進させる。
4.アームを閉じる
5.シュートする
アームをとじる動作を利用してピンポン玉をはじきとばす。
以下が、ピンポン玉をシュートするためのプログラムである。
shoot(); // ピンポン玉をはなす pinpon_catch(); //ピンポン玉をはじく }
ピンポン玉をシュートした後、A地点に入るプログラムを書くのを忘れてしまったが、その他はほとんど想定通りに動かすことができた。 ただ、何度か繰り返し動かしているうちに同じように動かしているはずなのに交差点を誤認識して失敗してしまうことがあった。原因を特定できず、follow_line2というプログラムを使用しごまかしてしまった。次回は何度やっても同じように動くロボット、プログラムを作成できるようにしたい。