#author("2020-01-10T12:10:01+09:00","kurisuke","kurisuke") #author("2020-01-10T12:11:14+09:00","kurisuke","kurisuke") [[2019b/Member]] 目次 #contents *課題2 [#e4a51b43] 下の図のようなコースを各チームで作成し,A地点を出発して黒い線に沿って進み,Iに置かれたボールをキャッチして出発点に戻るロボットを作成せよ. 私は,コース1を選択した.コース1は下図の赤線の通りで,A-B-D-E-F-G-H-I-J-Aの順番で進む.交差点では1秒間停止し,T字路では直角方向に進入する時のみ一時停止する. &ref(2019b/Member/kurisuke/Mission2/Inked2019b-mission2_LI.jpg,100%,コース図); **今回のポイント [#r93b0d77] 黒線を正確にトレースして進むことができるか,交差点を認識して止まることができるかが大きなポイントであった.また,ロボットのスピードと正確なライントレースのバランスを考えながらプログラムを組むのもポイントであった. *ロボットの説明 [#p4b74d62] **掴む機構 [#af220d59] ボールをしっかりつかみたかったので,掴む機構を両側からアームでボールををつかむ機構にした.歯車でモーターによる縦回転を横回転にしてアームが動くようにした. &ref(2019b/Member/kurisuke/Mission2/S__5455883_LI.jpg,30%,掴む機構); **車体の構造 [#u8debd6b] 基本的な構造は,NXTの設計例に載っているものとほとんど変わらないが,光センサーの取り付ける位置をなるべく床に近づけたいことや,タイヤとの位置を近くしたいということをで下の図のように位置を変えた.これにより,設計例に載っていた車体よりも正確にライントレースすることが可能になっ.また,急カーブや曲がり角の時のロボットと黒線のズレを小さくすることができた. &ref(2019b/Member/kurisuke/Mission2/ロボットの車体.jpg,30%,ロボットの車体); &ref(2019b/Member/kurisuke/Mission2/光センサーの位置.jpg,30%,光センサーの位置); *プログラムの説明 [#k2e277be] **定義 [#tde25d57] プログラムを簡潔にするためや値の変更を簡単にするために以下のように定義した.右左折や旋回は曲がりたい方向のモータを進行方向と逆向きに回転させることで黒線とのずれを少なくし,スムーズにロボットが動くようにした.値に関しては,一般化しようと試みたが時間が足りず何度も実験を重ねる(力技)で導き出した. #define turn_right OnFwd(OUT_C,28); OnFwd(OUT_B,-18); //右折 #define turn_left OnFwd(OUT_B,25); OnFwd(OUT_C,-15); //左折 #define around_right OnFwd(OUT_C,20); OnFwd(OUT_B,-25); //右旋回 #define around_left OnFwd(OUT_B,20); OnFwd(OUT_C,-25); //左旋回 #define go_straight OnFwd(OUT_BC,35); //直進 #define black 35 //黒の値は35 #define black_gray 43 //黒灰の値は43 #define white_gray 57 //白灰色の値は57 #define white 65 //白の値は65 #define catch OnFwd(OUT_A,-15);Wait(250); //ボールキャッチ 下図のように,ライントレースで重要となる閾値は4つに分けて考えた.これをどのように使用したかは次の項目で説明する. &ref(2019b/Member/kurisuke/Mission2/line..png,90%,ライントレースの閾値); **左のライントレース [#f3879664] 私の選んだ課題1は工夫をすれば,左ライントレースだけでゴールまでたどり着けると気づき,右ライントレースのプログラムは用いなかった.左ライントレースのプログラムは以下のようである. void follow_line(long tmin,long tmax) //左トレース { SetSensorLight(S1); long t = CurrentTick(); //ひとつ前のCurrentTick()を作った long t_start = CurrentTick(); //follow_lineのプログラムが開始してからの経過時間 while((CurrentTick()-t<100 || CurrentTick()-t_start<tmin)&& (CurrentTick()- t_start<tmax)){ if(SENSOR_1<black){ around_left;} //値<黒の閾値 else if(SENSOR_1<black_gray){turn_left; t = CurrentTick();} //黒の閾値<値<黒灰の閾値 else if(SENSOR_1<white_gray){ go_straight; t = CurrentTick();} //黒灰の閾値<値<白灰の閾値 else if(SENSOR_1<white){turn_right; t = CurrentTick();} //白灰の閾値<値<白の閾値 else if(SENSOR_1>=white){around_right; t = CurrentTick();} //白の閾値<=値 } Off(OUT_BC); Wait(1000); } ロボットをスムーズに真っ直ぐ進めるために,黒灰と白灰の閾値の間は直進,白灰と白の閾値の間は右折,黒と黒灰の閾値の間は左折するようにプログラムを組んだ.交差点を認識するプログラムは主に6行目から9行目で下の図のように,[閾値]>35の時はt=CurrentTick()としこの二つの差をなくし,[閾値]<35の時,t=CurrentTick()というプログラムを入れないことで二つの差を広げてその差が100(0.1秒)となればば交差点と認識するようにした.100という値は数回の実験により導き出した.tmin(この時間以内は交差点認識を行わない)やtmax(この時間が超えたら強制的にライントレースを終了させる)を使いプログラムに幅を持たせた. ロボットをスムーズに真っ直ぐ進めるために,黒灰と白灰の閾値の間は直進,白灰と白の閾値の間は右折,黒と黒灰の閾値の間は左折するようにプログラムを組んだ.交差点を認識するプログラムは主に6行目から9行目で下の図のように,[閾値]>35の時はt=CurrentTick()としこの二つの差をなくし,[閾値]<35の時,t=CurrentTick()というプログラムを入れないことで二つの差を広げてその差が100(0.1秒)となればば交差点と認識するようにした.100という値は数回の実験により導き出した.また,tmin(この時間以内は交差点認識を行わない)やtmax(この時間が超えたら強制的にライントレースを終了させる)を使いプログラムに幅を持たせた. &ref(2019b/Member/kurisuke/Mission2/交差点認識.png,52%,交差点認識); **ボールをつかむ動き [#n57d5846] void fetch_ball(long t1)//ボールキャッチ { go_straight; Wait(400); Float(OUT_BC); around_left; //ボールの前まで旋回 Wait(1560); Off(OUT_BC); Wait(500); catch; //ボールをつかむ Off(OUT_BC); Wait(4000); around_left; //旋回して方向転換 Wait(t1); Off(OUT_BC); Wait(1000); //以下ライントレースが続く } 今回は,超音波センサーを用いない方針にしたため,プログラムの3行目から9行目でHの交差点からボールの位置への調整移動を行った.これも,数回の実験(力技)により導き出した.また,ボールをつかんでから方向転換するための旋回時では,意外にも左ライントレースのプログラムが役に立った.下図のように,旋回をするときに,黒線の左側を超えてしまえばあとは白の閾値以上のため右旋回を行い,黒線の左側に自動的に戻ってくれるのである. &ref(2019b/Member/kurisuke/Mission2/sennkai.png,40%,旋回の説明); **交差点を渡る [#h7445faa] 交差点を渡るプログラムは下のようになる.交差点を認識したときに少し左に曲がるので,それを修正するために右折のプログラムを加えた.今回も,交差点を越えることができればライントレースのプログラムにより修正してくれるので確実に越えるため,直進する時間を少し長めにとった. void intersection_straight() { turn_right; //右折 Wait(100); go_straight; // 直進 Wait(300); Off(OUT_BC); //以下ライントレースが続く } **メインプログラム [#w2083b3d] 少し長いマクロをインライン関数を使うことで,メインのプログラムが簡潔になった.GからHまでは交差点を左折するときに再度交差点認識をしてしまうためtminを使って修正した.同様に,IからAまでにある初めのカーブは急なため交差点認識をしてしまうことがあったのでtminを使って修正した.最初と最後の“go_straight”はAの枠内からしっかりスタートするためとAの枠内にしっかりとロボットが入るようにするためである. task main() { go_straight; Wait(1500); follow_line(0,50000);//AからD intersection_straight();//交差点 follow_line(900,50000);//DからG follow_line(2500,5000);//GからH fetch_ball(3550);//HからI follow_line(10000,500000);//IからA go_straight; Wait(1500); Off(OUT_BC);//終了 } *課題2の反省と感想 [#f0f14ef7] 今回は,課題1の時よりもプログラミングに慣れ大まかなプログラムの作成には手間取ることがなかった.ロボット本体の作成に関しても,過去の受講生の考えやチームメイトの考えを参考にして,授業時間内に作り終えることができた.しかし,ボールをとる動作時に,ロボット全体を大きく作りすぎたため,超音波センサーを取り付けることができなかった.後から,他の受講生のロボットを見た時,超音波センサーをロボットの車体の上に付け,横からではなく上からボールの位置を特定しているチームが多数あり,私たちのチームも同じ方法を採用していたらうまくいっていたかもしれないと思った.また,正確さを優先しすぎたため,速度が落ちてしまった. 次の課題3では,今までの課題の反省を生かして,さらに良いロボットをつくり成功させたいと思う.