[[2011a]]

*課題2 黒い線上を動くロボットを作成せよ!! [#v522a89f]
次のような周回コース(黒い線)を動くロボットを作成せよ。

- 通常の交差点が2箇所以上ある
- ロータリー型の交差点が1箇所以上ある (ロータリーでは反時計まわりに進む)
- 直角に曲がるコーナーおよびそのコーナーをショートカットするコース(点線)が存在する
- 急なヘアピンカーブが1箇所以上ある
- スタート地点に目印がある
- 黒い線の幅は15〜20mm程度

センサー、モーターはいくつ使ってもよい。プログラムは次の2つを作成すること。

1. 直角のコーナーを通る~
2. 直角のコーナーを通らない(近道する)

ただし互いに逆方向に周回すること。
#contents


*メンバー [#jefdde39]
ばば~
中島


*製作過程 [#y2884bab]
**コース [#v375c6ed]
僕たちのチームは先生の考えたコースをもとにして、近道の部分は直角にしました。~
以下の写真が今回用いたコースです。~
#ref(kadai2_6.png)
このコースでセンサーが読み取るのは以下の4種類だけである。~
(センサー1、センサー3)~
1.(白、白)→黒い線を2つのセンサーがまたいでいるとき ⇒直進~
2.(白、黒)→センサー3(右)が黒を認識 ⇒右に修正~
3.(黒、白)→センサー1(左)が黒を認識 ⇒左に修正~
4.(黒、黒)→交差点(ロータリー)に差し掛かった ⇒直進or右に修正~

**ロボット本体 [#q967b082]
ロボット本体は、重々しいのが嫌だったのでシンプルにしました。

そして今回のポイントとなる光センサーも2人で違う形として使うために簡単に作りました。~
センサー間は3.0mmのです。~
#ref(kadai2_1.png)~
これを車体前方につけて~
#ref(kadai2_2.png)~
こうしてできた、今回のロボットはこちら↓~
#ref(kadai2_3.png)
中島は最初が急カーブなのでセンサーを少し改造!
#ref(robo.png)





*プログラム [#b55dc97c]
**ばば・作(左からSTART、直角コース) [#ocd393e1]
使用コース~
#ref(kadai2_4.png)~
 #define THRESHOLD 40                                 //閾値
 sub except_a_crossing()                //サブルーチンを定義
 sub except_a_crossing()
 { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))     //(白、白):直進
   { OnFwd(OUT_A+OUT_C); }
   if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD))   //(黒、白):左に修正
   { Off(OUT_A);
     OnFwd(OUT_C); }
   if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))   //(白、黒):右に修正
   { OnFwd(OUT_A);
     Off(OUT_C); }
 }
 sub Right()
 { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))    //(白、白):直進
    { OnFwd(OUT_A+OUT_C); }
   if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))    //(白、黒):右に大きく修正
    { OnFwd(OUT_A);
      OnRev(OUT_C); }
  }
 sub right()
 { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))    //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に修正
     { Off(OUT_A);
       OnFwd(OUT_C); }
  }
 sub b_b_go()
 { if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD))    //(黒、黒):直進
     { OnFwd(OUT_A+OUT_C);
       PlaySound(SOUND_CLICK); }           //交差点で音を鳴らす
 }
 sub b_w_left()
 { if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD))    //(黒、白):左に修正
     { Off(OUT_A);
       OnFwd(OUT_C); }
 }
 sub b_b_Right()
 { if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD))    //(黒、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C);
       PlaySound(SOUND_CLICK); }           //交差点で音を鳴らす
 }
 sub w_w__w_b_go()
 { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))    //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):直進
     { OnFwd(OUT_A+OUT_C); }
     b_w_left();
 }
 task main()
 { 
   SetSensor(SENSOR_1,SENSOR_LIGHT);         //センサー1は光センサー
   SetSensor(SENSOR_3,SENSOR_LIGHT);         //センサー3は光センサー
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=1200)             //12秒以下でwhile内を繰り返し
   { except_a_crossing();
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(黒、黒):直進
     { OnFwd(OUT_A+OUT_C);
       PlaySound(SOUND_CLICK); }           //交差点で音を鳴らす
    }
     b_b_go(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=300)              //3秒以下でwhile内を繰り返し
   { except_a_crossing();
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(黒、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C);
       PlaySound(SOUND_CLICK); }           //交差点で音を鳴らす
    }
     b_b_Right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=250)              //2.5秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(黒、白):左に修正
     { Off(OUT_A);
       OnFwd(OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):直進
     { OnFwd(OUT_A+OUT_C); }
    }
   { w_w__w_b_go();
     b_w_left(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=200)              //2秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C); }
    }
   { Right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=250)              //2.5秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に修正
     { OnFwd(OUT_A);
       Off(OUT_C); }
    }
   { right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=500)              //5秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C); }
    }
   { Right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=200)              //2秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(黒、白):左に修正
     { Off(OUT_A);
       OnFwd(OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C); }
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(黒、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C);
       PlaySound(SOUND_CLICK); }           //交差点で音を鳴らす
    }
   { Right();
     b_w_left();
     b_b_Right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=200)              //2秒内でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に修正
     { Off(OUT_A);
       OnFwd(OUT_C); }
    }
   { right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=200)              //2秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に大きく修正
     { OnFwd(OUT_A);
       OnRev(OUT_C); }
    }
   { Right(); }
   ClearTimer(0);                   //タイマーをリセット
   while(FastTimer(0)<=1000)             //10秒以下でwhile内を繰り返し
   { if((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(白、白):直進
     { OnFwd(OUT_A+OUT_C); }
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD))  //(黒、白):左に修正
     { Off(OUT_A);
       OnFwd(OUT_C); }
     if((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(白、黒):右に修正
     { OnFwd(OUT_A);
       OnRev(OUT_C); }
     if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD))  //(黒、黒):直進
     { OnFwd(OUT_A+OUT_C);
     PlaySound(SOUND_CLICK); }            //交差点で音を鳴らす
    }
   { Right();
     b_w_left();
     b_b_go();
   Off(OUT_A+OUT_C);
   PlaySound(SOUND_DOUBLE_BEEP);           //ゴールしたら音を鳴らす
   PlaySound(SOUND_DOUBLE_BEEP);              //ゴールしたら音を鳴らす
 }



**中島・作(右からSTART、近道コース) [#m51a3efa]
使用コース~
#ref(kadai2_7.png)
 #define threshold 40  
 #define turn_left(t) OnRev(OUT_A);OnFwd(OUT_C);Wait(t);Float(OUT_A+OUT_C);
 #define turn_right(t) OnRev(OUT_C);OnFwd(OUT_A);Wait(t);Float(OUT_A+OUT_C); 
 #define go_straight(t) OnFwd(OUT_A+OUT_C);Wait(t);Float(OUT_A+OUT_C);
 task main()
 sub line_trace()                       //ライン上を進む
 {
 SetSensor(SENSOR_1, SENSOR_LIGHT);       //センサー1は光センサー
 SetSensor(SENSOR_3, SENSOR_LIGHT);       //センサー3は光センサー
 ClearTimer(0);
 while(FastTimer(0) <= 1320)              //急カーブ
 {
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
   }
 }
 task main()
 {
 SetSensor(SENSOR_1, SENSOR_LIGHT);       //センサー1は光センサー
 SetSensor(SENSOR_3, SENSOR_LIGHT);       //センサー3は光センサー
 ClearTimer(0);
 while(FastTimer(0) <= 210)               //ロータリー
 while(FastTimer(0) <= 1320)              //急カーブの部分について
 {
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 210)               //ロータリーについて
 { 
  if(FastTimer(0) <= 40)
  if(FastTimer(0) <= 40)                  //0.4秒間右に曲がる
  {
  turn_right(40);
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 260)                 //一つ目無視して進む
 while(FastTimer(0) <= 260)               //一つ目無視して進むために
 { 
  if(FastTimer(0) <= 100)
  if(FastTimer(0) <= 100)                 //1秒間右回転
  {
  OnFwd(OUT_C);Wait(100);
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 425)              //ロータリー1終わり→3.8秒進む
 while(FastTimer(0) <= 425)               //ロータリー1終わり→3.8秒進む
 { 
  if(FastTimer(0) <= 45)
  {
  turn_right(45);
  turn_right(45);                         //4.5秒間右に曲がる
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 540)                //近道
 while(FastTimer(0) <= 540)               //近道について
 { 
  if(FastTimer(0) <=442)
  if(FastTimer(0) <=442)                  //4.42秒の間
  {
  turn_left(102);
  go_straight(230);
  turn_left(110);
  turn_left(102);                         //直角に左まわり
  go_straight(230);                       //2.3秒直進
  turn_left(110);                         //直角に左まわり
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 200)                 //ロータリー2
 while(FastTimer(0) <= 200)               //ロータリー2について
 { 
  if(FastTimer(0) <= 40)
  if(FastTimer(0) <= 40)                  //0.4秒間
  {
  turn_right(40);
  turn_right(40);                         //右に0.4秒                         
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 335)                   //一つ目無視
 while(FastTimer(0) <= 335)               //一つ目無視するために
 { 
  if(FastTimer(0) <= 100)
  if(FastTimer(0) <= 100)                 //1秒間
  {
  OnFwd(OUT_C);
  OnFwd(OUT_C);                           //1.7秒間左回転
  Off(OUT_A);
  Wait(170);
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 1400)               //ロータリー2終わり→13秒進む
 while(FastTimer(0) <= 1400)              //ロータリー2終わり→15.2秒進む
 { 
  if(FastTimer(0) <= 100)
  if(FastTimer(0) <= 100)                 //1秒間 
  {
  turn_right(100);
  turn_right(100);                        //右回転
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 ClearTimer(0);
 while(FastTimer(0) <= 250)                  //曲がりきる
 while(FastTimer(0) <= 250)               //最後がうまく曲がれないので
 {
 if(FastTimer(0) <= 150)
 if(FastTimer(0) <= 150)                  //1.5秒間
  {
  OnFwd(OUT_A);
  OnFwd(OUT_A);                           //右に回転
  Off(OUT_C);
  Wait(150);
  }
  if(SENSOR_3 < threshold)
  { 
  OnFwd(OUT_A);
  Off(OUT_C);
  } 
  if(SENSOR_1 < threshold)
  {                     
  Off(OUT_A);
  OnFwd(OUT_C);
  }
  else  
  {
  OnFwd(OUT_A);
  OnFwd(OUT_C);
  }
  line_trace();                           //ライン上を進む
 }
 Off(OUT_A+OUT_C);                        //終わり
 }

*評価 [#g04be9fb]
**交差点、ロータリーの攻略法 [#e48282a7]
交差点やロータリーでは2つのセンサーは(黒、黒)を認識します。なので交差点の時は(黒、黒)を認識したら直進するという命令を出しました。ロータリーでは(黒、黒)を認識したら右に曲がるように命令を出しました。その後、1つ目の道は無視しないといけないので(白、黒)を認識したら直進するように命令を出しました。ただ、その次の道は右に曲がらないといけないので、タイマーで時間を区切って(白、黒)で右に曲がるようにプログラミングしました。今回の最大の難関はこのロータリーの攻略だと思いました。


**その他の攻略法 [#y5d55149]
急カーブは普通に曲がっていてはコースから外れてしまうので、OffにしていたモーターをOnRevにして対応しました。また、直角や近道は(白、黒)のときに右折というプログラムでなんとかなりました。

**感想 [#mc7b834d]
今回の課題はロボット本体の製作にはあまり手こずらなかったが、その分プログラミングの難易度が高かった。課題1でやった関数やサブルーチンに加え、whileやifなども出てきて大変だった。一番難しかったのは、タイマーとwhileの調節です。この時間内にはこの条件という命令を出すのは厳しかったです。工夫した点は、サブルーチンを使ったところ。交差点以外は基本同じ動きをするので、except_a_crossing というサブルーチンを定義したら、プログラムがすっきりしました。さらに、交差点を通過するたび音を鳴らしたので、プログラムの修正中にちょっとした目印となった。今回の課題ではプログラミング力がついたと思うので、次の課題ではプログラムに工夫点をたくさん組み込んでいきたいです。

**反省 [#oa1b0290]
まずロータリーの仕組みを理解してなかったのはすごく反省しています。一度は完成したプログラムも全て書き直しました。課題そのものをちゃんと理解することが大切だと実感しました。~
前回の最大の反省点である「作業に取り掛かるのが遅すぎた」のは改善されましたが、少ない作業時間をもっと密度の濃いものにしていかないといけないと思った。自宅でタイマーの時間以外のプログラムを終わらせてきて、集まったときに時間調節をしたのは良かったと思うので、次の課題3でも自宅でできることは全部終わらせて集まったときは、その時にしかできないことをやりたいと思います。

*コメント [#k89b316f]
- 中島が使うロボットの写真も載せといて! -- [[ばば]] &new{2011-06-15 (水) 20:53:59};
- もう少し詳しいプログラムの説明をお願いします。交差点などをどのようにして認識したり通過したりしたかなど。またmainのプログラムが長くなりすぎるのでいくつかのサブルーチンに分けたほうがよいでしょう。 -- [[松本]] &new{2011-06-17 (金) 14:06:35};

#comment

----

Today:&counter(today);

Yesterday:&counter(yesterday);

All:&counter(all);


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