目次

課題について

下のような図をチームごとに作成し、黒い線の上を走るようなロボットを作成する。

2019a-mission2.png

課題の詳細

A地点を出発し、次の経路を黒い線にそって動き、最後にピンポン球をゴールに入れるロボットを作成する

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

ロボット本体について

ロボット全体

line_175788711878042.jpg

今回の機体を制作するにあたり、図上できちんと小回りがきくように、なるべく小さいロボットにした。

光センサー部分

line_175812470413242.jpg

光センサーの場所は、近すぎず遠すぎずなるべく正確な値を図れるようにした。

タイヤ部分

line_175792940901791.jpg

タイヤはなるべく光センサーに近くなるように設計した。
理由としては、光を検知し、タイヤをいち早く検知した光の値の時のプログラムを実行させ、動作する上での誤差をなくすためだ。

つかむ機構

line_175760293908939.jpg
Inkedline_175750132339776_LI.jpg

アームの開閉の構造は図を見てもらった方が分かりやすいが、
.癲璽拭爾鮓かって上から上方向に回すとアームを開く
▲癲璽拭爾鮓かって上から下方向に回すとアームが閉じる

個々のプログラムについて

ライントレース

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

Hikarinoatai.png

プログラミングでは、それぞれの値を以下のように定義する。

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

明かるさの値を5段階に分け、それらに対応する5つの動作を振り分ける。
下の図がその動作であり、明るさや場合によってどの動きになるかは異なる。

ugokuhoukou.png

以下がその動作を定義したプログラミングである。

#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);//
#define go_straight2 OnFwd(OUT_BC,15);//イ僚侘呂鮠し下げたもの

左側のライントレース

右側と左側とでのライントレースではプログラミングが異なってくるため
それぞれ分けて考える。

sub followline_L(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){
        if(SENSOR_1<black){
            rotate_left;         //明るさが20より小さいとき△瞭虻
        }else if(SENSOR_1<darkgray){
            turn_left;          //明るさが28より小さいときい瞭虻
        }else if(SENSOR_1>lightdark){
            turn_right;         //明るさが35より小さいときの動作
        }else if(SENSOR_1<center){
            go_straight;              //明るさが40より大きいときイ瞭虻
        }else{
            rotate_right;             //明るさが50より大きいとき,瞭虻
        }
    }
}

水色の矢印がプログラミングで動作する方向である。

InkedHikarinoatai_LI.jpg

右側のライントレース

左側のライントレースと同様に右側のライントレースも考える。

sub followline_R(int stop_time)
{
    long t0=CurrentTick();
    while(CurrentTick()-t0<stop_time){
        if(SENSOR_1<black){
            rotate_right;              //明るさが20より小さいとき,瞭虻
        }else if(SENSOR_1<darkgray){
            turn_right;                //明るさが28より小さいときの動作
        }else if(SENSOR_1>lightdark){
            turn_left;                 //明るさが35より小さいときい瞭虻
        }else if(SENSOR_1<center){
            go_straight;               //明るさが40より大きいときイ瞭虻
        }else{
            rotate_left;               //明るさが50より大きいとき△瞭虻
        }
    }
}
Inkedhikari2_LI.jpg

赤色の矢印がプログラミングで動作する方向である。

交差点認識

ライントレースをする際に途中で交差点にさしかかる。そのままライントレースをしてしまうと角に沿ってそのまま曲がっていってしまう。
そのために交差点を認識するプログラミングを作成する。それは、ライントレース中に特定の動作を指定した何秒間か行った場合にライントレースを終了させるというものだ。 又、今回は交差点を認識した際に、数秒間停止しなければならないので、数秒間停止するプログラミングもライントレースの中に付け加える。

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

左側のライントレースの場合、「黒」と「黒と境目の間」の△鉢い瞭虻遒
連続で何秒間か動作したときに、止まるようにする。 始めにt0=CurrentTickとおき、それぞれの変数の値の差(CurrentTick()-t0)は0である。t0=CurrentTickを下のプログラムのように
ifやelse ifのなかにいれ、それをロボットが認識するたびにこの変数の値の差は0(to=CurrentTick)となる。それは
to=CurrentTickと入れていないとそれぞれの変数の差は0に更新されず増え続けることになる。
すなわちifやelse ifの中にto=CurrentTickといれないならば、ロボットはto=CurrentTickを認識することは
出来ず、それぞれの変数の差は0にならずto=CurrentTickと入っていないifやelse ifの動作を実行している際は
この変数の値(CurrentTick)は増え続けているのである。そして、それぞれの変数の差(CurrentTick()-t0)に下記のプログラムのstop_timeのように上限を設け、stop_timeには特定の値を入れる。こうすることで、CurrentTick()-t0
がstop_timeに入れた値の時間分を超すとwhileの動作を停止し、次の動作であるOff(OUT_BC);Wait(1000);
を実行し、ロボットは1秒間止まる。これがプログラム中のt0=CurrentTick()と(CurrentTick()-t0<stop_time
の意味合いとなる。
そして左側のライントレースの場合 if(SENSOR_1<black)とelse if(SENSOR_1<darkgray)に
t0=CurrentTick();が入っておらずblackすなわち20より小さい値、darkgrayすなわち28より小さい値
を検知した時間がstop_timeの値の時間分を超過した場合にはwhileの動作を停止し、次の動作であるOff(OUT_BC);Wait(1000);
を実行し、ロボットは1秒間止まる

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

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

右側のライントレースの場合、「黒」と「黒と境目の間」の,鉢の動作が
連続で何秒間か動作したときに、止まるようにする。
この原理は左側のライントレースの場合と同じとなる。

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で止まるプログラミングを考えた結果、
右側のライントレースで「白」と「白の境目」の△鉢い瞭虻遒鯱続で行うと
止まるプログラミングが完成した。 この場合else if(SENSOR_1>lightdark) とelseに
t0=CurrentTick();が入っておらずlightdrayすなわち40より大きい値、whiteすなわち50より大きい値
を検知した時間がstop_timeの値の時間分を超過した場合にはwhileの動作を停止し、次の動作であるOff(OUT_BC);Wait(1000);
を実行し、ロボットは1秒間止まる。

Inked2019a-mission23_LI.jpg
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);
}

交差点横断

交差点を認識した後、直進、左折、右折の動作をしなければならない。
そこで私たちは、ある値を検知するまで一定の動作を行い続けるプログラミングを作った。

○直進
28より小さい値を検知している時は直進し、
28より大きい値を検知したら止まる。 →黒い線上では直進

sub Blackto_White()
{
    while(SENSOR_1<darkgray){   //darkdrayすなわち28より小さい値を検知すると直進する
        OnFwd(OUT_BC,15);
    }
    Off(OUT_BC);
}

○右折
40より小さい値を検知している時は右折し、
40より大きい値を検知したら止まる。 →黒い戦場では右折

sub Blackto_White_R()
{
    while(SENSOR_1<lightgray){   //lightdrayすなわち40より小さい値を検知すると右へ旋回
        OnFwd(OUT_C,20);
        OnRev(OUT_B,20);
    }
    Off(OUT_BC);
}

○左折
40より小さい値を検知している時は左折し、
40より大きい値を検知したら止まる。 →黒い戦場では左折

sub Blackto_White_L()
{
    while(SENSOR_1<lightgray){   //lightdrayすなわち40より小さい値を検知すると左へ旋回
        OnFwd(OUT_B,20);
        OnRev(OUT_C,20);
    }
    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 turn OnFwd(OUT_B,25);OnRev(OUT_C,25);Wait(1500);Off(OUT_BC);

コースを動く流れ

最終的には下記のような流れで動作を行う。

Inked2019a-mission234_LI.jpg
task main()
{
    SetSensorLight(S1);
    followline_L(200);   //1
    Blackto_White();        //2
    followline_L(150);      //3
    Blackto_White_R();      //4
    followline_R(200);      //5
    Blackto_White_R();      //6
    followline(150);        //7
    Blackto_White_R();      //8
    followline(150);        //9
    Blackto_White_R();      //10
    followline(150);        //11
    Blackto_White();        //12
    followline_R2(200);     //13
    catch;                  //ボールをつかむ
    turn;                   //左に旋回する
    followline_R(150);      //14
    Blackto_White();        //15
    followline_R(150);      //16
    Blackto_White_L();      //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,20);
#define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,20);
#define go_straight OnFwd(OUT_BC,20);
#define go_straight2 OnFwd(OUT_BC,15);
#define turn OnFwd(OUT_B,25);OnRev(OUT_C,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
#define center 35

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>lightdark){
            turn_right;
            t0=CurrentTick();
        }else if(SENSOR_1<center){
            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>lightdark){
            turn_left;
            t0=CurrentTick();
        }else if(SENSOR_1<center){
            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>lightdark){
            turn_left;
        }else if(SENSOR_1<center){
            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<lightgray){
        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_L(200);
    Blackto_White();
    followline_L(150);
    Blackto_White_R();
    followline_R(200);
    Blackto_White_R();
    followline(150);
    Blackto_White_R();
    followline(150);
    Blackto_White_R();
    followline(150);
    Blackto_White();
    followline_R2(200);
    catch;
    turn;
    followline_R(150);
    Blackto_White();
    followline_R(150);
    Blackto_White_L();
    followline_R(150);
    release;
    osidasi;
}

まとめ

今回の課題では、ミスをせずきちんと完走させ、ゴールすることが出来た。
ロボットの機体としての出来もよくきちんと走ってくれたが、所々電池のせいなのか
動きが鈍くなる時があった。 結果だけを見ると良かったものの、まだプログラミングにかける時間が長く
余計なプログラムもある。 今々考えてみると、途中の左旋回はいらなくて、そのままライントレース
させればプログラムがもっと短くなると思った。
まだまだ、プログラムの面で余計なところがあると思うので、
次の課題ではそのようなミスを減らして、簡潔でよりよいプログラムに
仕上げられるようにしたいと思う。


添付ファイル: fileInked2019a-mission234_LI.jpg 9件 [詳細] fileInked2019a-mission23_LI.jpg 11件 [詳細] fileInkedhikari2_LI.jpg 9件 [詳細] fileInkedHikarinoatai_LI.jpg 9件 [詳細] fileugokuhoukou.png 11件 [詳細] fileHikarinoatai.png 8件 [詳細] filehikarinoatai.png 4件 [詳細] fileInkedline_175750132339776_LI.jpg 9件 [詳細] fileline_175792940901791.jpg 5件 [詳細] fileline_175760293908939.jpg 11件 [詳細] fileline_175788711878042.jpg 10件 [詳細] fileline_175785492433148.jpg 2件 [詳細] fileline_175812470413242.jpg 6件 [詳細] fileline_175750132339776.jpg 3件 [詳細] fileInked2019a-mission2_LI.jpg 8件 [詳細] file2019a-mission2.png 8件 [詳細]

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