ライントレース 目次 #contents *課題2 [#n70edb74] **課題内容 [#j3f036d2] 次のいずれかのコースで黒い線に沿って動き、350mlの空き缶(黄色で表示)を移動させるロボットを製作せよ。 (相棒と違うコースを選ぶこと) #ref(./kadai2.map.png,100%,コース) ***選択したコース(第一コース) [#oc7d314c] 1.Aをスタート 2.Bを直進 3.Cで一時停止の後、直進 4.Dで一時停止の後、Xの空き缶をキャッチしてD地点に戻る 5.DからEに向かい、Eを直進 6.Fを左折 7.Gで一時停止の後、左折 8.Hで一時停止の後、右折 9.Iで一時停止の後、右折 10.Lを直進 11.Kを直進 12.Jで一時停止の後、空き缶をYに置きてJに戻りBに向かう 13.Bで一時停止の後、左折 14.Aで停止 (一時停止の指定がある場所は、1秒間停止すること) *ロボット本体 [#s256262b] **ロボットの概形 [#r71aaaee] #ref(./r1.jpg,100%,ロボット概形) 今回は車体が丈夫で安定したロボット!! クワガタとヘラクレスが合体してできたような形なので「ヘラクワミン」と命名しましょう! **ロボットの説明 [#t86b2e37] #ref(./rsk.jpg,80%,ロボット機構説明) ・赤枠が光センサーの位置を示し、ライントレースに利用する。 ・ピンク枠が缶を所定の位置に誘導する。 ・紫枠が所定の位置にある缶の固定をする。 #ref(./r3k.jpg,50%,センサー説明) 最初は青枠の所に光センサーを設置していたが、認識してから動き出すまでにラグが発生してしまう。光センサーは車体旋回における中心点より少し前に設置したほうが調子がいいことが分かった。 #ref(./rk.jpg,50%,ロボット機構説明) 黒い誘導である程度の範囲にある缶を回収し、所定の位置に収まると腕(アームが下がり)しっかり固定することができる。缶を離す時もしっかり所定の位置に缶を置くことができる。欠点は黒い誘導のせいで受け取る前、離す前に若干缶に触れてしまうことがある。 #ref(./r2k.jpg,90%,ロボット機構説明) -モータA 左側のタイヤを動かすことに使う -モータB 右側のタイヤを動かすことに使う -モータC 腕(アーム)を上げたり、下げたりするのに使う -光センサー3 *プログラムについて [#va73175c] **戦略 [#qbd8b886] #ref(./sen.jpg,90%,戦略図) 進む順番(光センサー)がたどる位置は図の赤(行き)、オレンジ(缶を持っていく)、紫(帰り)の順に進んでいく。 できるだけ曲がりやすいまたは一時停止しやすいように黒線の左、右を選んでいく。 緑の星印のある位置で一時停止 青枠の所では黒を越すように進む -C交差点で止まれるようにはじめは黒線の左側を通る -CからDにかけての直角では後のD交差点で止まれるように一度黒線を超すことにする(直角を 曲がれてしまうとD交差点も止まらず進んでしまう) -円(DEF)を通る時は外側(右回り時、線の左)にする(内側であると周り続ける) -GからHにかけての直角、急カーブをのり超えるために所々で黒線を越える(とても安定する) -円(IJKL)を通る時は外側(左回り時、線の右)にする(内側であると周り続ける) 結論 直角、急カーブを進む際は黒線を超えたほうが簡単に進める **プログラム [#e44bad3e] ***define,subルーチンについて [#aa009c1b] #define THRESHOLD 45 //基準(中間値)となる光の値 #define CROSSTIMER 10 //黒線でいくつで止まるか #define RETIMER 30 //軌道修正でよく使う #define STEP 1 #define TIMER1 10 //便利値10 #define TIMER2 20 //便利値20 #define TIMER100 100 //便利値100 #define STOPTIMER 200 //停止時の時間200 #define tunoTIME 30 //角の時間 動きを縦、斜め右、斜め左、右、左の五段階にした(動きを精密にできる) #define GO OnFwd(OUT_AC); //まっすぐ進む #define BACK OnRev(OUT_AC); //後ろ #define turn_left OnFwd(OUT_A);Off(OUT_C); //左回り #define turn_right Off(OUT_A);OnFwd(OUT_C); //右回り #define turn_hleft OnFwd(OUT_A);OnRev(OUT_C); //右旋回 #define turn_hright OnRev(OUT_A);OnFwd(OUT_C); //左旋回 #ref(./mitori.png,90%,方向図) subルーチン 光センサー:白(52〜)、白灰(46〜52)、灰(44〜46)、黒灰(38〜44)、黒(〜38) ・黒の時に旋回を入れないことで止まりやすい。左をたどる #ref(./kurosho.png,90%,A) sub tracestopl() //左をたどり時間止まり(黒小) { int n=0; while(n<CROSSTIMER){ if(SENSOR_3<THRESHOLD-1){ turn_left;n++; }else{ if(SENSOR_3<THRESHOLD+1){ GO; }else if(SENSOR_3<THRESHOLD+7){ turn_right; }else{ turn_hright; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); } ・黒の時に旋回を入れないことで止まりやすい。右をたどる #ref(./kuros.png,90%,B) sub tracestopr() //右をたどり時間止まり(黒小) { int n=0; while(n<CROSSTIMER){ if(SENSOR_3<THRESHOLD-1){ turn_right;n++; }else{ if(SENSOR_3<THRESHOLD+1){ GO; }else if(SENSOR_3<THRESHOLD+7){ turn_left; }else{ turn_hleft; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); } ・急カーブでも対応できる #ref(./kurodai.png,90%,C) sub tracestophl() //左をたどり時間止まり(黒白大) { int n=0; while(n<CROSSTIMER){ if(SENSOR_3<THRESHOLD-6){ turn_hleft;n++; }else{ if(SENSOR_3<THRESHOLD-1){ turn_left; }else if(SENSOR_3<THRESHOLD+1){ GO; }else if(SENSOR_3<THRESHOLD+8){ turn_right; }else{ turn_hright; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); } ・どちらも旋回を入れないためなめらかな線をたどる時安定する #ref(./kss.png,90%,D) sub tracestoprr() //右をたどり時間止まり(黒白小) { int n=0; while(n<CROSSTIMER){ if(SENSOR_3<THRESHOLD-1){ turn_right;n++; }else{ if(SENSOR_3<THRESHOLD+1){ GO; }else{ turn_left; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); } 黒を越し線をたどるプログラム #define STOPGOr while(SENSOR_3<THRESHOLD+7){GO;} tracestopr(); #define STOPGOl while(SENSOR_3<THRESHOLD+7){GO;} tracestopl(); ***task main [#i51a3086] task main() { SetPower(OUT_AC,3); //モータACの力を3にする SetPower(OUT_B,2); //モータBの力を2にする SetSensor(SENSOR_3,SENSOR_LIGHT); GO;Wait(80); //抜け出し tracestopl(); Off(OUT_AC);Wait(STOPTIMER); //C交差点止まる turn_right;Wait(RETIMER); tracestopl(); Off(OUT_AC);Wait(TIMER1); //直角止まる STOPGOr; Off(OUT_AC);Wait(TIMER1); //D交差点止まる turn_hleft;Wait(RETIMER); //つかむため軌道修正 Off(OUT_AC);Wait(STOPTIMER); GO;Wait(TIMER100);Off(OUT_AC); OnFwd(OUT_B);Wait(tunoTIME);Off(OUT_B);Wait(STOPTIMER); //缶をつかむ while(SENSOR_3>THRESHOLD-7){BACK;} while(SENSOR_3<THRESHOLD+1){turn_hleft;} GO;Wait(TIMER1); tracestopl(); turn_right;Wait(RETIMER); //E交差点通過 tracestophl(); Off(OUT_AC);Wait(STOPTIMER); //Fを通過後、G交差点止まる STOPGOr; STOPGOl; STOPGOr; STOPGOl; Off(OUT_AC);Wait(STOPTIMER); //H交差点止まる GO;Wait(RETIMER); turn_hright;Wait(140); //H交差点曲がる Off(OUT_AC);Wait(TIMER1); tracestoprr(); Off(OUT_AC);Wait(STOPTIMER); //I交差点止まる while(SENSOR_3<THRESHOLD+1){turn_hright;} GO;Wait(TIMER1); tracestopr(); turn_left;Wait(RETIMER); //L交差点通過 tracestopr(); turn_left;Wait(RETIMER); //K交差点通過 tracestopr(); Off(OUT_AC);Wait(STOPTIMER); //J交差点止まる GO;Wait(TIMER2); turn_hleft;Wait(160); //Jターン GO;Wait(TIMER2);Off(OUT_AC); OnRev(OUT_B);Wait(tunoTIME);Off(OUT_B);Wait(STOPTIMER); //缶放す BACK;Wait(80); turn_hright;Wait(160); tracestopl(); Off(OUT_AC);Wait(STOPTIMER); //直角B止まる STOPGOr; Off(OUT_AC);Wait(TIMER1); turn_hleft;Wait(RETIMER); Off(OUT_AC);Wait(STOPTIMER); //Aの前で止まる GO;Wait(TIMER100);Off(OUT_AC); //帰還!! } 交差点認識時音が鳴る。 缶を掴む際の進む時間、交差点で曲がる時曲がる時間、缶の話す位置にもっていく時間や離した後の下がる時間を手動入力した。出来れば手動入力を極力避けたい。 旋回を手動入力した際に線に戻る時少し前進したほうが調子がいい。H交差点では曲がる前に少し前進する。(理由:旋回後、下図の右の状態になってしまうので左の状態にもっていかないといけないから) 直角に曲がった後または前に(特に旋回を手動入力した際)に少し前進したほうがトレースがうまくいく。(理由:旋回後、下図の右の状態になってしまうので左の状態にもっていかないといけないから)原因は光センサーが車体の前についているため #ref(./tokus.png,70%,説明) 図の右側の場合自分のプログラムでは交差点と認識してしまう。よって右の状態は避けなければならない。 *まとめ [#qc55f982] **結果(動画リンク) [#h9a118a1] 成功した。まれに電圧の関係などで一部調子悪くなる。 全班の中で最速を目指せれると思う!!!ただ早すぎてミスも少々、おっちょこちょい https://youtu.be/n1soAQYhX14 **感想 [#ea51db5b] この課題を終えてまず感じたことはプログラミングが理解することができ、使えるようになったと感じた。ある程度のことができるようになりロボット制作共にプログラミングがより楽しくなったと感じた。ほかの人のプログラムを見ると皆が違い面白いと思った。今回の課題は思いのほか上手にできたと思う。しかし電圧に左右されないロボットを作ることができず少し残念。次回のミニロボコンは「これまで」を出せれたらと思う。