目次 #contents *課題2 [#cb85d3f7] 下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。 &ref(2018b/Member/Tom/Mission2/コース.png,70%,コース); 私のロボットが走行するコースは第1コースであり、詳しいコースの内容は以下の通りである。 赤い線が第1コースである。 &ref(2018b/Member/Tom/Mission2/第1コース.jpg,40%,第1コース); 1.ロボットを長方形X内におき、Aをスタート 2.Bを右折 3.Kで一時停止して左折 4.Jを直進 5,Iを直進 6.Hを左折 7.Gで一時停止して左折 8.Eで一時停止して右折 9.Lを経て正方形Y内に入って停止 (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧KJIH上にある時にQ地点の空き缶に当てる *今回のロボットについて [#bb4d5ebb] **光センサー部分 [#q8f94f5c] &ref(2018b/Member/Tom/Mission2/光センサー.jpg,25%,光センサー); 光センサーと紙が平行になるような位置にセンサーを取り付け、光センサーの値を正確に測ることができるようにした。タイヤの中点よりも右側に光センサを取り付けるようにした。 **タイヤの部分 [#h504b5f6] &ref(2018b/Member/Tom/Mission2/タイヤの工夫.jpg,25%,タイヤの工夫); ライントレースをスムーズに行うことができるように、タイヤの中点よりも右側に光センサーを取り付けるようにした。タイヤと光センサーの距離を近づけることにより急なカーブやUターンなどがしやすくなっている。 **超音波センサー部分 [#e0a53f13] &ref(2018b/Member/Tom/Mission2/超音波センサー.jpg,25%,超音波センサー); 空き缶との距離を正確に測るために、超音波センサーの前に他のセンサーとの接続コードがこないようにした。また、超音波センサーを少し下向きに傾けることで、空き缶を認識しやすいようにした。 *ロボットを動かすためのプログラム [#kd69694a] **ライントレース [#l0825368] 今回は、「黒と白の境界線をライントレースする」というプログラムを制作した。コース上で光センサーの明るさを測定してみると「白」「白と境界線の間」「境界線」「黒と境界線の間」「黒」 という5段階の明るさの値を測定できた。5つの測定できた値は以下のものとなった。 &ref(2018b/Member/Tom/Mission2/光センサーの値.jpg,25%,光センサーの値); 明るさの値が5段階存在するので、それぞれの明るさに対応した動きをする必要がある。そのために5段階で動きを制御することができるような以下のプログラムを作成した。 &ref(2018b/Member/Tom/Mission2/動き方.jpg,25%,動き方); #define go_forward OnFwd(OUT_B,40);OnFwd(OUT_C,40) //直進 #define turn_left1 OnFwd(OUT_B,35);OnFwd(OUT_C,-30) //左旋回 #define turn_left2 OnFwd(OUT_B,25);OnFwd(OUT_C,-20) //左折 #define turn_right1 OnFwd(OUT_C,35);OnFwd(OUT_B,-30) //右旋回 #define turn_right2 OnFwd(OUT_C,25);OnFwd(OUT_B,-20) //右折 また、黒と白の境界線には「黒線の右側をライントレースする」、「黒線の左側をライントレースする」という2種類の境界線が存在するので、これらのプログラムを分けて考えることにした。 ***右側のライントレース [#je8cb310] 白と黒の境界線の明るさの値が45なので #define THRESHOLD 45 //白と黒の境界線の明るさの値が45である。 と定義して、以下のようなプログラムを作成した。 void Rfollow_line(long max_t) //max_tにいれた時間分だけラインの右側をライントレースする。 { long t0=CurrentTick(); //現在の時間を記録する。 while (CurrentTick()-t0<=max_t) //現在の時間とt0の時間の差がmax_t以下の時、以下のプログラムを実行する。{ if (SENSOR_4<THRESHOLD-11) { if (SENSOR_4<THRESHOLD-11) { turn_left1; //明るさの値が34以下の時、turn_left1の動きをする。 } else if (SENSOR_4<THRESHOLD-7){ } else if (SENSOR_4<THRESHOLD-7){ turn_left2; //明るさの値が38以下の時、turn_left2の動きをする。 } else if (SENSOR_4<THRESHOLD+7){ } else if (SENSOR_4<THRESHOLD+7){ go_forward; //明るさの値が52以下の時、go_forwardの動きをする。 } else if (SENSOR_4<THRESHOLD+11){ } else if (SENSOR_4<THRESHOLD+11){ turn_right1; //明るさの値が56以下の時、turn_right1の動きをする。 } else { } else { turn_right2; //それ以外の時、turn_right2の動きをする。 } } } このプログラムは下図のように動く。 &ref(2018b/Member/Tom/Mission2/右側のライントレース.jpg,25%,右側のライントレース); ***左側のライントレース [#zed3c5e0] void Lfollow_line(long max_t) //max_tにいれた時間分だけラインの左側をライントレースする。 { long t0=CurrentTick(); //現在の時間を記録する。 while (CurrentTick()-t0<=max_t) //現在の時間とt0の時間の差がmax_t以下の時、以下のプログラムを実行する。{ if (SENSOR_4<THRESHOLD-11) { if (SENSOR_4<THRESHOLD-11) { turn_right1; //明るさの値が34以下の時、turn_right1の動きをする。 } else if (SENSOR_4<THRESHOLD-7){ } else if (SENSOR_4<THRESHOLD-7){ turn_right2; //明るさの値が38以下の時、turn_right2の動きをする。 } else if (SENSOR_4<THRESHOLD+7){ } else if (SENSOR_4<THRESHOLD+7){ go_forward; //明るさの値が52以下の時、go_forwardの動きをする。 } else if (SENSOR_4<THRESHOLD+11){ } else if (SENSOR_4<THRESHOLD+11){ turn_left1; //明るさの値が56以下の時、turn_left1の動きをする。 } else { } else { turn_left2; //それ以外の時、turn_left2の動きをする。 } } } このプログラムは下図のように動く。 &ref(2018b/Member/Tom/Mission2/左側のライントレース.jpg,25%,左側のライントレース); **交差点の認識 [#yf8fb02c] void follow_intersection(long min_t) //min_tにいれた時間分だけライントレースをする。 { long t1=CurrentTick(); //現在の時間を記録する。 while (CurrentTick()-t1<=min_t) //現在の時間とt1の時間の差がmin_t以下の時、以下のプログラムを実行する。(min_tの時間で交差点を認識する。){ if (SENSOR_4<THRESHOLD-11) { if (SENSOR_4<THRESHOLD-11) { Off(OUT_BC);Wait(1000); //明るさの値が34以下の時、B,Cのモータを1秒間停止させる。 } if (SENSOR_4<THRESHOLD-7){ } else if (SENSOR_4<THRESHOLD-7){ turn_left2; //明るさの値が38以下の時、turn_left2の動きをする。 t1=CurrentTick(); //現在の時間を記録する。 } else if (SENSOR_4<THRESHOLD+7){ } else if (SENSOR_4<THRESHOLD+7){ go_forward; //明るさの値が52以下の時、go_forwardの動きをする。 t1=CurrentTick(); //現在の時間を記録する。 } else if (SENSOR_4<THRESHOLD+11){ } else if (SENSOR_4<THRESHOLD+11){ turn_right1; //明るさの値が56以下の時、turn_right1の動きをする。 t1=CurrentTick(); //現在の時間を記録する。 } else { } else { turn_right2; //それ以外の時、turn_right2の動きをする。 t1=CurrentTick(); //現在の時間を記録する。 } } } **交差点の横断 [#bef0b719] 交差点を認識した後、直進、左折、右折などの動きをする必要があるので、交差点を横断するプログラムを考える。 #define across OnFwd(OUT_B,40);OnFwd(OUT_C,40);Wait(1000)//1秒間交差点を横断する。 #define across2 OnFwd(OUT_B,40);OnFwd(OUT_C,40);Wait(400)//0.4秒間交差点を横断する。 **空き缶を探すためのプログラム [#pd47708d] #define SPEED 50 #define SPEED_SLOW 30 const float diameter = 5.45; //タイヤの直径(cm) const float track = 10.35; //タイヤのトレッド幅(cm) const float pi = 3.1415; //円周率 void turnAng(long ang) // 角度 ang 度の時計回りの旋回する。 { long angle; angle = track/diameter*ang; RotateMotorEx(OUT_BC, SPEED_SLOW, angle, 100, true, true); } int searchDirection(long ang) // 現在の方向を中心にang度の範囲で探す。 // 障害物までの距離を返す。 { long angle, tacho_min=0, tacho_corr; int d_min; d_min=300; // 仮の最小値 angle = (track/diameter)*ang;// 旋回角度からタイヤの回転を計算する。 turnAng(ang/2); // 指定された角度の半分を旋回する。 ResetTachoCount(OUT_BC); // 角度計測をリセットする。 OnFwdSync(OUT_BC,SPEED_SLOW,-100);// 反時計回りに旋回する。 while(MotorTachoCount(OUT_B)<=angle){ if(SensorUS(S2)<d_min){ d_min=SensorUS(S2); // 仮の最小値を更新する。 tacho_min=MotorTachoCount(OUT_B); } } OnFwdSyncEx(OUT_BC,SPEED_SLOW,100,RESET_NONE); until(MotorTachoCount(OUT_B)<=tacho_min||SensorUS(S2)<=d_min); Wait(14); //微調整 Off(OUT_BC);Wait(500); return d_min; } **空き缶にボールを当てるためのプログラム [#tfe8bfe3] #define throw OnFwd(OUT_A,30);Wait(700);Off(OUT_A);Wait(2000); //アームを動かし、ボールを空き缶に当てる。 OnFwd(OUT_A,-35);Wait(700);Off(OUT_A); //アームをもとの位置に戻す。 *全体のプログラム [#g5173108] task main() { SetSensorLight(S4); //光センサを4に接続する。 SetSensorLowspeed(S2);//超音波センサを2に接続する。 Wait(3000);//スタートボタンを押してからすぐにロボットが動くのを防ぐために、3秒間ロボットを停止させる。 across;//1秒間交差点を横断する。 Rfollow_line(3500);//3.5秒間ラインの右側をライントレースする。 Rfollow_line(400);//0.4秒間ラインの右側をライントレースする。 follow_intersection(400);//0.4秒で交差点を認識する。 across2;//0.4秒間で交差点を横断する。 Rfollow_line(10000);//10秒間ラインの右側をライントレースする。 int d=searchDirection(360);//現在の方向を中心に360度回転し、最小値(空き缶)の方向を向く。 throw; //ボールを投げる。 turn_left2;Wait(3000);//ライントレースを続けるために向きを変える。 Rfollow_line(4000);//4秒間ラインの左側をライントレースする。 turn_right2;Wait(3000);交差点をぬけるために向きを変える across2;//0.4秒間で交差点を横断する。 Rfollow_line(19500);//19.5秒間ラインの右側をライントレースする。 follow_intersection(400);//0.4秒で交差点を認識する。 turn_left2;Wait(1000);//交差点をぬけるために向きを変える。 Lfollow_line(1500);//1.5秒間ラインの左側をライントレースする。 across;//ゴールに向かって前進する。 } *まとめ [#df6a3f18] 交差点を認識して止まることができるときとできないときがあったが、プログラムがうまく改善できたので良かった。しかし、同じプログラムでも結果に差が出るので、もっと精度を上げたプログラムができるように頑張りたいと思う。