2019a/Member

目次

課題2

下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。 黒線の幅は20mmでなるべく均等な濃さにすること。 ゴールには、長さ15または16のブロックおく。

map.png

コース

A地点から出発 → M → K(直進) → L(ピンポン玉をつかむ) → K(右折) → J(一時停止の後、左折) → I(直進) → H(直進) → G(左折) → F → E → D(一時停止の後、直進) → C(直進) → B(一時停止) → シュート→ A地点に入る(ゴール)

交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止すること。

map_line.png

ロボットについて

ロボットの全体

今回は,ロボティクスの最初の授業で作ったロボットを改良して作った.

robo_all.jpg

胴体

ボールを掴む部分の取り付けを考慮し,バッテリーの位置を後ろに移動させた.

robo_honntai.jpg

光センサー

小回りが利くようにできるだけロボットの車軸に近づけて作った.

senser.jpg senser_posi_new.jpg

つかむ部分

arm.jpgarm_explain.jpg

横から挟む機構にした. (向に回すとアームが開き,∧向の回すとアームが閉じる.

プログラムについて

ライントレース

まず,黒い線を追従するライントレースのプログラミングを作った. 「完全に真っ白」,「白と境目の間」,「境目」,「黒と境目の間」, 「完全に黒」の5つの部分に色を分けて光の値を測った. それらの値は以下の図のようになった.

light_number.png

プログラミングでは以下のように定義する.

#define black 20
#define white 50
#define lightgray 40
#define darkgray 28
#define center 35

また,トレース時の動作もそれぞれ定義しておく.

#define turn_right OnFwd(OUT_C,25);OnRev(OUT_B,15);//右折
#define turn_left OnFwd(OUT_B,25);OnRev(OUT_C,15);//左折
#define rotate_right OnFwd(OUT_C,20);OnRev(OUT_B,20);//右旋回
#define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,20);//左旋回
#define go_straight OnFwd(OUT_BC,20);//出力20の直進
#define go_straight2 OnFwd(OUT_BC,15);//出力15の直進

サブルーチン

左側のライントレース

sub followline_L(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){ //現在の時刻が一定の値を超えるまで
        if(SENSOR_1<black){            //センサーが黒の時
        rotate_left;                   //左旋回
        }else if(SENSOR_1<darkgray){   //センサーが黒灰なら
        turn_left;                     //左折
        }else if(SENSOR_1>lightgray){  //センサーが白灰なら
        turn_right;                    //右折
        t0=CurrentTick();              //時間をリセット
        }else if(SENSOR_1<35){         //明るさ35以下で
        go_straight;                   //直進
        t0=CurrentTick();              //時間をリセット
        }else{                         //それ以外は
        rotate_right;                  //右旋回
        t0=CurrentTick();              //時間をリセット
        }
    }    
    Off(OUT_BC);          //時刻が一定の値を超えると停止
    Wait(1000);           //1秒間停止
}

右側のライントレース

sub followline_R(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){  //現在の時刻が一定の値を超えるまで
        if(SENSOR_1<black){             //センサーが黒の時
        rotate_right;                   //右旋回
        }else if(SENSOR_1<darkgray){    //センサーが黒灰なら
        turn_right;                     //右折
        }else if(SENSOR_1>lightgray){   //センサーが白灰なら
        turn_left;                      //左折
        t0=CurrentTick();               //時間をリセット
        }else if(SENSOR_1<35){          //センサーが35以下なら
        go_straight;                    //直進
        t0=CurrentTick();               //時間をリセット
        }else{                          //それ以外は
        rotate_left;                    //左旋回
        t0=CurrentTick();               //時間をリセット
        }
    }    
    Off(OUT_BC);           //一定の時間を超えると停止
    Wait(1000);            //一秒間停止
}

J地点でのT字路まで右側をトレースするサブルーチン

sub followline_R2(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){   //時刻がある一定の値より小さいとき
        if(SENSOR_1<black){              //黒なら
        rotate_right;                    //右旋回
        t0=CurrentTick();                //時間をリセット
        }else if(SENSOR_1<darkgray){     //灰黒色なら
        turn_right;                      //右折
        t0=CurrentTick();                //時間をリセット
        }else if(SENSOR_1>lightgray){    //灰白色なら
        turn_left;                       //左折
        }else if(SENSOR_1<35){           //明るさ35以下で
        go_straight2;                    //ゆっくり直進
        t0=CurrentTick();                //時間をリセット
        }else{                           //それ以外なら
        rotate_left;                     //左旋回
        }
    }    
    Off(OUT_BC);            //停止
    Wait(2000);             //2秒間停止
}

交差点横断

  • 直進 黒灰(28)より小さい値を検知している時は直進し, 黒灰(28)より大きい値を検知したら止まる.→黒い線上では直進
    sub Blackto_White()
    {
        while(SENSOR_1<darkgray){
            OnFwd(OUT_BC,15);
        }
        Off(OUT_BC);
    }
  • 右旋回 白灰(40)より小さい値を検知している時は右折し, 白灰(40)より大きい値を検知したら止まる. →黒い線上では右旋回
    sub Blackto_White_R()
    {
        while(SENSOR_1<lightgray){
            OnFwd(OUT_C,20);
            OnRev(OUT_B,20);
        }
        Off(OUT_BC);
    }
  • 左旋回 白灰(40)より小さい値を検知している時は左折し, 白灰(40)より大きい値を検知したら止まる.→黒い線上では左旋回
    sub Blackto_White_L()
    {
        while(SENSOR_1<lightgray){
            OnFwd(OUT_B,20);
            OnRev(OUT_C,20);
        }
        Off(OUT_BC);
    }

交差点認識

ライントレースをしている際,交差点にたどり着いてもそのままトレースを続けてしまい曲がってしまう.そのため,交差点を認識するプログラムを作成した.また,条件である交差点での1秒停止のプログラムを組み込んだ.

左側トレースの交差点認識

left_trace.png

左側のライントレースの場合,「黒」と「黒灰」の△鉢い瞭虻遒連続で何秒間か続いたとき,止まるようにする.

sub followline_L(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){ //stop_timeにいれた値を超過すると次のプログラムへ
        if(SENSOR_1<black){             //blackすなわち20より小さい値を検知すると左へ旋回
            rotate_left;        //この動作が連続すると止まる
        }else if(SENSOR_1<darkgray){  //darkgrayすなわち28より小さい値を検知すると左へ
            turn_left;               //この動作が連続すると止まる
        }else if(SENSOR_1>lightdark){  //lightdrayすなわち40より大きい値を検知すると右へ曲がる
            turn_right;              //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else if(SENSOR_1<center){   //centerすなわち35より小さい値を検知すると直進する
            go_straight;             //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else{             //whiteすなわち50より大きい値を検知すると右へ旋回
            rotate_right;            //この動作中はライントレースし続ける
            t0=CurrentTick();
        }
    }
    Off(OUT_BC);
    Wait(1000);
}

右側トレースの交差点認識

right_trace.png

左側と同様に「黒」と「黒灰」の,鉢の動作が連続で何秒間か続いたとき止まるようにする.

sub followline_R(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){ //stop_timeにいれた値を超過すると次のプログラムへ
        if(SENSOR_1<black){             //blackすなわち20より小さい値を検知すると右へ旋回
            rotate_right;                //この動作が連続すると止まる
        }else if(SENSOR_1<darkgray){  //darkgrayすなわち28より小さい値を検知すると右へ
            turn_right;                  //この動作が連続すると止まる
        }else if(SENSOR_1>lightdark){  //lightdrayすなわち40より大きい値を検知すると左へ曲がる
            turn_left;                   //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else if(SENSOR_1<center){   //centerすなわち35より小さい値を検知すると直進する
            go_straight;                 //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else{             //whiteすなわち50より大きい値を検知すると左へ旋回
            rotate_left;                 //この動作中はライントレースし続ける
            t0=CurrentTick();
        }
    }
    Off(OUT_BC);
    Wait(1000);
} 

また,コースのKからLに向かい,Lで止まるプログラミングにおいては,右側のライントレースで「白」と「白の境目」の△鉢い瞭虻遒鯱続で行うと止まるようにした。lightdrayすなわち40より大きい値、whiteすなわち50より大きい値を検知した時間がstop_timeの値の時間分を超過した場合にはwhileの動作が停止する.

sub followline_R2(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){ //stop_timeにいれた値を超過すると次のプログラムへ
        if(SENSOR_1<black){               //blackすなわち20より小さい値を検知すると右へ旋回
            rotate_right;        //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else if(SENSOR_1<darkgray){    //darkgrayすなわち28より小さい値を検知すると右へ
            turn_right;                   //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else if(SENSOR_1>lightdark){   //lightdrayすなわち40より大きい値を検知すると左へ曲がる
            turn_left;                    //この動作が連続すると止まる
        }else if(SENSOR_1<center){     //centerすなわち35より小さい値を検知すると直進する
            go_straight2;                 //この動作中はライントレースし続ける
            t0=CurrentTick();
        }else{               //whiteすなわち50より大きい値を検知すると左へ旋回
            rotate_left;                  //この動作が連続すると止まる
        }
    }
    Off(OUT_BC);
    Wait(2000);
}

ボールのシュート

今回の課題では,コースの途中でボールを掴み,ゴール前で放し,シュートする動きがある.私たちの グループでは,ボールを放した後にロボット本体で前に押し出してシュートするプログラムを作った.また,それぞれを #define で定義した.

  • ボールを掴むプログラム
    #define catch OnRev(OUT_A,25);Wait(500);Off(OUT_A);
  • ボールを放すプログラム
    #define release OnFwd(OUT_A,25);Wait(500);Off(OUT_A);
  • ボールを押し出すプログラム モーターの出力を大幅に上げてボールがまっすぐ進むようにした.
    #define osidasi OnFwd(OUT_BC,100);Wait(100);Off(OUT_BC);

コース上を動かす

コースの上を動く流れは次のようになる.

map_junnbann.png

メインプログラム

task main()
{
    SetSensorLight(S1);
    followline_R(150);     //1
    Blackto_White_L();     //2
    followline_L(200);     //3
    Blackto_White_R();     //4
    followline_R2(200);    //5
    catch;                 //ボールを掴む
    turn;                  //左に旋回
    followline_R(150);     //6
    Blackto_White();       //7
    followline_L(150);     //8
    Blackto_White_L();     //9
    followline_L(200);     //10
    Blackto_White();       //11
    followline_L(200);     //12
    Blackto_White();       //13
    followline_L(200);     //14
    Blackto_White();       //15
    followline_R(150);     //16
    Blackto_White();       //17
    followline_R(150);     //18
    release;               //ボールを放す
    osidasi;               //ゴールする
}

全体のプログラム

#define turn_right OnFwd(OUT_C,25);OnRev(OUT_B,15);
#define turn_left OnFwd(OUT_B,25);OnRev(OUT_C,15);
#define rotate_right OnFwd(OUT_C,20);OnRev(OUT_B,25);
#define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,25);
#define go_straight OnFwd(OUT_BC,20);
#define go_straight2 OnFwd(OUT_BC,15);
#define turn OnRev(OUT_C,25);OnFwd(OUT_B,25);Wait(1500);Off(OUT_BC);
#define catch OnRev(OUT_A,25);Wait(500);Off(OUT_A);
#define release OnFwd(OUT_A,25);Wait(500);Off(OUT_A);
#define osidasi OnFwd(OUT_BC,100);Wait(100);Off(OUT_BC);
#define black 20
#define white 50
#define lightgray 40
#define darkgray 28

sub followline_L(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){
if(SENSOR_1<black){
   rotate_left;
}else if(SENSOR_1<darkgray){
   turn_left;
}else if(SENSOR_1>lightgray){
   turn_right;
   t0=CurrentTick();
}else if(SENSOR_1<35){
   go_straight;
   t0=CurrentTick();
}else{
   rotate_right;
   t0=CurrentTick();
}
    }    
    Off(OUT_BC);
    Wait(1000);
}

sub followline_R(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){
if(SENSOR_1<black){
   rotate_right;
}else if(SENSOR_1<darkgray){
   turn_right;
}else if(SENSOR_1>lightgray){
   turn_left;
   t0=CurrentTick();
}else if(SENSOR_1<35){
   go_straight;
   t0=CurrentTick();
}else{
   rotate_left;
   t0=CurrentTick();
}
    }    
    Off(OUT_BC);
    Wait(1000);
}

sub followline_R2(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){
if(SENSOR_1<black){
   rotate_right;
   t0=CurrentTick();
}else if(SENSOR_1<darkgray){
   turn_right;
   t0=CurrentTick();
}else if(SENSOR_1>lightgray){
   turn_left;
}else if(SENSOR_1<35){
   go_straight2;
   t0=CurrentTick();
}else{
   rotate_left;
}
    }    
    Off(OUT_BC);
    Wait(2000);
}

sub Blackto_White()
{
    while(SENSOR_1<darkgray){
    OnFwd(OUT_BC,15);
    }
    Off(OUT_BC);
}

sub Blackto_White_R()
{
    while(SENSOR_1<darkgray){
    OnFwd(OUT_C,20);
    OnRev(OUT_B,20);
    }
    Off(OUT_BC);
}

sub Blackto_White_L()
{
    while(SENSOR_1<lightgray){
    OnFwd(OUT_B,20);
    OnRev(OUT_C,20);
    }
    Off(OUT_BC);
}

task main()
{
    SetSensorLight(S1);
    followline_R(150);
    Blackto_White_L();
    followline_L(200);
    Blackto_White_R();
    followline_R2(200);
    catch;
    turn;
    followline_R(150);
    Blackto_White();
    followline_L(150);
    Blackto_White_L();
    followline_L(200);
    Blackto_White();
    followline_L(200);
    Blackto_White();
    followline_L(200);
    Blackto_White();
    followline_R(150);
    Blackto_White();
    followline_R(150);
    release;
    osidasi;
}

まとめ

今回もなんとか課題をクリアすることができた. しかし,プログラミングの制作時には,プログラム自体は間違ってないはずなのに,ロボットが動かなかったり動きが鈍くなることが多々あった.その原因はモータの劣化などの原因もあるだろうが,おそらく電池切れではないかと考えられた.前回の課題の時にはほとんどなっかたハプニングだったために,電池切れということに気付かず多くの無駄な時間を費やしてしまった.常にあらゆる可能性や原因を考慮して制作していく必要があると感じた.また,プログラム自体もまだまだ余計な所があると思うので,次回の課題では簡潔なより良いプログラムを制作したい.


添付ファイル: fileright_trace.png 6件 [詳細] fileleft_trace.png 7件 [詳細] filearm_explain.jpg 5件 [詳細] filemap_junnbann.png 5件 [詳細] filelight_number.png 10件 [詳細] filearm.jpg 9件 [詳細] filesenser.jpg 7件 [詳細] filesenser_posi_new.jpg 6件 [詳細] filerobo_honntai.jpg 10件 [詳細] filerobo_all.jpg 5件 [詳細] filemap_line.png 6件 [詳細] filemap.png 5件 [詳細]

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