[[2015b/Member]] *課題2 ライントレース [#i0c9b3fe] 今回の課題は下の図のB地点から出発し、P地点(右折)→Q地点(右折)→P地点(左折)→Q地点(左折)→Q地点(直進)→P地点(直進)→A地点と進むものである #ref(2015b/Member/kaito012534/Mission2/2015b-mission2.png) **製作したロボット [#q2bbbc70] 説明書に掲載されていたものをそのまま使用している 説明書に掲載されていたものをそのまま使用している。 B,Cの端子に接続したモーターでタイヤを動かし(Bが右輪、Cが左輪)、3の端子に接続した光センサーを本体の前部に取り付け、センサーの示す値によってライン上か否かを判定している。 **プログラムを書くにあたっての当初の方針 [#aadb68d7] -ライントレースはラインの左端をたどっていく -一定時間以上左旋回または左折した場合、交差点での処理に移る。この部分はifで記述した **制作にあたって発生した問題点 [#b541b51f] -ラインのどちらかの端だけをたどっていると、半径の小さいカーブや直角の角を交差点と誤認してしまう -進入時の状況がそれぞれで異なる交差点でいかにして曲がるか **工夫点 [#xb5d1f7f] -半径の小さいカーブの対策として、できるだけカーブの外側を回れるように、プログラム起動からの時間によってラインの左右どちらをたどるかを切り替えるようにした。&br;具体的には、Q地点での右折直後からP地点での左折の後までの間のみ右側をたどるようにした。 -半径の小さいカーブの対策としてもう一つ、交差点がない区間(これもプログラム起動からの時間で管理した)では交差点を認識する処理を行わないようにした。&br;具体的には、Q地点の右折直後からP地点での左折の少し前までと、P地点を直進で通過してからA地点に到着するまでの2区間で交差点を認識する処理を行わないようにした。 -各交差点での処理は交差点と認識した(させた)回数に応じて挙動を変えるようにした。&br;特にQ地点を左折するときの処理はかなり特殊な方法をとった **プログラム [#o7d8287c] defineでの定義 -モーターの回転力 pow -センサーの閾値 ikiti_bb,ikiti_b,ikiti_w,ikiti_ww -交差点を識別するために連続して曲がっている時間の上限値 tLim -ライントレース中の処理 migi_t,migi,mae,hidari,hidari_t それぞれ右旋回、右折、直進、左折、左旋回をする処理 -ライントレース中の処理 migi_t,migi,mae,hidari,hidari_t&br;それぞれ右旋回、右折、直進、左折、左旋回をする処理 変数 -P・Q地点での処理の回数 X これの値とifを使うことで、交差点での挙動を変えている -連続して曲がっている時間を計るための tt ラインの左側をたどる間は右旋回、右折、直進したときこの値にCurrentTickを代入してリセットしている 右側をたどるときは左旋回、左折、直進のときにリセットしている CurrentTickとの差が設定した上限値tLimを超えたとき、交差点に着いたと認識して交差点での処理に移る -プログラム起動からの時間を計るための t0 交差点を抜けた後やカーブにさしかかる時間を計っておき、CurrentTickとの差に応じてラインのどちらの端をたどるかを管理させている -P・Q地点での処理の回数 X&br;これの値によって交差点での挙動を変えている -連続して曲がっている時間を計るための tt&br;ラインの左側をたどる間は右旋回、右折、直進したときこの値にCurrentTickを代入してリセットしている&br;右側をたどるときは左旋回、左折、直進のときにリセットしている&br;CurrentTickとの差が設定した上限値tLimを超えたとき、交差点に着いたと認識して交差点での処理に移る -プログラム起動からの時間を計るための t0&br;交差点を抜けた後やカーブにさしかかる時間を計っておき、CurrentTickとの差に応じてラインのどちらの端をたどるかを管理させている 製作したプログラム #define pow 25 #define ikiti_bb 30 #define ikiti_b 38 #define ikiti_w 52 #define ikiti_ww 60 #define tLim 350 #define migi_t OnRev(OUT_B,pow);OnFwd(OUT_C,pow); #define migi Off(OUT_B);OnFwd(OUT_C,pow); #define mae OnFwd(OUT_BC,pow); #define hidari OnFwd(OUT_B,pow);Off(OUT_C); #define hidari_t OnFwd(OUT_B,pow);OnRev(OUT_C,pow); task main() { SetSensorLight(S3); int X = 0; long tt = CurrentTick(); long t0 = CurrentTick(); while (true){ while ((CurrentTick() - t0 <= 16000)||(CurrentTick() - t0 >= 40000)&(CurrentTick() - t0 <= 70000)){ // プログラム起動〜16秒、40秒〜70秒 // ラインの左側をたどる処理 if (SENSOR_3 < ikiti_bb) { hidari_t; } else if (SENSOR_3 < ikiti_b) { hidari; } else if (SENSOR_3 < ikiti_w) { mae; tt = CurrentTick(); } else if (SENSOR_3 < ikiti_ww) { migi; tt = CurrentTick(); } else { migi_t; tt = CurrentTick(); } Wait(1); // 一定時間以上左に曲がるか旋回していれば交差点と認識 if (CurrentTick() - tt >= tLim) { if(X == 0) { // P地点を右折(右に旋回後、直進してラインから外れる) Off(OUT_BC); Wait(1000); tt = CurrentTick(); migi_t; Wait(500); OnFwd(OUT_BC,pow); Wait(500); X = X + 1; } else if(X == 1) { // Q地点を右折(直進してラインから外れ、右に旋回してラインに近づける) Off(OUT_BC); Wait(1000); tt = CurrentTick(); OnFwd(OUT_BC,pow); Wait(800); migi_t; Wait(500); X = X + 1; } else if(X == 3) { // Q地点を左折(1度ラインを外れてからさらにラインを跨ぐまで左に旋回) Off(OUT_BC); Wait(1000); hidari_t; until(SENSOR_3 > ikiti_w); until(SENSOR_3 < ikiti_b); until(SENSOR_3 > ikiti_w); tt = CurrentTick(); X = X + 1; } else { // P、Q地点を直進(直進して交差点を通過する) Off(OUT_BC); Wait(1000); tt = CurrentTick(); OnFwd(OUT_BC,pow); Wait(500); X = X + 1; } } } // ラインの左から右に移る処理 migi_t; until(SENSOR_3 < ikiti_b); Wait(200); while ((CurrentTick() - t0 >= 16000)&(CurrentTick() - t0 <= 35000)||(CurrentTick() - t0 >= 70000)){ // 16秒〜35秒、70秒〜(A地点到着まで) // ラインの右側をたどる処理 ただし交差点は認識しない if (SENSOR_3 < ikiti_bb) { migi_t; } else if (SENSOR_3 < ikiti_b) { migi; } else if (SENSOR_3 < ikiti_w) { mae; tt = CurrentTick(); } else if (SENSOR_3 < ikiti_ww) { hidari; tt = CurrentTick(); } else { hidari_t; tt = CurrentTick(); } Wait(1); } while ((CurrentTick() - t0 >= 35000)&(CurrentTick() - t0 <= 40000)){ // 35秒〜40秒 // ラインの右側をたどる処理 if (SENSOR_3 < ikiti_bb) { migi_t; } else if (SENSOR_3 < ikiti_b) { migi; } else if (SENSOR_3 < ikiti_w) { mae; tt = CurrentTick(); } else if (SENSOR_3 < ikiti_ww) { hidari; tt = CurrentTick(); } else { hidari_t; tt = CurrentTick(); } Wait(1); // 一定時間右に曲がるか旋回していれば交差点と認識 if (CurrentTick() - tt >= tLim) { // P地点を左折する処理(左に旋回後、直進してラインから外れる) Off(OUT_BC); Wait(1000); tt = CurrentTick(); hidari_t; Wait(500); OnFwd(OUT_BC,pow); Wait(500); X = X + 1; } } // ラインの右から左に移る処理 hidari_t; until(SENSOR_3 < ikiti_b); Wait(200); } } **問題点・反省点 [#k61aaae4] 凹凸や周りの人の影などの紙面の状況によって交差点を認識するタイミングが変わってしまい、そのせいで上手く曲がることができないことが多かった。&br;閾値の設定を変えたり曲がる処理の部分でモーターを動かす時間を変えたりといった方法はあったはずだが、製作時間が足りなくなってしまい十分な調整ができなかった。