#author("2020-01-12T16:59:27+09:00","udon","udon") [[2019b/Member]] *目次 [#ac4c4c45] #contents *課題2:ライントレースして、ボールを取り、元の位置に戻る [#s14c0288] **コース [#k5e444b6] #ref(2019b-mission2.png) 私は二人目だったので、コースは -1 A地点から出発 -2 J -3 H (直進) -4 I (ボール or キューボイドをつかんでUターン) -5 H (右折) -6 G (一時停止の後、直進) -7 D (右折) -8 E, F 通過 -9 G (一時停止の後、直進) -10 C (一時停止の後、左折) -11 B (一時停止) -12 A地点に入る(ゴール) のルートをたどる。 *ロボットの説明 [#mf0767a0] 今回の課題では下の写真のロボットを使用した。 #ref(IMG_1407.jpeg) このロボットは3つ目のモーターを利用してアームを動かし、上からアームを下ろしてボールを取ることができるようにした。 #ref(IMG_1420.jpeg) また、光センサーの反応がロボットの動きによって誤作動を起こさないように、光センサーを紙面と垂直になるように設置し、できるだけ固定した。 #ref(IMG_1410.jpeg) *プログラミングの説明 [#cb858ddd] **ロボットの動作 [#hdc9d9d0] #define SPEED_X 40 #define SPEED_L 30 #define turn_right1 OnRL(-SPEED_L,SPEED_L); #define turn_left1 OnRL(SPEED_L,-SPEED_L); #define turn_right2 OnRL(-SPEED_L,SPEED_L); #define turn_left2 OnRL(SPEED_L,-SPEED_L); #define go_forward OnFwd(OUT_BC,30); #define go OnFwd(OUT_BC,30);Wait(800); #define right Off(OUT_B);OnFwd(OUT_C,40);Wait(300); #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL); float GetAngle(float d) { const float diameter=5.45; const float pi=3.1415; const float distance=12.5; float ang=(distance*d)/diameter; return ang; } void u_turn() { int angle=GetAngle(160); RotateMotorEx(OUT_BC,SPEED_L,angle,100,true,true); } void turn1() { int angle=GetAngle(90); RotateMotorEx(OUT_BC,SPEED_L,angle,-100,true,true); } このようにしてロボットの前進や旋回、そして回転を定義した。 **ライントレース(左)[#v3a80993] void follow_lineleft() { long to; SetSensorLight(S3); to=CurrentTick(); while(CurrentTick()-to <100){ if(SENSOR_3<36){ turn_left1 }else{ if(SENSOR_3>59){ turn_right1 to=CurrentTick(); }else if((51<=SENSOR_3)&&(SENSOR_3<=59)){ turn_right2 to=CurrentTick(); }else if((42<SENSOR_3)&&(SENSOR_3<51)){ go_forward to=CurrentTick(); turn_left2 to=CurrentTick(); }}} Off(OUT_BC); } このプログラミングで黒線の左側をライントレースできるようにした。さらに交差点で止まるため、光センサーの数値が36を下回る時間が、0.1秒より長くなると止まるように値を定めた。 **ライントレース(右) [#rded0106] void follow_lineright1(long tmin=2000, long tmax=10000) {   long to; SetSensorLight(S3); to=CurrentTick(); while(CurrentTick()-to<80){ if(SENSOR_3<36){ turn_right1 }else{ if(SENSOR_3>59){ turn_left1 to=CurrentTick(); }else if((51<=SENSOR_3)&&(SENSOR_3<=59)){ turn_left2 to=CurrentTick(); }else if((42<SENSOR_3)&&(SENSOR_3<51)){ go_forward to=CurrentTick(); }else{ turn_right2 to=CurrentTick(); }}} Off(OUT_BC); } void follow_lineright2(long t) {   long to; SetSensorLight(S3); to=CurrentTick(); while(CurrentTick()-to<t){ if(SENSOR_3<36){ turn_right1 }else{ if(SENSOR_3>59){ turn_left1; }else if((51<=SENSOR_3)&&(SENSOR_3<=59)){ turn_left2; }else if((42<SENSOR_3)&&(SENSOR_3<51)){ go_forward; }else{ turn_right2; }}} Off(OUT_BC); } 地点IでUターンして地点Hで右折するためには、Uターンした後黒線の右側をライントレースするようにしなければならなかったので、このプログラミングを用いた。 また、tminをうまく用いることができなかったため、follow_lineright2のプログラミングをし、時間tに達するまで交差点で止まらず、ライントレースするようにした。 **ボールを取る [#rddcefd4] void fetch_ball() { SetSensorLowspeed(S1); int d,s; long to; to=CurrentTick(); while(CurrentTick()-to<100){ d=SensorUS(S1); if(d<10){ OnFwd(OUT_A,-20);Wait(700);Off(OUT_A);} else{ go_forward; to=CurrentTick(); }} Wait(1000); u_turn(); } このプログラミングで、超音波センサーが反応したらアームを下ろし、ボールを取ってUターンできるようにした。 **main関数 [#dc1c7dbf] task main() { SetSensorLight(S3); go; follow_lineleft(); Wait(500); right; ここまでで地点Aを出発して地点Jを通り、地点Hを直進した。 fetch_ball(); Wait(2000); follow_lineright2(4000); ここまでで地点Iにあるボールを取り、Uターンして地点Hで右折した。 follow_lineright1(); go; follow_lineright2(8500); follow_lineright1(); go; ここまでで地点Gを直進し、地点D,E,Fを右折して、再び地点Gを直進した。 follow_lineright1(); turn1(); go; follow_lineleft(); go; } そして最後に地点Cを左折し、地点Bで一時停止して地点Aに戻ってきた。 *今回の課題の反省点や感じたこと [#w1704261] 今回の課題では、課題1よりも時間がかかり、特にロボットを考えるのにとても苦労した。発表会ではボールを取った後Uターンするとき、ボールを固定するために置いていたタイヤが、後輪に引っかかってしまったのでゴールすることができなかった。練習ではうまくいっていたため、本番で失敗してしまいとても残念だった。また、最後にもう一度うまく走るか確認してから、本番に挑むべきだったと思ったので、次の課題ではこのようなことがないようにしっかりと最終調整してから本番に挑むようにしたい。