目次 #contents ~ *メンバー [#jcb1c0bc] bosoo 主にロボット製作を担当 ~snowdrop 主にプログラム、コース作成を担当 ~ *課題について [#a567a6b1] 右のような、黒い線を描いた紙を用意する。 http://yakushi.shinshu-u.ac.jp/robotics/?plugin=ref&page=2014a%2FMission1&src=2014a-mission1.png ~ ~ルールは以下の通り。 ~ ~1.スタート地点から出発し、黒い線にそって動く。 ~2.一つ目の十字の交差点と二つめの十字の交差点の間に置かれたピンポン玉をつかむ。 ~3.さらに黒線に沿って動いてゴール地点を目指す。 ~4.ゴールに向けてピンポン玉をシュートする。 ~ただしT字路では、直進、右折、左折を正しく判断させること。また二人一組で同じロボットを使用し、互いにスタート地点とゴール地点を入れ替えること。ロボット本体は共通のものを使うとする。 ~ ~さらに以下のような動作に挑戦することが望ましい。 ~ ~ゴールエリア外からピンポン玉をシュートする。 ~ ~曲線部中央の障害物に接触しないようにすること。 ~ *ロボット本体について [#vac092c2] #ref(IMG_0167.jpg) ~本体は元のベースを用いて、それにアーム(Bに接続)とライントセンサー(SENSOR2に接続)を取り付ける形にした。 ~ *プログラムについて [#na9cd0e4] **定義 [#d23c0bcd] +速さについて #define SPEED 30 #define THRESHOLD 50 ~動く速度が大き過ぎるとうまくいかないことが多かったため、30に設定した。 ~THRESHOLDはライトセンサーの閾値を表す。 ~ ~+曲がり方について #define GO OnFwd(OUT_AC,SPEED); #define turn_right1 OnFwd(OUT_C,SPEED);Off(OUT_A); #define turn_right2 OnFwd(OUT_C,35);OnRev(OUT_A,10); #define turn_left1 OnFwd(OUT_A,SPEED);Off(OUT_C); #define turn_left2 OnFwd(OUT_A,SPEED);OnRev(OUT_C,20); #define catch OnRev(OUT_B,SPEED);Wait(80); #define shoot OnFwd(OUT_B,SPEED);Wait(200);Off(OUT_B);GO;Wait(1000); ~右のタイヤはモーターA、左はC、アームはBに接続した。 ~ ~曲がり方はそれぞれ2種類あり、どちらも1のよりも2のほうが旋回に近い。 ~黒い線の中心から遠いほど、旋回に近い形にした。 ~ ~catch:開いているアームを閉じる ~shoot:アームを開いてロボット本体を前進させる動作を表す。 #define short_break Off(OUT_AC);Wait(1000); #define cross_curb turn_right2;Wait(900); #define chokkaku_turn_left2;Wait(1000); ~short_breakはロボットが交差点を認識した際にいったん動きを停止する時に使用した。 ~ ~cross_curbは右折しながら交差点を渡る動作、chokkakuは直角の部分を移動する動作を表す。 #define nMAX 8 #define STEP 1 ~nMAXはライトセンサが連続で黒い線の部分を認識できる上限。 ~これは何度かの施行により数値を決めた。 ~ **プログラムの流れ [#w6acdcfb] +スタート〜10秒経過 task main() { SetSensorLight(S2); int nOnline=0; //続けて黒になった回数(カウンタ) int nWhite=0; long t0 = CurrentTick(); //タイマーを設定 while(CurrentTick()-t0 <10000){ //10秒以下の場合以下の動作を繰り返す while(nOnline < nMAX){ //黒い線の上に来た回数が8回以内の場合 if(SENSOR_2 < THRESHOLD-17){ //黒と認識 turn_left1; //左折 nOnline++; //カウンタが1増加 }else{ //それ以外(白と認識) turn_right1; //右折 nOnline=0; //カウンタをいったんリセット } Wait(STEP); //以上の動作をSTEPごとに判断 ~まず、ロボットが動き出す直前にタイマーを設定して時間を計り始める。 ~(ロボットが動き始める瞬間=0秒) ~また、nOnlineは連続して黒になった回数を数えるためのカウンタを表す。 ~ ~黒と認識するとnOnlineの値を1ずつ増やす。 ~黒い線を連続して認識した回数が8回以内のときにwhileの中の動作を繰り返す。 ~ ~ロボットが白い部分(明るさ大)を認識した時、右に移動し、ロボットが黒い部分(明るさ小)を認識した時、左に移動するようにプログラムした。 ~この2つの動作を繰り返すことで、ロボットは黒い線に沿って左右に進み、前進することができる。 ~ ~黒の部分を8回以上認識したとき } //それ以外(nOnline >=nMAX) PlaySound(SOUND_CLICK); //8回以上黒い線の上に来たらピッと音が鳴る short_break; //小休止 cross_curb; //交差点を渡る nOnline=0; //変数(カウンタ)をリセット } ~nOnlineの値が増えて8回以上になった場合、ロボットはこの動作に移る。 ~交差点であることを認識したときは、音が鳴るようにした。 ~こうすることで、ロボットがきちんと動作していることがこちらにも分かるようにするためだ。 ~右に旋回しながら交差点を渡りきり、いったん変数をリセットし、次の動作へ移る。 +10秒〜ボールをキャッチ ~ if(CurrentTick()-t0 >= 10000){ //10秒以上経つと以下の動作を繰り返す| ~ロボットが動く前に設定したタイマーがまだ効いているのでこれを利用。 PlaySound(SOUND_UP); //10秒経過すると音が鳴る short_break; //小休止 turn_right2; //1.6秒右旋回 Wait(1600); GO; //1.7秒前進 Wait(1700); catch; //ボールをつかむ ~10秒経った後はまた音が鳴らし、その後少し停止する。 ~右旋回、後に前進で置いてあるボールに向かう。そしてアームを閉じる。 ~この時、少しでもボールがずれるとつかめないことがあった。 +ボールをキャッチ〜交差点渡りきる cross_curb; //交差点を渡る ~ボールをつかんだ時点でちょうど交差点にロボット本体が来ているので、 ~そのまま右に旋回しながら交差点を渡り切る。 while(nOnline < nMAX){ //黒い線の上に来た回数が8回以内の場合 if(SENSOR_2 < THRESHOLD-17){ turn_left1; //左折 nOnline++; //カウンタが1増加 }else{ turn_right1; //右折 nOnline=0; //カウンタをいったんリセット } Wait(STEP); //以上の動作をSTEPごとに繰り返す ~10秒経過するまでの動作とほぼ同じ。 } PlaySound(SOUND_DOWN); short_break; cross_curb; nOnline=0; } ~8回以上黒い線の上に来た時、音を鳴らして交差点を渡る。 +交差点を渡りきる〜シュート long t1 = CurrentTick(); //タイマーt1を設定| ~ここで新しくタイマーを設定します。 ~(交差点を渡り切った時=0秒) while(CurrentTick() - t1 <= 25000){ //25秒以内の場合以下の動作を繰り返す if(SENSOR_2 < THRESHOLD-17){ turn_left1; //左折 nOnline++; //1増加 }else{ turn_right1; //右折 nOnline=0; //カウンタをいったんリセット } Wait(STEP); //以上の動作をSTEPごとに判断 ~交差点を渡り切ってから25秒以内の場合は、再びロボットはラインに沿って前進。 ~25秒経過時、ゴール前と認識して次の動作へ。 } shoot; //ボールをシュート Off(OUT_AC); } ~アームを開いてボールをシュート。これでプログラム終了。 **反省点 [#y3842880] 今回の課題は、「ロボットに自身が置かれている状況をどれだけ把握させることができるか」ということが一番のネックとなったのではないかと思う。 ~プログラムを用いて、どうすれば安全に、かつ精密にボールをシュートするところまで持ってい行くことができるのか。 ~今回は、プログラムの課題が初めていうこともあり、やはり変数などのその場に応じたものより、時間に頼るなどの人為的、かつ不安定なものになってしまった。 ~これらを今後のプログラムに生かしていきたいと思う。