2018b/Member

課題

ボール運搬ロボット 以下のコースを移動し青と赤のボールを運搬して、それぞれ所定の350ml缶の上に乗せる

コース3.png

ロボットの説明

robo3.jpg

ロボットの全体像

robo2.jpg

後輪の2つのキャスター

ロボットの土台は付属の冊子に記載されているロボットを参考にしたのだが、課題3のロボットはNXT本体を2台も乗せるためキャスターにかかる負荷が大きかった。そのためキャスターを2つに増やし、負荷を軽減した。

robo1.jpg

ボールを掴む機構

制作初期の頃は下のような腕でボールを掴もうと考えていたのだが、この腕を取り付けるためにはどうしても斜めに設置することしかできなく、かなり正確に本体をボールに知被けなければうまくつかむことができなかった。そこで、上の写真のように手のひらを大きくすることで、少し距離に誤差があったとしても漏れることなく持ち上げることができる。

robotto5.jpg
robo4.jpg

試作段階の腕

前方の2つのセンサー

ロボットの前面はセンサーや部品が集中しているため、超音波センサーの取り付けには苦労した。ロボットを制作しているときは、的となる缶だけでなくボールも超音波センサーで探すように考えていたため、センサーはかなり低く取り付け、少し下に傾けた。

プログラムの説明

ボールを掴むプログラム

#define UP OnFwd(OUT_B,20);Wait(4750);Off(OUT_BC);   //腕上げ
#define DOWN OnRev(OUT_B,20);Wait(2600);Off(OUT_BC);  //腕下げ
#define CATCH OnRev(OUT_C,15);Wait(725);Off(OUT_BC);  //手掴み

task main()
{
DOWN
CATCH
UP
}

ボールを置くプログラム

#define LOST OnFwd(OUT_C,15);Wait(685);Off(OUT_C);  //手離す

task main()
{      //ボールを持って腕は上がっている状態
LOST 
}

課題をこなすプログラム

#define turn_l1 OnFwd(OUT_B,33);OnRev(OUT_C,33);  //左旋回
#define turn_r1 OnFwd(OUT_C,33);OnRev(OUT_B,33);  //右旋回
#define turn_l0 OnFwd(OUT_B,30);Off(OUT_C);  //左折
#define turn_r0 Off(OUT_B);OnFwd(OUT_C,30);  //右折
#define go_s OnFwd(OUT_BC,30); //直進
#define stoop Off(OUT_BC);  //止まる
#define speed 70
#define speed_s 50
#define CONN 1
                                                                                         
const float diameter=5.54;                                                
const float track=10.35; 
const float pi=3.1415;


void fwdDist(float d)
{
   long angle;                                                         
   angle= d/(diameter*pi)*360.0;
   RotateMotorEx(OUT_BC,speed_s,angle,0,true,true);                       
}

void turnAng(long ang)
{
   long angle;
   angle=track/diameter*ang;
   RotateMotorEx(OUT_BC,speed_s,angle,100,true,true);
}                                                                      

int searchDirection(long ang)                                           

{
   long angle,tacho_min=0,tacho_corr;
   int d_min;

   d_min=500;

   angle=(track/diameter)*ang;                                                 
   turnAng(ang/2);
   ResetTachoCount(OUT_BC);                                               
 
   OnFwdSync(OUT_BC,speed_s,-100);
   while(MotorTachoCount(OUT_B)<=angle){
       if(SensorUS(S4)<d_min){
           d_min=SensorUS(S4);
           tacho_min=MotorTachoCount(OUT_B);
       }
   }                                                                           
   OnFwdSyncEx(OUT_BC,speed_s,100,RESET_NONE);
   until(MotorTachoCount(OUT_B)<=tacho_min||SensorUS(S4)<=d_min);              
 
   Wait(14);
   Off(OUT_BC);Wait(500);
   return d_min;
}
 
void tuuzyou()
{
   SetSensorLight(S1);  //通常のライントレース
   long t0;                                                                    
   t0=CurrentTick(); 
   while(CurrentTick()-t0<90){   //交差点(黒が一定時間以上)につくまでライントレース
       if(SENSOR_1>58){
           turn_r1;   
           t0=CurrentTick();                         
       }else if(SENSOR_1>53){
           turn_r0;
           t0=CurrentTick();
       }else if(SENSOR_1>44){
           go_s;                                                     
           t0=CurrentTick();
       }else if(SENSOR_1>34){
           turn_l0;
           t0=CurrentTick();   //黒以外はt0をリセット         
       }else{
           turn_l1;
             
       }
   } 
}                                                                             


void massugu() //一定時間の直進
{                                                                             
   turn_r1;
   Wait(150);
   go_s;
   Wait(1200);
}
                                                                              
 
void massugu2()  //一定時間の直進 
{
   turn_l1;                                                             
   Wait(400);
   go_s;
   Wait(2000);
}
          
                                                                            
 
void special()  //特別なライントレース
{
   SetSensorLight(S1);                                                        
   long t1;                                                                       
   t1=CurrentTick()
   while(CurrentTick()-t1<23500){   //一定時間内は交差点を認識しない
       if(SENSOR_1>58){
           turn_r1;                                                     
       }else if(SENSOR_1>53){                                      
           turn_r0;
       }else if(SENSOR_1>44){
           go_s;
       }else if(SENSOR_1>34){                                             
           turn_l0;                                                          
       }else{
           turn_l1;
       }                                                                            
   }                                                                      
}
 
 void sirotuuzyou()  //Dで止まるプログラム
{
   SetSensorLight(S1);
   long t2;                                                                   
   t2=CurrentTick(); 
   while(CurrentTick()-t2<90){   //白を一定時間以上認識したら止まる
       if(SENSOR_1>58){                                        
           turn_r1;                            
       }else if(SENSOR_1>53){
           turn_r0;
           t2=CurrentTick();
       }else if(SENSOR_1>44){
           go_s;
           t2=CurrentTick();
       }else if(SENSOR_1>34){
           turn_l0;
           t2=CurrentTick();
        else{
           turn_l1;
           t2=CurrentTick();   //白以外はt2をリセット
           
       }
   }
}
  
 
void gyakutuuzyou()   //逆走する                                                      
{
   SetSensorLight(S1);
   long t5;                                                                            
   t5=CurrentTick(); 
   while(CurrentTick()-t5<90){   
       if(SENSOR_1>56){
           turn_l1; 
            t5=CurrentTick();                           
       }else if(SENSOR_1>51){
           turn_l0;
           t5=CurrentTick();                                                      
       }else if(SENSOR_1>42){
           go_s;
           t5=CurrentTick();
       }else if(SENSOR_1>34){
           turn_r0;
           t5=CurrentTick();                                                         
       }else{
           turn_r1;

                                                                             
       }
   }
}
 
 
void gyakuspe()  //DE間を「逆走」
{
   SetSensorLight(S1);
   long t6;                                                              
   t6=CurrentTick();                                                
   while(CurrentTick()-t6<6000){   //一定時間内は交差点を無視
       if(SENSOR_1>58){
           turn_l1;                            
       }else if(SENSOR_1>53){
           turn_l0;
       }else if(SENSOR_1>44){
           go_s;
       }else if(SENSOR_1>34){
           turn_r0;                                                         
       }else{                                                        
           turn_r1;   
       }
   }
}
 
 
task main()  //ボールを掴んだあと缶の位置を調べるプログラム
{
     
   go_s;                                                                 
   Wait(1000);
   stoop;
   RemoteStartProgram(CONN,"CATCH.rxe");   //通信によりボールを掴む
   Wait(9000);                                     
   go_s;
   Wait(2000);
   special();
   tuuzyou();
   massugu();                                                      
   sirotuuzyou();
   SetSensorLowspeed(S4);
   int d=searchDirection(360);  //位置を調べる
   if (d>13.5){                    
       long t3,t4;
       t3=CurrentTick();
       fwdDist(d-13.5);
       t4=CurrentTick();
       stoop;
       RemoteStartProgram(CONN,"lost.rxe");   
       Wait(2000);
       OnRev(OUT_BC,30);
       Wait(t4-t3);                                                
       } 
   gyakuspe();
   gyakutuuzyou();
   go_s;
   Wait(700);
   stoop;
   RemoteStartProgram(CONN,"CATCH.rxe");   
   Wait(9000);                                                                       
   SetSensorLowspeed(S4);
   int e=searchDirection(100);
   if (e>12){                                                       
       fwdDist(e-12.0);
       RemoteStartProgram(CONN,"lost.rxe");   
       Wait(2000);
   stoop;
       }  
}

感想

今回はロボットを今までの基礎を使わずに、1から作り直したこともあって政策に時間がかかった。また、プログラムにおいても、NXT同士の通信や、今までのライントレースの応用など難しいものが多かったように感じる。しかし、このゼミを通してロボットの動作において、いかにプログラミングが大事かということを学び、これからの工学部の授業や将来の仕事に役立てたいとおもいます。 また、前日までプログラムやロボットの調整をしていてギリギリになってしまい、余裕をもって全体の調整をすることができなかったのが残念だった。


添付ファイル: filerobotto5.jpg 133件 [詳細] fileコース3.png 162件 [詳細] filerobo4.jpg 175件 [詳細] filerobo3.jpg 183件 [詳細] filerobo2.jpg 162件 [詳細] filerobo1.jpg 202件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-02-17 (日) 20:36:44