[[2015b/Member]] #contents *課題 [#x08873a6] &size(20){ライントレース}; **ミッション [#a8ef6f75] 次のいずれかの経路を黒い線にそって動くロボットを作成する。ただし、なるべく速く正確に動くロボットになるように工夫して、交差点では1秒間停止すること。 コース -A地点 → P直進 → Q直進 → Q右折 → P右折 → Q左折 → P左折 → B地点 #ref(2015b/Member/velocity/Mission2/2015b-mission2.png,50%,コース) *ロボット [#m8c9c207] 今回使用したロボットはライトセンサーを用いた次のようなロボットである。 #ref(2015b/Member/velocity/Mission2/IMG_20160107_162620.jpg,50%,y動作) #ref(2015b/Member/velocity/Mission2/IMG_20160107_162620.jpg,50%,ロボット) **仕組み [#x7aa538a] ***ライトセンサー [#v4cdfbd9] できるだけ周りの影響を受けないように高さ約1mmの箇所に設置した。 #ref(2015b/Member/velocity/Mission2/IMG_20160107_162637.jpg,50%,y動作) #ref(2015b/Member/velocity/Mission2/IMG_20160107_162637.jpg,50%,ロボット) ***進み方 [#wee820ac] ライトセンサーを使いコースの線の境を沿って進んでいく。センサーの閾値を次の五段階に分けそれそれ指示を与える。 -a&size(18){左旋回};<40<b&size(18){左};<45<c&size(18){前進};<52<d&size(18){右};<58<e&size(18){右旋回}; #ref(2015b/Member/velocity/Mission2/sikiiti.png,50%,閾値) ***交差点 [#rc85affb] ある一定時間旋回を続けると、そこを交差点と認識するようにした。 交差点に侵入した場合、指示通り一時停止した後、右折左折直進それぞれの動作に移るようにした。詳しくはプログラムのサブルーチン交差点で述べる。 今回は便宜上90度カーブも交差点とみなすこととする。 *プログラム [#b5e81784] **定義 [#j84a738e] #define right_turn OnFwd(OUT_A,20);OnRev(OUT_B,20); //右旋回 #define right OnFwd(OUT_A,90); //右 #define go OnFwd(OUT_AB,80); //前進 #define left OnFwd(OUT_B,90); //左 #define left_turn OnFwd(OUT_B,20);OnRev(OUT_A,20); //左旋回 #define tMAX 250 //交差点認識時間 int n = 1; //nのいう文字を定義し、1を代入 それぞれ基本となる動作を定義した。 **サブルーチン [#v2d2493e] ***交差点 [#k382b9e7] はじめに定義したnを使い交差点の数を数えていく。 sub kousaten() { PlaySound(SOUND_UP); //交差点に入ったことを示す音 Off(OUT_AB); Wait(1000); //一時停止 if(n <= 2){ //交差点1個目、2個目ならば right_turn; //一旦戻って、前進せよ Wait(600); Off(OUT_AB); go; Wait(300); Off(OUT_AB);} else if(n = 3){ //交差点3個目ならば right_turn; //右向きに約180度回転し、交差点を右折せよ Wait(1100); Off(OUT_AB); go; Wait(150); Off(OUT_AB);} else if(n = 7){ //交差点7個目ならば left_turn; //左向きに約180度回転し、交差点を左折せよ Wait(1100); Off(OUT_AB); go; Wait(150); Off(OUT_AB);} else{} //その他の交差点は特に何もせずそのままライントレースを続けろ n++; //交差点の数を数えるためのカウンタに1を加える } 交差点と認識するとまず指示通り1秒間一時停止し、交差点に入ったことを示す音を鳴らす。 その後、何個目の交差点かによって直進右折左折をし、最後に次に通過する交差点の数を示すnを1増やして交差点の作業は終了。 交差点番号は次の通り #ref(2015b/Member/velocity/Mission2/2015b-mission23.png,50%,y動作) **タスクメイン [#i8219603] task main() { long t0 = CurrentTick(); //交差点認識用タイマー long ta = CurrentTick(); //初めからの時間 SetSensorLight(S1); while(true){ long tz = CurrentTick(); long taz = tz - ta; //これまで走ったトータルの時間 if(((taz < 25000) || (75000 < taz < 900000))||(11500 < taz)){ //交差点が存在し得ない時間帯 if(SENSOR_1 <= 40){ //明るさにより行動を選択 left_turn; t0 = CurrentTick();} else if(SENSOR_1 <= 45){ left; t0 = CurrentTick();} else if(SENSOR_1 <= 52){ go; t0 = CurrentTick();} else if(SENSOR_1 <= 58){ right; t0 = CurrentTick();} else{right_turn; t0 = CurrentTick();} Wait(1); }else if(CurrentTick()-t0 < tMAX){ //交差点が存在し得る時間で、交差点に侵入していない場合 if(SENSOR_1 <= 40){ //明るさによって行動を選択 その際旋回時にはタイマーをリセットしない left_turn;} else if(SENSOR_1 <= 45){ left; t0 = CurrentTick();} else if(SENSOR_1 <= 52){ go; t0 = CurrentTick();} else if(SENSOR_1 <= 58){ right; t0 = CurrentTick();} else{right_turn;} Wait(1); }else {kousaten();}} //ある一定時間旋回し、交差点と認識した場合 } 旋回した時間を資料とし、交差点を認識している。なので旋回時にはタイマーをリセットしていない。 *最後に [#wea7611c] **工夫点 [#recd1661] -交差点の認識 何度やっても交差点でないのに交差点と認識してしまうポイントがあった。それを改善するため、トータルの時間による制御を行った。交差点に侵入しえない時間に関しては、交差点のプログラムが誤って出てこないよう、ただのライントレースを繰り返すだけとした。 以下の図の赤い部分が交差点警戒範囲として設定した部分である。 #ref(2015b/Member/velocity/Mission2/2015b-mission22.png,50%,交差点警戒範囲) -交差点での行動の選択 交差点と一口に言っても、その後の行動パターンは直進、左折、右折の3種類である。そこでどの動作を行うのかを交差点の数で判断するようにした。変数nを使い、交差点動作が終わるたびに+1していく。それにより交差点での行動を選択した。 **壁 [#ife92742] 工夫点でも述べたが、交差点の誤認識に悩まされた。初めは閾値をいじっていたが、閾値を変えてしまうと、通常のライントレースに影響が出てしまう。そこで思いついたのが時間による制御である。それまで交差点認識にしか使っていなかったタイマーをもう2つ用意し、これまで走ったトータルの時間をあらわした。 **改善点・欠点 [#sc40c962] 今回は交差点の動作のみをサブルーチンで表した。しかし当初の予定は、通常のライントレースの動作もサブルーチンで表したかった。しかし、変数(t0など)との組み合わせにより上手くプログラムを組むことができなかった。このことにより、プログラムの量が増えてしまった。変数を定義する位置、定義の仕方に問題があったのではないかと思う。 閾値を決めて、それを元に動作を決めていたが、今回作成したコースは濃さが均等ではなく、かつ折り曲げてしまっていたことから正確にラインを沿うのが難しくなっていた。実際すべて成功することは少なく、どこかでコースをそれてしまうことが多々あった。 **感想 [#c152c5b1] 課題2では課題1に比べプログラムが複雑で、悩む部分も多かった。時間通りに終わらないことも増え、完成したプログラムでも思い取りにいかなく不安だった。しかし、前回に比べてプログラムを書くことに慣れてきた部分はあったので、そこは成長できたなと思う。