[[2013b/Member]]
*交差点、直角を含むライントレース [#ga1931f3]
&ref(2013b/Member/chikuwa/Mission1/今回の課題用コース.jpg,50%,使用ロボット);

**今回の課題の内容 [#lcdc08b1]
数のコースをラインに沿ってロボットを走らせ、缶をどかした後もとの場所に戻して、再びライントレースをする。(交差点は渡るものとする)


&ref(2013b/Member/chikuwa/Mission1/缶を置いたコース.PNG,70%,コース);





#contents
**ロボットの作成 [#td990e64]
***まずははじめのただのライントレース用 [#s44a1784]
&ref(2013b/Member/chikuwa/Mission1/20131122_175237.jpg,50%,使用ロボット);


 


普通にマインドストームの説明書通りに組み立てた。

このロボットをそのまま使用してもバランスや走行の仕方などに
これといった不自由は感じられなかったのでそのまま使用した。

この頃は光センサは適度な高さにあったので、ご認識はなかった。

また後輪のつけ方を変えてみようかたと思ったが、結局この付け方に落ち着いた。


***次に缶をつかむためのアームつきver [#b750e0bf]
&ref(2013b/Member/chikuwa/Mission1/缶つかみ用ロボ.jpg,50%,使用ロボット(その2));



特に歯車を使って別の場所に回転を伝えたり、回転方向を変換したりはしない。

モーターに直接アームがついており、缶を見つけるとアームが左回りに回転し自分の方に引き寄せる。

その後、ゴムの付いた左手と右手(アーム)でしっかりキャッチ。
これで缶をもたっまま回転などしても途中で缶を離したりすることもない。

(下図参照)

・缶を掴んだ状態を上からみた図

&ref(2013b/Member/chikuwa/Mission1/缶をつかんだ機体.PNG,60%,缶をつかんだ機体);




最初は缶を元の場所に離しておくとき倒れてしまった。

下図のように缶をもつ位置が高すぎると、下に擦れて本体が回転して、アームが缶を離すときに
缶が傾いてしまう。

※正面図


&ref(2013b/Member/chikuwa/Mission1/高すぎると.PNG,60%,高すぎると);


結果として缶が倒れてしまうので、ちょうどいい高さになるようにアームを何度も調節した。



ただ難点として、アームが重すぎて機体自体の重心が少し右寄りになってしまった。

**コースのセクション分け [#f34c967d]
&ref(2013b/Member/chikuwa/Mission1/今回の課題用コース(色分け).jpg,50%,コース(色分け));


今回のポイントである‘直角と交差点の違い‘を理解させるためにコースを3セクションに分けた。

それぞれ

青色を"第一セクション"

黄色を"第二セクション"

ピンク色を"第三セクション"

と名づけた。


**ソースコード [#xf1bcebe]
 
 #define THRESHOLD 60 //しきい値は60に設定
***まずは定義文やセンサの用意  [#a661dfab]

 #define THRESHOLD 60 //しきい値の設定 
 
 #define SPEED_A 10
 #define SPEED_B 20
 #define SPEED_C 30
 #define SPEED_D 40
 #define SPEED_E 50
 #define SPEED_F 60
 #define SPEED_G 70
 #define SPEED_H 80
 #define SPEED_I 90
 〜〜
 #define SPEED_J 100
 #define STEP 1
 //一気に SPEED_AからSPEED_Jまでそれぞれ10から100を定義//

 #define STEP 1 //一回の白黒の判断にかける時間

 #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
 #define go_forward OnRL(SPEED_D,SPEED_D);
 #define go_forward_1 OnRL(SPEED_C,SPEED_C);
 #define go_forward_2 OnRL(SPEED_D,SPEED_D);
 #define turn_first_curve OnRL(SPEED_H,-SPEED_H);
 #define turn_left0 OnRL(SPEED_C,0);
 #define turn_left0_2 OnRL(SPEED_B,0);
 #define turn_left1 OnRL(SPEED_B,-SPEED_B);
 #define turn_left2 OnRL(SPEED_H,-SPEED_H);
 #define turn_left2 OnRL(SPEED_F,-SPEED_F);
 #define turn_right0 OnRL(0,SPEED_B);
 #define turn_right00 OnRL(0,SPEED_F);
 #define turn_right000 OnRL(0,SPEED_H);
 #define turn_right00 OnRL(0,SPEED_C);
 #define turn_right000 OnRL(0,SPEED_D);
 #define turn_right1 OnRL(-SPEED_B,SPEED_B);
 #define turn_right2 OnRL(-SPEED_D,SPEED_D);
 #define turn_right3 OnRL(-SPEED_F,SPEED_F);
 //曲がるときのスピードをそれぞれのセクションごとに変えているので、
 曲げ方がかなり増えた//

 #define nMAX_A 150
 #define nMAX_B 200
 #define nMAX_C 250
 #define nMAX_D 300
 //この回数だけ黒をカウントすると交差点と判断する値
 交差点ごとに微妙に異なっているので4つほど用意した//
 
 
 #define short_break Off(OUT_BC);Wait(1000);
 //缶をつかむ時に一つ一つの動作の間に休憩時間を設ける//

 #define CROSS_TIME 400
 #define cross_line OnRL(SPEED_C,SPEED_C);Wait(CROSS_TIME);short_break; 
   //ラインを渡るためのプログラム //
 //交差点を渡る時間。これはどの交差点でも共通してこの値だった//

 #define cross_line OnRL(SPEED_C,SPEED_C);Wait(CROSS_TIME);short_break;
 //交差点を渡る時に使用//

 #define udefuri OnFwd(OUT_A,SPEED_B);Wait(400); //アーム用
 
 #define short_break Off(OUT_BC);Wait(1000); //主に缶の移動時に使用する
 
 task main() 
 {
  SetSensorLight(S1);
  long t0=CurrentTick();
  int nOnline=0;
  while(CurrentTick()-t0<7000){ //第一セクション(開始から7秒は次の通り動く)
   if(SENSOR_1<THRESHOLD-15){
     turn_right000;
 SetSensorLight(S1);
 SetSensorLowspeed(S2);
 long t0=CurrentTick();
 int nOnline=0;

***第一セクション [#v76810f9]
 while(CurrentTick()-t0<41000){ //第一セクション
  while(nOnline<160){
    if(SENSOR_1<THRESHOLD-15){
     turn_right2;
     nOnline++;
    }else{
      if(SENSOR_1<THRESHOLD-8){
        turn_right00;
          }else if(SENSOR_1<THRESHOLD+5){
           go_forward;
        turn_right2;
          }else if (SENSOR_1<THRESHOLD){
           go_forward_1;
          }else if(SENSOR_1<THRESHOLD+10){
           turn_left1;
           turn_left0_2;
          }else{
           turn_left1;
            } 
           turn_left0;
             }
           nOnline=0;
           }
         Wait(STEP); 
 } 
  while(CurrentTick()-t0<10000){ //第二セクション(開始から7〜10秒は次の通り動く)
   PlaySound(SOUND_UP);
   while(nOnline<140){
     if(SENSOR_1<THRESHOLD-15){
      turn_right2;
      nOnline++;
     }else{
       if(SENSOR_1<THRESHOLD-8){
         turn_right2;
           }else if (SENSOR_1<THRESHOLD){
            go_forward;
           }else if(SENSOR_1<THRESHOLD+10){
            turn_left0_2;
           }else{
            turn_left0;
              }
            nOnline=0;
             }
           Wait(STEP);
         }
       short_break;
       turn_right1;
       Wait(100);
       cross_line;
       long t1=CurrentTick(); //ここから最初の円用のプログラム
       while(CurrentTick()-t1<7800){
        if(SENSOR_1<THRESHOLD-15){
        turn_right1;
        }else{
          if(SENSOR_1<THRESHOLD-8){
           turn_right0;
           }else if (SENSOR_1<THRESHOLD+5){
            go_forward;
           }else if(SENSOR_1<THRESHOLD+10){
            turn_left0;
           }else{
            turn_left1;                   
             }
            nOnline=0;
             }
           Wait(STEP);  
       }
       PlaySound(SOUND_DOWN);
       nOnline=0;    
  }
  while(CurrentTick()-t0<39000){ //第三セクション(開始から10〜39秒は次の通り動く)
   PlaySound(SOUND_UP);
   while(nOnline<160){
     if(SENSOR_1<THRESHOLD-15){
            }
          Wait(STEP);
        }
      short_break;
      turn_right1;
      nOnline++;
     }else{
       if(SENSOR_1<THRESHOLD-8){
         turn_right0;
           }else if (SENSOR_1<THRESHOLD+5){
            go_forward;
           }else if(SENSOR_1<THRESHOLD+10){
            turn_left0;
           }else{
            turn_left1;                   
             }
            nOnline=0;
             }
           Wait(STEP);
         }
       short_break;
       turn_left1;
       Wait(100);
       cross_line;
       PlaySound(SOUND_DOWN);
       nOnline=0;    
  }
      Wait(100);
      cross_line;
      long t1=CurrentTick(); //ここから最初の円用のプログラム
      while(CurrentTick()-t1<13500){
       if(SENSOR_1<THRESHOLD-15){
       turn_right3;
       }else{
         if(SENSOR_1<THRESHOLD-8){
          turn_right2;
          }else if (SENSOR_1<THRESHOLD+5){
           go_forward_1;
          }else if(SENSOR_1<THRESHOLD+10){
           turn_left0;
          }else{
           turn_left1;                   
            }
           nOnline=0;
            }
          Wait(STEP);  
      }
      nOnline=0;    
 }
**ライントレースの方法 [#u332e545]
&ref(2013b/Member/chikuwa/Mission1/進み方.PNG,80%,フローチャート);
 turn_right1;Wait(100);

・出くわした問題
[最初の急カーブが回りきれない]

原因:左に曲がる時のスピードが遅すぎる

基本的にはセンサが
改善策:この時のスピードを少し早めに変更(20→40)

”白を感知したら右へ”
結果:カーブを曲がりきれるようになった。

”黒を感知したら左へ”
***第二セクション [#w284373f]
 while(CurrentTick()-t0<63000){ //第二セクション
  PlaySound(SOUND_UP);
  while(nOnline<70){
    if(SENSOR_1<THRESHOLD-15){
     turn_right1;
     nOnline++;
     }else{
      if(SENSOR_1<THRESHOLD-8){
        turn_right0;
          }else if (SENSOR_1<THRESHOLD+5){
           go_forward_1;
          }else if(SENSOR_1<THRESHOLD+10){
           turn_left0;
          }else{
           turn_left1;                   
            }
           nOnline=0;
          }Wait(STEP);
        }
      short_break;
      cross_line;
      turn_right1;Wait(100);
      nOnline=0;    
  }

曲がるようにプログラムされている。
・出くわした問題
[〇型のカーブが曲がりきれない]

原因:センサが白を感知する前に黒を感知。結果黒を長い間感知してしまい、そこを交差点とみなしてしまう

**基本的な流れ [#yd3ad064]
&ref(2013b/Member/chikuwa/Mission1/キャプチャ.PNG,100%,フローチャート);
改善策(その1):右に曲がるスピードを早くしてみる。→車幅が広すぎるため、解決せず。(結局交差点とみなしてしまった)


改善作(その2):交差点を渡ったあとにこの〇型のカーブ専用のプログラムを作った。
 
**工夫した点 [#j6acd557]
1.与えられたコースを第一〜第三セクションに区切り、直角と交差点の判断を混乱させないようにした。
 while(CurrentTick()-t1<13500){
       if(SENSOR_1<THRESHOLD-15){
       turn_right3;
       }else{
         if(SENSOR_1<THRESHOLD-8){
          turn_right2;
          }else if (SENSOR_1<THRESHOLD+5){
           go_forward_1;
          }else if(SENSOR_1<THRESHOLD+10){
           turn_left0;
          }else{
           turn_left1;                   
            }
           nOnline=0;
            }
          Wait(STEP);  
      }

結果:円をきちんとなぞって回転できるようになった。ただ一周にかかる時間がバッテリーの残量でかなり変わってくることが何度も試してわかったので、タイマーを使わない方法が思いつけなかったのが残念だった。

2.下図の赤色で示した部分をぐるぐると回る際に黒色を数えすぎて交差点と勘違いするのでプログラムを修正し、交差点を渡ったあとは(約8秒間)普通のライントレースをするようにした。(ソースコードの”最初の円用のプログラム”)


&ref(2013b/Member/chikuwa/Mission1/20131206_165431(赤線アリ).jpg,40%,コース(赤));
***第三セクション [#ca8c3721]
  while(CurrentTick()-t0<200000){ //第三セクション
    if(SENSOR_1<THRESHOLD-15){
     turn_right1;
    }else{
      if(SENSOR_1<THRESHOLD-8){
        turn_right0;
          }else if (SENSOR_1<THRESHOLD+5){
           go_forward_1;
          }else if(SENSOR_1<THRESHOLD+10){
           turn_left0;
          }else{
           turn_left1;                   
            }
           nOnline=0;
            }
          Wait(STEP);
***缶に遭遇した時除去するプログラム [#g798b701]
 if(SensorUS(S2)<8){ //缶を移動させるプログラム
  short_break;
  OnFwd(OUT_BC,50);Wait(200); //ちょっと前進
  short_break;
  udefuri; //缶を掴む
  short_break;
  OnFwd(OUT_B,40);OnRev(OUT_C,40);Wait(1900); //半回転
  short_break;
  OnRev(OUT_BC,SPEED_B);Wait(6000); //6秒バック
  short_break;
  OnRev(OUT_A,SPEED_B);Wait(400); //缶を離す
  short_break;
  OnRev(OUT_BC,SPEED_B);Wait(1000); //1秒バック
  short_break;
  OnFwd(OUT_C,40);OnRev(OUT_B,40);Wait(800); //半回転
  OnFwd(OUT_BC,50);Wait(700); //0.7秒前進
  short_break;
   }
  }
 }
//終了//

**問題点 [#g0058dd4]
**缶を移動させるプロセス [#ed8ea97c]
&ref(2013b/Member/chikuwa/Mission1/缶発見.PNG,70%,缶発見);


&ref(2013b/Member/chikuwa/Mission1/前進.PNG,70%,前進);


&ref(2013b/Member/chikuwa/Mission1/キャッチ.PNG,70%,キャッチ);


&ref(2013b/Member/chikuwa/Mission1/回転.PNG,70%,回転);


&ref(2013b/Member/chikuwa/Mission1/バック.PNG,70%,バック);


&ref(2013b/Member/chikuwa/Mission1/さらにバック.PNG,70%,さらにバック);


&ref(2013b/Member/chikuwa/Mission1/復帰.PNG,70%,復帰);


**ハード、コース上の問題点 [#r5e455e3]
前述した通り機体の左側が大きすぎて、走行中にアームで缶を倒してしまうことがあった。
さらに、NXT本体がしっかり固定されず、ぐらついていたのも問題であった。

また改造を加えていった結果、センサと地面の距離が近すぎてしまい、20蕃教室以外では正常に動かないことがあった。


**ソフト上の問題点 [#g0058dd4]
プログラムが長すぎるので、今後書き換えるときにミスが生じやすい。もっとたくさん関数を利用してプログラムを簡素にしたい。
またタイマーに頼りきっているので、このコース以外では走ることができないので、どんなコースにも対応できるようにプログラムを改良したい。
またタイマーに頼りきっているので、このコース以外では走ることができない。次からはどんなコースにも対応できるようにプログラムを改良したい。

また全体を通して、結局どこが悪いから今回の課題がクリアできないのかがあやふやであった点が悔やまる。結果、うまくいかないことがある度に、ハードやソフトを何箇所もいじくりまわしてしまい、問題解決のための目処が全く立たなくなり、成功したりしなかったりという最悪な状態になってしまった。

次からは
 
 
 どこか悪いところがある→プログラムのある一箇所を変更(またはハードの改良)→試してみる

というプロセスでじっくりどこに問題があるのか明瞭にして課題の解決に望みたい。


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