[[2019a/Member]]

*目次 [#ie15bf3a]
#contents
*課題 [#m1dc624d]
ボール運搬ロボットの作成
ピンポン玉または青と赤のボールを運搬して、所定の容器の中に入れる。
#ref(2019a/Member/yuka/Mission3/課題のルート,15%,課題のルート)
#ref(2019a/Member/yuka/Mission3/順路,15%,順路)
**フィールドの説明 [#z2643552]
-フィールドは課題2で使用した紙を使用する。-
-生協のお弁当の四角いプラ容器2つをそれぞれ円内に置き、片方に玉を2個入れる。-
-残りの2個の玉は課題2と同じ位置に置く。その際、ゴムタイヤやプレートの上に置いてもよい。-
-プラ容器には色をつけたり文字や記号を書いてもよい。-
-プラ容器は両面テープ等でフィールドに固定してもよい。-
-2枚の紙の境界にはそれぞれ幅1cm、合計2cmの黒線を描いてもよい。-
-フィールドは課題2で使用した紙を使用する。
-生協のお弁当の四角いプラ容器2つをそれぞれ円内に置き、片方に玉を2個入れる。
-残りの2個の玉は課題2と同じ位置に置く。その際、ゴムタイヤやプレートの上に置いてもよい。
-プラ容器には色をつけたり文字や記号を書いてもよい。
-プラ容器は両面テープ等でフィールドに固定してもよい。
-2枚の紙の境界にはそれぞれ幅1cm、合計2cmの黒線を描いてもよい。

*基本ルール [#dcf13771]
-競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
-図のA地点または(および)A'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。
-開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
-競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
-途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
-競技終了後、ロボットが、ゴールのプラ容器に触れていてはいけない。
-競技終了後、もともと玉が入っていたプラ容器が、ゴールのプラ容器に触れていてはいけない。

※さらに詳しいルールは課題3を参照にしてください。
*ロボットの構造 [#b7853832]
**床に落ちているボールを拾うロボット [#d1444c92]
--床に落ちているボールは以下ような順路で拾っていく。
#ref(2019a/Member/yuka/Mission3/床(順路),15%,床(順路))
--床に落ちているボールは輪ゴムの弾性力を使ってアームが床に着いた時ボールがアームに張った輪ゴムの上に乗ることでボールを拾う仕組みをとった。
--輪ゴムを4本張ることで、安定してボールが取れるようにした。
--以下の図のようにボールを拾う。
#ref(2019a/Member/yuka/Mission3/アーム1,15%,アーム1) 
#ref(2019a/Member/yuka/Mission3/アーム2,15%,アーム2)
#ref(2019a/Member/yuka/Mission3/アーム3,15%,アーム3)
#ref(2019a/Member/yuka/Mission3/アーム4,15%,アーム4,)
--部品は以下のようなものを使った。
#ref(2019a/Member/yuka/Mission3/床部品,15%,床部品)
**容器の中に入っているボールを拾うロボット [#n6160315]
#ref(2019a/Member/yuka/Mission3/容器(順路),15%,容器(順路))
--容器に入っているボールは上図のような順路で、容器ごと持ち上げて、2つのボールを一度に転がして入れる方法にした。
#ref(2019a/Member/yuka/Mission3/容器1,15%,容器1)
#ref(2019a/Member/yuka/Mission3/容器2,15%,容器2)
#ref(2019a/Member/yuka/Mission3/容器3,15%,容器3)
--本体に容器を持ち上げるために長いアームを付けて容器ごとと持ち上げる。
--アームの先にツメがついていて落ちにくい設計になっている。
#ref(2019a/Member/yuka/Mission3/容器ロボット,15%,容器ロボット)
*プログラム [#x48edfa4]
**床に落ちているボールを拾うロボット [#lff4a0a1]
**容器の中に入っているボールを拾うロボット [#ud80dfb1]
***定義したこと [#z004855b]
-define MOVE_TIME 250 // ライントレースする時間
-define SPEED_H 35 
-define SPEED_L 20  
-define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL) // 右の車輪と左の車輪を違うスピードで動かす。
-define go_straight OnRL(SPEED_H,SPEED_H) // 直進
-define rot_r OnRL(-SPEED_L,SPEED_L) // 右に旋回
-define turn_r OnRL(0,SPEED_L) // 右に曲がる
-define rot_l OnRL(SPEED_L,-SPEED_L) // 左に旋回
-define turn_l OnRL(SPEED_L,0) // 左に曲がる
-define B1 43 // ラインの真ん中の閾値
-define G 53 // ラインの境界の閾値
-define W1 59 //ラインから近いところの閾値
-define W2 61 // ラインから遠いところの閾値
-define BACK OnRL(-SPEED_H,-SPEED_H) // 後進
-sub follow_line_l()  // ライントレース
  {
    SetSensorLight(S2); // センサーを起動
    long t0=CurrentTick(); // 基準の設定
    while(CurrentTick()-t0<MOVE_TIME){
        if(SENSOR_2>W1){
            rot_r;t0=CurrentTick(); //光センサがW1以上の時右に旋回
        }
        else if(SENSOR_2>W2){
            turn_r;t0=CurrentTick(); ///光センサがW1以上の時右に旋回
        }
        else if(SENSOR_2>G){
            go_straight;t0=CurrentTick();//光センサがG以上の時直進
        }
        else if(SENSOR_2>B1){
            turn_l;t0=CurrentTick();//光センサがB2以上の時左に曲がる
        }
        else{
            rot_l;// その他の時左に旋回
          }
      }
 }
-sub follow_line_r() // 交差点を見分ける
 {
    SetSensorLight(S2);
    long t0=CurrentTick();
    while(CurrentTick()-t0<MOVE_TIME){
        if(SENSOR_2>W1){
            rot_l;t0=CurrentTick(); //光センサがW1k以上の時右に旋回
        }
        else if(SENSOR_2>W2){
            turn_l;t0=CurrentTick();//光センサがW1以上の時右に旋回
        }
        else if(SENSOR_2>G){
            go_straight;t0=CurrentTick();//光センサがG以上の時直進
       
        }
        else if(SENSOR_2>B1){
            turn_r;t0=CurrentTick();光センサがB1以上の時左に曲がる
        }
        else{
            rot_r;その他の時右に旋回
        }
     }
 }
-sub short_break() // 小休止
 {
    Off(OUT_BC);
    Wait(1000);
 }
-sub arm_down() // 床に落ちているボールを取るときにアームを下げる
{
    OnFwd(OUT_A,70);
    Wait(600);
    Off(OUT_A);
    Wait(500);
    OnRev(OUT_A,50);
    Wait(500);
    Off(OUT_A);
}
-sub shoot()  //  ボールを容器の中に入れる
{
    OnRev(OUT_A,60);
    Wait(700);
    Off(OUT_A);
    OnFwd(OUT_A,55);
    Wait(500);
    Off(OUT_A);
}
-sub back(long t)  // 後進する時間
{
    BACK;
    Wait(t);
    Off(OUT_BC);
}
***全体のプログラム [#q7bbb65f]
{
    Off(OUT_A);
    go_straight; //枠から脱出する
    Wait(1000);
    Off(OUT_BC);
    follow_line_l();
    short_break();
    rot_r;
    Wait(400);
    Off(OUT_BC);
    go_straight;
    Wait(800);
    Off(OUT_BC);
    arm_down(); //床のボールの二個目は引きずって運ぶ
    turn_r;
    Wait(3500);
    Off(OUT_BC);
    shoot();
    Wait(1000);
    rot_r;
    Wait(3800);
    Off(OUT_BC);
    go_straight;
    Wait(6600);
    Off(OUT_BC);
    arm_down();
    back(3000);
    OnRL(0,-SPEED_L);
    Wait(300);
    Off(OUT_BC);
    shoot();//ボールを入れる
}
今回はライントレースするよりも1つ1つの動きを決めた方が早く、確実に進んだので動きは定義してプログラムにした。
**容器の中に入っているボールを拾うロボット [#ud80dfb1] 
***定義したこと [#ec59cc27]
-define MOVE_TIME 250 //ライントレースする時間
-define SPEED_H 35
-define SPEED_L 20
-define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL) //その場で回る
-define go_straight OnRL(SPEED_H,SPEED_H) //直進
-define rot_r OnRL(-SPEED_L,SPEED_L) // 右に旋回
-define turn_r OnRL(0,SPEED_L) // 右に回る
-define rot_l OnRL(SPEED_L,-SPEED_L) // 左に旋回
-define turn_l OnRL(SPEED_L,0) //左に回る
-define B1 43 // ラインの真ん中の閾値
-define G 53 // ラインの境界の閾値
-define W1 59 // ラインに近いところ
-define W2 61 // ラインより遠いところ
-define BACK OnRL(-SPEED_H,-SPEED_H) //後進
-sub follow_line_l() // ラインの左側をトレース
 {
    SetSensorLight(S2);
    long t0=CurrentTick();
    while(CurrentTick()-t0<MOVE_TIME){
        if(SENSOR_2>W1){
            rot_r;t0=CurrentTick();
        }
        else if(SENSOR_2>W2){
            turn_r;t0=CurrentTick();
        }
        else if(SENSOR_2>G){
            go_straight;t0=CurrentTick();
        }
        else if(SENSOR_2>B1){
            turn_l;t0=CurrentTick();
        }
        else{
            rot_l;
        }
    }
 }
- sub follow_line_r() // 右側をトレース
 
    SetSensorLight(S2);
    long t0=CurrentTick();
    while(CurrentTick()-t0<MOVE_TIME){
        if(SENSOR_2>W1){
            rot_l;t0=CurrentTick();//光センサがW1以上の時右に旋回
        }
        else if(SENSOR_2>W2){
            turn_l;t0=CurrentTick();//光センサがW2以上の時右に旋回
        }
        else if(SENSOR_2>G){
            go_straight;t0=CurrentTick();//光センサがG以上の時右に旋回
        }
        else if(SENSOR_2>B1){
            turn_r;t0=CurrentTick();//光センサがB1k以上の時右に旋回
        }
        else{
            rot_r;
        }
    }
  }
- sub cross_line_1() // 交差点を見分ける。左に回る
 {
    while(SENSOR_2<W1){
        go_straight;//光センサがW1以下の時右に旋回
    }
    while(SENSOR_2>G){
        turn_l;//光センサがG以上の時右に旋回
    }
    Off(OUT_BC);
 }  
-sub cross_line_2() // 交差点を見分ける。左に旋回する。
 {
    while(SENSOR_2<W1){
        go_straight;//光センサがW1以下の時右に旋回
    }
    while(SENSOR_2>G){
        rot_l;//光センサがG以上の時右に旋回
    }
    Off(OUT_BC);
 }  
-sub short_break() // 小休止
 {
    Off(OUT_BC);
    Wait(1000);
 }
-sub arm_down() // アームを下げる。この時他の場所よりも出力を上げて、ボールが輪ゴムに引っかかりやすくした。
 {
    OnFwd(OUT_A,50);
    Wait(500);
    Off(OUT_A);
    Wait(500);
    OnRev(OUT_A,50);
    Wait(500);
    Off(OUT_A);
  }
-sub shoot() // 容器をひっくり返してボールを入れる
 {
    OnRev(OUT_A,60);
    Wait(600);
    Off(OUT_A);
    OnFwd(OUT_A,90);
    Wait(800);
    Off(OUT_A);
  }
-sub back(long t) // 後進
  {
    BACK;
    Wait(t);
  }
***全体のプログラム [#u8e13c65]
 {
    go_straight;
    Wait(1000);
    Off(OUT_BC);
    rot_l; //90℃曲がる
    Wait(2800);
    Off(OUT_BC);
    go_straight;
    Wait(3000);
    Off(OUT_BC);
    rot_l;
    Wait(4500);
    Off(OUT_BC);
    go_straight;
    Wait(3000);
    turn_l;
    Wait(8700);
    Off(OUT_BC);
    Wait(27000);
    OnFwd(OUT_A,50);
    Wait(700);
    OnRev(OUT_BC,60);
    Wait(700);
    Off(OUT_BC);
    shoot(); ボールを入れる
 }

* 感想 [#mb3262f3]
-ロボットを一台にするか二台にするかでグループ内でたくさん議論した。結果的に二台にした方がプログラミングが簡潔になるということで二台にした。
-少しの条件の変化、例えば電池の残量や起動時間、床の条件なのでロボットの動きが変わってしまったのでボールを確実に取って確実に箱に入れることができることはなかった。
-普段使っているロボットがいかに汎用性が高く、環境に左右されないんだなと思った。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS