目次

課題説明

コースの画像

今回の課題は、ピンポン玉と紙コップを別々に回収し、それぞれ指定された場所に置くというものである。紙コップは重ねて集めると加点され、障害物を動かしてしまうと減点になる。詳しいルールは下のページから↓

2017b/Mission3

ロボット概要

今回ロボットを2台作成した。ロボット本体のつくりはほとんど同じであるが、1台ずつ別々に作ったので本体は少し、プログラムは完全に違ったものとなっている。なので、それぞれロボット1、ロボット2として、分けて説明していく。自分が作ったのはロボット1なのでロボット2の詳しい説明については下のページで見てください。↓

2017b/Member/Yoshi/Mission3

2017b/Member/takeshi/Mission3

ロボット1

ロボット1画像
ロボット1画像

タイヤが付いたモーターが2つとモーター1つで動くアーム、それと超音波センサーがついている。超音波センサーは縦につけた方がいいとのことだったので、縦に取り付けた。

ロボット2

ロボット2画像
ロボット2画像

基本的にロボット1と同じである。違うところとして、写真では見えにくいが光センサーがついているのと、スタートする時に使うタッチセンサーがついている。

紙コップをつかみ、持ち上げる機構

今回作ったロボットの1番の特徴はモーター1つで紙コップをつかみ、持ち上げる機構である。その仕組みとしては、まず、モーターを回すと、つかむところのアームが閉まる。アームがそれ以上閉まらないところまでいくと、持ち上がるという仕組みである。

つかんで、持ち上げる機構1

アームが開いた状態で紙コップのところまで行く。(アームがロボットの後ろについているので、180度回ってから紙コップを取ることになる。なので、アームを長くして紙コップがとれる確率を上げている。)また、アームの後ろにはそれ以上開かないようにストッパーがつけてある。

つかんで、持ち上げる機構2

モーターを回し始めると、アームが紙コップをつかみそれ以上閉まらなくなる。

つかんで、持ち上げる機構3

そうすると、紙コップと一緒にアームが上がり始める。

つかんで、持ち上げる機構4

このくらいの高さでモーターをとめると、紙コップだけが上がり、ピンポン玉が散らばらない。この状態で移動させることで、割りばしで作った囲いを超えてピンポン玉をその中に入れることができる。

つかんで、持ち上げる機構5

ピンポン玉を放したあと、さらにモーターを回すと、構造上部品同士がぶつかってしまいこれ以上上がらなくなる。

つかんで、持ち上げる機構6

しかし、その高さは紙コップを超える高さなので、

つかんで、持ち上げる機構7

モーターを逆にすこし回転させると、、紙コップを重ねることができる。(アーム部分を軽くしているので、モーターを逆に回転させたときに、先にアームが開くようになっている。ただし、アーム部分の歯車のかみ合い具合で先に下に降りたりもする。)

機体を動かす順番

今回ロボットを2つにしたので、2台がぶつからないように経路を考えた。

経路1

ロボット1が左側、ロボット2が右側から出発する。

経路2

まず、ロボット1が超音波センサーで正面の紙コップを探し、手前まで移動してから、反転し、少し後ろに下がって紙コップをつかめる位置までいき、紙コップを、少し持ち上げる。その間、ロボット2は待機しておく。

経路3

ロボット1を右に旋回させピンポン玉を割りばしの枠の中に、入れてから最大まで紙コップを上げる。この作業が終わったくらいで、ロボット2が動き出す。

経路4

ロボット1を上まで移動させ障害物である紙コップを超音波センサーで感知させその手前で止まる。動き出したロボット2はモーターを時間指定で回し目的の紙コップの前で反転し、紙コップを少し持ち上げる。

経路5

ロボット2を回転させロボット1と同じようにピンポン玉を枠に入れた後、紙コップを最大まで上げる。ロボット1はロボット2から信号がくるまで停止している。

経路6

ロボット2が紙コップをY地点に置き、そのまま邪魔にならない位置に移動する。その後、ロボット1に信号を送る。

経路7

信号を受け取ったロボット1は、障害物をよけてからY地点の紙コップを超音波センサーで探し、その上に自分の持っている紙コップを重ねる。

経路8

少し前に出てから旋回し、最後の紙コップを少し持ち上げる。

経路9

その場で旋回して、ピンポン玉を枠の中に入れる。そして、紙コップを最大まで上げる。

経路10

旋回して少し距離をあけてから、超音波センサーでY地点の紙コップを見つけて、同じように反転してから紙コップを重ねたら終了。

ロボット1のプログラムについて

定義

#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 - 10)でその手前10cmのところまで行くことができるプログラム。

紙コップを上げ下げするサブ関数

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);
}

角度指定でモーターがd度回るようにしてある。

本文

task main()
{
    SetSensorLowspeed(S1);

    int d = searchDirection(30);  //紙コップの方向を探した後、近づいて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()がうまく動かなかったのでいれました(以下、微調整)
    baDist(12.0);   //12cm後進

    c_up(260);   //紙コップをつかむ

スタート位置から紙コップを探し、手前まで行き反転してから後進して紙コップを取るまでのプログラムである。(最初のサーチで、超音波センサーの取り付け角度によってうまく感知しないことがあるので調整が必要になる。)また、今回前進、後進するのに角度指定のプログラムを使っており、電池消費でもそこまで影響を受けないようにななっている。

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

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

    c_up(330);    //ピンポン玉をはなす

    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文で信号がきていない間は停止させ、信号が来たらbreak文を使ってwhile文から抜け出すようになっている。その後の3秒停止は信号を使わないとき(1台で動かすとき)に使っていたものである。

    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);  //紙コップの方向を探した後、近づいて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);       //紙コップを放す

    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);            //アームを最大まで上げる

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

    ResetTachoCount(OUT_AB);  //角度計測をリセット
    int g = searchDirection(20);  //紙コップの方向を探した後、近づいて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);             //紙コップを少し持ち上げる

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

    c_up(340);          //紙コップをあげてピンポン玉を放す

最初に、アームを最大まであげて基準とし、次の紙コップを取る時に最初と同じ値を使えるようにしている。2つ目の紙コップも1つ目と変わらずサーチしてつかんで、回してピンポン玉を入れるという流れである。2つ目の旋回の後は、特に前後に移動する必要がなかったのでそのままにしている。

    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);   //紙コップの方向を探した後、近づいて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);         //紙コップを放す

    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前進

}

最初の290度は時計回りしかできなかったため無駄に回っている。反時計回りのプログラムを作ろうといてみたがうまくいかず、時間もなかったし、必ず必要なわけでもなかったのであきらめた。回った後少し離れて紙コップをサーチしやすくなるようにしている。そのあとは、前と一緒で近づいて反転して、後進し紙コップを放し、揺らして終了である。

ロボット2のプログラムについて

プログラムについても、別々に作ったので詳細は下のページを参考にしてください。↓

2017b/Member/Yoshi/Mission3

2017b/Member/takeshi/Mission3

定義

#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)
{
    long angle=d/(diameter*pi)*360.0;
    RotateMotorEx(OUT_AB,SPEED_SLOW,angle,0,true,true);
}
void turnAng(long ang)
{
    long angle=track/diameter*ang;
    RotateMotorEx(OUT_AB,SPEED_SLOW,angle,100,true,true);
}
int SearchDirection(long ang) //現在の方向を中心にang度の範囲で探し障害物までの距離を返す

{
    SetSensorLowspeed(S3);
    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(S3)<d_min){   //現在の距離が仮の最小値より小さい場合
    d_min = SensorUS(S3);  //仮の最小値を更新
    tacho_min = MotorTachoCount(OUT_A);//このときのタイヤの回転数を記録
     }
   }
    OnFwdSyncEx(OUT_AB,SPEED_SLOW,100,RESET_NONE);
    until(MotorTachoCount(OUT_A)<=tacho_min||SensorUS(S3)<=d_min);
    
    Wait(14); //微調整
    Off(OUT_AB);Wait(500);
    return d_min;
}

超音波センサーで紙コップを見つけてその手前まで行くサブ関数

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);
    SetSensorLowspeed(S3);
    int lsw=SENSOR_1;
    int lsb=cyari(lsw);
    while(SENSOR_4==0) {}
    fwdDist(15);
    Wait(15000);

少し進んでから15秒間停止

    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);

1つ目の紙コップの手前まで行き紙コップをつかむ

    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) {}
}

紙コップを回してピンポン玉を枠に入れてから紙コップをY地点に運び紙コップを置いたら、ロボット1に信号を送る。そして、少し、離れて終了。

結果

本番では片方の機体がうまく紙コップを取れず、取れなかった紙コップがもう1つの機体の妨害をしてしまい、1点も取ることができなかった。なので、2回目にするときは、動かす機体の順番を変えてとりあえず点を取れるように変えたところ5点とることができた。

感想

今回は、今までとは違ってロボットを2台使って課題に取り組んだが、お互いにどのようにするかの方針をしっかり立てて、作っている時もコミュニケーションを取りながら作ることが重要だったと思う。今までの課題でもそうだったが、最終的には時間との勝負になってしまい少し雑になってしまったと思う。しかし、最後まであきらめず取り組みできるところまではやったので満足している。大変だったが楽しかった。


添付ファイル: fileIMG_2179.JPG 61件 [詳細] fileIMG_2177.JPG 88件 [詳細] fileIMG_2162.jpg 47件 [詳細] fileIMG_2160.jpg 55件 [詳細] fileIMG_2157.jpg 54件 [詳細] fileIMG_2156.jpg 45件 [詳細] fileIMG_2154.jpg 57件 [詳細] fileIMG_2153.jpg 60件 [詳細] fileIMG_2152.jpg 99件 [詳細] fileIMG_2148.jpg 41件 [詳細] fileIMG_2147.jpg 44件 [詳細] fileIMG_2173.jpg 60件 [詳細] fileIMG_2172.jpg 41件 [詳細] fileIMG_2171.jpg 58件 [詳細] fileIMG_2170.jpg 45件 [詳細] fileIMG_2169.jpg 66件 [詳細] fileIMG_2168.jpg 50件 [詳細] fileIMG_2167.jpg 54件 [詳細] fileIMG_2166.jpg 54件 [詳細] fileIMG_2165.jpg 51件 [詳細] fileIMG_2164.jpg 45件 [詳細] file2017b-mission3.png 51件 [詳細]

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