指定されたコースにそって動くロボットを作成する。詳しくは課題2を参照。
自分はE地点右折コースを選択した。
ロボットの構造で工夫した点は、センサーの位置をタイヤの軸上に近づけ、センサーの動きを調整しやすくしたことである。
結論から言うと、このプログラムは私の勘違いにより全体的に間違っている。今回のコースでたまたまゴール出来ただけで、プログラムとしては問題点が多い。また、事前にコースがわかっていないと使えない。詳細は後述する。
まず、関数を1つ作り、黒線の右側、左側をトレースするプログラムを定義した。しかし、問題点の多いプログラムとなっている。
プログラムの内容は、変数aで何回機体が急激に右(左)に曲がったかを記録し、その回数が引数x(y)回以上になると交差点と認識し、トレースは終了するようになっている。
ここでの問題点は、わざわざ引数を設定する必要がなかったことである。task mainでは引数に色々な数字をいれているが、交差点では引数の数を20かえても見てわかるような違いは起きない。また、この方法で交差点を認識しようとすると、直線ではaは増えないが、カーブなどでもaは増えるので、誤認が増える要因となった。カーブを越えるために違うプログラムをいれたので(これにも問題はあったが)、結果的には使いにくい認識の仕方となってしまった。
int a; sub migi_susumu(int x) //黒線の右側をトレースする { a=0; while(a<=x){ if(SENSOR_1>=55){ OnFwd(OUT_A,30); OnRev(OUT_C,30); }else if(SENSOR_1>=50){ OnFwd(OUT_A,30); Off(OUT_C); }else if(SENSOR_1>=45){ OnFwd(OUT_C,30); Off(OUT_A); }else{ OnFwd(OUT_C,30); OnRev(OUT_A,30); a=a+1; } } } sub hidari_susumu(int y) //黒線の左側をトレースする { a=0; while(a<=y){ if(SENSOR_1>=55){ OnFwd(OUT_C,30); OnRev(OUT_A,30); }else if(SENSOR_1>=50){ OnFwd(OUT_C,30); Off(OUT_A); }else if(SENSOR_1>=45){ OnFwd(OUT_A,30); Off(OUT_C); }else{ OnFwd(OUT_A,30); OnRev(OUT_C,30); a=a+1; } } }
次に、音を鳴らすプログラムを定義する。
sub sound_down() //SOUND_DOWNを鳴らし、1秒止まる { PlaySound(SOUND_DOWN); Off(OUT_AC); Wait(1000); } sub sound_up() //SOUND_UPを鳴らす { PlaySound(SOUND_UP); }
上記のサブルーチンを使って、メインのプログラムを書いた。
途中のwhileの中は「曲がり始めやカーブなどを交差点と誤認しないようにするためで、最初の〜秒間はトレースするサブルーチンの引数を大きくしてサブルーチンが終了しないようにし、誤認しやすいカーブなどをすべて曲がり切る。〜秒後、while文は終了し、続けてサブルーチンの引数を小さく設定したサブルーチンが新たに始まり、機体は交差点を認識する」ということを考えて書いたが、実際にはwhileは指定した秒数を越えても1度while内の文が終了するまでは続くので、while(現在の時刻-トレース開始時刻<曲がり始めやカーブを越える秒数){migi_susumu(3)}で良かった。
また、その後のmigi_susumu(3)も必要なかった。
今回のプログラムで引数に色々な数値が入っているのは、カーブによってaの数が変わるためと思っていれたが、全く意味のないものであった。
また、交差点と認識した後のOnFwdやOnRevは、交差点を認識して停止したとき、機体は少し曲がって停止するので、交差点を直進したいときに曲がり始めた機体を修正したり、もしくはトレースする側を変更するためにいれてある。
task main() { SetSensorLight(S1); OnFwd(OUT_AC,30); //スタート地点から出るため Wait(600); migi_susumu(3); sound_up(); //地点E OnFwd(OUT_AC,30); //機体を黒線の左側にする Wait(350); hidari_susumu(3); sound_down(); //地点P long t = CurrentTick(); while(CurrentTick()-t<1000){ hidari_susumu(10); } hidari_susumu(3); sound_up(); //地点Q OnFwd(OUT_C,30); //交差点を直進するため OnRev(OUT_A,30); Wait(500); OnFwd(OUT_AC,30); Wait(400); hidari_susumu(3); sound_up(); //地点R t=CurrentTick(); while(CurrentTick()-t<1000){ hidari_susumu(10); } hidari_susumu(3); sound_down(); //地点T OnFwd(OUT_C,30); //交差点を直進するため OnRev(OUT_A,30); Wait(500); OnFwd(OUT_AC,30); Wait(400); t = CurrentTick(); while(CurrentTick()-t<12000){ hidari_susumu(20); } hidari_susumu(3); sound_down(); //地点T OnFwd(OUT_C,30); //交差点を直進するため OnRev(OUT_A,30); Wait(600); OnFwd(OUT_AC,30); Wait(500); migi_susumu(3); sound_up(); //地点H t = CurrentTick(); while(CurrentTick()-t<25000){ migi_susumu(50); } migi_susumu(3); sound_up(); //地点G OnFwd(OUT_AC,30); Wait(350); hidari_susumu(3); sound_down(); //地点S t = CurrentTick(); while(CurrentTick()-t<1000){ hidari_susumu(10); } hidari_susumu(3); sound_up(); //地点P OnFwd(OUT_C,30); //交差点を直進するため OnRev(OUT_A,30); Wait(500); OnFwd(OUT_AC,30); Wait(400); hidari_susumu(3); sound_up(); //地点Q OnFwd(OUT_AC,30); //機体を黒線の右側にする Wait(600); migi_susumu(3); sound_up(); //地点F t = CurrentTick(); while(CurrentTick()-t<1000){ migi_susumu(10); } migi_susumu(3); OnFwd(OUT_A,30); //ゴール地点に入るため OnRev(OUT_C,30); Wait(200); OnFwd(OUT_AC,30); Wait(1300); }
今回の間違ったプログラムでゴールできた理由は、引数aの数がかなり大きく違っても、機体の動きはほとんど変わらないことである(見た目に違いがあれば作っている途中に気づけたかもしれない)。引数の数値を変えず、カーブなどを越える秒数のみをいれていれば、もっと簡単なプログラムにできていた。
ロボット自体と黒線をトレースするプログラムは比較的すぐに出来上がり、上手くいっていたが、交差点を判別するのが難しかった。今回はプログラムが全くうまくできなかったので、次はきちんとしたものを作れるようにしたい。また、同じプログラムでも数回動かすと結果が変わったりして調整が大変だった。