[[2011b]] *ライントレース [#lf4957de] **目次 [#kb2ba24b] #contents **ロボットの構造 [#gece41c0] #ref(2011b/A4/課題2右/PH_311.jpg,50%,ロボットの本体です。) ロボットの構造は組み立て方説明書にある構造をほぼそのまま流用しています。中心部分の長いブロックを延長してその先にセンサーを設置しています。またセンサーは右がモノクロセンサー、左がカラーセンサーとなっています。また、顔(っぽい部分)は超音波センサーを使用していますが、コードがつながっていないのでただの飾りです。 **コース [#t4436953] 我々A4チームはコースは次のようなものを使用します。 #ref(2011b/A4/課題2右/PH_323.jpg,50%,ロボットの本体です。) ろにゃは時計回り(近道)、SINANO470は反時計回りを担当します。 **プログラム [#u072506b] ***ろにゃver [#y8425034] 黒線を右と左のセンサーではさんで進んでいく。交差点(右と左のセンサーの両方が同時に黒になったとき)の数を数えて数に何個目の交差点かによって行動を決定する。グローバル変数countで交差点の数を数え、switch文で分岐する。main関数の中を短くわかりやすくなるよう工夫した。 #define border1 40 #define border3 30 #define speed 35 #define time 0020 #define angle 90 int count=0; sub right_pivotTurn(){ OnFwd(OUT_C,speed); OnRev(OUT_A,speed-7); } sub left_pivotTurn(){ OnFwd(OUT_A,speed); OnRev(OUT_C,speed-7); } sub right_turn(){ OnFwd(OUT_C,speed); Off(OUT_A); } sub left_turn(){ OnFwd(OUT_A,speed); Off(OUT_C); } sub hairpin(){ Off(OUT_AC); Wait(0500); right_turn(); Wait(1300); } sub rotary(){ int count=0; bool flag = true; Off(OUT_AC); Wait(0500); right_turn(); Wait(1100); for(int i=0;i<2;i++){ //左が黒 while(Sensor(IN_1)>border1){ if(Sensor(IN_3)<border3){ if(count<5){ left_pivotTurn(); Wait(time); } //両方白 }else{ OnFwd(OUT_AC,speed); } } Off(OUT_AC); Wait(0500); if(flag){ Off(OUT_AC); Wait(0500); left_turn(); Wait(0500); flag = false; count = 0; }else{ Off(OUT_AC); Wait(0500); right_pivotTurn(); Wait(0450); Off(OUT_AC); Wait(0500); break; } } } sub ignore(){ Off(OUT_AC); Wait(0500); OnFwd(OUT_AC,speed); Wait(0500); } sub in_shortway(){ Off(OUT_AC); Wait(0500); right_turn(); Wait(1100); count++; } sub out_shortway(){ Off(OUT_AC); Wait(0500); right_turn(); Wait(1100); } task main(){ SetSensorLight(IN_1); SetSensorColorRed(IN_3); while(true){ //両方黒 if(Sensor(IN_1)<border1 && Sensor(IN_3)<border3){ switch(count){ case 0: hairpin(); count++; break; case 1: rotary(); count++; break; case 2: case 3: ignore(); count++; break; case 4: rotary(); if(Sensor(IN_1)<border1) in_shortway(); count++; break; case 5: in_shortway(); break; case 6: out_shortway(); count++; break; case 7: case 8: ignore(); count++; break; } //右が黒 }else if(Sensor(IN_1)<border1 && Sensor(IN_3)>border3){ right_pivotTurn(); Wait(time); //左が黒 }else if(Sensor(IN_1)>border1 && Sensor(IN_3)<border3){ left_pivotTurn(); Wait(time); //両方白 }else{ OnFwd(OUT_AC,speed); } } } } ***SINANO470ver [#hb077c5b] 自分はモノクロセンサーのみを使用しています。基本的に黒の中を進み、外れたら右へ左へと本体を振ることで黒を探します。ロータリーに侵入するまでは黒の中を進み、侵入したらタイマーで黒の左や右を進むプログラムに変更することでロータリーを突破するようにしています。 #define tim 0060 #define speed 50 #define light 50 sub rightturn(int t){ OnFwd(OUT_A,speed); OnRev(OUT_C,speed); Wait(t); Off(OUT_AC); } sub leftturn(int t){ OnFwd(OUT_C,speed); OnRev(OUT_A,speed); Wait(t); Off(OUT_AC); } sub rightcourse(){ int t,i,count=0; SetSensorLight(IN_1); while(true){ t=tim; i = 0; while(Sensor(IN_1)>light){ OnFwd(OUT_AC,speed); } Off(OUT_AC); while(true){ if(i){ rightturn(t); if(Sensor(IN_1)>light) break; i--; t+=tim; count++; }else{ leftturn(t); if(Sensor(IN_1)>light) break; i++; t+=tim; count++; if(count>8){ OnFwd(OUT_C,speed); OnRev(OUT_A,speed); count=0; if(Sensor(IN_1)>light){ Off(OUT_AC); break; } } } } } } sub leftcourse(){ int t,i,count=0; SetSensorLight(IN_1); while(true){ t=tim; i = 0; while(Sensor(IN_1)>light){ OnFwd(OUT_AC,speed); } Off(OUT_AC); while(true){ if(i){ leftturn(t); if(Sensor(IN_1)>light) break; i--; t+=tim; count++; }else{ rightturn(t); if(Sensor(IN_1)>light) break; i++; t+=tim; count++; if(count>8){ OnFwd(OUT_C,speed); OnRev(OUT_A,speed); count=0; if(Sensor(IN_1)>light){ Off(OUT_AC); break; } } } } } } sub middle(){ int t,i,count=0; while(true){ t=tim; i = 0; while(Sensor(IN_1)<light){ OnFwd(OUT_AC,speed); } Off(OUT_AC); while(true){ if(i){ leftturn(t); if(Sensor(IN_1)<light) break; i--; t+=tim; count++; }else{ rightturn(t); if(Sensor(IN_1)<light) break; i++; t+=tim; count++; if(count>8){ OnFwd(OUT_C,speed); OnRev(OUT_A,speed); count=0; if(Sensor(IN_1)<light){ Off(OUT_AC); break; } } } } } } task main(){ long t0,time; SetSensorLight(IN_1); t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<28000){ middle();//基本的に黒の内側を進みます。 } if(time>28000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<1000){ leftcourse();//黒の左側を通ります。ここでロータリーの写真上側のT字路を回避します。 } if(time>1000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<5000){ rightcourse();//黒の右側を通ります。右側を通ることでロータリーから脱出します。 } if(time>5000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<6000){ leftcourse();//黒の左側を通ります。写真左下の四角い部分のコースの内側を通すことでミスを減らします。 } if(time>6000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<1000){ middle();//黒の内側を通ります。ロータリーに侵入する前の十字路を通過し、ロータリーに再侵入します。 } if(time>1000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<0900){ leftcourse();//コースの左側を通します。この辺になるとタイマーの誤差が出てくるので、ロータリー前の十字路をうまく通れないことがあるのでこうしました。 } if(time>0900){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<0600){ middle();黒の内側を通ります。ロータリーにうまく入るには黒の内側を通らなければならないからです。 } if(time>0600){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<4000){ leftcourse();//黒の左側を通ります。写真右側のT字路を回避します。 } if(time>4000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<4000){ middle();//黒の内側を通ります。 } if(time>4000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<5000){ rightcourse();//黒の右側を通ります。それによってロータリーから脱出します。 } if(time>5000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<20000){ middle();//黒の内側を通ります。このままゴールまで行きますが、ヘアピンカーブも問題なくこなします。 } if(time>60000){ break; t0 = CurrentTick(); t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<28000){ middle();//基本的に黒の内側を進みます。 } if(time>28000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<1000){ leftcourse();//黒の左側を通ります。ここでロータリーの写真上側のT字路を回避します。 } if(time>1000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<5000){ rightcourse();//黒の右側を通ります。右側を通ることでロータリーから脱出します。 } if(time>5000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<6000){ leftcourse();//黒の左側を通ります。写真左下の四角い部分のコースの内側を通すことでミスを減らします。 } if(time>6000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<1000){ middle();//黒の内側を通ります。ロータリーに侵入する前の十字路を通過し、ロータリーに再侵入します。 } if(time>1000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<0900){ leftcourse();//コースの左側を通します。この辺になるとタイマーの誤差が出てくるので、ロータリー前の十字路をうまく通れないことがあるのでこうしました。 } if(time>0900){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<0600){ middle();黒の内側を通ります。ロータリーにうまく入るには黒の内側を通らなければならないからです。 } if(time>0600){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<4000){ leftcourse();//黒の左側を通ります。写真右側のT字路を回避します。 } if(time>4000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<4000){ middle();//黒の内側を通ります。 } if(time>4000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<5000){ rightcourse();//黒の右側を通ります。それによってロータリーから脱出します。 } if(time>5000){ break; } } t0 = CurrentTick(); while(true){ time = CurrentTick()-t0; if(0<time&&time<60000){ middle();//黒の内側を通ります。このままゴールまで行きますが、ヘアピンカーブも問題なくこなします。 } if(time>20000){ break; } } } **反省・感想 [#k964561b] SINANO470:家やためしなど、どうでもいいときばかり成功するので勘弁してほしかった。やはりセンサー1個は辛いです。 **コメント [#l27b267d]