目次
#contents

*課題2  [#gc83284e]

下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。

自分はコース1を選択した。

#ref(2018b-mission2.png)

*ロボットについて [#o99e9921]

ロボットの写真
#ref(zentaizu2.JPG)


前方から撮影したセンサー部分の写真
#ref(sensor.jpeg)

**ロボット本体への工夫 [#oac0b510]

カラーセンサーを設計図よりタイヤに近づけるためにできるだけ元の車体バランスを崩さないようにしながらNXTの真下の部品を1段分後ろに下げた。

それによって急なカーブをより良い精度で通過できるようになった。

**センサー部分への工夫 [#vab13230]

前述の通り設計図と比べてタイヤの近くに配置することで急なカーブの成功率を上げた。

**ボールを保持するための部分の説明 [#m5d5a43a]
3つ目のモーターで上下できる柵を取り付けた。

ボールをシュートした後も柵を完全に上げきることでちょうどNXTの上部に来るので柵の重さによって車体が傾き、地面とカラーセンサーの距離があまり変わらないようにした。

**ボールをシュートする方法 [#f7193112]

缶の方向を向いた後に柵を上げ前進することでボールに体当たりをする。ロボットの設計段階で道順の中でボールを拾うと勘違いしていたのでタッチセンサーがついているが修正する時間がなかったのでシュートするときにボールが当たる部分として使うことにした。

**改善点 [#q1c201c4]

シュートする部分に関して、他のグループが作っていたようにロボット上部から転がすという形を取っていればシュートの精度もプログラムの質も格段に上がったように思った。

*プログラムについて [#j8cc8344]

プログラム中の説明は次のコース攻略に詳しい説明を書きました。

**実際のプログラム [#tae93a47]


#define THRESHOLD 54                   //しきい値
#define SPEED 30
#define speed 20
#define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
#define LEFT OnRL(speed,-speed);   //左旋回
#define left OnRL(speed,0);    //左折
#define straight OnRL(SPEED,SPEED);  //直進
#define right OnRL(0,speed);   //右折
#define RIGHT OnRL(-speed,speed);    //右旋回
#define STEP 1
#define nMAX 300            
#define short_break Off(OUT_BC);Wait(1000);    //小休止
#define CROSS_TIME 700
#define cross_line OnFwd(OUT_BC,speed);Wait(CROSS_TIME);short_break;
#define turn_time 3000
#define turn_left LEFT;Wait(turn_time);short_break;
#define turn_right RIGHT;Wait(turn_time);short_break;
#define kaiten OnRL(SPEED,-SPEED);
#define kaiten_time 5500     //360°回転するのにかかる時間
#define arm_up OnRev(OUT_A,SPEED);Wait(500);Off(OUT_A);   //柵を上げる



sub kousaten_trace()        //交差点を判断して一時停止した後横断する
 {
    SetSensorLight(S3);
    int nOnline=0;

   while (nOnline < nMAX) {                          //黒を認識した回数がnMAX(300)を越えたら交差点判断して横断
    if (SENSOR_3 < THRESHOLD-10) {
     RIGHT;
     nOnline++;}
    else {
     if (SENSOR_3 < THRESHOLD-3) {right;}
     else if (SENSOR_3 < THRESHOLD+2) {straight;}
     else if (SENSOR_3 < THRESHOLD+6) {left;}
     else {LEFT;}
     nOnline=0;}
    Wait(STEP);
   }
   short_break;
   LEFT;
   Wait(nMAX*STEP);
   cross_line;
   nOnline=0;
  }

sub kousaten_usetsu()       //交差点を判断して一時停止した後右折する
 {
    SetSensorLight(S3);
    int nOnline=0;
   while (nOnline < nMAX) {                    //黒を認識した回数がnMAX(300)を越えたら交差点判断して横断
    if (SENSOR_3 < THRESHOLD-8) {
     LEFT;
     nOnline++;}
    else {
     if (SENSOR_3 < THRESHOLD-3) {left;}
     else if (SENSOR_3 < THRESHOLD+2) {straight;}
     else if (SENSOR_3 < THRESHOLD+6) {right;}
     else {RIGHT;}
     nOnline=0;}
    Wait(STEP);
   }
   short_break;
   RIGHT;
   Wait(nMAX*STEP);
   turn_right;
   nOnline=0;
  }

sub kousaten_teishi()            //交差点を判断したら1秒間停止した後再発進
 {
    SetSensorLight(S3);
    int nOnline=0;
   while (nOnline < nMAX) {
    if (SENSOR_3 < THRESHOLD-8) {
     LEFT;
     nOnline++;}
    else {
     if (SENSOR_3 < THRESHOLD-3) {left;}
     else if (SENSOR_3 < THRESHOLD+2) {straight;}
     else if (SENSOR_3 < THRESHOLD+6) {right;}
     else {RIGHT;}
     nOnline=0;}
    Wait(STEP);
   }
   short_break;
   nOnline=0;
  }

sub serch_kan()          360°回転して障害物(缶)を見つけ出しその方向に向かう
 {
  SetSensorLowspeed(S4);
  long t10,t11;           
  int L=10000;      //仮の最小値
  t10=CurrentTick();     //回転前の時刻
  while(CurrentTick()-t10<=kaiten_time){
   OnRL(speed,-speed);
   if(SensorUS(S4)<L)
   {
    L=SensorUS(S4);
    t11=CurrentTick()-t10;   //仮の最小値より近いものを見つけた時の時間
   }
  }
  OnRL(-speed,speed);
  Wait(kaiten_time-t11);
  Off(OUT_BC);
  }
 
 
sub shoot()         //シュート(体当たり)をする
 {
  arm_up;
  OnFwd(OUT_BC,100);
  Wait(200);
  Off(OUT_BC);
  }

task main()
 {
  SetSensorLight(S3);
  SetSensorLowspeed(S4);
  long t0,t1,t2,t3;         //それぞれの時間を定義
  t0=CurrentTick();     //スタートした時間をt0とする
  while(CurrentTick()-t0<=15000){      //15秒間ライントレースをする
      if(SENSOR_3<THRESHOLD-8){RIGHT;}
      else if(SENSOR_3<THRESHOLD-3){right;}
      else if(SENSOR_3<THRESHOLD+2){straight;}
      else if(SENSOR_3<THRESHOLD+6){left;}
      else{LEFT;}
     Wait(STEP);
     }
  kousaten_trace();   //交差点Kを発見したら横断    //スタートからここまでが攻略��
  t1=CurrentTick();    //K地点を横断したらその時間をt1とする
  while(CurrentTick()-t1<=15000){      //15秒間ライントレースをする
      if(SENSOR_3<THRESHOLD-8){RIGHT;}
      else if(SENSOR_3<THRESHOLD-3){right;}
      else if(SENSOR_3<THRESHOLD+2){straight;}
      else if(SENSOR_3<THRESHOLD+6){left;}
      else{LEFT;}
     Wait(STEP);
     }
  serch_kan();    //缶を探す。見つけたらボールに体当たりしてシュートする
  shoot();          //�,�らここまでが攻略��
  t2=CurrentTick();
  while(CurrentTick()-t2<=18000){
      if(SENSOR_3<THRESHOLD-8){LEFT;}
      else if(SENSOR_3<THRESHOLD-3){left;}
      else if(SENSOR_3<THRESHOLD+2){straight;}
      else if(SENSOR_3<THRESHOLD+6){right;}
      else{RIGHT;}
     Wait(STEP);
     }
  kousaten_teishi();  //交差点Gを発見したら一時停止      //�△�らここまでが攻略��
  t3=CurrentTick();   //地点Gを出発する時間をt3とする
  while(CurrentTick()-t3<=40000){      //40秒間ライントレースをする
      if(SENSOR_3<THRESHOLD-8){LEFT;}
      else if(SENSOR_3<THRESHOLD-3){left;}
      else if(SENSOR_3<THRESHOLD+2){straight;}
      else if(SENSOR_3<THRESHOLD+6){right;}
      else{RIGHT;}
     Wait(STEP);
     }
  kousaten_usetsu();   //交差点Eを発見したら右折    //��からここまでが攻略��
  kousaten_trace();   //交差点Lを発見したら横断
  OnFwd(OUT_BC,SPEED);   前進して枠内に入る
  Wait(2000);
  Off(OUT_BC);
  }              //�い�らここまでが攻略��



**ライントレースのプログラムについて [#je912043]

交差点判断をしないライントレースについては白から黒の色の値を白、白よりの灰色、灰色、黒よりの灰色、黒の五段階に分けそれぞれについて順に大きくライン側に旋回、ライン側に曲がる、スピードを出して直進、ラインから離れる方向に曲がる、ライン側から離れるように旋回という風にしてラインのどちらかをジグザグと移動するような形にした。

交差点判断をするときは上記の通りのライントレースの中で300回(0.3秒間)以上黒を検出し続けたらその地点を交差点と判断し曲がった分だけ角度を戻してから少しだけ直進して交差点を横断するプログラムとした。

 
**プログラムの説明と反省 [#y27f08f7]
 
基本的にはタイマーで時間を計りながら交差点判断をするかしないかを決めている。そのためこのコースでしか使えないうえに想定した以上にスムーズに進んだり時間がかかったりしてしまうとコースを間違えてしまうためコースを完走しないことが多くなってしまった。
時間ではなく、タイヤの回転角などで距離を測りながら進むと今よりは成功率の高いプログラムになったのではないだろうか。また、task mainの中の時間を計測しながらのライントレースもサブルーチンとして簡略化できたなどの改善点も見つかった。



*実際のコース攻略 [#udea7385]

**計画 [#q9faae0e]

計画図
#ref(keikaku.jpeg)

��A地点をスタートし、ラインの右側をトレースする。スタート後15秒間は交差点判断をしないのでB地点を右折。何度かタイム計測をした結果15秒以内にK地点まではたどり着けないのでK地点では交差点と判断し、横断。円HIJKの内側に入る。

��円HIJKの内部を18秒間トレースする。大体15秒程度でI地点を過ぎたあたりに到着する予定である。ボールをシュートするときの前進で円HIJKの外側に出て外側のトレースを開始する。

��ボールをシュートした後通常通りのトレースをする。G地点で交差点を判断したら一時停止した後交差点判断をしないトレースを開始する。


��G地点を曲がりだすところからスタート。40秒間で通常のF地点までたどり着き、E地点で交差点を判断したら右折する。

�ゥ薀ぅ鹹未蠅膨梢覆掘�交差点(L地点)を横断した後2秒間前進して四角の中に入って停止する。

**失敗例 [#w1b2a956]

�◆哨轡紂璽帆�

18秒間でI地点を超えられず、本来G地点で行うはずの一時停止をI地点で行ってしまう。(時間以外の方法でどれくらい進んだかを測っていれば防げたのではないか)

�◆哨轡紂璽隼�

18秒間でH地点近くまで来てしまいシュート時の前進で円HIJKの外側に出られない。(時間以外の方法でどれくらい進んだかを測っていれば防げたのではないか)

��‐最後、�ぁ昇能�

G地点を曲がり切れずに直進してしまう。(停止した後一度後退してトレースしなおすとよかったのではないか)

�ぁ承泙淵�ーブ

稀に曲がり切れずにコースアウトしてしまう(しきい値を計測しなおす、ロボットを改造するなど様々な対策があたのではないか)

��-F地点

40秒間でたどり着けないとここで交差点判断をしてコースアウトしてしまう。(時間以外の方法でどれくらい進んだかを測っていれば防げたのではないか)


��-E地点

40秒間以内に辿り着いてしまうと交差点判断をすることができずに、道順を間違えてしまう。(時間以外の方法でどれくらい進んだかを測っていれば防げたのではないか)


*全体を通して [#q23ba7ce]

前回のプログラムに比べればコンパクトで綺麗なプログラムに仕上がったと思うが、ほかのグループの人たちと比べるとプログラム、ロボットへの工夫や綺麗さは劣っているので、ロボコンまでにできる限り同じレベルになれるように頑張りたい。また、前回に比べて綺麗に仕上がったといってもまだ無駄の多く回りくどい方法をとったプログラムであると思うのでもう少しコンパクトなプログラムを書けるように努力したい。レポートに関しても画像が表示できずURLを貼っているなど詰めの甘い部分は自分のダメなところであるので改善していきたい。(改善済み)

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS