目次
今回の課題2の内容は上図のコースにライントレーサーを走らせ、途中に置いてあるピンポン球を掴み、ゴールにシュートするというものである。僕はA地点をスタート→P地点直進→Q地点直進→ピンポン球を掴む→Q地点直進→R地点右折→P地点直進→S地点左折→D地点へシュートというものである。
横から見た写真 重心が後ろによっている
後ろから見た写真
下から見た写真
前から見た写真
なるべくセンサーと紙の間の距離が近くになるようにするため、本体は低めに組み立てた。後ろに小さいタイヤをつけようとしたが、ロボットのバランスが悪くなってしまったのでつけるのをやめた。 構造上タイヤ間の距離が離れてしまったが特に問題はなかった。
アームはショベルカーのような構造にした。ピンポン球は丸くてとても軽いので、アームで本体のほうに引き寄せると途中で球が浮いてアームの上に乗った。アームの左右には球が落ちないように壁を付けた。こうすることによって球が横から落ちなくなる。なので球をとった後に球が落ちるかもしれないということを気にせずにプログラミングができる。
ロボットはラインの黒と紙の白い部分を交互に読み込みながら進むのでジグザグした動きになる。また、今回はラインの右側を走らせることにした。そうすることで急なカーブが少なくなるので楽に曲がれるようになるからだ。
交差点を判断するにはタイマーを用いて黒と認識ししている時間を測りこれを利用する。ロボットはジグザグした動きをし、センサーの値が37以下の時に黒と認識、38の時に中間、40以上で白と認識したとする。黒と認識した時間が0.6もあるとT字路か交差点と判断する。普通のカーブの場合は0.6秒も黒を認識せずジグザグにカーブをたどる。またnの値によってそれぞれの交差点またはT字路上で異なる動作を実行するものとする。このnの値によって交差点上では音を鳴らし一旦停止するプログラムを入れ、交差点上に来たことを知らせる。
#define turnright OnFwd(OUT_C,40);//右に曲がる #define turnleft OnFwd(OUT_B,40);//左に曲がる #define senkairight OnFwdSync(OUT_BC,40,-100);//右に旋回 #define senkaileft OnFwdSync(OUT_BC,40,100);//左に旋回 #define gomae OnFwdSync(OUT_BC,40,0);//前進 #define kousatenmigi OnFwd(OUT_C,40); Wait(500);OnFwdSync(OUT_BC,40,-100); Wait(1400);Off(OUT_BC);Wait(300);OnFwdSync(OUT_BC,40,0);Wait(500);Off(OUT_BC);n++; //交差点での動作。右に曲がる。動作を実行し終わった後にnの値が1増える #define kousatenzensin OnFwd(OUT_C,40);Wait(1000);OnFwdSync(OUT_BC,40,0);Wait(200);n++;//交差点で体勢を立て直し前進する。その後nの値が増える。
#define armup OnFwd(OUT_A,25);Wait(700);Off(OUT_A);//アームを上げる #define armdown OnRev(OUT_A,25);Wait(700);Off(OUT_A);//アームを下げる
#define oto PlaySound(SOUND_CLICK);Wait(600);Wait(1000);//音を鳴らす
交差点に差し掛かったことを確認するために音を鳴らす。T字路では鳴らさない。
task main() { SetSensorLight(S1);//光センサー起動 int n=0; //nの値を決める。 long t0 = CurrentTick();//時間を測り始める直前の時刻をt0に代入する armup//アームを上げる
まず、タイマーと光センサーを起動させる。
自分のロボットが走るコースにはP,Q,Q,R,P,Sの順に交差点またはT字路がある。今回は交差点やT字路に差し掛かった時にnの値によって、動作を変えるようにプログラミングした。1つの交差点での動作が終了するとnの値が1つ増えるようにした。
while(n<7){ t0 = CurrentTick(); while(CurrentTick()-t0<600){ //CurrentTick()とt0の差が0.6秒以下の時 if(SENSOR_1>42){ //もしセンサーの値が42以上だったら左に旋回してタイマーをリセット senkaileft t0 = CurrentTick(); } else if(SENSOR_1>40){ //もしセンサーの値が40以上なら左に曲がりタイマーをリセット turnleft t0 = CurrentTick(); } else if(SENSOR_1>38){ //もしセンサーの値が38以上なら前進してタイマーをリセット gomae t0 = CurrentTick(); } else if(SENSOR_1>37){ //もしセンサーの値が37以上なら右に曲がりタイマーをリセット turnright t0 = CurrentTick(); } else{ senkairight //どれでもなければ右に旋回 } } Off(OUT_BC);
nの値が7以下で、CurrentTick()とt0の差が0.6秒以下の時それぞれの条件によって右に曲がったり左に曲がったりまっすぐ進むことによりラインをたどることができる。
while(n==6){ //T字路なので音を鳴らさない kousatenzensin Off(OUT_BC); armup OnFwdSync(OUT_BC,40,0); Wait(300); n++; }
ゴールにあるT字になったところを読み取った後、アームを上げてそのまま本体で押し込んでシュートする。
while(n==5){ //T字路なので音を鳴らさない senkaileft Wait(700); n++; }
S地点
while(n==4){ oto //音を鳴らす kousatenzensin }
P地点
while(n==3){ //T字路なので音は鳴らさない kousatenmigi }
R地点
while(n==2){ oto //音を鳴らす kousatenzensin }
Q地点
while(n==1){ //nが1の時 oto //音を鳴らす kousatenzensin PlaySound(SOUND_CLICK); //球をとるとき音を鳴らす Wait(500); t0 = CurrentTick(); //タイマーを使う while(CurrentTick()-t0<6000){ //CurrentTick()とt0の差が0.6秒以下の時 if(SENSOR_1>42){ //センサーの値が42以上なら左に旋回 senkaileft } else if(SENSOR_1>40){ //センサーの値が40以上なら左に曲がる turnleft } else if(SENSOR_1>38){ //センサーの値が38以上なら前進 gomae } else if(SENSOR_1>37){ //センサーの値が37以上なら右に曲がる turnright } else{ //どれでもなければ右に旋回 senkairight } } Off(OUT_BC); Wait(500); armdown //球をとる }
Q地点 この地点ではうまくラインを読み込んでくれなかったのでwhile文をまた入れた。
while(n==0){ //nの値が0の時十字路に到達 oto //音を鳴らす kousatenzensin
P地点
} } }
今回の課題でライントレーサーのプログラムは簡単そうだなと最初は思ったが、スムーズに動くためにまず黒いラインのしきい値を探すのに何回も数値を測って動かしての繰り返を行ったので苦労した。途中でタイヤが空回りして前に進まなくなることがあった。原因はロボットの本体の重心が後ろによっていたので、前輪が浮いてしまっていたからだ。なのでもう少し機械のほうを本体の前側に持っていってたらスムーズに走っていたかもしれない。本体の後ろに小さいタイヤをつければよかったかもしれない。そうすれば後ろの摩擦が減るからだ。一部分だけラインを読み取ってくれない部分があったので、読み取ってくれるように何回もいろいろ試したのがつらかった。