課題2: 黒い線に沿って動くロボットを作成せよ

各チームで交差点が2つ以上のコースを作成し、そのコースを3周するロボットを作成する。 交差点のうちの1つには500㎖の空の紙パックを置き、次のような動作をするプログラムを作成せよ。

1、紙パックを迂回する、あるいは紙パックを元の位置に戻した後コースに戻って進む。
  (交差点を通過後、紙パックが元の位置にあればよい。)
2、紙パックを次の交差点まで運んでいき、その交差点に紙パックを残して更に黒い線に沿って進む。

早さと正確さにも気をつけること。

ロボットの概要

一番こだわったところは紙パックをつかむ、または移動させる部分です。
モーターの回転を利用し、紙パックをしっかりつかめるようにしました。

tukamil.jpg

↑試作
紙パックをうまくつかむことはできたのですが、重すぎて何かの拍子に本体から外れてしまうことが,,,

tukamis.jpg

↑試作
試作,魴變眠修靴燭發里任后今度は紙パックがうまく固定できず、移動の最中に紙パックが外れてしまいました。

そして最終的に出来上がったロボットの本体はこちら!!

hontai.jpg

試作,茲蠅盞變眠修掘∪菽爾縫乾爐魎きつけることによって紙パックを滑らないようにしてしっかりつかめるようになりました。
また、動きやすくするために両側に大きなタイヤを付け、後方に小さなタイヤを付けました。

コースの紹介

course.jpg

交差点は3つにしました。
カーブはできるだけ急にならないようにし、曲がりやすいようにしました。

プログラム

迂回Ver.

<その1>

#define THRESHOLD 40                                               //閾値の設定
#define turn_180    OnFwd(OUT_A);OnRev(OUT_C);Wait(130);Off(OUT_A+OUT_C);Wait(100);  //180°回転の定義

task main (){ 

      int i;
      i = 0;      //変数の設定     
      SetSensor(SENSOR_1,SENSOR_LIGHT);    //センサー1=光センサー
      SetSensor(SENSOR_2,SENSOR_TOUCH);   //センサ−2=タッチセンサー
      SetSensor(SENSOR_3,SENSOR_LIGHT);    //センサ−3=光センサー
      
      SetPower(OUT_A+OUT_C,2);               //少しゆっくり動くように設定
      Wait(100);               //ボタンを押してからスタートするまで1秒待つ
      
     while (i < 18){
       if(SENSOR_1 > THRESHOLD){
                if(SENSOR_3 > THRESHOLD){
                  OnFwd(OUT_A+OUT_C);
                }              //1も3も白=直進
                else{   
                  OnFwd(OUT_A);
                  Off(OUT_C);
                }              //1は白、3は黒=右折
       }
          else{
                if(SENSOR_3 > THRESHOLD){
                  OnFwd(OUT_C);
                  Off(OUT_A);
                }              //1は黒、3は白=左折
                else{            //1も3も黒だったら
                  Off(OUT_A+OUT_C);
                  Wait(100);
                  OnFwd(OUT_B);
                  Wait(50);                  //紙パックをつかむ
                  Off(OUT_A+OUT_C);
                  Wait(100);                 
                  OnFwd(OUT_A+OUT_C);
                  Wait(120);         //少し前に出て
                  turn_180;          //回転して
                  OnRev(OUT_B);
                  Wait(50);          //紙パックを置く
                  OnRev(OUT_A+OUT_C);     //少し下がって
                  Wait(80);
                  turn_180;                   //回転
                  i = i+1;          //変数に1加える
                }             
          }
                      
      }               
          if(SENSOR_2 == 1){        //タッチセンサーが反応したら
                 OnRev(OUT_A+OUT_C);    //少し戻って..
                 Wait(100);
                 Off(OUT_A+OUT_C);     //停止して相手が通り過ぎるのを待つ
                 Wait(300);
          }
         
          if(i == 18){           //交差点を18回(1周6回×3周)通過したら
                 Off(OUT_A+OUT_C);     //自動的に停止
          }        
                  
}

このプログラムはタッチセンサーがうまく反応しなかったときに作ったプログラムです。
光センサーが両方とも黒に反応したとき、交差点とみなして紙パックをつかむようにしたのですが、
これでは紙パックがない交差点でもつかむ動作をしてしまうのであまりいいプログラムではありません,,,
そこでもう一つ、タッチセンサーに反応したらつかむ動作をするプログラムを作りました。
途中までは<その1>と同じです。

#define THRESHOLD 40
#define turn_180    OnFwd(OUT_A);OnRev(OUT_C);Wait(150);Off(OUT_A+OUT_C);Wait(100);

task main (){ 

      int i;
      i = 0;     
      SetSensor(SENSOR_1,SENSOR_LIGHT);
      SetSensor(SENSOR_2,SENSOR_TOUCH);
      SetSensor(SENSOR_3,SENSOR_LIGHT);
      
     
      Wait(100);
      
     while (i < 3){
       if(SENSOR_1 > THRESHOLD){
                if(SENSOR_3 > THRESHOLD){
                  OnFwd(OUT_A+OUT_C);
                }
             else{   
                  OnFwd(OUT_A);
                  Off(OUT_C);
                }
       }
             else{
                if(SENSOR_3 > THRESHOLD){
                  OnFwd(OUT_C);
                  Off(OUT_A);
                }
                else{
                  OnFwd(OUT_A+OUT_C);             
                }
             }
                      
    }               
        if(SENSOR_2 == 1){            //タッチセンサーが反応したら
                  Off(OUT_A+OUT_C);
                  Wait(100);
                  OnFwd(OUT_B);         //つかむ動作をする
                  Wait(50);
                  Off(OUT_A+OUT_C);
                  Wait(100);                 
                  OnFwd(OUT_A+OUT_C);
                  Wait(120);
                  turn_180;
                  OnRev(OUT_B);
                  Wait(50);
                  OnRev(OUT_A+OUT_C);
                  Wait(80);
                  turn_180;
                  i = i+1;
         }
         
         if(i == 3){
                 Off(OUT_A+OUT_C);       //紙パックをつかむ動作を3回(1周1回×3周)で自動的に停止
         }
}

<その2>は、光センサーが両方とも黒に反応したとき(普通の交差点)は直進、
タッチセンサーが反応したとき(紙パックがある交差点)では紙パックをつかむ動作をするようにしました。
1台だけで走らせるようだったのでもう一つのロボットを避けるプログラムは必要なかったので、
タッチセンサーを紙パックに反応する方にまわしました。

運搬Ver.

sub trace_head()        //前にトレースするサブ 
   {  if((SENSOR_1>40)&&(SENSOR_3>40)){OnFwd(OUT_A+OUT_C);}
       if((SENSOR_1>40)&&(SENSOR_3<40)){OnFwd(OUT_A);Off(OUT_C);Wait(1);}
       if((SENSOR_1<40)&&(SENSOR_3>40)){OnFwd(OUT_C);Off(OUT_A);Wait(1);}}
       
sub trace_tail()    //後ろにトレースするサブ
   {  if((SENSOR_1>40)&&(SENSOR_3>40)){OnRev(OUT_A+OUT_C);}
       if((SENSOR_1<40)&&(SENSOR_3>40)){OnRev(OUT_C);OnFwd(OUT_A);Wait(1);}
       if((SENSOR_1>40)&&(SENSOR_3<40))OnRev(OUT_A);OnFwd(OUT_C);Wait(1);}     
       if((SENSOR_1<40)&&(SENSOR_3<40)){OnRev(OUT_A+OUT_C);}}
  
  int across ;     //交差点を渡った回数
       
task main(){        

    OnRev(OUT_B);Wait(50); //まず腕を開く

SetSensor(SENSOR_1,SENSOR_LIGHT);
SetSensor(SENSOR_2,SENSOR_TOUCH);
SetSensor(SENSOR_3,SENSOR_LIGHT); 

across = 0 ;         

while(across <=7)  //交差点18回(=コース3周)するまで動く
{ 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
   
   trace_head();
   
   if((SENSOR_1<=40)&&(SENSOR_3<=40)){across=across+1;Off(OUT_A+OUT_C);Wait(50);OnFwd(OUT_A+OUT_C);Wait(20);Off(OUT_A+OUT_C);Wait(80);}//交差点に着いたらカウントしてから乗り越える     
    
    if(SENSOR_2==1){Off(OUT_A+OUT_C);Wait(50);OnFwd(OUT_B);Wait(50);紙パックにぶつかったら腕で掴み、以下の作業を実行・・・       
               until((across ==2)||(across==4)||(across==8)||(across==10)||  (across==14)||(across==16)){          //紙パックを離すべき交差点に着くまで交差点をカウントしつつ進む
                     trace_head();
                     if((SENSOR_1<=40)&&(SENSOR_3<=40))
                    { across =across+1;Off(OUT_A+OUT_C);  Wait(50);               OnFwd(OUT_A+OUT_C);Wait(20);Off(OUT_A+OUT_C);Wait(100);}
               
               if((across ==2)||(across==4)||(across==8)||(across==10)||  (across==14)||(across==16)){      //紙パックを離す作業
                       ClearTimer(0);while(Timer(0)  <10){trace_head();}Off(OUT_A+OUT_C);Wait(50);//交差点の前に出る
              
                       OnFwd(OUT_C);OnRev(OUT_A);Wait(60);while(SENSOR_3>40)  {OnFwd(OUT_C);OnRev(OUT_A);}Off(OUT_A+OUT_C);Wait(50);//道を手探りしつつUターン
              
                       until((SENSOR_1<40)&&(SENSOR_3<40))  {trace_head();}Off(OUT_A+OUT_C);Wait(50);
                       ClearTimer(0);while(Timer(0)  <=5){trace_tail();}Off(OUT_A+OUT_C);Wait(40);OnRev(OUT_B);Wait(50);
                       ClearTimer(0);while(Timer(0)<=6){trace_tail();}   Off(OUT_A+OUT_C);Wait(50);    //交差点の上に紙パックを置く
             
                       OnFwd(OUT_C);OnRev(OUT_A);Wait(60);while(SENSOR_3>40) {OnFwd(OUT_C);OnRev(OUT_A);}Off(OUT_A+OUT_C); Wait(50);
                               }  //Uターンして元に戻る
                     
                     
                  }//kousaten
      
   }//boxtukamu
    }//while
    }//taskmain

交差点に着いたとき、通り過ぎてからパックを後ろに置き去るようにしたのですが、Uターンが余りうまくいきませんでした。この調整に多くの時間がかかりました。また、最初の内は紙パックをセンサーで感知できず、そのため「スタート地点を固定しておき、交差点の数によって掴む・離すを制御」としたのですが、実際にはセンサーが巧く働いたので、それからプログラムの一部のみをあわてて変更しました。なんだかおかしなルーチンになってしまったのはその為です。

反省、感想

なかなかうまくいきませんでした。もっとプログラムを簡略化したり、ロボットを軽量化したり、できることがあったと思うので今後の課題に生かしたいと思いました。紙パックが思ったより軽くて思うようにタッチセンサーが働かなかったのですが、タッチセンサーの位置をもっと工夫すれば働いたと思います。紙パックをつかむモーター部分は本当によくできていました(相方に感謝!!)

コメント

コメントよろしくお願いします。

  • センサーのif部分、実はもっとスリム化できます。センサーが白か黒か(もしくは触っていないか触っているか)を、その都度ifで判断するのではなく、「無反応なら0を、反応なら1を返す関数」を作ってみるといいかもしれません。 -- こさか? 2009-07-02 (木) 21:57:24
  • プログラムを停止する条件を、i == 3のようにしてしまうと、なんらかの理由でiが3を飛ばして4に増えてしまった場合、永遠に止まらないプログラムになってしまいます。安全性のために、i >= 3としておいた方が良いでしょう。 また、なぜacross変数が2,4,8,10,14,16のときに紙パックを離すのかがいまいちわかりません…というか、whileの条件でacross<=7のときだけループ内が実行されるのならば、across==8とか10とかは意味があるのでしょうか?あと、コースは3周する決まりだったと思います。 -- こさか? 2009-07-17 (金) 04:02:15
  • やってみたんですけど、うまくできませんでした。。 -- えり? 2009-07-17 (金) 17:06:51
  • はい。3周の間違いでした。訂正しました。 -- だんと? 2009-07-19 (日) 22:52:44


添付ファイル: filetukamis.jpg 227件 [詳細] filetukamil.jpg 222件 [詳細] filehontai.jpg 209件 [詳細] filecourse.jpg 224件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-07-19 (日) 23:01:58 (3687d)