#contents
*課題 [#y81382c6]
#ref(http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2016b%2FMission2&openfile=2016b-mission2.png)
ルート1を担当する。

「A地点をスタートしてQ付近の3/4円周上でピンポン玉をつかみ、そのピンポン玉をD地点においたゴールへシュートする 

Aスタート → P直進 → Q直進 → (ピンポン玉をキャッチ) → Q直進 → R右折 → P直進 → S左折 → Dへシュート

ただし、

なるべく速く正確に動くロボットになるように工夫して、交差点では1秒間停止すること。

ピンポン玉はQ近くの3/4円周上ならどこにおいてもよい

可能であればC,Dのゴールエリアライン上からシュートする」

*ロボット [#bd99d88b]
**全体像 [#hce31d60]
#ref(7ケーブル有り.jpg)
RISに比べれば巨大になった。本体のボタンは押しやすい。
**各パーツ [#hbdb37bb]
#ref(1ケーブル無し.jpg)
光センサは紙面と垂直にギリギリまで接近させた。精度よく、閾値の設定が楽になった。

前輪は左右に激しく揺れるので滑りにくいゴムタイヤはつけなかった。ロボットが動き続けていると左右のモーターが八の字に開いて負荷が掛かってしまうので、本体から離れないよう補強した。
#ref(8中心部.jpg)
本体、モーターA、光センサ、超音波センサだけを取り出した写真。モーターAと光センサを本体の下、中心線上に置くためにロボットが高くなった。
#ref(6横棒.jpg)
左右のモーターが八の字に開かないよう後ろから横棒のパーツを足した。
#ref(キャッチボール.jpg)
超音波センサの真下にボールが来た時、モーターAのアームで枠をボールが落ちない高さまでおろしてつかむ。

アームが上がっているとき、超音波センサのすぐ前を棒が遮るのだが、センサの値には影響しなかったのでそのまま。センサが反応してアームが下ろせればほぼつかむことができた。

カーブで機体が揺れると失敗するので点Qを通過したあとすぐにボールをおいた。

*プログラム [#e14514df]
**サブルーチンプログラム [#fea0d26a]
***線を追う [#c3b5760e]

・定義

 #define turn_right      OnRev(OUT_B,40);
 #define turn_right_slow OnRev(OUT_B,40); OnFwd(OUT_C,30);
 #define turn_left       OnRev(OUT_C,40);
 #define turn_left_slow  OnRev(OUT_C,40); OnFwd(OUT_B,30); 
 #define go              OnRev(OUT_BC,40);
 #define MAX_TIME 500

40%のスピードが最もコースから外れにくく、交差点の誤認識が少ないとわかった。

交差点で進路を確かめるために旋回したり、機体の向きを整えるプログラムは作らなかったので、機体の向きが甘い変わらないよう交差点を認識する時間MAX_TIMEは最小(0.5秒)に抑えた。

 sub FOLLOW_LINE()
 {
   long t0=CurrentTick();
 
   while(CurrentTick()-t0<MAX_TIME){
     if(SENSOR_1<=42){         //線上黒なら右折
       turn_right;
     }else if(SENSOR_1<=48){
       turn_right_slow;
       t0=CurrentTick();
     }else if(SENSOR_1<=58){    //丁度黒線と白紙の境界線上なら直進
       go;
       t0=CurrentTick();
     }else if(SENSOR_1<=65){
       turn_left_slow;
       t0=CurrentTick();
     }else{
       turn_left;              //線外白なら左折
       t0=CurrentTick();
     }
   }
   Off(OUT_BC);
   PlaySound(SOUND_UP);         //停止した時=交差点認識した時ピロリンと音がなる
  Wait(2000);
 }

交差点でない限り、ロボットが黒線の左側を追って走り続けるプログラム。


・QR間の急なカーブを曲がる

#ref(10ヘアピンミス.jpg)
授業の発表時、FOLLOW_LINEではQR間の急なカーブを曲がりきれなかった。(R=4のカーブで機体の幅が広いが右タイヤが動かず、線は辿れるものの機体の中心がコースから大きく外れてしまった。またモーターに負担をかけていた)

なのでこの区間だけ小刻みにタイヤを動かしてしっかり線上を進むような定義とプログラムを追加した。

 #define kokizami_right  OnRev(OUT_B,50); OnFwd(OUT_C,40);
 #define kokizami_left   OnRev(OUT_C,50); OnFwd(OUT_B,40);

 sub FOLLOW_LINE_KOKIZAMI()
 {
   long t0=CurrentTick();
 
   while(CurrentTick()-t0<MAX_TIME){
     if(SENSOR_1<=42){
       kokizami_right;        //変更
     }else if(SENSOR_1<=48){
       turn_right_slow;
       t0=CurrentTick();
     }else if(SENSOR_1<=58){
       go;
       t0=CurrentTick();
     }else if(SENSOR_1<=65){
       turn_left_slow;
       t0=CurrentTick();
     }else{
       kokizami_left;        //変更
       t0=CurrentTick();
     }
   }
   Off(OUT_BC);
   PlaySound(SOUND_UP);
   Wait(2000);
 }

FOLLOW_LINEとほとんど変更していないが、QR間を辿れるようになった。
#ref(12ヘアピンクリア.jpg)

***右折・左折・直線 [#nede7519]

おおよその動きは以下のGIFを参照

#ref(cross_gif.gif)

 sub USETSU()
 {
   OnFwd(OUT_BC,50); Wait(500); Off(OUT_BC);
   OnRev(OUT_C,50); Wait(1500); Off(OUT_C);
 }

点Rで右折する。Rで交差点認識した時、機体は左寄りに進みすぎているので少しバックしてから曲がる。

 sub SASETSU()
 {
   OnFwd(OUT_BC,50); Wait(500); Off(OUT_BC);
   OnRev(OUT_B,50); Wait(1500); Off(OUT_B);
 }

点Sで左折する。Sで交差点認識した時、機体は進みすぎているので(線の右側に出てしまう)少しバックしてから曲がる。

 sub CROSS()
 {
   go; Wait(800); Off(OUT_BC); 
 }

点P.Qで2回ずつ交差点を直進する。垂直の線の幅をまっすぐ通り抜けてしまえば、白紙の上でFOLLOW_LINEに従いロボットは右折しようとして進むべき線に戻ることができる。

***ボールをつかむ [#r1421a19]
 sub CATCH_BALL()
 {
  go;
  until (abs(SensorUS(S2)-13)>=4);
  if(abs(SensorUS(S2)-13)>=4){
    Off(OUT_BC);                            //ボールを認識したら止まる
    OnRev(OUT_A,30); Wait(500); Off(OUT_A); //アームを下ろす
  }
 }
点Qを過ぎてからはFOLLOW_LINEではガタガタしてボールを認識しにくいのでgoで進んでいる。

平常時のSensorUS(S2)の値は13cm、ボールが真下に来た時は8cm。だが球体との距離を図るのは難しいので、ボールに近づいた時は5cm~24cm程度に値が振れる。

なので絶対値を計算する関数abs()で平常時の13cmから4cm前後変化した時ボールがあると判断するようにさせた。

***ゴールにシュート [#m3d8c6fb]
 sub GOAL()
 {
   OnFwd(OUT_A,30); Wait(300); Off(OUT_A);   //Aのアームを上げる
   OnFwd(OUT_BC,40); Wait(800); Off(OUT_BC); //少しロボットを後退させる
   OnRev(OUT_A,30); Wait(500); Off(OUT_A);   //Aのアームを下げる
   OnRev(OUT_BC,60); Wait(500); Off(OUT_BC); //ロボットを勢い良く走らせアームのバーにぶつける。シュート。
 }
発表時は距離が足りずボールに当たらなかった。
紙の上でボールの位置が安定しないのでこのアームの形だと難しい。

**メインプログラム [#ua9900a3]

 task main()
 {
   SetSensorLight(S1);
   SetSensorLowspeed(S2);  //光センサ、超音波センサを設定
 
   FOLLOW_LINE();
   CROSS();                //直進P
   FOLLOW_LINE();
   CROSS();                //直進Q
   CATCH_BALL();           //ボールをキャッチ
   FOLLOW_LINE();
   CROSS();                //直進Q
   FOLLOW_LINE_KOKIZAMI();
   USETSU();               //右折R
   FOLLOW_LINE();
   CROSS();                //直進P
   FOLLOW_LINE();
   SASETSU();              //左折S
   FOLLOW_LINE();
   GOAL();                 //ゴール
 }
全ての動作を部品化したのでとても見やすい。メンテナンスもしやすい。

*実演の反省 [#a6a9a55c]
・初めてスタートからゴールまで走りきってくれた。

・QR間が曲がりきれなかった。→解決した

・ボールをゴールにシュートできなかった。→不可能ではないが、成功率はかなり低い

*学んだこと・課題 [#r6b9eff9]
・前回の反省(プログラムしやすいようにロボットを組み立てる)を実行できた。次回もこれに続きたい。

・一つの動作が終わった時に音や画面表示などサインを出して、プログラムのミスやロボットの不調を見つけやすくなった。

・閾値の設定やFOLLOW_LINEの定義の値はまだ改善の余地があるのでは?ロボットごとにある誤差をもう少し実験したほうがよいと思われる。

*感想 [#p819a847]
やっとNXTに慣れてきたと感じた。それでもわからないことはたくさんあったので相方と他のいろんな班の人に教えてもらった。ありがとう。

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS