課題

マップ.png

上のようなマップ上でピッチャーロボットとバッターロボットで通信しながら野球盤ゲームをする 詳細なルールについては課題3を参照

ロボット

バッターロボット

作成は自分が担当した。

前から.png

課題2の反省(光センサーが床面と近すぎると進むのが遅く負荷がかかる)を生かして、少しだけ高い位置に光センサーをつけた。

ばらばら.png

補強した部分が多くパーツが大きいが、NXTの箱にはしまいやすい

真上コード.png

立幅は20cmぎりぎり、横幅は15cmない程度。基本ルール「スタート時はそれぞれA地点B地点の枠内に収まること(高さの制限はなし)」、「M地点、B地点では接地している部分が枠内に入っていること」をクリア。ボールをしっかりつかむ形のアームが大きく横についているので、本体やモーター、タイヤの部分はコンパクトになった。

開.png
閉.png

アームの構造。モーターAで上半分を開閉させる。上半分はモーターに完全に固定され、連動して動く。下半分はぶら下がっているので閉じている時、半分開けている時は背面が床面に垂直を維持する。大きく開けたときは背面も持ち上がるので、下部の黒い棒に当ててボールを射出することができる。

アーム0.png

このアームの形はバッターらしくはないが、理論上はボールを掴んでかなり正確にコントロールを効かせて射出できる。だが実際のロボコンでは、ピッチャーが投げてからとバッターが射出してから、床面のわずかな凹凸の影響を受けて直線的にボールが転がらず、掴めず入らず得点につながらなかった。なのでほかの多くの班の様に左右のフリッパーでとりあえずボールに当てて打つ構造のほうが、得点を多く得られたかもしれない。

ピッチャーロボット

詳しくはこちらのページを参照。

ななめのレールに球を一つ一つ落として、球の自重で転がる仕組みである。マウンドに入る位置はかなり正確だったが、この仕組み故球の威力が弱かったり、球が2つ同時に出たり詰まったりする問題があった。

プログラム

Bのバッターボックスにつくまでのプログラム

ロボットがCからスタートしてBで向きを変える所までのプログラムを作った。 下のGIFにおおよその動きとその説明をまとめた。

3TRUE.gif

PR間につくまで

#define go_straight(t)  RotateMotor(OUT_BC,50,t);
#define go_nonstop      OnFwd(OUT_BC,50);
#define SASETSU         OnRev(OUT_BC,50); Wait(400); Off(OUT_BC); OnFwd(OUT_C,50); Wait(1500); Off(OUT_C);

決まった距離だけ直進するときはgo_straight(t)、光センサーでラインを認識するまで直進するときはgo_nonstopを使い分けるようにした。 また、SASETSUは課題2で使用したものを流用した。

sub BEGIN()
{
    Wait(1500);
    turn(120);
    go_straight(1300);
    PlaySound(SOUND_CLICK);
    go_nonstop;
    until(SENSOR_3<=40);
    Off(OUT_BC);
    PlaySound(SOUND_CLICK);
    Wait(1000);
    SASETSU;
}

五秒間ライントレース

#define turn_right      OnFwd(OUT_B,40);
#define turn_right_slow OnFwd(OUT_B,40); OnRev(OUT_C,30);
#define turn_left       OnFwd(OUT_C,40);
#define turn_left_slow  OnFwd(OUT_C,40); OnRev(OUT_B,30);
#define go_line         OnFwd(OUT_BC,40);
#define FOLLOW_TIME 5000
sub FOLLOW_LINE()
{
    long t0=CurrentTick();

    while(CurrentTick()-t0<FOLLOW_TIME){
      if(SENSOR_3<=38){
        turn_right;
      }else if(SENSOR_3<=45){
        turn_right_slow;
      }else if(SENSOR_3<=50){
        go_line;
      }else if(SENSOR_3<=59){
        turn_left_slow;
      }else{
        turn_left;
      }
    }
    Off(OUT_BC);
}

課題2で書いたライントレースを少し変えて、五秒の間だけ実行し、交差点認識はしないプログラムを作った。角度制御だけではズレが重なって大幅に方向が変わるので、一度ここで「必ず一定の方向(R-Bの線に平行)を向く」動作が必要だった。

また、時間以外の制御方法がわからなかったので何回か試走させて五秒に決めた。

安定して定位置につく

初めはBの枠で交差点認識した時に停止させてから向きを調整する考えでいたが、

・交差点認識の誤差が大きい

・交差点認識した後の機体がマップの外に向き、そこから軌道修正が安定しない

等の理由で、交差点認識ではなく、R-Bの線に平行な向きのまま、前後移動のみでBの枠を内側から判断して、そこからの距離で機体の位置を決めるプログラムを作った(詳しくは上のGIFを参照)。

sub READY()
{
    go_straight(500);
    OnRev(OUT_BC,50);
    until(SENSOR_3<=40);
    Off(OUT_BC);
    PlaySound(SOUND_CLICK);
    Wait(1000);
    turn(20);
    go_straight(400);
    turn(-70);
    PlaySound(SOUND_UP);
}

ピッチャーに向き合うとき、超音波センサーを当初利用しようとしたが、プログラムでうまく使いこなせなかった。超音波センサーの周りに競走馬のブリンカーのようなものをつけたが、認識の感度は変わらなかった。

メインプログラム

task main()
{
    SetSensorLight(S3); 

    BEGIN();
    FOLLOW_LINE();
    READY();
}

ピッチングプログラム

本課題ではピッチャーロボットがマスターである。より詳しい説明はこちらのページを参照

#define TURNR(A) RotateMotorEx(OUT_BC,40,A,100,true,true);Wait(1000);
#define TURNL(L) RotateMotorEx(OUT_BC,40,L,-100,true,true);Wait(1000);
#define TYOKUSIN OnFwdSync(OUT_BC,40,0);
#define CM(K) RotateMotorEx(OUT_BC,40,20.47315*K,0,true,true);Wait(1000);
#define HASSYA RotateMotor(OUT_A,-90,90);Wait(1000);RotateMotor(OUT_A,-90,-90);

ロボットがマウンドに入るまでのサブルーチン。

sub BASYO()
{
    SetSensorLight(S1); 

    TYOKUSIN;
    until(SENSOR_1<35);
    Off(OUT_BC);
    Wait(500);
    CM(5);
    Wait(500);
}
task main()
{
int SIREI;
TURNR(110);
CM(36);
TURNR(150);
repeat(3){
 BASYO();
 }
CM(-13);
TURNR(130);
until(BluetoothStatus(1)==NO_ERR);
RemotePlayTone(1,440,1000);
Wait(1000);
RemoteStartProgram(1,"DAGEKI.rxe");        //バッターロボットにDAGEKIを実行させる命令
while(SIREI<12){                           //SIREIが12未満の間繰り返し
 ReceiveRemoteNumber(MAILBOX1,true,SIREI);
 if(SIREI==11){                            //SIREIが11のとき球を発射
  PlaySound(SOUND_CLICK);
  Wait(200);
  HASSYA;
  SIREI=0;
  }
 }
}

バッティングプログラム

バッターロボットがスレイブである。より詳しい説明はこちらのページを参照

#define CATCH Wait(500);RotateMotor(OUT_A,70,45);Wait(1000);        //球が来る時間に合わせてキャッチする
#define UTU RotateMotor(OUT_A,-90,45);Wait(1000);                   //アームを大きく上げて球を打つ
#define TURN(s,t) RotateMotorEx(OUT_BC,40,s,t,true,true);Wait(1000); //その場で機体が回転してゴールに向きを定める

int x=1;
sub BATTING()
{
    SendRemoteNumber(0,MAILBOX1,11);
    Wait(1500);
    CATCH;
    if(x==1){           //球によってゴールを変える
        TURN(80,100);   //右側4点のゴール
        UTU;
        TURN(80,-100);
        x = x+1;
    } else if(x==2){
        TURN(95,-100);  //左側4点のゴール
        UTU;
        TURN(95,100);
        x = x+1;
    } else if(x==3){
        TURN(40,100);   //右側6点のゴール
        UTU;
        TURN(40,-100);
        x = x+1;
    } else if(x==4){
        TURN(45,-100);  //左側6点のゴール
        UTU;
        TURN(45,100);
        x = x+1;
    } else {
        TURN(45,-100);  //左側6点のゴール
        UTU;
        TURN(45,100);
        x = x+1;
    }
}

10点のゴールは遠く、ボールがピッチャーロボットにぶつかりやすいので断念した。またはピッチャーロボットの下部のレールに入り込み、次弾の障害になるケースもあった。

ピッチャーロボットからDAGEKIの命令が送られるたびに実行し、5回が終わったら12の値を送り返して終了する。

task main()
{
    UTU;
    while(x<6){
        BATTING();
    }
    SendRemoteNumber(0,MAILBOX1,12);
}

実演の反省

総合3位だった。点数が入ったのは二巡目の6点のみ。

感想

ロボティクス入門ゼミの感想

気軽な興味で参加し、マインドストームもプログラミングも触れるのは初めてでしたが、すばらしい経験になったと思います。根気よくコンパイルエラーを見直したり、何度もレゴを組みなおしたりするのも楽しかったです。いえ、苦しかったです。実際のロボット作りならば、部品の制約がないのだからもっと難しいのでしょう。ゼミ生同士で課題解決に向けて相談・議論する過程という、ゼミならではの大きなメリットも得られました。今回もまた、一方的に教えてもらうことが多々ありました。協力者の方々には感謝しています。


添付ファイル: fileばらばら.png 198件 [詳細] fileアーム0.png 212件 [詳細] file閉.png 258件 [詳細] file開.png 179件 [詳細] file真上コード.png 215件 [詳細] file前から.png 212件 [詳細] fileマップ.png 197件 [詳細] file3TRUE.gif 253件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-02-13 (月) 01:13:34