目次
今回の課題はロボットが黒い線に沿って進むライントレースであった。途中には緩めのカーブ、きつめのカーブ、ヘアピンカーブといった難所があった。また、途中で紙コップを拾いそのまま紙コップを移動させ、指定の場所まで運ぶという課題もあった。
A地点出発→B地点直進→C地点右折→F地点直進→R地点左折(一時停止)→P地点直進→X地点の紙コップを回収しコースに戻る→Q地点左折→S地点直進(一時停止)→Y地点に紙コップを置きコースに戻る→S地点直進(一時停止)→F地点左折(一時停止)→C地点右折(一時停止)→D地点到着
ロボットは右の写真のように説明書に載っているモータを水平に設置するものををベースとした。本体はアームのモータを土台として水平に老いた。光センサーの位置を出来るだけ地面と接するように装着し光センサーの位置も中心にし車輪をどのくらい動かせば良いかなどの調整をしやすくした。これらのようにできるだけシンプルにすることができプログラミングに多く時間を使うことが出来た。また、右の写真のようにアームの位置を車輪と車輪の間にする事で紙コップを回収しやすくした。そして回収するためのアームの輪っかはあらかじめ大きく作ることによって紙コップの位置がずれた場合でも回収できるようにした。
プログラミングのマクロは次の通りにした。
#define SPEED_CURVE 25 //コーナーの進むスピードはゆっくりめに25とした。 #define SPEED_FAST 40 //直線ではコーナーより少し早めの40にした。 #define CROSS_TIME 300 //ラインを横切るための時間。 #define THRESHOLD 53 //しきい値を試験の結果53にしておいた。 #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL); //OnRLを何度も使うのでここで簡単に定義しておく。 #define go_forward OnRL(SPEED_FAST,SPEED_FAST); //交差点などで前進するためのもの。 #define turn_right_high OnRL(-40,SPEED_CURVE); //右へ急に曲がるための定義。 #define turn_right_low OnRL (0,SPEED_CURVE); //右へ曲がるための定義。 #define turn_left_high OnRL(SPEED_CURVE,-40); //左へ急に曲がるための定義。 #define turn_left_low OnRL (SPEED_CURVE,0); //右へ曲がるための定義。 #define nMAX 160 //繰り返す回数は試験の結果160にしておいた。
プログラミングのサブ関数は次の通りにした。しかし、あまりにも分けすぎたため多くなってしまった。
sub arm_up() //紙コップ回収時のプログラム。 { RotateMotor(OUT_A,25,35); //モーターAを速さ25で35度回転。 Off(OUT_A); } sub arm_down() //紙コップ設置時のプログラム。 { RotateMotor(OUT_A,25,-35); //モーターAを速さ25で−35度回転。 Off(OUT_A); }
sub change_E() //E地点における回転。 { RotateMotor(OUT_C,25,210); //モーターCを速さ25で210度回転。 Off(OUT_C); }
sub follow_line() //ライントレースの基本のプログラム。黒い部分が0,2秒間にnMAX回つまり今回の場合は160回続いた場合には交差点と判断されるプログラミングを組んだ。 { long t0=CurrentTick(); //時間を計測。 while(CurrentTick()-t0<200){ //0,2秒間続ける。もし、0,2秒間以上以下の動作をしても黒のままである場合には交差点と判断される。 SetSensorLight(S1); int n=0; while(n <= nMAX){ //黒と判断された回数がnMAX回以下の時続ける。 if (SENSOR_1 < THRESHOLD -14){ turn_right_high; n++; //右へ急旋回された場合、カウントする。 }else{ if (SENSOR_1< THRESHOLD -7){ turn_right_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_left_low; } else { turn_left_high; } n=0; //右へ急旋回以外の行動をした場合、カウントをリセット。 } } } Off(OUT_BC); PlaySound(SOUND_CLICK); }
sub follow_line_BC() //地点BC間におけるプログラム。ここではnMAXでは実験の結果から小さすぎたためnMAXではなく355にした。 { long t0=CurrentTick(); while(CurrentTick()-t0<400){ SetSensorLight(S1); int n=0; while(n <= 355){ if (SENSOR_1 < THRESHOLD -14){ turn_right_high; n++; }else{ if (SENSOR_1< THRESHOLD -7){ turn_right_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_left_low; } else { turn_left_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line_FR() //地点FR間におけるプログラム。(その1)nMAXがここでも小さすぎたため大きめの400に設定した。これより小さくなるとヘアピンが始まってすぐに交差点と判断され、大きすぎると逆に交差点の部分が交差点と判断されなくなる。 { long t0=CurrentTick(); while(CurrentTick()-t0<400){ SetSensorLight(S1); int n=0; while(n <= 600){ if (SENSOR_1 < THRESHOLD -11){ turn_right_high; n++; }else{ if (SENSOR_1< -6){ turn_right_low; }else if (SENSOR_1 < THRESHOLD +6){ go_forward; }else if (SENSOR_1 < THRESHOLD +10){ turn_left_low; } else { turn_left_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line_FR2() //地点FR間におけるプログラム。(その2) { long t0=CurrentTick(); while(CurrentTick()-t0<400){ SetSensorLight(S1); int n=0; while(n <=580){ if (SENSOR_1 < THRESHOLD -11) turn_right_high; n++; }else{ if (SENSOR_1< -6){ turn_right_low; }else if (SENSOR_1 < THRESHOLD +6){ go_forward; }else if (SENSOR_1 < THRESHOLD +11){ turn_left_low; } else { turn_left_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line_RP() //地点RP間におけるプログラム。 { long t0=CurrentTick(); while(CurrentTick()-t0<200){ SetSensorLight(S1); int n=0; while(n <=nMAX){ if (SENSOR_1 < THRESHOLD -14){ turn_left_high; n++; }else{ if (SENSOR_1< -7){ turn_left_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_right_low; } else { turn_right_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line_QS() //地点QS間におけるプログラム。 { long t0=CurrentTick(); while(CurrentTick()-t0<400){ SetSensorLight(S1); int n=0; while(n <=300){ //0,3秒間続ける。もし、連続して0,3秒間以上以下の動作をしても変化が無い場合には交差点と判断される。
if (SENSOR_1 < THRESHOLD -14){ turn_left_high; n++; }else{ if (SENSOR_1< -7){ turn_left_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_right_low; } else { turn_right_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line_SS() //地点QS間におけるプログラム。 { long t0=CurrentTick(); while(CurrentTick()-t0<400){ SetSensorLight(S1); int n=0; while(n <= nMAX){ if (SENSOR_1 < THRESHOLD -14){ turn_right_high; n++; }else{ if (SENSOR_1< -7){ turn_right_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_left_low; } else { turn_left_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line1() //ライントレースの基本のプログラム。(境界が左バージョン) { long t0=CurrentTick(); while(CurrentTick()-t0<200){ SetSensorLight(S1); int n=0; while(n <= nMAX){ if (SENSOR_1 < THRESHOLD -14){ turn_left_high; n++; }else{ if (SENSOR_1< -7){ turn_left_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_right_low; } else { turn_right_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); } sub follow_line_FC() //地点QS間におけるプログラム。
{ long t0=CurrentTick(); while(CurrentTick()-t0<200){ SetSensorLight(S1); int n=0; while(n <= nMAX){ if (SENSOR_1 < THRESHOLD -14){ turn_right_high; n++; }else{ if (SENSOR_1< -7){ turn_right_low; }else if (SENSOR_1 < THRESHOLD +7){ go_forward; }else if (SENSOR_1 < THRESHOLD +14){ turn_left_low; } else { turn_left_high; } n=0; } } } Off(OUT_BC); PlaySound(SOUND_CLICK); }
task main() { go_forward; //地点Aから発車。 Wait(1000); Off(OUT_BC); follow_line(); //AB間 go_forward; //Bを直進。 Wait(CROSS_TIME); Off(OUT_BC);// follow_line_BC(); //CF間 RotateMotor(OUT_C,25,330);//右へ曲がる。 Off(OUT_C); follow_line();//CF間(試験で途中で切れた時があったために2つ入れておいた。) follow_line(); OnFwd(OUT_B,35); //交差点を直進するためのプログラム。交差点認識の際のズレを補正するために傾くように動かす。 OnFwd(OUT_C,25); Wait(600); Off(OUT_BC); follow_line_FR(); //地点FR間の途中までのFE間のためのプログラム。試験の時にヘアピンで交差点認識されるためいくつかプログラムを組んでおいた。 follow_line_FR2(); follow_line_FR2(); follow_line(); change_E(); //地点Eにおいて右折。 follow_line(); //ER間(試験で途中で切れた時があったために2つ入れておいた。) follow_line(); Wait(1000); //地点Rにおいて一時停止。(1秒間) OnFwd(OUT_B,35); //地点Rにおいて左折。 Wait(1500); Off(OUT_C); follow_line_RP(); //RP間 OnFwd(OUT_C,25); //地点Pを直進。交差点認識の際のズレを補正するために傾くように動かす。 Wait(600); Off(OUT_BC); OnFwd(OUT_B,35); //ここから紙コップを回収するためのプログラム。(sub関数を使用することを忘れていたため非常に長くなった。)少し前進。 OnFwd(OUT_C,35); Wait(800); Off(OUT_BC); OnFwd(OUT_B,25); //左へ約90度回転。 OnFwd(OUT_C,-25); Wait(1500); Off(OUT_BC); arm_down(); //紙コップを回収。 OnFwd(OUT_B,-25); //右へ約90度回転。 OnFwd(OUT_C,25); Wait(1500); Off(OUT_BC); follow_line_RP();// //PQ間 OnFwd(OUT_B,35); //地点Qにおいて左折。交差点認識の際のズレを補正するために傾くように動かす。 OnFwd(OUT_C,10); Wait(500); Off(OUT_BC); follow_line_QS(); //QS間(試験で途中で切れた時があったために2つ入れておいた。) follow_line_QS(); Wait(1000); //地点Sにおいて一時停止。 OnFwd(OUT_C,35); //地点Sを直進。交差点認識の際のズレを補正するために傾くように動かす。 OnFwd(OUT_B,10); Wait(1500); Off(OUT_BC); follow_line_SS(); //SS間 OnFwd(OUT_B,-25); //ここから紙コップを切り離すためのプログラム。(sub関数を使用することを忘れていたため非常に長くなった。)右へ約90度回転。 OnFwd(OUT_C,25); Wait(1200); Off(OUT_BC); OnFwd(OUT_B,25); //後退。 OnFwd(OUT_C,25); Wait(1100); Off(OUT_BC); arm_up(); //紙コップを切り離し。 OnFwd(OUT_B,25); //左へ約180度回転。 OnFwd(OUT_C,-25); Wait(2800); Off(OUT_BC); OnFwd(OUT_B,25); //少し前進。 OnFwd(OUT_C,25); Wait(800); Off(OUT_BC); OnFwd(OUT_B,-25); //右へ約90度回転。 OnFwd(OUT_C,25); Wait(1800); Off(OUT_BC); Wait(1000); //地点Sにおいて一時停止。 OnFwd(OUT_B,35); //地点Sを直進。交差点認識の際のズレを補正するために傾くように動かす。 OnFwd(OUT_C,25); Wait(500); Off(OUT_BC); follow_line(); //SF間 Wait(1000); //地点Fにおいて一時停止。 RotateMotor(OUT_B,25,200); //地点Fにおいて左折。 Off(OUT_B); follow_line_FC(); //FC間 Wait(1000); //地点Cにおいて一時停止。 go_forward; //地点Cにおいて右折。まず少し前進。 Wait(800); Off(OUT_BC); OnFwd(OUT_B,-25); //右へ約約90度回転。 OnFwd(OUT_C,25); Wait(1800); Off(OUT_BC); follow_line1(); //CD間 go_forward; //地点Dを前進。 Wait(1000); Off(OUT_BC); }
今回はライントレースということで前回の文字を書くことよりは簡単に思われたが、想像以上に難しい課題であった。具体的には何度も試験走行をすることで電池の消耗が激しくなり、電池を交換することになりそこでまたプログラミングにズレが生まれる。そのズレが交差点を判断できなくなったり紙コップをきちんと回収できないという問題が生じた。実際に紙コップがアームの部分に当たり、紙コップが回収できないという事態があったため改善点としては紙コップの回収時にロボット本体を横に揺らし、アームを下げ紙コップを回収するというプログラミングを組むべきであった。また他の班のロボットと違って自分の班のロボットは動くスピードが遅いためもう少し直線の所はスピードを上げるべきであった。そしてコーナーの部分は慎重に行くべきではあるがこれもあまりにも遅すぎるため、モーターの回転する速度をあと10%ほ上げるべきであった。