目次

課題

コース図

ピンポン玉と紙コップを別々に回収してピンポン玉はX地点、紙コップはY地点に運ぶ。ルールやフィールドの詳細についてはこちらを参照してください。

2017b/Mission3

ロボットの説明

機体A→機体Aの写真 機体B→機体Bの写真

今回同じようなつくりの機体を2機作成した。それぞれ別で作成したので細かいところなどの多少の違いはある。ただプログラムに関しては全く別のもので動かしている。紙コップを掴んで持ち上げる機構は2機とも同じ機構である。自分が担当したのは機体Aなので、機体Aについて詳しく説明していく。

機体A

前 機体Aの写真前 後ろ 機体の写真後ろ

機体の前に超音波センサー、後ろに紙コップを掴んで持ち上げるためのアームをつけた。この機構のアームを前につけると超音波センサーの邪魔になってしまうので後ろにつけた。超音波センサーは縦につけた方が正確に測れるということで縦に取り付けた。

機体B

基本的にはAと同じような機構である。Bにはライトセンサーとスタートの時に使うタッチセンサーがついている。詳しくは下のページをご覧ください。

2017b/Member/takeshi/Mission3

2017b/Member/Yoshi/Mission3

紙コップを掴んで持ち上げる機構

機体本体にモーターを2つ使ってしまっているので、1つのモーターで紙コップを掴む・持ち上げるを両方行う機構を作成した。まず掴むアームの部分が閉まり、それ以上閉まらないとなるとアーム全体が持ち上がるという仕組みだ。写真にあるように、3つの歯車と写真では確認しづらいのだが小さい歯車によってこの仕組みが出来ている。

アーム

紙コップを掴む・持ち上げる・重ねる流れは次の通りだ。

アーム → アーム → アーム →

掴むアームを開いた状態で紙コップの前に行き、紙コップがアーム内に入るように前進する。そして紙コップを掴む。

アームアーム → アーム →

掴むアームがこれ以上閉まらないとなると、アーム全体が上がり始める。アーム全体は少しだけあげて止める。ピンポン玉が少し見えるくらいに紙コップを上げることで、ピンポン玉を割り箸の枠に入れることが紙コップは枠に引っかからず、ピンポン玉は枠を乗り越えてくれるのでスムーズに行える。そしてアーム全体を上げることでピンポン玉は紙コップから出てくる。

アーム → アーム → アーム

紙コップを掴んで持ち上げた状態で動き、すでに置かれている紙コップの前に行く。写真でも分かるように、紙コップを持った状態でもその下に紙コップが入れるような高さは確保出来るように作成した。そして掴むアームを少し開くと持っていた紙コップは落ちる。アーム部分を軽くしているため、モーターを逆に回転させたときに、掴むアームが先に開くようになっている。

プログラムの説明

コース図

機体Aは左側、機体Bは右側からスタートする。紙コップは左上のものを紙コップ1、最もX地点に近いものを紙コップ2、下の方にあるものを紙コップ3として説明していく。×のついている紙コップは障害物である。(写真参照)

紙コップを取り、ピンポン玉をX地点へ置く順番は、1→2→3の順である。 Y地点に紙コップを置く順番は、2→1→3の順である。 紙コップ1と3は機体A、紙コップ2は機体Bが担当する。

機体A

正確さや調整のしやすさを考えて遅めのスピードに定義した。

#define SPEED_SLOW 25

紙コップを探して、その紙コップの手前まで進むプログラムである。

const float diameter = 5.45;  //タイヤの直径(cm)
const float track = 10.91;   //タイヤのトレッド幅(cm)
const float pi = 3.1415;    //円周率

void fwdDist(float d) //距離 d cm 前進
{
    long angle = d/(diameter*pi)*360.0;   //必要なタイヤの回転角度
    RotateMotorEx(OUT_AB,SPEED_SLOW, angle,0,true,true);
}

void baDist(float d) //距離 d cm 後進
{
    long angle = d/(diameter*pi)*360.0;   //必要なタイヤの回転角度
    RotateMotorEx(OUT_AB,SPEED_SLOW, -angle,0,true,true);
}

void turnAng(long ang)  //角度ang度の時計回りの旋回
{
    long angle = track/diameter * ang;   //必要なタイヤの回転角度
    RotateMotorEx(OUT_AB,SPEED_SLOW, angle,100,true,true);
}

void nturnAng(long ang)  //角度ang度の時計回りの旋回
{
    long angle = track/diameter * ang;   //必要なタイヤの回転角度
    RotateMotorEx(OUT_AB,SPEED_SLOW, angle,0,true,true);
}

int searchDirection(long ang)  //現在の方向を中心にang度の範囲で探し
                                   //障害物までの距離を返す
{
    long tacho_min ;   //もっとも近い距離を実現するタイヤの回転数
    int d_min = 300 ;  //もっとも近い距離の仮の最小値

    long angle = (track/diameter)*ang;  //旋回角度からタイヤの回転を計算
    turnAng(ang/2);           //指定された角度の半分を旋回
    ResetTachoCount(OUT_AB);  //角度計測をリセット

    OnFwdSync(OUT_AB,SPEED_SLOW,-100);   //反時計回りに旋回
    while(MotorTachoCount(OUT_A)<=angle){
       if (SensorUS(S1)<d_min){         //現在の距離が仮の最小値より小さい場合
            d_min = SensorUS(S1);       //仮の最小値を更新
            tacho_min = MotorTachoCount(OUT_A); //この時のタイヤの回転数を記録
        }
    }
    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    until(MotorTachoCount(OUT_A)<=tacho_min || SensorUS(S1)<=d_min);

    Wait(14);  //微調整
    Off(OUT_AB);Wait(500);
    return d_min;
}

本文の一番初めのプログラムを例にすると、int d = searchDirection(30)で現在向いている方向を中心に15度ずつの計30度の範囲で紙コップを超音波センサーによって探し、fwdDist(d-25.0)で紙コップの手前25cmまで行くというようなプログラムである。

紙コップを掴んで持ち上げる・アームを開いて下げるプログラムである。角度指定でd度モーターを回して動かしている。アームを閉じて上げる一連の動きがモーターの回転角がおよそ645度だったのでこれを最大として進めた。

sub c_up(float d)   //645で最大
{
    RotateMotor(OUT_C,-30,d);
    Off(OUT_C);
}

sub c_down(float d)
{
    RotateMotor(OUT_C,30,d);
    Off(OUT_C);
}

プログラムの本文である。

紙コップを取る流れとしては、探して近づき反転してアームを動かして掴む。基本的に動きは角度指定なので電池残量に出来るだけ左右されないようにしている。

task main()
{
    SetSensorLowspeed(S1);


    int d = searchDirection(30);  //紙コップ1の方向を探した後、近づいて25cm手前で停止
    if (d > 10){
        fwdDist(d-25.0);
    }

ここの検知は超音波センサーの取り付け角度の具合でうまくいかなかったりしたので調整が必要だった。

    turnAng(200);  //200度の時計回りの旋回

    c_down(640);  //アームを開いて下げる

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //この2つを入れないと次の行動がうまく動かなかった(以降、微調整として記していく)
    baDist(12.0);  //12cm後退

    c_up(260);   //紙コップ1をつかんで少し上げる

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(110);  //110度の時計回りの旋回

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(11.0);  //11cm後退

    c_up(330);    //紙コップ1を上げ、ピンポン玉をはなす

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(90);  //90度の時計回りの旋回

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    fwdDist(17.0);  //17cm前進

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(80);  //80度の時計回りの旋回

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    int e = searchDirection(40);  //障害の紙コップの方向を探した後、その方向を向いて停止

    int msg;  // 受け取った値を格納する変数
    while (true) {             //メッセージを受け取るまで停止して待機
        ReceiveRemoteNumber(MAILBOX1,true,msg);
        if (msg == 1){
            break;    //while文を抜け出す
        } else {
        Off(OUT_AB);
        }
        Wait(100);
        }

    Off(OUT_AB);Wait(3000);  //3秒停止

while文で機体Bからの信号が来るまで停止させ、信号が来たらbreak文でwhile文から抜け出すようになっている。3秒の停止は信号を使っていないときに少し間を取るために使っていたものである。

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(30);  //30度の時計回りの旋回

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    fwdDist(15.0);  //15cm前進

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    int f = searchDirection(30);  //紙コップ2の方向を探した後、近づいて25cm手前で停止
    if (f > 10){
        fwdDist(f-25.0);
    }

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(156);  //156度の時計回りの旋回

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(8.0);  //8cm後退

    c_down(100);  //アームを開き、紙コップ1をはなす

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(2.0);  //2cm後退 

紙コップをはなすだけでは紙コップが完全に入らなかったり引っかかったりしたので、次の後退で少し揺らして入るようにしている。

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    fwdDist(12.0);  //12cm前進

    c_up(100);  //アームを最大まで上げる

アームを最大まで上げることで、紙コップ3も1の時と同様の数値と流れで動かせるようにしている。

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(230);  //230度の時計回りの旋回

    ResetTachoCount(OUT_AB);  //角度計測をリセット
        int g = searchDirection(20);  //紙コップ3の方向を探した後、近づいて25cm手前で停止
        if (g > 10){
            fwdDist(g-25.0);
    }

    turnAng(190);  //190度の時計回りの旋回

    c_down(630);  //アームを開いて下げる

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(16.0);  //16cm後退

    c_up(270);  //紙コップ3をつかんで少し上げる

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(140);  //140度の時計回りの旋回

    c_up(340);  //紙コップ3を上げ、ピンポン玉をはなす

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(290);  //290度の時計回りの旋回

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(12.0);  //12cm後退


    ResetTachoCount(OUT_AB);  //角度計測をリセット
        int h = searchDirection(20);  //紙コップ1の方向を探した後、近づいて25cm手前で停止
        if (h > 10){
            fwdDist(h-25.0);
    }

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    turnAng(156);  //156度の時計回りの旋回

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(8.0);  //8cm後退

    c_down(100);  //アームを開き、紙コップ3をはなす

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    baDist(2.0);  //2cm後退

    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    Off(OUT_AB);                  //微調整
    fwdDist(12.0);  //12cm前進

}

紙コップ3も1と同様にうまく入るように少し揺らす動きを入れている。

機体B

スピードや時間などを定義している。

#define Apower 37

#define Bpower 34  //直進するのに必要な出力

#define ttime 695  //90度曲がるのに必要な時間

#define SPEED 50

#define SPEED_SLOW 30

サブルーチン。

sub go_for()  //前進

{

    OnFwd(OUT_A,Apower);

    OnFwd(OUT_B,Bpower);

}

sub go_back()   //後退

{

    OnFwd(OUT_A,-Apower);

    OnFwd(OUT_B,-Bpower);

}

sub turnL(float c)  //左に曲がる

{

    OnFwd(OUT_A,Apower);OnFwd(OUT_B,-Bpower);

    Wait(c*ttime);

    Float(OUT_AB);  //左に曲がる(c×90)度

}

sub turnR(float c)  //右に曲がる

{

    OnFwd(OUT_A,-Apower);OnFwd(OUT_B,Bpower);

    Wait(c*ttime);

    Float(OUT_AB);  //右に曲がる(c×90)度

}

int cyari(int lsw)  //スタート時の位置調整

{

    ResetTachoCount(OUT_C);

    SetSensorLight(S1);

    SetSensorMode(S1,SENSOR_MODE_RAW);

    SetSensorTouch(S4);

    int i=1;

    int lsb=SENSOR_1;

    int lsb2=SENSOR_1-1;

    while (i==1){

        go_for();

        lsb2=SENSOR_1;

        NumOut(80,LCD_LINE4,lsb2);

        if (lsb>lsb2) {

            lsb=lsb2;

            }

        if (lsb+10<lsb2) {

            i=10;

            }

        if (lsb>lsw-150) {

            i=1;

            }    

        }

    Off(OUT_AB);

    NumOut(80,LCD_LINE1,lsw);

    NumOut(80,LCD_LINE2,lsb);

    return lsb;

}
const float diameter=5.45;  //タイヤの直径

const float track=11.35;  //タイヤのトレッド幅

const float pi=3.1415;  //円周率

void fwdDist(float d)  //距離dcm前進

{

    long angle=d/(diameter*pi)*360.0;

    RotateMotorEx(OUT_AB,SPEED_SLOW,angle,0,true,true);

}

void turnAng(long ang)  //角度ang度の時計回りの旋回

{

    long angle=track/diameter*ang;

    RotateMotorEx(OUT_AB,SPEED_SLOW,angle,100,true,true);

}
 sub arm(int c)  //アームを動かす

{

        RotateMotor(OUT_C, 40,c);

    Off(OUT_C);

}

プログラムの本文である。

 task main ()

{

    ResetTachoCount(OUT_C);

    SetSensorLight(S1);

    SetSensorMode(S1,SENSOR_MODE_RAW);

    SetSensorTouch(S4);

    int lsw=SENSOR_1;

    int lsb=cyari(lsw);

    while(SENSOR_4==0) {}

    fwdDist(15);

    Wait(15000);

    turnL(1.1);//1

    PlaySound(SOUND_UP);

    Wait(1000);

    fwdDist(30);

    Wait(1000);

    turnAng(40);

    PlaySound(SOUND_UP);

    turnAng(180);

    Wait(1000);

    fwdDist(15);

    Wait(1000);

    arm(550);

    Wait(1000);

    go_back();

    Wait(2000);

    Off(OUT_AB);

    arm(-180);

    Wait(1000);

    arm(-45);

    Wait(1000);

    turnL(1.05);//2

    Wait(1000);

    arm(-200);

    fwdDist(35);

    turnL(0.4);

    Wait(1000);

    arm(100);

    PlaySound(SOUND_UP);

    SendRemoteNumber(1,MAILBOX1,1);

    fwdDist(20);

    while(SENSOR_4==0) {}

}

機体Bの大まかな動きの流れとしては、機体Aが紙コップ1のピンポン玉をX地点へはなすまでは、少し前進して待機している。その後、紙コップ2を取りに行き、ピンポン玉をX地点ではなしてY地点に紙コップ2を置く。最後に機体Aに信号を送って終了というような流れである。機体Bのプログラムの詳細については下のページをご覧ください。

2017b/Member/takeshi/Mission3

2017b/Member/Yoshi/Mission3

プログラムの理想の流れ

プログラムがすべて完璧に動いた場合の理想とする流れである。

プログラムの流れ1 まず機体Aが紙コップ1を検知して、紙コップ1の前へ進む。

プログラムの流れ2 機体Aは紙コップ1を掴む。機体Bは少し前進。

プログラムの流れ3 機体Aは紙コップ1をX地点まで運び、紙コップ1の中にあったピンポン玉をX地点へ置く。機体Bは待機。

プログラムの流れ4 機体Aは紙コップ1を持った状態で紙コップ2の上方にある紙コップを検知してそこで停止して待機。機体Bは紙コップ2掴む。

プログラムの流れ5 機体Aは待機。機体Bは紙コップ2をX地点まで運び、紙コップ2の中にあったピンポン玉をX地点へ置く。

プログラムの流れ6 機体Aは待機。機体Bは紙コップ2をY地点へ置き、機体Aに信号を送る。

プログラムの流れ7 機体Aは信号を受け取った後、Y地点の紙コップ2を検知してその前まで行き、紙コップ2に重ねて紙コップ1を置く。機体Bは邪魔にならないよう移動。

プログラムの流れ8 機体Aは紙コップ3を検知して移動し、紙コップ3を掴む。

プログラムの流れ9 機体Aは紙コップ3をX地点まで運び、紙コップ3の中にあったピンポン玉をX地点へ置く。

プログラムの流れ10 機体AはY地点の紙コップ1及び2を検知してその前まで行き、紙コップ1の上に重ねて紙コップ3を置く。

実際は紙コップ1のピンポンを置くところまではうまくいき、紙コップ2のところでうまくいかずそこまでになってしまうことが多かった。練習でも紙コップ1と2の調整に時間がかかり紙コップ3はほとんど手をつけられなかった。

結果と反省

本番では、実は機体Bが最初に紙コップ2を取りに行き、その後機体Aが動き出すプログラムであった。しかし、機体Bのとれなかった紙コップやピンポン玉が機体Aの障害となってしまい機体Aもうまくいかず、結果0点となってしまった。再度の挑戦の時は、少しでも点を取りに行くことを考えて上記のように比較的成功率の高かった機体Aを先に動かした。結果5点を獲得することが出来た。どちらかが失敗してしまうと、もう一方もだめになってしまうようなプログラムだったことが反省点だと感じた。もっとよりうまく2機の連携のとれたプログラムに出来たのではないかと感じた。

感想

今回は、4人で行う課題でロボットも2台だったのでうまく分担して協力して課題に取り組めた。限られた時間しかなかったので、しっかり計画性を持ってみんなで確認しながら取り組んでいくことが大事だと感じた。時間もあまりなく焦りもあったが、最後の最後まであきらめずにやれたのは良かったと思う。上記にあるような理想の形にはならなかったが、課題への取り組みは楽しかった。メンバーのみんなには本当に感謝したいと思う。


添付ファイル: fileロボティクス32.jpg 59件 [詳細] fileロボティクス31.jpg 36件 [詳細] fileロボティクス30.jpg 36件 [詳細] fileロボティクス29.jpg 38件 [詳細] fileロボティクス28.jpg 67件 [詳細] fileロボティクス27.jpg 56件 [詳細] fileロボティクス26.jpg 43件 [詳細] fileロボティクス25.jpg 49件 [詳細] fileロボティクス24.jpg 41件 [詳細] fileロボティクス23.jpg 38件 [詳細] fileロボ課題3_23.jpg 39件 [詳細] fileロボティクス課題3_21.jpg 59件 [詳細] fileロボティクス課題3_19.jpg 35件 [詳細] fileロボティクス課題3_17.jpg 46件 [詳細] fileロボ課題3_16.jpg 44件 [詳細] fileロボティクス課題3_15.jpg 56件 [詳細] fileロボ課題3_9.jpg 56件 [詳細] fileロボティクス課題3_13.jpg 57件 [詳細] fileロボティクス課題3_12.jpg 40件 [詳細] fileロボティクス課題3_11.jpg 33件 [詳細] fileロボティクス課題3_9.jpg 16件 [詳細] fileロボティクス課題3_22.jpg 45件 [詳細] file課題3_22.jpg 48件 [詳細] fileロボティクス課題3_4.jpg 36件 [詳細] fileロボティクス課題3_8.jpg 33件 [詳細] fileロボティクス課題3_6.jpg 47件 [詳細] fileロボティクス3_32.jpg 17件 [詳細] fileロボティクス3_31.jpg 18件 [詳細] fileロボティクス3_30.jpg 18件 [詳細] fileロボティクス3_29.jpg 14件 [詳細] fileロボティクス3_28.jpg 22件 [詳細] fileロボティクス3_27.jpg 21件 [詳細] fileロボティクス3_26.jpg 21件 [詳細] fileロボティクス3_25.jpg 29件 [詳細] fileロボティクス3_24.jpg 22件 [詳細] fileロボティクス3_23.jpg 20件 [詳細] fileロボティクス課題3_27.jpg 15件 [詳細] fileロボティクス課題3_26.jpg 17件 [詳細] fileロボティクス課題3_25.jpg 22件 [詳細] fileロボティクス課題3_24.jpg 20件 [詳細] fileロボティクス課題3_23.jpg 17件 [詳細] file2017b-mission3.png 48件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-02-13 (火) 22:57:27 (551d)