[[2018a/Member]]
#contents
*課題 [#aba61475]
#ref(2018a-mission2.png)
#ref(2018a-mission2a.png)
ラインをトレスして、缶を運ぶ。道順は見た通りで、Xにて350mL缶をYに移動させる。この時、缶は引きずっても構わない。
*ロボットの説明 [#a6f6d99d]
#ref(robon1.jpg)
#ref(robon2.jpg)
一枚目は光センサー部分。二枚目は分かりづらいのだが…クワガタのような二つのアームの写真だ。

プログラム
* プログラム[#rc4849e0]
定義、プログラムの順に適宜解説をしていく。
**光センサー [#ab5910af]
今回は光センサーを用いるので、数値を定義した。
 #define BLACK 36
 #define LITTLE_BLACK 40
 #define LITTLE_WHITE 44 
 #define WHITE 48
**トレス時の行動パターン [#l9835ec8]
トレス時における、微細な移動も定義した。
 #define LEFT OnFwd(OUT_C,40);OnRev(OUT_A,30);Wait(1);Off(OUT_C);
 #define LITTLE_LEFT OnFwd(OUT_C,30);OnFwd(OUT_A,20);Wait(1);Off(OUT_AC);
 #define LITTLE_RIGHT OnFwd(OUT_A,30);OnFwd(OUT_C,20);Wait(1);Off(OUT_AC);
 #define RIGHT OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(1);Off(OUT_A);
 #define FRONT OnFwd(OUT_AC,30);Wait(1);Off(OUT_AC);
最初に定義したとき、Offをつけるのを忘れ直線番長となってしまった。その後、Offを入れた場合Waitがないため、ほんの少ししずつしか動かなかった。そのため、Wait(1)を入れることにより解決した。
**ライントレスの定義 [#d84b77b9]
先に光センサーの反応で行動を変えるものも作った。たびたび現れる『KAZU』は、黒い部分を踏むことにより増加する関数となっている。
 #define LINE_LEFT if (SENSOR_1 < BLACK) {LEFT;KAZU += 3;} else if (SENSOR_1 < LITTLE_BLACK)  {LITTLE_LEFT;KAZU += 1;} else if (SENSOR_1 > WHITE) {RIGHT;KAZU -= 1;}   else if (SENSOR_1 >LITTLE_WHITE) {LITTLE_RIGHT;KAZU -= 3;} else {FRONT;KAZU *= 0;}
 #define LINE_RIGHT if (SENSOR_1 < BLACK) {RIGHT;KAZU += 3;} else if (SENSOR_1 < LITTLE_BLACK) {LITTLE_RIGHT;KAZU += 1;} else if (SENSOR_1 > WHITE) {LEFT;KAZU -= 1;}else if (SENSOR_1 > LITTLE_WHITE) {LITTLE_LEFT;KAZU -= 3;} else {FRONT;KAZU *= 0;}         
 #define LINE_RIGHT if (SENSOR_1 < BLACK) {RIGHT;KAZU += 3;} else if (SENSOR_1 < LITTLE_BLACK) {LITTLE_RIGHT;KAZU += 1;} else if (SENSOR_1 > WHITE) {LEFT;KAZU -= 1;}else if (SENSOR_1 > LITTLE_WHITE) {LITTLE_LEFT;KAZU -= 3;} else {FRONT;KAZU *= 0;}
この定義により、一度のライントレスを
 while(KAZU < 任意の値){LINE_LEFT;};
で行えるようになっている。

また、交差点を直進や曲がったときに、復帰するときにも
 repeat(任意の回数){LINE_LEFT;};
で復帰することが可能となっている。
***FRONT時の関数計算 [#j27bfe69]
ライントレスは黒に近いと『KAZU』が増加し、白に近いときは減少するようになっている。が、グレーの時は0をかけて、KAZUが0になるような計算している。その理由としては、例えば白いところを長い間、ぐるぐると周り続けてからライントレスに復帰したとき、KAZUが限りなく小さくなり正確なトレスができなくなる。これを防ぐために0をかけるようにし、正確なトレスが可能となった。
***復帰のプログラム [#a72abb96]
"repeat"を使うよりも、時間を定義し、何秒か繰り返すという方が容量が少なくなるのだが、なぜかうまくいかなかったので、"repeat"にした。


**缶をつかむ [#z7a63c37]
 #define AGERU OnRev(OUT_B,10);Wait(1500);Off(OUT_B);
 #define SAGERU OnFwd(OUT_B,10);Wait(2000);Off(OUT_B);
つかむ動作は"AGERU"。離す動作は"SAGERU"と定義されていて、矛盾している。これにはちゃんとした理由がある。発表直前まで缶を上から輪を下ろし、引きずるという機構だった。これを直前にクワガタのような挟める形に変えたため、定義の名称まで変更する時間がなかったのだ。
**プログラム [#o0993c45]

 task main()
 {
    SetSensorLight(S1);
    int KAZU=0; 
 
 
 
    AGERU;
 
    OnFwd(OUT_AC,30);Wait(700);Off(OUT_AC);
    repeat(5000){LINE_LEFT;};KAZU *= 0;
    Off(OUT_AC);
 
    while(KAZU < 100)
        {LINE_LEFT;}; 
    Off(OUT_AC);
    PlaySound(SOUND_DOUBLE_BEEP);
    while(KAZU < 100){LINE_LEFT;}; Off(OUT_AC);
 
    Wait(1000);KAZU *= 0;           //Cヲ感知
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;           //Cヲ感知
 
    OnFwd(OUT_AC,30);Wait(400);Off(OUT_AC);
    repeat(3000){LINE_LEFT;};KAZU *= 0;               //Cを通過の後トレスに戻る
 
    while(KAZU < 250)
         {LINE_LEFT;};
    Off(OUT_AC);
    PlaySound(SOUND_UP);
    while(KAZU < 250){LINE_LEFT;};Off(OUT_AC);
 
    KAZU *= 0;Wait(500);          //CDの曲がり角を感知
    PlaySound(SOUND_UP);KAZU *= 0;Wait(500);          //CDの曲がり角を感知
 
    OnRev(OUT_A,40);OnFwd(OUT_C,40);Wait(2000);Off(OUT_AC);
    repeat(1200){LINE_LEFT};KAZU *= 0;
    while(KAZU < 100){LINE_LEFT;};           //曲がって復帰
    Off(OUT_AC);
 
    KAZU *= 0;
    PlaySound(SOUND_DOUBLE_BEEP);         //Dを感知
    while(KAZU < 100){LINE_LEFT;};Off(OUT_AC);         //曲がって復帰
 
    SAGERU;//35缶をキャッチする
    KAZU *= 0;PlaySound(SOUND_DOUBLE_BEEP);         //Dを感知
 
    SAGERU;              //35缶をキャッチする
 
    OnRev(OUT_A,30);OnFwd(OUT_C,30);Wait(2500);Off(OUT_AC);
    repeat(1500){LINE_LEFT};KAZU *= 0;          //Dを曲がって復帰
 
    while(KAZU < 80){LINE_LEFT;};
    Off(OUT_AC);
    while(KAZU < 80){LINE_LEFT;};Off(OUT_AC);
 
    KAZU *= 0;PlaySound(SOUND_UP);         //Eを感知
 
    OnFwd(OUT_A,30);Wait(600);Off(OUT_AC);
    repeat(2000){LINE_LEFT;};KAZU *= 0;
    while(KAZU < 100){LINE_LEFT;};
    Off(OUT_AC);
    KAZU *= 0;         //Fを感知 
 
    while(KAZU < 100){LINE_LEFT;};Off(OUT_AC);
    
    PlaySound(SOUND_DOUBLE_BEEP);Wait(500);
    PlaySound(SOUND_DOUBLE_BEEP);Wait(500);KAZU *= 0;         //Fを感知 
 
    OnRev(OUT_A,40);OnFwd(OUT_C,40);Wait(1500);Off(OUT_AC);
    repeat(800){LINE_LEFT;};KAZU *= 0;
    while(KAZU < 100){LINE_LEFT;};
    Off(OUT_AC);KAZU *= 0;              //Gを感知
 
    PlaySound(SOUND_DOUBLE_BEEP);
    Wait(1000);
    while(KAZU < 100){LINE_LEFT;};Off(OUT_AC);           
 
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;    //Gを感知
 
    repeat(30000){
                     if (SENSOR_1 < BLACK) {OnRev(OUT_A,40);Wait(1);Off(OUT_AC);} 
                     else if (SENSOR_1 < LITTLE_BLACK) {LEFT;}
                     else if (SENSOR_1 > WHITE) {OnRev(OUT_C,30);Wait(1);Off(OUT_AC);}
                     else if (SENSOR_1 > LITTLE_WHITE) {RIGHT;} 
                     else {FRONT;}
                            };
                   if (SENSOR_1 < BLACK) {OnRev(OUT_A,40);Wait(1);Off(OUT_AC);} 
                   else if (SENSOR_1 < LITTLE_BLACK) {LEFT;}
                   else if (SENSOR_1 > WHITE) {OnRev(OUT_C,30);Wait(1);Off(OUT_AC);}
                   else if (SENSOR_1 > LITTLE_WHITE) {RIGHT;} 
                   else {FRONT;}
                  };
    repeat(1000){LINE_LEFT;};KAZU *= 0;
    while(KAZU < 120){LINE_LEFT;};
    Off(OUT_AC);                 //Hを感知
 
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;
    while(KAZU < 120){LINE_LEFT;};Off(OUT_AC);                
 
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;       //Hを感知
 
    OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(2500);Off(OUT_AC);
 
 
 
    repeat(3000){LINE_RIGHT;};KAZU *= 0;
    while(KAZU < 120){LINE_RIGHT;};
    Off(OUT_AC);               //Iを感知
    while(KAZU < 120){LINE_RIGHT;};Off(OUT_AC);               
 
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;   //Iを感知
   
    OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(2500);Off(OUT_AC);
 
    while(KAZU < 150){LINE_RIGHT};Off(OUT_AC);
 
    PlaySound(SOUND_UP);KAZU *= 0;            //Lを感知
 
    OnFwd(OUT_C,30);Wait(300);Off(OUT_AC);
    while(KAZU < 150){LINE_RIGHT;};
    Off(OUT_AC);
 
    while(KAZU < 150){LINE_RIGHT;};Off(OUT_AC);
 
    PlaySound(SOUND_UP);KAZU *= 0;               //Kを感知
 
    OnFwd(OUT_C,30);Wait(300);Off(OUT_AC);
 
    while(KAZU < 100){LINE_RIGHT;};Off(OUT_AC);
 
    PlaySound(SOUND_DOUBLE_BEEP);KAZU *= 0;Wait(1000);           //Jを感知
 
    OnFwd(OUT_C,30);OnRev(OUT_A,30);Wait(2500);Off(OUT_AC);
 
    AGERU;
 
    OnRev(OUT_AC,30);Wait(1000);Off(OUT_AC);
    OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(4000);Off(OUT_AC);
 
    repeat(2000){LINE_LEFT;};KAZU *= 0;
    while(KAZU < 100){LINE_LEFT;};
    Off(OUT_AC);
 
    while(KAZU < 100){LINE_LEFT;};Off(OUT_AC);
 
    PlaySound(SOUND_DOUBLE_BEEP);Wait(1000);KAZU *= 0;            //Bを感知
 
    OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(1500);Off(OUT_AC);
 
    repeat(1000){LINE_LEFT;};KAZU *= 0;
    while(KAZU < 100){LINE_LEFT;};
    Off(OUT_AC);
 
    while(KAZU < 100){LINE_LEFT;};Off(OUT_AC);
 
    OnFwd(OUT_AC,30);Wait(500);Off(OUT_AC);
 
 }

…あまり解説をすることがない…

***小さな工夫 [#oac04c12]
-交差点にて停止する際に、音が鳴るようになっている。これは決められた交差点では一秒停止しなければならない交差点での停止と、それ以外での停止の際になる音を分けている。
-GからHにかけての小さなカーブが一番の鬼門なのだが、そこはさらに細かく慎重にトレスする振り分けを使っている

*最後に [#v3c761d3]
今回も今回とてかなり時間がかかってしまった。が、プログラムに関する知識はかなり上がり、どこを直したらいいか、分かるようになってきた。つまり、成長を感じている。このまま、次回のミッションも頑張りたいと思う。


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