#author("2020-01-09T15:13:35+09:00","minami","minami") #contents *課題2 [#j9c6ac10] #ref(./S__17530895.jpg,600x400,コース); 1. A地点から出発~ 2. B~ 3. C (直進)~ 4. D (一時停止の後、直進)~ 5. E, F 通過~ 6. G (一時停止の後、左折)~ 7. H (一時停止の後、左折)~ 8. I (ボール or キューボイドをつかんでUターン)~ 9. H(直進)~ 10.J (一時停止)~ 11.A地点に入る(ゴール)~ *ロボットの説明 [#o297fb89] **センサ [#n93287a7] #ref(./S__17530898.jpg,500x300,センサー); 光センサーはできるだけ地面に近づけ、周りの環境の影響を受けにくいように工夫した。~ 超音波センサーは上から地面の方向につけた。~ 初めは、前向きにつけていたがそれだと上手くボールを見つけることが出来なかった。~ **アーム [#cf3930d2] #ref(./S__17629191.jpg,500x300,コース); *プログラミングの説明 [#nab36970] **閾値と進行方向の設定 [#a65a5ec6] &ref(2019b/Member/minami/Mission2/S__17547277.jpg,450x250,光センサの値); &ref(2019b/Member/minami/Mission2/S__17547275.jpg,550x250,進行方向); #define average 50 //基準の値 #define go1 OnFwd(OUT_B,30);OnFwd(OUT_C,-20); //go1の方向に進む(図参照) #define go2 OnFwd(OUT_B,20);OnFwd(OUT_C,-10); //go2の方向に進む(図参照) #define go3 OnFwd(OUT_BC,30); //go3の方向に進む(図参照) #define go4 OnFwd(OUT_B,-10);OnFwd(OUT_C,30); //go4の方向に進む(図参照) #define go5 OnFwd(OUT_B,-20);OnFwd(OUT_C,30); //go5の方向に進む(図参照) 基準の値との差で進行方向を考えるプログラムを作ったので、他のコースでする場合でも基準の値を変えるだけでそれなりにライントトレースすることが出来る。 **右左折と直進の設定 [#ga091e3b] ●左折~ 当初、変数を用いなかったが左折する場面が数回ありそれぞれで微調整出来るように変数を用いた。 #define left(s,t) OnFwd(OUT_B,s);Wait(t);Off(OUT_B); //左折 右折も作ったが今回使うことはなかった。 #define right(s,t) OnFwd(OUT_C,s);Wait(t);Off(OUT_C); //右折 ●直進~ 左折と同様の理由で変数を用いた。 #define straight(s_b,s_c,t) OnFwd(OUT_B,s_b);OnFwd(OUT_C,s_c);Wait(t);Off(OUT_BC); //直進 直進プログラムの変数を変えることで右左折することが出来るが、メインプログラムを見たとき一目で分かりやすいようにあえて右左折それぞれ分けてみた 。 **Uターンとボールをとる動作の設定 [#d3e07315] #define uturn OnFwd(OUT_B,-75);OnFwd(OUT_C,70);Wait(700);Off(OUT_BC); //Uターン #define ball OnFwd(OUT_A,-30);Wait(300);Off(OUT_A); //ボール この2つを用いてロボットを動かすと、ボールをとりUターンすることが出来た。 **ライントレース [#q63fb666] 交差点を認識するライントレースのプログラムを作った。 交差点を認識するために、左側の場合はgo1の動作を連続で何秒間か行った場合プログラムが終了するサブルーチンを作った。~ また右側の場合はgo5の動作で考える。 ●左側のライントレース sub LeftSide(int Stop_time) { long tL = CurrentTick(); while (CurrentTick() -tL < Stop_time{ //Stop_timeの時間go1をするとプログラムは終了 if (SENSOR_1 < average-11){ go1; }else if (SENSOR_1 < average-7){ go2; tL = CurrentTick(); //go2の最中は続行 }else if (SENSOR_1 < average+7){ go3; tL = CurrentTick(); //go3の最中は続行 }else if (SENSOR_1 < average+11){ go4; tL = CurrentTick(); //go4の最中は続行 }else{ go5; tL = CurrentTick(); //go5の最中は続行 } } Off(OUT_BC); } ●右側のライントレース sub RightSide(int Stop_time) { long tR = CurrentTick(); while (CurrentTick() -tR < Stop_time{ //Stop_timeの時間go5をするとプログラムは終了 if (SENSOR_1 < average-11){ go5; }else if (SENSOR_1 < average-7){ go4; tR = CurrentTick(); //go4の最中は続行 }else if (SENSOR_1 < average+7){ go3; tR = CurrentTick(); //go3の最中は続行 }else if (SENSOR_1 < average+11){ go2; tR = CurrentTick(); //go2の最中は続行 }else{ go1; tR = CurrentTick(); //go1の最中は続行 } } Off(OUT_BC); } 右側を使うつもりはなかったが、コース終盤の小回りが左側だと交差点だと認識してしまい上手くいかなかったので、少しでも大回りになる右側のライントレースも作った。 **超音波センサーでボールを見つける [#abc76d08] まず、このプログラムは成功しなかった。~ 今回の課題でwhileの使い方が身についていないことが分かった。 #ref(./S__17547278.jpg,500x400,センサー); sub Ball_Stop() { while (true) { LeftSide(1000); //10秒以上go1するとまでループ if (SensorUS(S2)<4){ //もし超音波センサーとの距離が4cm未満なら ball; //ballの動作を行う } } Off(OUT_BC); } これだとtrueの間、つまり永久にLeftSide(1000)が実行されてしまうのだと思う。~ なのでwhileを使わず以下のようなプログラムを考えた。~ しかし時間の都合でこのプログラムを実行することは出来なかったので、実際の所は分からない。 sub Ball_Stop2() { if (SensorUS(S2)>4) { //もし超音波センサーとの距離が4cm以上なら LeftSide(1000); //10秒以上go1するまで左側のライントレースをする }else{ //そうでないなら ball; //ballの動作を行う } Off(OUT_BC); } **メインプログラム [#k63c86de] #define average 50 //基準の値 #define go1 OnFwd(OUT_B,30);OnFwd(OUT_C,-20); //go1の方向に進む(図参照) #define go2 OnFwd(OUT_B,20);OnFwd(OUT_C,-10); //go2の方向に進む(図参照) #define go3 OnFwd(OUT_BC,30); //go3の方向に進む(図参照) #define go4 OnFwd(OUT_B,-10);OnFwd(OUT_C,30); //go4の方向に進む(図参照) #define go5 OnFwd(OUT_B,-20);OnFwd(OUT_C,30); //go5の方向に進む(図参照) #define left(s,t) OnFwd(OUT_B,s);Wait(t);Off(OUT_B); //左折 #define right(s,t) OnFwd(OUT_C,s);Wait(t);Off(OUT_C); //右折 #define straight(s_b,s_c,t) OnFwd(OUT_B,s_b);OnFwd(OUT_C,s_c);Wait(t);Off(OUT_BC); //直進 #define uturn OnFwd(OUT_B,-75);OnFwd(OUT_C,70);Wait(700);Off(OUT_BC); //Uターン #define ball OnFwd(OUT_A,-30);Wait(300);Off(OUT_A); //ボール sub LeftSide(int Stop_time) //左側のライントレース { long tL = CurrentTick(); while (CurrentTick() -tL < Stop_time{ //Stop_timeの時間go1をするとプログラムは終了 if (SENSOR_1 < average-11){ go1; }else if (SENSOR_1 < average-7){ go2; tL = CurrentTick(); //go2の最中は続行 }else if (SENSOR_1 < average+7){ go3; tL = CurrentTick(); //go3の最中は続行 }else if (SENSOR_1 < average+11){ go4; tL = CurrentTick(); //go4の最中は続行 }else{ go5; tL = CurrentTick(); //go5の最中は続行 } } Off(OUT_BC); } sub RightSide(int Stop_time) //右側のライントレース { long tR = CurrentTick(); while (CurrentTick() -tR < Stop_time{ //Stop_timeの時間go5をするとプログラムは終了 if (SENSOR_1 < average-11){ go5; }else if (SENSOR_1 < average-7){ go4; tR = CurrentTick(); //go4の最中は続行 }else if (SENSOR_1 < average+7){ go3; tR = CurrentTick(); //go3の最中は続行 }else if (SENSOR_1 < average+11){ go2; tR = CurrentTick(); //go2の最中は続行 }else{ go1; tR = CurrentTick(); //go1の最中は続行 } } Off(OUT_BC); } sub Ball_Stop() //このサブルーチンは成功していない { while (true) { LeftSide(1000); //10秒以上go1するとまでループ if (SensorUS(S2)<4){ //もし超音波センサーとの距離が4cm未満なら ball; //ballの動作を行う } } Off(OUT_BC); } ~ task main() { SetSensorLight(S1); //光センサ起動 SetSensorLowspeed(S2); //超音波センサ起動 LeftSide(150); //1.5秒go1を繰り返すまで左側のライントレース Wait(1000); //交差点直前で1秒停止 straight(20,30,500); //交差点を 直進 LeftSide(180); //1.8秒go1を繰り返すまで左側のライントレース Wait(1000); //交差点で1秒停止 left(70,600); //交差点を左折 Ball_Stop(); //ボールを探し、キャッチする uturn; //Uターン RightSide(100); //1秒go5を繰り返すまで右側のライントレース straight(20,30,500); //直進してゴール } *まとめ [#y99ee845] 結果として課題を成功させることが出来なかった。~ 主な反省点は、「急カーブと交差点の見分け」「交差点を横断する動きの正確性に欠ける」「while文が使えていない」の3点である。~ 改善策として、tmaxやtminを含んだプログラミングを作ることで正確に交差点を認識できるのではないかと考えた。~ また、交差点認識後の右左折直進に関して、今回のプログラミングでは電池の残量などにより若干の誤差が出たので~ 黒を見つけるまで左折するようなプログラミングなら残量などの影響を受けないのではと考えた。~ ~ 今回は、成功出来なかった分、学ぶことがたくさんあった課題となった。~ ロボットに関してもプログラミングに関しても途中で臨機応変に変更していけたのはよかったと思う。~ 次回が最終課題となるが、今回の失敗を活かし成功させたいと感じた。