index

ロボットの説明

  • ロボットのタイヤにはキャタピラを使用することで頑丈にしようとした。ハサミに関してはウォームギアを使うことで持つ力を強くし、3個までの缶を持つことを前提として柱を作り3個までなら安全に運べるようになっている。

ロボットの全体図 ハサミ

  • 缶を上に持ち上げるため、地面に垂直な方向に動く動作をする必要がありその役割が出来る下の図のようなエレベータ式のロボットを作った。メリットは地面に垂直な方向に動く動作しかしないため缶を落とすリスクが減る。デメリットは缶にロボットを寸前まで近づけないといけない。

エレベータ

  • 地面の方に向いている光センサー2つがライントレース用であり、残り1つが缶認識用である。ライントレース用のはライントレースの説明で話すため省略。缶認識用に関してはsekkinという値以上になったら目の前にカンがあると判断。(sekkinの値を調べる前は近づくと暗くなるから値は低くなるだろうと予想していたが、光センサーの光が缶に反射したためか明るくなるため近づくにつれsekkinの値が高くなった。)

光センサー

コース説明

地図

  • ロボットが走る順番は(細線)赤→水色→ピンク→(太線)緑→紫→黄色→赤→水色→茶色である。コースを色分けしたのはプログラムの簡略化のため。色が切り替わるのはだいたい交差点やT字路である。
  • 1〜6までの数字はこのロボットが取ろうとしている缶の位置である。まずは1〜3までを取って上に積んでいき3つ重なったものをgoalにいれ、4〜6までをまた積んでいって3つ重なったものをgoalにいれて終了。

ライントレース

  • 光センサーを二つでライントレースをする。 ({左の光センサーが判断した色,右の光センサーが判断した色}→){黒,黒}{線上,線上}{白,白}のとき前進、{黒,線上}{黒,白}{線上,白}のとき左旋回、{白,黒}{白,線上}{線上,黒}のとき右旋回する。前進or左旋回or右旋回する時間は1回の光センサーの判断につき0.01秒であり、0.01秒移動したらまた光センサーで白、線上、黒の判断をする。それの繰り返しでライントレース出来る。光センサー1つの時と比べると交差点判断が楽になったが、曲線で交わる交差点(ex. 太線黄色→太線赤)では誤作動を起こしやすく1つの時と同様に左右が黒の値を何連続で取ったか、などを調べて交差点と判断させ時間で強制的に渡らせる必要がある。

缶の持ち運び

缶の動き

  • この間はエレベータが1秒上がり、1秒エレベータのモーターを止める動作を連続して行っている。

缶の動き

  • この間もエレベータが1秒上がり、1秒エレベータのモーターを止める動作を連続して行っている。

缶の動き

  • 後は3つ重なった缶を引きずりながらゴールまで運ぶだけ。

メッセージの送受信のやり方

  • (車体の方のRCXをRCX_1、ハサミ&エレベータの方のRCXをRCX_2とする)まずはRCX_1が缶の前orゴールの前にきたとき、HOLDまたはTUMU_UPまたはTUMUまたはHASAMIというメッセージを0.4秒間に1回の周期でRCX_2に送る。この間RCX_1は動かず、RCX_2は送られたメッセージにしたがって行動する。RCX_2は一連の動作を終えたら、RCX_1に2秒間の間0.05秒に1回の周期でGOというメッセージを送る。このときRCX_1はメッセージを送り続けてるため0.4秒に1回という周期を避けている。無事送られればRCX_1はメッセージを送るのをやめ、ライントレースなどの動作に戻る。

プログラム

車体用のプログラム

#define left_kuro 28//黒とみなす最大の値
#define right_kuro 34//黒とみなす最大の値
#define left_sen 38//線上とみなす
#define right_sen 43//線上とみなす
#define sekkin 40//缶が接近したときの値
#define HIPOWER 7//強い力
#define LOWPOWER 5//弱い力
#define set_power_H SetPower(OUT_AC,HIPOWER);//モーターを強い力に設定
#define set_power_L SetPower(OUT_AC,LOWPOWER);//モーターを弱い力に設定
#define senkai_left set_power_L;OnRev(OUT_A);OnFwd(OUT_C);//左旋回
#define senkai_right set_power_L;OnRev(OUT_C);OnFwd(OUT_A);//右旋回
#define go_forward set_power_H;OnFwd(OUT_AC);//前進
#define back set_power_L;OnRev(OUT_AC);//後退
#define CROSS(t,p,q)  set_power_L;go_forward;Wait(t);senkai_left;Wait(p);senkai_left;Wait(q);//T字路や交差点を渡る時のプログラム
#define STEP 1 //ライントレースで判断された動作を0.01秒間続ける。
#define SAIDAI 3 //T字路や交差点付近である条件に3連続でなったらT字路や交差点と判断
#define short_break Off(OUT_AC);Wait(80);//小休憩
#define counter3 PlaySound(SOUND_CLICK);//3回鳴ると交差点を渡る
#define GO 1//もうひとつのRCXからこのメッセージが送られてきたらこのRCXのプログラムが再始動する
#define HOLD 2//1つ目の缶を持ち上げる動作をもうひとつのRCXに送るメッセージ
#define TUMU_UP 3//1つ目の缶を2つ目の缶に積んで2つ目の缶を持ち上げる動作をもうひとつの RCXに送るメッセージ
#define TUMU 4//1,2目の缶を3つ目の缶に積んで3つ目の缶を挟む動作をもうひとつのRCXに送るメッセージ
#define HASAMI 5//ハサミを広げる動作をもうひとつのRCXに送るメッセージ
sub line_race()                                  //普通の黒線を走るプログラム
{
    if(SENSOR_1<=left_kuro){
       if(SENSOR_3<=right_kuro){
         go_forward;}
       else if(SENSOR_3<=right_sen){
         senkai_left;}
       else{senkai_left;}}
    else if(SENSOR_1<=left_sen){
       if(SENSOR_3<=right_kuro){
          senkai_right;}   
       else if(SENSOR_3<=right_sen){
          go_forward;}
       else{senkai_left;}}
    else{
       if(SENSOR_3<=right_kuro){
          senkai_right;}   
       else if(SENSOR_3<=right_sen){
          senkai_right;}
       else{go_forward;}}Wait(STEP);
}

sub before_cross_line_1()                //T字路付近の黒線を走るプログラム
{
 int nOnline=0; 

  while (nOnline < SAIDAI){
   if(SENSOR_3<=right_kuro){
       if(SENSOR_1<=left_kuro){
         go_forward;}
       else if(SENSOR_1<=left_sen){
         senkai_right;}
       else{senkai_right;}
     nOnline++;
   }else{
     if(SENSOR_3<=right_sen){
       if(SENSOR_1<=left_kuro){
          senkai_left;}   
       else if(SENSOR_1<=left_sen){
          go_forward;}
       else{senkai_right;}}
    else{
       if(SENSOR_1<=left_kuro){
          senkai_left}   
       else if(SENSOR_1<=left_sen){
          senkai_left;}
       else{go_forward;}}
      nOnline=0;}
   Wait(STEP);
  }                                            //while(<saidai)文終わり               
}

sub before_cross_line_2()                   //T字路付近の黒線を走るプログラム
{
 int nOnline=0; 

  while (nOnline < SAIDAI){
   if(SENSOR_1<=left_kuro){
       if(SENSOR_3<=right_kuro){
         go_forward;}
       else if(SENSOR_3<=right_sen){
         senkai_left;}
       else{senkai_left;}
     nOnline++;
   }else{
    if(SENSOR_1<=left_sen){
       if(SENSOR_3<=right_kuro){
          senkai_right;}   
       else if(SENSOR_3<=right_sen){
          go_forward;}
       else{senkai_left;}}
    else{
       if(SENSOR_3<=right_kuro){
          senkai_right;}   
       else if(SENSOR_3<=right_sen){
          senkai_right;}
       else{go_forward;}}
     nOnline=0;}
   Wait(STEP);
  }                                            //while(<saidai)文終わり               
}


sub before_cross_line_3()          //T字路or十字路付近の黒線を走るプログラム
{
int nOnline=0; 
while (nOnline < SAIDAI){
  if(SENSOR_1<=left_kuro&&SENSOR_3<=right_kuro){
         go_forward;nOnline++;}
  else if(SENSOR_1<=left_sen&&SENSOR_3<=right_sen){
         go_forward;nOnline++;}
  else if(SENSOR_1<=left_kuro){
       if(SENSOR_3<=right_sen){
         senkai_left;}
       else{senkai_left;}nOnline==0;}
  else if(SENSOR_1<=left_sen){
       if(SENSOR_3<=right_kuro){
          senkai_right;}   
       else{senkai_left;}nOnline==0;}
  else{
       if(SENSOR_3<=right_kuro){
          senkai_right;}   
       else if(SENSOR_3<=right_sen){
          senkai_right;}
       else{go_forward;}nOnline==0;}
  Wait(STEP);
}                                                //while(<saidai)文終わり 
}
task main(){
 

 SetSensor(SENSOR_1,SENSOR_LIGHT);//左側の光センサー
 SetSensor(SENSOR_2,SENSOR_LIGHT);//缶の判断用
 SetSensor(SENSOR_3,SENSOR_LIGHT);//右側の光センサー
 int nCross=0;

while(nCross<=8){


   if(nCross==0){                                   //細線赤色に相当
     senkai_right;Wait(50);
     go_forward;
     until(SENSOR_3<=left_sen);
     senkai_left;Wait(60);                                //ここでラインの上に乗っかる
     while(SENSOR_2>=sekkin){
      line_race();}
     Off(OUT_AC);                                          
     while(Message() != GO){SendMessage(HOLD);Wait(40);} //缶をつかむ&上に持ち上げる
     senkai_left;Wait(410);
     nCross++;
     }

   else if(nCross==1){                              //細線水色に相当
     while(SENSOR_2>=sekkin){
       line_race();}
     Off(OUT_AC);                                          
     while(Message() != GO){SendMessage(TUMU_UP);Wait(40);}//缶を積む&上に持ち上げる 
     ClearTimer(0);
     while(FastTimer(0)<300){
      line_race();}
     before_cross_line_1();
     CROSS(50,0,0);
     nCross++;
     }

   else if(nCross==2){                           //細線ピンク色に相当
     while(SENSOR_2>=sekkin){
       line_race();}                                    
     Off(OUT_AC);
     while(Message() != GO){SendMessage(TUMU);Wait(40);}      //缶を積む          
     ClearTimer(0);
     while(FastTimer(0)<830){
      line_race();}
     before_cross_line_3();
     CROSS(150,0,0);
     senkai_right;Wait(130);
     Off(OUT_AC);
     while(Message() != GO){SendMessage(HASAMI);Wait(40);}      //ハサミを広げる
     back;Wait(100);
     senkai_right;Wait(235);
     go_forward;Wait(150);
     nCross++;
     }

  else if(nCross==3){                               //太線緑に相当
     ClearTimer(0);
     while(FastTimer(0)<1000){
      line_race();}
     before_cross_line_2();
     CROSS(50,150,0);
     nCross++;
    }

  else if(nCross==4){                          //太線紫色に相当
      ClearTimer(0);
      while(FastTimer(0)<200){
         line_race();}
      before_cross_line_3();
      CROSS(50,0,150);
      nCross++; 
    }

   else if(nCross==5){                           //太線黄色に相当
     while(SENSOR_2>=sekkin){
       line_race();}                  
     Off(OUT_AC);                                         
     while(Message() != GO){SendMessage(HOLD);Wait(40);}     //缶をつかむ&上に持ち上げる          
     ClearTimer(0);
     while(FastTimer(0)<1600){
      line_race();}
     before_cross_line_3();
     go_forward;Wait(50);
     CROSS(50,0,0);
     nCross++;
     }

   else if(nCross==6){                                  //太線赤に相当
     while(SENSOR_2>=sekkin){
       line_race();}
     Off(OUT_AC);
     while(Message() != GO){SendMessage(TUMU_UP);Wait(40);}  //缶を積む&上に持ち上げる
     while(SENSOR_2>=sekkin){
       line_race();}
     Off(OUT_AC);
     while(Message() != GO){SendMessage(TUMU);Wait(40);}      //缶を積む        
     ClearTimer(0);
     while(FastTimer(0)<300){
      line_race();}
     before_cross_line_1();
     go_forward;Wait(50);
     senkai_right;Wait(150);
     CROSS(50,0,150);
     nCross++;
     }

   else if(nCross==7){                          //太線水色に相当
     ClearTimer(0);
     while(FastTimer(0)<200){
        line_race();}
     before_cross_line_3();
     go_forward;Wait(50);
     senkai_right;Wait(150);
     CROSS(50,0,150);
     nCross++; 
    }

   else if(nCross==8){                     //太線茶色に相当
     ClearTimer(0);
     while(FastTimer(0)<1000){
      line_race();}
     before_cross_line_3();
     CROSS(50,0,0);
     senkai_right;Wait(100);                    
     Off(OUT_AC);
     while(Message() != GO){SendMessage(HASAMI);Wait(40);}      //ハサミを広げる
     back;Wait(500);      
     nCross++;
     }

}                                                                //while(nCross<=8)終わり
stop main;                                                     //task main()を終了
}

ハサミ&エレベータのプログラム

#define GO 1//このメッセージを送るともう一つのRCXが再始動する
#define HOLD 2//もう一つのRCXからこのメッセージが送られると1つ目の缶を持ち上げる動作をする
#define TUMU_UP 3//もう一つのRCXからこのメッセージが送られると1つ目の缶を2つ目の缶に積んで2つ目の缶を持ち上げる動作をする
#define TUMU 4//もう一つのRCXからこのメッセージが送られると1,2目の缶を3つ目の缶に積んで3つ目の缶を挟む動作をする
#define HASAMI 5//もう一つのRCXからこのメッセージが送られるとハサミを広げる動作をする
#define hasamu OnRev(OUT_A);Wait(50);Off(OUT_A);//ハサミを閉じる
#define hirogeru OnFwd(OUT_A);Wait(50);//ハサミを広げる
#define up OnRev(OUT_C);Wait(150);Off(OUT_C);//エレベータを上げる
#define down(t) OnFwd(OUT_C);Wait(t);Off(OUT_C);//エレベータを下げる
#define go_sin PlaySound(SOUND_UP);//goというサインを出したときわかりやすく音を鳴らす
sub send_go(){                              //goというサインを出すサブルーチン
 ClearTimer(0);
 while(FastTimer(0)<=200){SendMessage(GO);Wait(5);}
}
task main(){
int n=1;
while(true){
  
 ClearMessage();  
 SetPower(OUT_A,4);
 SetPower(OUT_C,5);
  
 if(Message() == HOLD){                //1つ目の缶を持ち上げる
   n=0;
   hasamu;
   up;
   go_sin;
   send_go();
 }
  
 else if(Message() == TUMU_UP){      //1つ目の缶を2つ目の缶に積んで2つ目の缶を持ち上げる
   n=0;
   down(20);
   hirogeru;
   down(130);
   hasamu;
   up;
   go_sin;
   send_go();
 }

 else if(Message() == TUMU){            //1,2目の缶を3つ目の缶に積んで3つ目の缶を挟む
   down(20);
   hirogeru;
   down(130);
   hasamu;
   go_sin;
   send_go();
   n=1;
 }

 else if(Message() == HASAMI){         //ハサミを広げる
   hirogeru;
   go_sin;
   send_go();
   n=1;
 }

 if(n==0){SetPower(OUT_C,1);OnRev(OUT_C);Wait(100);Off(OUT_C);Wait(100);}

}
}

プログラムの補強説明

  • 車体用のプログラム
    • nCrossという関数はロボットが走るコースを複数に分けプログラムもそれに応じて分けるようにして、前の区切りから次の区切りのプログラムに向かうとき+1される数字。分けた理由は、プログラムが何行にもわたり連続していると第三者に対してわかりにくいものになってしまうから。
  • CROSS(t,p,q)のtは前進する時間、pは左旋回する時間、qは右旋回する時間に対応している。
  • ハサミ&エレベータ用のプログラム
    • nという関数はHOLD or TUMU_UPというメッセージが送られた時だけエレベータが1秒上がり、1秒エレベータのモーターを止めるようにするために作った。なおエレベータが1秒上がり、1秒エレベータのモーターを止める動作をさせたいときはn=0、させたくなければnが0以外になるようにする。
  • エレベータが1秒上がり、1秒エレベータのモーターを止める動作をいれた理由はエレベータがモーターを止めても重さで下がってきてしまうので、一定の時間にエレベータを上にあげる動作が必要だと思ったから。

この講義の反省と感想

  • ロボットの製作に時間をかけすぎたのが一番の反省点です。前回の課題1ではプログラムに時間をかけすぎていたためかロボット制作のほうばかり頭に入っていたのが原因です。さらにロボットの耐久性を考慮にあまり入れていなかったため、当日になってキャタピラのほうが調子が悪くなってしまった。課題2の大きな目標である缶を積むという動作に集中しすぎたためでしょう。当日にロボットをほとんど動かせず残念でした。チームワークに関してはロボット製作が得意な人、プログラムが得意な人が程よくいて環境としては良かったのですが、作業に取り掛かる時間が遅かったかなと思っていました。私のほうからもっと早くに取り組むように働きかけていたら良い結果が出せたのにと反省しています。感想としては第一印象はロボットという言葉にひかれてやってきたけれど、予想以上に時間がかかる作業だったり、答えが複数ある事柄に出くわしたりと他の講義では中々味わえない経験をさせていただきました。後、ロボット制作に欠かせないギアに関する知識は、工学部である私にとっては貴重なものとなりました。

添付ファイル: filekan_36.jpg 174件 [詳細] filekan_25.jpg 178件 [詳細] filekan_14.jpg 172件 [詳細] filehikari.jpg 184件 [詳細] filehasami.jpg 182件 [詳細] fileerebe.jpg 196件 [詳細] filezentai.jpg 228件 [詳細] fileVAN.gif 185件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-02-06 (木) 22:13:42