目次
2019b/Mission1を参照 自分は第二コースを走らせた。
今回のロボットは、基本は最初に配布される資料に書かれてあるものを参考にして作成した。そのために非常にシンプルなをとっている構造をとっているが、それがロボットの拡張性を高め、結果大量の時間をプログラミングに費やせるようになった。
このアームはほかの班が多く採用している、ボールを囲ってそのまま運搬する方式ではなく、挟み込んでしっかりとボールをつかむようにした。これにより、大きくロボット本体の設計を変える必要なく、優れた拡張性を生かした形となった。しかし、これを作るときに一番の難点になったのはモータ−1つで二つの棒を動かすところであったが、そこは過去の多くの作品例を見て、その結果上の図の白線のように1つのモーターに左右二つずつ、計四つの歯車を連動させることで解決している。
工夫した点は、2つで、ラインとセンサー部の距離をできるだけ近づけようとしたことと、センサー部をがっしりとタイヤの中央部に固定して、回転などのときに考慮するものを減らした。
上の図の通りである。見ずらかったら申し訳ない。これを作成するときにはできるだけ色にむらなく、何重にも塗りなおすことでセンサーがとる値を安定させた。
#define turn_right OnFwd(OUT_C,25);OnRev(OUT_B,15);//右折 #define turn_left OnFwd(OUT_B,25);OnRev(OUT_C,15);//左折 #define rotate_right OnFwd(OUT_C,20);OnRev(OUT_B,25);//右旋回 #define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,25);//左旋回 #define go_straight OnFwd(OUT_BC,30);//直進 #define black 35//黒の値は35 #define white 65//白の値は65 #define lightgray 57//灰白色は57 #define darkgray 43//灰黒色は43 sub followline_L(int stop_time,long tmin,long tmax) //左側のライントレース { SetSensorLight(S1); long t0=CurrentTick(); long t_start=CurrentTick(); while((CurrentTick()-t0<=stop_time||CurrentTick()-t_start<=tmin)&&CurrentTick()- t_start<=tmax){//現在の時刻が一定の値を超えるまで if(SENSOR_1<black){//センサーが黒の時 rotate_left;//左旋回 }else if(SENSOR_1<darkgray){//センサーが黒灰なら turn_left;//左折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<lightgray){//明るさ50以下で go_straight;//直進 t0=CurrentTick();//時間をリセット }else{//それ以外は rotate_right;//右旋回 t0=CurrentTick();//時間をリセット } } Off(OUT_BC);//時刻が一定の値を超えると停止 Wait(1000);//1秒間停止 } sub followline_R(int stop_time,long tmin,long tmax) { SetSensorLight(S1); long t0=CurrentTick(); long t_start=CurrentTick(); while((CurrentTick()-t0<=stop_time||CurrentTick()-t_start<=tmin)&&CurrentTick()- t_start<=tmax){//現在の時刻が一定の値を超えるまで if(SENSOR_1<black){//センサーが黒の時 rotate_right;//右旋回 }else if(SENSOR_1<darkgray){//センサーが黒灰なら turn_right;//右折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<lightgray){//明るさ50以下で go_straight;//直進 t0=CurrentTick();//時間をリセット }else{//それ以外は rotate_left;//左旋回 t0=CurrentTick();//時間をリセット } } Off(OUT_BC);//時刻が一定の値を超えると停止 Wait(1000);//1秒間停止 } sub catch_ball(){ OnFwd(OUT_A,-15); Wait(4000); } task main (){ SetSensorLight(S1); OnFwd(OUT_BC,25);Wait(1000); followline_L(100,10000,100000); OnFwd(OUT_B,-18);OnFwd(OUT_C,18);Wait(650); Off(OUT_BC); OnFwd(OUT_BC,30); Wait(750); Off(OUT_BC); catch_ball(); Wait(2000); Off(OUT_BC); OnFwd(OUT_B,20);OnFwd(OUT_C,-20);Wait(500); followline_R(100,10000,100000); Off(OUT_BC); OnFwd(OUT_BC,20);Wait(800); followline_R(100,10000,8500); Off(OUT_BC); OnFwd(OUT_BC,30);Wait(1700); Off(OUT_BC); Wait(3000); Off(OUT_BC); }
プログラミングの全体像はこうなっている。見たらわかるかもれないが、殆どのメインプログラムが先に設定されている定義のプログラムとサブルーチンのプログラムによって構成されている。 詳細は以下で説明する。
#define turn_right OnFwd(OUT_C,25);OnRev(OUT_B,15);//右折 #define turn_left OnFwd(OUT_B,25);OnRev(OUT_C,15);//左折 #define rotate_right OnFwd(OUT_C,20);OnRev(OUT_B,25);//右旋回 #define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,25);//左旋回 #define go_straight OnFwd(OUT_BC,30);//直進 #define black 35//黒の値は35 #define white 65//白の値は65 #define lightgray 57//灰白色は57 #define darkgray 43//灰黒色は43
これが、定義化してしまったもので、上半分がロボットの動作(直進、右左折)、下半分はロボットの光センサーの値を固定化したものである。
sub followline_L(int stop_time,long tmin,long tmax) //左側のライントレース { SetSensorLight(S1); long t0=CurrentTick(); long t_start=CurrentTick(); while((CurrentTick()-t0<=stop_time||CurrentTick()-t_start<=tmin)&&CurrentTick()- t_start<=tmax){//黒と認識した時間が0.1s以上で交差点認識、またこの時間は判別しない、動ける最大時間 if(SENSOR_1<black){//センサーが黒の時 rotate_left;//左旋回 }else if(SENSOR_1<darkgray){//センサーが黒灰なら turn_left;//左折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<lightgray){//明るさ50以下で go_straight;//直進 t0=CurrentTick();//時間をリセット }else{//それ以外は rotate_right;//右旋回 t0=CurrentTick();//時間をリセット } } Off(OUT_BC);//時刻が一定の値を超えると停止 Wait(1000);//1秒間停止 }
このプログラムは、左側のライントレース並びに交差点に差し掛かった場合に一度停止してから再度ライントレースを行うプログラムとなっている。メインプログラムにをいては、int stop_timeに0.1秒になるように数価を設定している。この値は計測によって得られたものである。各時間の設定(int stop_time,long tmin,long t_max)は下のように扱っている。
int stop_time//
センサーが黒の値を検知し続けた時間が一定の値を超えた場合、それを交差点と認識する値。 long tmin ここに設定した時間の間は、交差点の認識を行わずに、ライントレースだけを行うようなっている。 long tmax ここに設定した時間は、ロボットの稼働可能時間の最大値で、ロボットがこの値を超えてうごかないようになっている。しかし、作ったのはいいがメインプログラムでは活躍しなかった。
sub followline_R(int stop_time,long tmin,long tmax) { SetSensorLight(S1); long t0=CurrentTick(); long t_start=CurrentTick(); while((CurrentTick()-t0<=stop_time||CurrentTick()-t_start<=tmin)&&CurrentTick()- t_start<=tmax){//現在の時刻が一定の値を超えるまで if(SENSOR_1<black){//センサーが黒の時 rotate_right;//右旋回 }else if(SENSOR_1<darkgray){//センサーが黒灰なら turn_right;//右折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<lightgray){//明るさ50以下で go_straight;//直進 t0=CurrentTick();//時間をリセット }else{//それ以外は rotate_left;//左旋回 t0=CurrentTick();//時間をリセット } } Off(OUT_BC);//時刻が一定の値を超えると停止 Wait(1000);//1秒間停止 }
先ほど説明した左側のライントレースの旋回や右左折の仕様を逆にしたもの。
sub catch_ball(){ OnFwd(OUT_A,-15); Wait(4000); }
これはロボットのアームの動作に関するプログラム。モーター一つの駆動なのでこれだけになっている。
task main (){ SetSensorLight(S1); OnFwd(OUT_BC,25);Wait(1000);ライントレースのスタート位置に移動 followline_L(100,10000,100000);左側のライントレースの開始 JからHまで OnFwd(OUT_B,-18);OnFwd(OUT_C,18);Wait(650);ボールに対してアームが正面になるよう調整 Off(OUT_BC); OnFwd(OUT_BC,30);アームとボールとの距離を再調整 Wait(750); Off(OUT_BC); catch_ball();ボールを確保 Wait(2000); Off(OUT_BC); OnFwd(OUT_B,20);OnFwd(OUT_C,-20);Wait(500);Gに向かうよう機体の向きを調整 followline_R(100,10000,100000);右側のライントレースを開始 HからDまで Off(OUT_BC); OnFwd(OUT_BC,20);Wait(800);交差点の通過 followline_R(100,10000,8500);右側ライントレースの再開 DからBまで Off(OUT_BC); OnFwd(OUT_BC,30);Wait(1700);ゴールイン Off(OUT_BC); Wait(3000); Off(OUT_BC);
これがメインプログラムです。
今回はひじょうにうまくいった。この調子で最後の課題もこなしたい。