#contents *ロボットの説明 [#xefd4b91] **ロボット全体 [#s0fe2ba3] ベースはそのまま使用し、前方の光センサーを少しタイヤ近づけました。 #ref(2016a/Member/kurokouchi/Mission2/01.jpg,100%,01) **ロボットの改良 [#qfc487e6] ロボットの後ろタイヤを外し、カーブを曲がりやすくしました。 #ref(2016a/Member/kurokouchi/Mission2/03.jpg,100%,01) カーブを曲がりやすくしたことで短い区間でも機体の姿勢を戻すことが出来る様になりました。 #ref(2016a/Member/kurokouchi/Mission2/04.jpg,100%,01) しかし、機体が左右に細かく動くためタイヤが外れやすくなりました。また、交差点をカーブとして認識することが多いことなど安定性があまりないため上の機体の状態に戻しました。 *プログラムの説明 [#o7f33ffa] **ライントレース [#a6417992] 線の左側境界部分をトレースするプログラムです。 光センサーでの色判別は - 白部分・・・・光センサーの値:52以降 - 弱白部分・・・光センサーの値:50以降〜52以下 - 境界部分・・・光センサーの値:42以降〜50以下 - 弱黒部分・・・光センサーの値:38以降〜42以下 - 黒部分・・・・光センサーの値:38未満 とする。 タイマーについては - FastTimer(0):交差点判別用のタイマー ~ 光センサーが黒部分の判定をしている時にカウントをして、0.3秒以上続いたら交差点として判別する。また、黒部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。 - FastTimer(1):交差点誤判別防止用のタイマー ~ 小さなカーブを交差点として誤判別しないために指定秒数間交差点判別を行わないようにする。ここで、指定秒数を変数としてl_timeをグローバル変数として定義する。また、ライントレース開始時にClearTimer(1)でFastTimer(1)を初期化する。 とする。 sub line_l(){ int ch=0; //ループ脱出用変数 ClearTimer(0); //交差点判別用のタイマー初期化 ClearTimer(1); //交差点誤判別防止用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { if(SENSOR_2 > 52) //白部分 右回転 int ch=0; //ループ脱出用変数 ClearTimer(0); //交差点判別用のタイマー初期化 ClearTimer(1); //交差点誤判別防止用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnFwd(OUT_A); OnRev(OUT_C); if(SENSOR_2 > 52) //白部分 右回転 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnFwd(OUT_A); OnRev(OUT_C); } else if(SENSOR_2 > 50) //弱白部分 右旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_A); Off(OUT_C); } else if(SENSOR_2 > 42) //境界部分 直進 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,4); //直進部分では素早く進むために力を強めに設定する OnFwd(OUT_A); OnFwd(OUT_C); } else if(SENSOR_2 >38 ) //弱黒部分 左旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_C);; Off(OUT_A); } else{ //黒部分 左回転 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnRev(OUT_A); OnFwd(OUT_C); } if(FastTimer(0)>30&&FastTimer(1)>l_time){ //交差点判別 Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } else if(SENSOR_2 > 50) //弱白部分 右旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_A); Off(OUT_C); } else if(SENSOR_2 > 42) //境界部分 直進 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,4); //直進部分では素早く進むために力を強めに設定する OnFwd(OUT_A); OnFwd(OUT_C); } else if(SENSOR_2 >38 ) //弱黒部分 左旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_C);; Off(OUT_A); } else{ //黒部分 左回転 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnRev(OUT_A); OnFwd(OUT_C); } if(FastTimer(0)>30&&FastTimer(1)>l_time){ //交差点判別 Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } } **交差点の判別 [#m4335358] 上記のライントレース用プログラム内の交差点判別部分について詳しく説明する。 if(FastTimer(0)>30&&FastTimer(1)>l_time){ //交差点判別 Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } 交差点は黒部分が長く続いた時に交差点として判別するようにした。そこでタイマーを使い黒部分以外の時は以下の関数でタイマーを初期化するようにした。また交差点と判別したことが分かるように、判別したら音を鳴らすようにした。 ClearTimer(0); タイマーが0.3秒より長い時間が経過した時に交差点として判別する。 if(FastTimer(0)>30) しかし、上記のプログラムではカーブを交差点として誤判別してしまう事があるので、それを防ぐためにタイマーをもう一つ追加して次の指定秒数をカウントしなければ交差点と判別しないようにした。 if(FastTimer(0)>30&&FastTimer(1)>l_time) l_timeを上記の指定秒数として、メインプログラムで指定する。 **交差点での処理 [#pffb2821] 前進 #ref(2016a/Member/kurokouchi/Mission2/08.png,100%,01) 角度を戻してそのまま直進する。 sub top(){ OnRev(OUT_C); OnFwd(OUT_A); Wait(40); OnFwd(OUT_AC); Wait(10); OnRev(OUT_C); OnFwd(OUT_A); Wait(40); OnFwd(OUT_AC); Wait(10); } 左折 #ref(2016a/Member/kurokouchi/Mission2/07.png,100%,01) 角度を戻してそのままライントレースさせる。 sub left(){ OnRev(OUT_A); OnFwd(OUT_C); Wait(20); OnRev(OUT_A); OnFwd(OUT_C); Wait(20); } 右折 #ref(2016a/Member/kurokouchi/Mission2/09.png,100%,01) 角度を右寄りにして外側の線に機体を移動する。 sub right(){ OnRev(OUT_C); OnFwd(OUT_A); Wait(80); OnRev(OUT_C); OnFwd(OUT_A); Wait(80); } **特別な交差点の判別 [#u883c8f5] #ref(2016a/Member/kurokouchi/Mission2/06.png,100%,01) 上の様な交差点判別するにはロボットの姿勢をすぐに戻さなければいけないが、機体の性能上判別が困難なため以下のプログラムを追加した。 sub line_r(){ int ch=0; //ループ脱出用変数 ClearTimer(0); //交差点判別用のタイマー初期化 ClearTimer(1); //交差点誤判別防止用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { if(SENSOR_2 > 52) //白部分 左回転 int ch=0; //ループ脱出用変数 ClearTimer(0); //交差点判別用のタイマー初期化 ClearTimer(1); //交差点誤判別防止用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnFwd(OUT_C); OnRev(OUT_A); if(SENSOR_2 > 52) //白部分 左回転 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnFwd(OUT_C); OnRev(OUT_A); } else if(SENSOR_2 > 50) //弱白部分 左旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_C); Off(OUT_A); } else if(SENSOR_2 > 42) //境界部分 直進 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,4); //直進部分では素早く進むために力を強めに設定する OnFwd(OUT_A); OnFwd(OUT_C); } else if(SENSOR_2 >38 ) //弱黒部分 右旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_A);; Off(OUT_C); } else{ //黒部分 右回転 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnRev(OUT_C); OnFwd(OUT_A); } if(FastTimer(0)>30&&FastTimer(1)>l_time){ //交差点判別 Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } else if(SENSOR_2 > 50) //弱白部分 左旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_C); Off(OUT_A); } else if(SENSOR_2 > 42) //境界部分 直進 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,4); //直進部分では素早く進むために力を強めに設定する OnFwd(OUT_A); OnFwd(OUT_C); } else if(SENSOR_2 >38 ) //弱黒部分 右旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 SetPower(OUT_AC,2); //旋回しすぎないように力を弱めに設定する OnFwd(OUT_A);; Off(OUT_C); } else{ //黒部分 右回転 SetPower(OUT_AC,2); //回転しすぎないように力を弱めに設定する OnRev(OUT_C); OnFwd(OUT_A); } if(FastTimer(0)>30&&FastTimer(1)>l_time){ //交差点判別 Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } } これによってひとつ前の交差点から線の左側をトレースしていたものを右側をトレースさせるようにした。 **最後の交差点の判別 [#jc9ff40f] ゴール地点の四角の中に入るために、最後の交差点を判別したら以下の処理を実行する。 sub last(){ OnRev(OUT_C); //姿勢をまっすぐにする OnFwd(OUT_A); Wait(40); OnFwd(OUT_AC); //前進 Wait(200); //2秒間待つ Off(OUT_AC); //停止 ClearTimer(0); //交差点判別用のタイマー初期化(初期化しなくてもよいが最後なので一応初期化) ClearTimer(1); //交差点誤判別防止用のタイマー初期化(初期化しなくてもよいが最後なので一応初期化) OnRev(OUT_C); //姿勢をまっすぐにする OnFwd(OUT_A); Wait(40); OnFwd(OUT_AC); //前進 Wait(200); //2秒間待つ Off(OUT_AC); //停止 ClearTimer(0); //交差点判別用のタイマー初期化(初期化しなくてもよいが最後なので一応初期化) ClearTimer(1); //交差点誤判別防止用のタイマー初期化(初期化しなくてもよいが最後なので一応初期化) } **メインプログラム [#d9c9b7dd] task main () { SetSensor(SENSOR_2, SENSOR_LIGHT); SetSensor(SENSOR_2, SENSOR_LIGHT); l_time=300; //次の交差点までの秒数を3秒に設定 line_l(); //左側境界部分をトレース left(); //S地点を左折 line_l(); left(); //P地点を左折 line_l(); top(); //Q地点を直進 l_time=700; //交差点誤判別防止用秒数を7秒に設定 line_l(); top(); //Q地点を直進 l_time=300; //交差点誤判別防止用秒数を3秒に設定 line_l(); right(); //R地点を右折 line_r(); //右側境界部分をトレース left(); //P地点を左折 l_time=700; //交差点誤判別防止用秒数を7秒に設定 line_l(); last(); l_time=300; //次の交差点までの秒数を3秒に設定 line_l(); //左側境界部分をトレース left(); //S地点を左折 line_l(); left(); //P地点を左折 line_l(); top(); //Q地点を直進 l_time=700; //交差点誤判別防止用秒数を7秒に設定 line_l(); top(); //Q地点を直進 l_time=300; //交差点誤判別防止用秒数を3秒に設定 line_l(); right(); //R地点を右折 line_r(); //右側境界部分をトレース left(); //P地点を左折 l_time=700; //交差点誤判別防止用秒数を7秒に設定 line_l(); last(); } *課題結果 [#p077b3a2] 課題コースはC地点 → S左折 → P左折 → Q直進 → Q直進 → R右折 → P左折 → A地点のコースです。 #ref(2016a/Member/kurokouchi/Mission2/05.png,100%,01) C地点からA地点までのタイムは1分10秒でした。 *反省・感想 [#qd4c5222] C地点からA地点までのタイムは1分10秒で到達タイムが1分切れなかったことが残念でした。しかし、到達率がほぼ10割で、安定性のあるプログラムが書けたことはよかったです。 今回の課題から光センサーを使い始めたので一つ一つの動作を時間指定しなくてよくなった部分があり電池の残量などによる動作の不安定さがなくなった分、プログラムが複雑になったと感じました。 また、機体の都合で増やした処理もあったのでロボット本体にもう少し工夫した方が良かったと思いました。次回の課題ではプログラムだけではなくロボットにも工夫したいです。