目次 #contents *メンバー [#f83a2d5e] ・snowdrop…このページの執筆者。ものづくりがしたくてこのゼミを選択。プログラミングは全くの初心者。 ・bosoo… 工学部機シスに所属、ロボットはほとんど彼の手によるものです。 *課題の説明 [#e4a841cf] 右のような、黒い線を描いた紙を用意する。 http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2014a%2FMission1&openfile=2014a-mission1.png ルールは以下の通り。 1.スタート地点から出発し、黒い線にそって動く。 2.一つ目の十字の交差点と二つめの十字の交差点の間に置かれたピンポン玉をつかむ。 3.さらに黒線に沿って動いてゴール地点を目指す。 4.ゴールに向けてピンポン玉をシュートする。 ただしT字路では、直進、右折、左折を正しく判断させること。また二人一組で同じロボットを使用し、互いにスタート地点とゴール地点を入れ替えること。ロボット本体は共通のものを使うとする。 さらに以下のような動作に挑戦することが望ましい。 •ゴールエリア外からピンポン玉をシュートする。 •曲線部中央の障害物に接触しないようにすること。 詳しい説明は[[2014a/Mission1]]を見てください。 *ロボット本体 [#i2926ef1] **ドライブベース [#oa4c0591] &ref(2014a/Member/snowdrop/Mission1/robotto base.jpg,50%ロボット本体); 今まで使っていたロボットでも不都合がなさそうだったのでそのまま使いました。 **アーム [#eda0f4d0] &ref(2014a/Member/snowdrop/Mission1/arm.jpeg,50%,); ボールに向かって直進し、左右から挟んでボールを捕らえます。2個の歯車を組み合わせて1つのモーターでも左右のアームが同時に動くようにしました。 **ライトセンサ [#yb9f5b0f] &ref(2014a/Member/snowdrop/Mission1/sensor1.jpg,100%,); ライトセンサは歯車のモーターの右側につけました。 なるべく紙の表面にセンサを近づけようとしたらセンサが紙に接触してしまったので、 写真左側の灰色の部品を組み合わせて少し浮かせるようにしています。 *プログラム [#lfa1bb5e] **定義 [#o2f41927] まずは#defineで定義したものの紹介です。 #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 syuuto OnFwd(OUT_B,SPEED);Wait(200);Off(OUT_B);GO;Wait(1000); 右のタイヤはモーターA、左はC、アームはBに接続しています。 右折、左折はそれぞれ2種類ありますが、どちらも1のよりも2のほうが強い動きをします。 (以下のプログラムでは弱いほうを「左折」、強いほうを「左旋回」と表記しています。) catchは開いているアームを閉じる動作、 syuutoはアームを開いてロボット本体を前進させる動作を表します。 #define short_break Off(OUT_AC);Wait(1000); #define cross_curb turn_right2;Wait(900); #define tyokkaku turn_left2;Wait(1000); short_breakはロボットが交差点を認識した際にいったん動きを停止する時に使いました。 後の二つは右折しながら交差点を渡る動作、直角の部分を移動する動作です。 #define nMAX 8 #define STEP 1 nMAXはライトセンサが連続で黒い線の部分を認識できる上限です。 詳しくは後のプログラムで説明します。 **スタート〜10秒経過 [#oe36bb61] では、プログラム本体に入っていきましょう。 ちなみに、このプログラムは線の左側にロボットを置いたときのものです。 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秒が経過しています。 **10秒〜ボールをキャッチ [#ab3daeaa] 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秒経った後はまた音が鳴ります。(さっき交差点を認識したときの音とは違うものです) その後少し停止し、右旋回+前進 で置いてあるボールに向かいます。 ちなみに、ボールが置いてある場所は課題の紙の下側、白い○の位置です。 無事にボールを囲めたら、アームを閉じてキャッチします。 **ボールをキャッチ〜2つ目の交差点渡る [#c28dac10] **ボールをキャッチ〜交差点渡る [#c28dac10] 次に、ボールをつかんだ後の動作です。 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回以上黒い線の上に来た時、音を鳴らして交差点を渡ります。 これで課題のうえでの交差点はすべてクリアしたことになります。 **交差点を渡りきる〜ゴール [#gc8b2f2b] 最後に、3つ目の交差点を渡った後の動作を説明します。 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秒経過するとゴールに近づくので…次の動作に移ります。 } syuuto; //ボールをシュート Off(OUT_AC); } アームを開いてボールをシュートします。以上で終わりです。 *反省点 [#y8c3f2e1] タイマーでボールをつかむまでの時間やシュートの時間を計ったので、 ロボットの動きが少しずれただけで課題がこなせませんでした。 交差点を渡る回数でロボットの動きを指定するようなプログラミングを作れば ある段階でロボットの動作が遅れたとしてもそのミスが蓄積せず、段階的に動いてくれたのではないかと思います。 また、6月末は相方も自分も忙しくてなかなか話し合う時間を取れなかったのも原因の一つです。 次回はグループ全員で協力しようという姿勢を大事にしていきたいです。