[[2009a/A10/課題2右]]

*目次 [#a1292144]
#contents

*課題 [#r0c05e65]
1.交差点にある牛乳パックを迂回してコースを3周するロボット

2.交差点にある牛乳パックを次の交差点に運搬し3周するロボット

3.交差点を右に次の交差点を左に曲がることを繰り返し3周するロボット

この3つが我々に与えられた今回の課題である。

*工夫した点:コース編 [#k75780b9]
我々はコースにも工夫を施した。3人いる班ならではの工夫である。&br;
3人いる班は交差点を左右に曲がるプログラムを作らなければならない。&br;
そのためコースを工夫すれば、簡単なプログラムでも問題なく走行することができる、と考えたのである。

#ref(2009a/A10/課題2右/2009062511490000.JPG,50%)
上が完成したコース。&br;交差点を右に、次の交差点を左に、次の交差点を右にというのを繰り返していくと、コースの円の部分を避けて走行することができるのである。&br;高橋のプログラムを見ても分かる通り、プログラム自体を簡単にすることができた。
 
*初号機制作 [#e84435d3]
機体制作は高橋が担当することになった。
まずは土台である。

土台は前回同様に基本的な構造で決まった。
#ref(2009a/A10/課題2右/2009061819550001.JPG,50%)
#ref(2009a/A10/課題2右/2009061819550000.JPG,50%)
駆動部は車輪を採用してオーソドックスな体型となった。
#ref(2009a/A10/課題2右/2009061819560000.JPG,50%)
次にセンサー類である。今回はタッチセンサーと光センサーの2つをいかにして本体に組み込むかも成功の鍵である。&br;
考えた末に土台の一部を削除し、タッチセンサーを土台に埋め込む形で設計した。&br;その上から光センサーを幅を広めにセットした。
#ref(2009a/A10/課題2右/2009061819560001.JPG,50%)
#ref(2009a/A10/課題2右/2009061819560002.JPG,50%)
#ref(2009a/A10/課題2右/2009061819570000.JPG,50%)
#ref(2009a/A10/課題2右/2009061819580000.JPG,50%)
このロボットで3つ目の課題はこなすことができるようになった。
#ref(2009a/A10/課題2右/2009061819590000.JPG,50%)
#ref(2009a/A10/課題2右/2009061820000000.JPG,50%)
次に牛乳パックをどのように動かすかである。&br;本体がどのような向きでパックにぶつかるか分からないため、円の形でパックを掴むことにした。
#ref(2009a/A10/課題2右/2009061820010000.JPG,50%)
#ref(2009a/A10/課題2右/2009061820010001.JPG,50%)
#ref(2009a/A10/課題2右/2009061820010002.JPG,50%)
#ref(2009a/A10/課題2右/2009061820020000.JPG,50%)
こうしてわれらのロボットが完成した。
#ref(2009a/A10/課題2右/2009061820020001.JPG,50%)
#ref(2009a/A10/課題2右/2009061820020002.JPG,50%)
#ref(2009a/A10/課題2右/2009061820030000.JPG,50%)
#ref(2009a/A10/課題2右/2009061820030001.JPG,50%)
#ref(2009a/A10/課題2右/2009061820040000.JPG,50%)

**工夫した点:初号機編 [#bec7cbeb]
ロボットが牛乳パックをつかみ易いように交差点への侵入角度を90度になるように、交差点を十字路にした。

次が牛乳パックを掴むアームである。&br;この様なアームによりロボットがどの方向に動いても牛乳パックが離れないようにした。
#ref(2009a/A10/課題2右/2009061820000000.JPG,50%)
#ref(2009a/A10/課題2右/2009061820010002.JPG,50%)
#ref(2009a/A10/課題2右/2009061820020000.JPG,50%)

*零号機制作 [#hf70a4e5]
初号機でプログラムを実行させたところ、タッチセンサーの反応が鈍いことが判明した。&br;
そのためタッチセンサーの感度を上げた機体制作に取り組んだ。
#ref(2009a/A10/課題2右/2009062511420001.JPG,50%)
#ref(2009a/A10/課題2右/2009062511420000.JPG,50%)
#ref(2009a/A10/課題2右/2009062511430000.JPG,50%)
#ref(2009a/A10/課題2右/2009062511430001.JPG,50%)
試行錯誤の結果、完成したのが零号機である。&br;
上の画像が零号機アームモードであり、下の画像が零号機ノーマルモードである。
#ref(2009a/A10/課題2右/2009062511430002.JPG,50%)
#ref(2009a/A10/課題2右/2009062511430003.JPG,50%)
#ref(2009a/A10/課題2右/2009062511440001.JPG,50%)
#ref(2009a/A10/課題2右/2009062511440002.JPG,50%)
**工夫した点:零号機編 [#i7a9e141]
零号機制作の目的がタッチセンサーの感度性能向上であるため、もちろんタッチセンサーが大幅に改良した。&br;その他の初号機からの改良点は光センサーとアームである。

タッチセンサーの改良は「てこの原理」により、支点から力点までの距離を延長して今までより少ない力でも反応するように仕上げた。&br;初号機よりもセンサーからバンパーまでの距離を伸ばしている。
#ref(2009a/A10/課題2右/2009062511440001.JPG,50%)
光センサーは取り付け場所の高さによって読み取る値が変わってくる。&br;さらに、機体のパーツがどのように付随しているかも重要な考慮要素の1つである。&br;
そのため、初号機と取り付け位置を同じくし、走行場所や光環境が変わっても同じような値がとれるように可変式に変更した。&br;上下左右への可変タイプとなった。
#ref(2009a/A10/課題2右/2009062511440002.JPG,50%)
アームについてはタッチセンサーの感度性能が向上した。&br;しかし、パックを移動させるときにセンサーが反応してしまう恐れがあった。&br;そのために、アーム部分にストッパーを2つ取り付けた。
#ref(2009a/A10/課題2右/2009062511450002.JPG,50%)
#ref(2009a/A10/課題2右/2009062511460001.JPG,50%)
1つめのストッパーは牛乳パックの固定性能を上げるストッパーである。&br;
画像にある2つのL字パーツが牛乳パックの固定性能を高めるとともに、牛乳パックをセンサーにあまり近づかないようにしている。&br;下の画像が1つ目のストッパーである。
#ref(2009a/A10/課題2右/2009062511460002.JPG,50%)
#ref(2009a/A10/課題2右/2009062511470000.JPG,50%)
2つめのストッパーはタッチセンサーの機能を低下させる働きを持ったものである。&br;
画像中央にある灰色の一見はみ出したように見えるパーツの一部がストッパーである。&br;
このストッパーはアームがパックを固定したときに発動し、タッチセンサーの可動部を上から押さえてセンサーの機能を低下させることができるのである。&br;下の画像が2つ目のストッパーである。
#ref(2009a/A10/課題2右/2009062511470001.JPG,50%)
#ref(2009a/A10/課題2右/2009062511480000.JPG,50%)
*プログラム一覧 [#j4a198ff]
**橋本のプログラム [#k93c49a6]
#define RUN_TIME 1800  3周する時間

task main ()
{
       SetSensor(SENSOR_1,SENSOR_LIGHT);  
       SetSensor(SENSOR_2,SENSOR_TOUCH);  
       SetSensor(SENSOR_3,SENSOR_LIGHT);
       
       
       while ((true)&(Timer(0)<=RUN_TIME)) {  
       if (SENSOR_1 <  36) {         左に旋回 
       OnFwd(OUT_C);
       Off(OUT_A);
       }
    if(SENSOR_3 < 36) {           右に旋回
    OnFwd(OUT_A);
    Off(OUT_C);
    }
    if((SENSOR_1>36)&&(SENSOR_3>36)){   白い道を走る
    OnFwd(OUT_A+OUT_C);
    }
    if((SENSOR_1< 36 )&&(SENSOR_3< 36)){  黒い線を走る
    Off(OUT_A+OUT_C);
    Wait(130);
    OnFwd(OUT_A+OUT_C);
    Wait(25);
    }
    if(SENSOR_2==1){{            タッチセンサーが触れた場合
    Off(OUT_A+OUT_C);
    Wait(200);
    OnFwd(OUT_B);
    Wait(50);
    OnRev(OUT_A+OUT_C);
    Wait(50);
    Off(OUT_A+OUT_C);
    Wait(100); 
    if(SENSOR_1<36){
    OnFwd(OUT_C);
    Off(OUT_A);
    }
    if(SENSOR_3<36){
    OnFwd(OUT_A);
    Off(OUT_C);
    }
    if((SENSOR_1>36)&&(SENSOR_3>36)){
    OnFwd(OUT_A+OUT_C);
    }
    if((SENSOR_1<36)&&(SENSOR_3<36)){
    Off(OUT_A+OUT_C);
    Wait(130);
    OnFwd(OUT_A);
    OnRev(OUT_C);
    Wait(100);
    OnRev(OUT_B);
    Wait(70);
    OnRev(OUT_A+OUT_C);
    Wait(70);
    OnFwd(OUT_A);
    OnFwd(OUT_C);
    Wait(100);    
    }
    }
    }
    }}
**河島のプログラム [#w4ce238e]
河島が制作したプログラムは交差点にある牛乳パックを避けて3周するモノである。

今回のプログラムは難しかったのでほぼ全部、高橋に手伝ってもらっての作業だった。

下に貼ってあるのが今回制作したプログラムです。


 #define set     SetSensor(SENSOR_3,SENSOR_LIGHT);SetSensor(SENSOR_1,SENSOR_LIGHT);SetSensor(SENSOR_2,SENSOR_TOUCH);SetPower(OUT_A+OUT_C,2);SetPower(OUT_B,0);
 #define mae     OnFwd(OUT_A+OUT_C);
 #define ura     OnRev(OUT_A+OUT_C);
 #define tomare  Off(OUT_A+OUT_C);
 #define r       OnFwd(OUT_A);Off(OUT_C);
 #define l       OnFwd(OUT_C);Off(OUT_A);
 #define rsenkai OnFwd(OUT_A);OnRev(OUT_C);
 #define lsenkai OnFwd(OUT_C);OnRev(OUT_A);
 #define al      38
 #define sl      30
 #define s1      SENSOR_1
 #define s2      SENSOR_2
 #define s3      SENSOR_3

回避するタスクの使用に関して質問があったので説明します。&br;
このタスクは牛乳パックにぶつかりタッチセンサーが反応すると起動するようになっています。&br;
タスクを起動すると同時進行することになりますが、このタスクの起動命令がかかれているwhileの( )の中はタイマーで定義してあります。&br;
さらに回避タスクの起動時間に合わせて定義しているため、回避タスクの終了と同時に次のwhileに進む仕組みになっています。&br;
その結果、同時進行しているように見えても、実は別々に動く仕組みになっています。&br;
この説明でまだ不明なところがありましたら、また質問してください。&br;
回避するタスクが2つあるのは、コースの仕様上で1周すると2回パックにぶつかるので、2つのタスクを用意してみました。

上記は変更の証として残しておきます。
回避タスクを1つにしろと言われたのでやってみました。
変更したところは「」をしておきました。
この変更により、回避タスクの修正が終わり、1つのタスクにまとめることができました。
高橋には本当に感謝です。
回避タスク2は変更の証として残しておきます。
消した方がいい場合は言ってください。
 task kaihi1 (){PlayTone(900,10); 回避するタスク1 タッチセンサーにより起動
  ura;Wait(50);   後進
  lsenkai;Wait(90); 左旋回
  mae;Wait(110);   前進
  rsenkai;Wait(100); 右旋回
  mae;until((s1 < sl)||(s3 < sl));  「ラインに反応するまで前進」
  mae;Wait(70);    ちょっと前進
  rsenkai;Wait(80); 右旋回
  mae;Wait(130);   前進  この動作でパックを回避終了
  rsenkai;until((s3 < al-1)&&(s3 > sl+1)); 光センサーの値まで右旋回
  rsenkai;Wait(20);PlayTone(900,50);    ちょっと右旋回して行動確認音発声
  tomare;      その場で停止
 }   

 task kaihi2(){PlayTone(900,10); 回避するタスク2 タッチセンサーにより起動
  ura;Wait(50);   後進
  lsenkai;Wait(60); 左旋回
  mae;Wait(150);   前進
  rsenkai;Wait(100); 右旋回
  mae;Wait(270);   前進
  rsenkai;Wait(100); 右旋回
  mae;Wait(150);   前進  この動作でパックを回避終了
  rsenkai;until((s3 < al-1)&&(s3 > sl+1)); 光センサーの値まで右旋回
  rsenkai;Wait(30);PlayTone(900,50);    ちょっと右旋回して行動確認音発声
  tomare;      その場で停止
 } 

 task main (){set;mae;Wait(30);repeat(3){ 3周するので3回リピート
  while(s3 > sl){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}
   }tomare;mae;Wait(30);ClearTimer(0); タイマーを作動させる
  while(Timer(0) < 90){if(s2==0){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}}    タッチセンサーが反応したらタイマーをもう1度作動させる そして回避プログラム1発動
   if(s2==1){ClearTimer(0);start kaihi1;until(Timer(0) == 90);}
   }tomare;Wait(30);ClearTimer(1);   タイマーを作動させる
  while(Timer(1) < 90){if(s2==0){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}}    タッチセンサーが反応したらタイマーをもう1度作動させる そして回避プログラム2発動
   if(s2==1){ClearTimer(1);start kaihi2;until(Timer(1) == 90);}
   }tomare;Wait(30);
  while(s3 > sl){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}
   }tomare;mae;Wait(30);
  while(s3 > sl){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}
   }tomare;mae;Wait(30);
  while(s1 > sl){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}
   }tomare;mae;Wait(30);
  while(s1 > sl){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}
   }tomare;mae;Wait(30);
  while(s3 > sl){
   if((s1 > al)&&(s3 > al)){mae;}
   if((s1 > al)&&(s3 < al)){r;}
   if((s1 < al)&&(s3 > al)){l;}
   }tomare;mae;Wait(30);  
 }tomare;}
**高橋のプログラム [#jd9a1964]
今回、高橋は3の「交差点を右に次の交差点を左に曲がり3周するロボット」のプログラムを作った。

今回使用したマクロ
 #define set SetSensor(SENSOR_3,SENSOR_LIGHT);SetSensor(SENSOR_1,SENSOR_LIGHT);SetPower(OUT_A+OUT_C,2); 
 センサーとパワーの初期値設定
 #define ss1     SetSensor(SENSOR_3,SENSOR_TOUCH);SetSensor(SENSOR_1,SENSOR_LIGHT); 
 左の光センサーのみを使用し右のセンサーを実質的に切る 交差点を左に曲がるときに右センサーが邪魔なため
 #define ss3     SetSensor(SENSOR_3,SENSOR_LIGHT);SetSensor(SENSOR_1,SENSOR_TOUCH); 
 右のセンサーのみを使用し左のセンサーを実質的に切る 交差点を右に曲がるときに左のセンサーが邪魔なため 
 #define mae     OnFwd(OUT_A+OUT_C);  前進するためのマクロ 
 #define ura     OnRev(OUT_A+OUT_C);  後進するためのマクロ
 #define tomare  Off(OUT_A+OUT_C);  停止を指示したマクロ
 #define r       OnFwd(OUT_A);Off(OUT_C);  右に曲がるためのマクロ
 #define l       OnFwd(OUT_C);Off(OUT_A);  左に曲がるためのマクロ
 #define rsenkai OnFwd(OUT_A);OnRev(OUT_C);  その場で右旋回するためのマクロ
 #define lsenkai OnFwd(OUT_C);OnRev(OUT_A);  その場で左旋回するためのマクロ
 #define al      39  area line の略、光センサーの黒と白の境界の指定
 #define sl      30  stop line の略、交差点の判断に用いる停止線の指定

今回のプログラム
 task main ()
 {set;mae;until((SENSOR_1 < sl)||(SENSOR_3 < sl));tomare; 初めの交差点まで前進
 repeat(6){  3周分のリピート と プログラムが長くならないように(6)
 PlayTone(440,50);  交差点到達音
 ura;Wait(30);rsenkai;Wait(50);mae;Wait(30);tomare;Wait(50);
 PlayTone(880,50);  右折開始音
 ClearTimer(0);ss3;  右センサーのみ使用
 while(Timer(0) < 50){if(SENSOR_3 < al){r;}else{l;}} 右折開始から5秒間は右センサーのみを使用して右センサーがarea lineより暗いところにいるなら右に明るいところにいるなら左に曲がる
 until(Timer(0) > 50);set; 5秒間待ったのちに両方の光センサーを使用
 while(SENSOR_1 > sl){  左センサーが停止線に行くまで行動
 if((SENSOR_1 > al)&&(SENSOR_3 > al)){mae;}  両方の光センサーが白の時は前進
 if((SENSOR_1 > al)&&(SENSOR_3 < al)){r;}  右センサーだけが境界にいるときは右に曲がる
 if((SENSOR_1 < al)&&(SENSOR_3 > al)){l;} }  左センサーだけが境界にいるときは左に曲がる
 tomare; whileを抜けたら停止 すなわちstop lineにセンサーが反応したら停止

 PlayTone(523,50);  交差点到達音
 ura;Wait(30);lsenkai;Wait(50);mae;Wait(30);tomare;Wait(50);
 PlayTone(1047,50);  右折開始音
 ClearTimer(0);ss1;  左センサーのみ使用
 while(Timer(0) < 50){if(SENSOR_1 < al){l;}else{r;}} 左折開始から5秒間は左センサーのみを使用して左センサーがarea lineより暗いところにいるなら左に明るいところにいるなら右に曲がる
 until(Timer(0) > 50);set; 5秒間待ったのちに両方の光センサーを使用
 while(SENSOR_3 > sl){   右センサーが停止線に行くまで行動
 if((SENSOR_1 >= al)&&(SENSOR_3 > al)){mae;}  両方の光センサーが白の時は前進
 if((SENSOR_1 >= al)&&(SENSOR_3 < al)){r;}   右センサーだけが境界にいるとき右曲がり
 if((SENSOR_1 <= al)&&(SENSOR_3 > al)){l;} }  左センサーだけが境界にいるとき左曲がり
 tomare; whileを抜けたら停止 すなわちstop lineにセンサーが反応したら停止
 }
 PlayTone(523,52);Wait(62);  行動停止音
 PlayTone(523,52);Wait(62);
 PlayTone(523,26);Wait(36);
 PlayTone(587,26);Wait(36);
 PlayTone(659,26);Wait(36);
 PlayTone(698,26);Wait(36);
 PlayTone(784,52);Wait(62);
 PlayTone(698,26);Wait(36);
 PlayTone(784,26);Wait(36);
 PlayTone(695,40);Wait(50);
 }
*感想 [#c593485e]
橋本:前回以上に時間に追われたプログラム制作だった。またもまずは課題の完成を第一にしてしまったので、
複雑なプログラムを作ることができなかった。時間があるときにもう少しプログラムの調整が出来ればと思う。

河島:今回の課題は前回の課題より時間がかかったように思える。プログラムの製作はかなりを高橋君に依存してしまった。次はできる限り自分でできるように精進していきたい。時間に余裕を持って発表に臨めるようにしていきたい。

高橋:今回の課題は前回の課題より行うことがはっきりしていて、自分としては前回よりリラックスして取り組めた。自分の役割以上の活躍ができたと思う。人の分のプログラムまで書くのは大変だった。次は自力で頑張って欲しい。今回も難儀した活動だったが結果的に楽しめたので良かった。



*コメントよろしくお願いします。 [#r30d494a]
- コースとロボットの説明は非常にわかりやすいです。ただ、プログラムについては、taskを利用して複数同時実行をするようですが、どんなときにどのtaskが同時実行されるのでしょうか?もう少し説明が欲しいです。 -- [[こさか]] &new{2009-07-02 (木) 23:01:39};
- 回避タスクの説明分かりました。ただ、とてもよく似たタスクが2つあるというのは、やはり工夫して1つを使いまわせるようにしたほうが美しいだろうと思います。また、みなさんプログラムが見やすいように必要に応じてインデント(ifなどの中身の字下げ)を行ってみてください。それと、ifの条件とその動作について(例えば「右が黒で左が白だから右折」とかいうふうに)説明してください。 -- [[こさか]] &new{2009-07-10 (金) 12:49:06};
- ロボットの説明は充実していると思います。プログラムに関しては、もう少し説明が詳しいと分かりやすいと思います。詳しくとは、図や動画を使って、各部分がロボットのどのような動きと対応しているか、フローチャートなどを用いて全体の動きをわかりやすくするなどです -- [[FI]] &new{2009-07-26 (日) 19:56:33};

#comment

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