課題2:ライントレースカー 下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。
次のいずれかの経路を黒い線にそって動くロボットを作成する (他のメンバーとは別の経路になるようにする)。ただし、なるべく速く正確に動くロボットになるように工夫して、交差点では1秒間停止すること。
今回の僕のミッションは一人目のA地点からB地点へ移動するミッションです。
ドライブベースを元に、車幅を小さくしタイヤからセンサまでの距離を短く作りました。(戸谷くんが作ってきてくれた
モータにつながっている左右の二つのタイヤと、補助の後輪一つで支えています。 後輪はカーブを曲がる際に妨げにならないように車輪にゴムをつけず、タイヤが左右に動くように幅を持たせています。
回転軸から光センサまでの距離が長いほどモーターの回転による左右の振れ幅は大きくなります。
左右の振れ幅が大きくなると、その分左右のタイヤを止める時間が長くなるのでコースを完走するのにかかる時間が長くなってしまいます。 また、回転半径の小さいカーブでは振れ幅が大きいと交差点と誤認識してしまうことがあります。 こういったことを防ぐためにタイヤからセンサまでの距離を短くするように製作しました。
よく使うものや、後から調節するために変更しそうな値をあらかじめ定義しておきました。
/* 交差点判定を無効化する時間:3秒 */ #define STARTIME 300 /* 交差点かどうか判定する時間:220ミリ秒 */ #define CHECKCROSSTIME 22 /* 前進 */ #define fwd(OUT) Off(OUT);OnFwd(OUT) /* 後進 */ #define rev(OUT) Off(OUT);OnRev(OUT) /* 左回転 */ #define TURNLEFT rev(OUT_A);fwd(OUT_C) /* 左旋回 */ #define LEFT Off(OUT_A);fwd(OUT_C) /* 右回転 */ #define TURNRIGHT rev(OUT_C);fwd(OUT_A) /* 右旋回 */ #define RIGHT Off(OUT_C);fwd(OUT_A) /* 直進 */ #define STRAIGHT fwd(OUT_AC) /* 交差点ではないかどうか判定する式 */ #define ISNOTCROSS FastTimer(0) <= CHECKCROSSTIME || FastTimer(1) <= STARTIME
光センサの値によってタイヤの動きを変えてトレースします。 交差点を発見するとサブルーチンを終了します。 ライントレースロボットは直進と左右の旋回・回転ができるので、センサの値の範囲を五段階に区切りました。完全な白と黒の場合のセンサの値を計測すると、41(黒)と56(白)でした。 ただし、そのまま五段階に区切ると振れ幅が大きく直進の動きに収束しないので、一番よく使う直線や旋回の動作をする値の範囲を少し大きめにとって、それぞれの境界を54,51,46,43としました。
sub trace(){ /* 交差点判定用のタイマをリセットする(ここから計測を始める) */ ClearTimer(0); while(ISNOTCROSS){ /* 交差点判定を無効化している間は判定用のタイマをリセットし続ける */ if(FastTimer(1) < STARTIME){ ClearTimer(0); } if(54 <= SENSOR_2){ TURNRIGHT; }else if(51 <= SENSOR_2){ RIGHT; }else if(46 <= SENSOR_2){ STRAIGHT; }else if(43 <= SENSOR_2){ LEFT; }else { TURNLEFT; } /* 白を認識した場合、交差点判定用のタイマをリセットする */ if(44 <= SENSOR_2) ClearTimer(0); } Off(OUT_AC); Wait(100);//一秒間停止する ClearTimer(0); }
交差点は300ミリ秒直進することで交差点を直進することができます。 交差点かどうか判定するのに交差点の直前から最低でも220ミリ秒必要になりますが、その間にロボットは交差点に対して左斜めの方向へ向きます。 そのまま直進すると交差点を超えて線の左側の白い領域へ進入しますが、トレースを開始するとロボットは白を検知している間右回転するので、線を発見しトレースを続けることができます。
sub go_straight(){ STRAIGHT; Wait(30); }
ライントレースロボットはラインの左側に沿ってトレースしているため、次のトレースを再開し交差点判定を数秒間無効化するだけで左折する事ができます。 clearTimer(1)でトレースの交差点判定無効化を開始することができます。
sub turn_left(){ ClearTimer(1); }
右折は左折とは異なり、ラインの反対側なのでそのままトレースを再開するだけでは右折する事はできません。 ここでは、右折する時だけ一時的にラインの右側をトレースするようにしました。 数秒たつと左側のトレースが再開するのでラインの右側から左側へロボットが移動します。
sub turn_right(){ ClearTimer(1); while(ISNOTCROSS){ if(FastTimer(1) >= STARTIME){ ClearTimer(0); ClearTimer(1); break; } if(53 <= SENSOR_2){ TURNLEFT; }else if(50 <= SENSOR_2){ LEFT; }else if(47 <= SENSOR_2){ STRAIGHT; }else if(44 <= SENSOR_2){ RIGHT; }else { TURNRIGHT; } } TURNLEFT; Wait(10); Off(OUT_AC); ClearTimer(0); ClearTimer(1); }
task mainに交差点ごとの動作を記述していきます。 交差点を検知するまでトレースをし、ミッションを遂行するのを繰り返しています。 交差点の数をカウントアップしてそれぞれの動作を記述する事も可能ですが、通過する交差点はたかだか六つ程度なのでループを書くほどでもないと判断しました。
task main(){ /* センサを用意 */ SetSensor(SENSOR_2,SENSOR_LIGHT); /* 三秒間交差点判定を無効化 */ ClearTimer(1); trace(); /* 一つ目の交差点: 直進 */ go_straight(); trace(); /* 二つ目の交差点: 直進 */ go_straight(); trace(); /* 三つ目の交差点: 右折 */ turn_right(); trace(); /* 四つ目の交差点: 右折 */ turn_right(); trace(); /* 五つ目の交差点: 左折 */ turn_left(); trace(); /* 六つ目の交差点: 左折 */ turn_left(); trace(); }
ロボットに関しては戸谷くんが作ってきてくれてそれ任せだったのですが、ギア比とかもう少し改良余地はあったのかなあと今では思っています。そこまで考えが回っていなかった。
おもしろいプログラムをかければいいなと考えていたのですが、最後までいいアイデアが思い浮かばず何回かプログラムを書き直したのですが、結局ナイーブなプログラムになってしまいました。タイマを使って制御するのは楽なのですが、電池の残量によって変動したりするので大変でした。最終的なプログラムはタイマを極力使わないようにできたのでよかったです。おもしろいプログラムとして残された希望がPID制御しかなかった・・・
前回の反省を顧みずにやってしまった気がします。前回は割と早い段階で自分の作りたいものが決まっていたので自分としては納得できるものが作れたのですが、今回はなかなか具体的な形が決まらずに時間が過ぎてしまいました。課題2を振り返って予習はできるだけやっておこうと思いました。特に今回はライントレースロボットでしたが、センサ一つでライントレースをするというところから始まりいろいろなテクニックがあったので、授業より早いうちに理解しておいて、最終的な形を早めに決めることが重要だと思いました。あと、課題3は四人で行うので、みんなで協力して迷惑かけないように(←重要)やります。