[[2018b/Member]]

目次
#contents
*課題3 ボール運搬ロボット [#r2136047]

青と赤のボールを運搬して、それぞれ所定の350ml缶の上に乗せる。

その他のルール、採点方法などは課題3についてのページを参照してください。
#ref(2018b-mission3.png,around)
#ref(2018b-mission3.png)



*ロボット本体の工夫 [#j1881746]

#ref(zentaizu.JPG,around)
#ref(armgawa.JPG,around)
#ref(zentaizu.JPG)
#ref(armgawa.JPG)


**車体、各センサー(マスター担当) [#hf0b6f0c]

タイヤを動かすためのモーター二つでアーム用のモーターを挟んで固定した。
また、前方に光センサーを取り付けたが、説明書よりもタイヤ間の幅が広かったため光センサーを二個付けた。超音波センサーはアーム側を固定するパーツからアームを邪魔しないギリギリのところまで伸ばした。NXT本体は邪魔にならない程度に取り付けた。工夫として余ったパーツでコードを束ねられるようにした。

#ref(code.JPG)


**アーム(スレーブ担当) [#e65c1e1f]

#ref(armonly.JPG)

ボールをつかむアーム(手)と手を持ち上げるアーム(腕)で構成した。本当はアームを前方に取り付けたかったが、その場合NXTが後方に設置され重心が後ろ向きになってしまいアームを上げたタイミングでひっくり返ってしまう可能性があったので仕方なく後ろ向きに設置し180°回転する手間を増やしてしまった。ボールをつかむ仕組みは細い棒状のパーツと湾曲したパーツでボールをすくい上げることをイメージした。すくい上げたボールをアームの回転軸の下の部分で押さえつけて固定しアームを上げることで超音波センサーなどにも支障がないようにしている。


**全体的なバランス [#f6cd0236]

前方に光センサーを取り付けライントレースを、後方にアームと超音波センサーをー取り付け缶へボールを乗せる作業を、というように前後で仕事を分業している。前方にはNXT本体、後方にアームがあるので重心がどちらかに偏ったり、車体バランスの問題で転倒することはないがどちらも重いので小さい力ではタイヤを動かせず、NXTが微妙に車体左側に寄ってしまっているため転倒はせずともOnFwdSyncなどを使っても真っ直ぐ走れず絶妙なパワー調節を余儀なくされた。また、これによって最小値を求めてもその場に戻れない、回転しようとしても左車輪が動かないなどの問題がたびたび起こった。


*プログラムについて [#ze9a629c]
**マスター側のプログラム [#e8b186b0]


#define CONN 1
#define SIGNALA 11
#define SIGNALB 12
#define SIGNALC 13
#define SIGNALD 14
#define SIGNALE 15
#define SIGNALF 16
#define SIGNALG 17        //メッセージについては全体の流れで説明します
#define THRESHOLD 57
#define SPEED 50
#define speed 40
#define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
#define leftleft OnRL(speed,0);    //きついカーブの部分でショートカットをするため旋回しないようにした
#define left OnRL(speed,0);
#define straight OnRL(SPEED,SPEED);
#define right OnRL(0,speed+5);
#define rightright OnRL(-speed,speed+5);
#define MOVE_TIME_1 3000
#define MOVE_TIME_2 22500
#define MOVE_TIME_3 2000
#define zenshin OnFwd(OUT_B,speed);OnFwd(OUT_C,speed+6);
#define koutai OnRev(OUT_B,speed-10);OnRev(OUT_C,speed-4);   //車体バランスの影響で左右のモーターの強さを変えてある
#define teishi Off(OUT_BC);
#define kaiten_R1 OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);
#define kaiten_R2 OnFwd(OUT_B,speed);OnRev(OUT_C,speed);
#define kaiten_L1 OnRev(OUT_B,SPEED);OnFwd(OUT_C,SPEED);
#define kaiten_L2 OnRev(OUT_B,SPEED);OnFwd(OUT_C,SPEED);
#define kaiten_time_R1 2500     //缶を見つけるには短すぎた最小値を見つけるために回転する時間
#define kaiten_time_L1 1500
#define KAITEN RotateMotorEx(OUT_BC,50,400,100,true,false);   //180°回転
#define go_forward OnRL(SPEED,SPEED);
#define STEP 1
#define yasumi Off(OUT_BC);Wait(500);

sub serch_R1()      //反時計回りで缶を探す
 {
  SetSensorLowspeed(S4);
  long t10,t11;
  int L=1000;
  t10=CurrentTick();
  while(CurrentTick()-t10<=kaiten_time_R1){
   kaiten_R1;
   if(SensorUS(S4)<L)
   {
    L=SensorUS(S4);
    t11=CurrentTick()-t10;
   }
  }
  kaiten_L1;
  Wait(kaiten_time_R1-t11+100);  //車体バランスの問題を改善するための微調整+100
  Off(OUT_BC);
  Wait(500);
  }
 
inline sub serch_R2(int l)   lcm以下の距離のものを見つけたら止まる
 {
  SetSensorLowspeed(S4);
  kaiten_R1
  until(SensorUS(S4)<=l);
  Off(OUT_BC);
  }
 
sub serch_L()    時計回りで缶を探す
 {
  SetSensorLowspeed(S4);
  long t12,t13;
  int L=1000;
  t12=CurrentTick();
  while(CurrentTick()-t12<=kaiten_time_L1){
   kaiten_L1;
   if(SensorUS(S4)<L)
   {
    L=SensorUS(S4);
    t13=CurrentTick()-t12;
   }
  }
  kaiten_R1;
  Wait(kaiten_time_L1-t13+80);    //車体バランスの問題を改善するための微調整+80
  Off(OUT_BC);
  Wait(500);
  }

inline void sekkin(int d)   目標に接近するためのプログラム
 {
  SetSensorLowspeed(S4);
 
  while(SensorUS(S4)>=d){
  koutai;
  }
  teishi;
 }
 
sub LT_R()      //ライントレース
 {
    SetSensorLight(S3);
    long t0=CurrentTick();
    while(CurrentTick()-t0<=MOVE_TIME_2){
     if(SENSOR_3<THRESHOLD-10){
     rightright;
    }else if(SENSOR_3<THRESHOLD-7){
     right;
    }else if(SENSOR_3<THRESHOLD+2){
     straight;
    }else if(SENSOR_3<THRESHOLD+3){
     left;
    }else{
     leftleft;
    }
    Wait(STEP);
   }
  }

task main()
 {
 SetSensorLight(S2);
 SetSensorLight(S3);
 SetSensorLowspeed(S4);


 OnRev(OUT_BC,30);
 Wait(500);
 teishi;        //初期位置から赤いボールをキャッチする場所までの微調整
 int msg;
 SendRemoteNumber(CONN,MAILBOX1,SIGNALA);   スレーブ側にボールをつかんでもらう
 while(true){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
  if(msg==SIGNALE){
   koutai;
   Wait(MOVE_TIME_1);  
   KAITEN;      //後退して180°回転する。交差点を越えたあたりでライントレースを始められるようにする
   teishi;
   yasumi;
   LT_R();    //ライントレースを開始
   teishi;    //想定では大体地点Eに到着したあたりで停止
   serch_R1();   //缶をサーチ
   teishi;
   sekkin(15);   //15�僂竜�離まで接近
   koutai;
   Wait(1000);   //微調整   
   teishi;
   SendRemoteNumber(CONN,MAILBOX1,SIGNALB);   スレーブ側にボールを缶に乗せてもらう
  }
  if(msg==SIGNALF){
  zenshin;      
  Wait(MOVE_TIME_3);     //大体地点Eに戻る(多少ずれていても問題なし)
  kaiten_R1;
  Wait(100);        //青いボールを察知する前にボールを乗せた缶を見つけないように少し回転
  yasumi;
  serch_R2(25);    //25�儖米發鵬燭�を見つけたら停止
  yasumi;
  zenshin;
  Wait(500);     //青いボールと超音波センサーが近すぎたときのために少し離れる
  sekkin(10);
 koutai;
  Wait(200);         //青いボールをキャッチできる位置まで確認    
  yasumi;
  SendRemoteNumber(CONN,MAILBOX1,SIGNALC);   スレーブ側にボールをキャッチしてもらう
  }
  if(msg==SIGNALG){
   koutai;
   Wait(2000);  //目標に少し近づく   
   kaiten_R1; 
   Wait(500);  //仮に青側の缶が�△世辰疹豺腑機璽組楼呂砲覆ぞ豺腓�あるので少し回転
   serch_L();   //缶をサーチ
   teishi;
   sekkin(15);   //15�僂竜�離まで接近
   teishi;
   koutai;  
   Wait(1000);    //微調整
   SendRemoteNumber(CONN,MAILBOX1,SIGNALD);   スレーブ側にボールを缶に乗せてもらう
   teishi;       //停止
  }
 }
}
**スレーブ側のプログラム [#ycdd4674]


#define POWER 50
#define Power 25
#define power 15
#define time 300
#define Time 600
#define TIME 1000
#define hand_catch OnRev(OUT_B,POWER);Wait(Time);Off(OUT_B);  //ボールをつかむ
#define arm_Up OnFwd(OUT_C,POWER);Wait(TIME);Off(OUT_C);   //腕を上げる
#define hand_release OnFwd(OUT_B,power);Wait(TIME);Off(OUT_B);   //手を離す
#define arm_Down OnRev(OUT_C,POWER);Wait(Time+200);Off(OUT_C);   //腕を下げる
#define arm_up OnFwd(OUT_C,POWER);Wait(Time);Off(OUT_C);    //腕を少しだけ上げる
#define arm_down OnRev(OUT_C,Power);Wait(Time);Off(OUT_C);   //腕を少しだけ下げる
#define yasumi  Off(OUT_BC);Wait(500);
#define SIGNALA 11
#define SIGNALB 12
#define SIGNALC 13
#define SIGNALD 14
#define SIGNALE 15
#define SIGNALF 16
#define SIGNALG 17


sub ball_catch()    ボールを掴んで持ち上げる
 {
  Wait(Time);
  arm_Down;
  hand_catch;
  arm_Up;
  Off(OUT_BC);
  }
  
sub ball_release()    ボールを缶の上に置く
 {
  Wait(Time);
  arm_down;
  yasumi;
  hand_release;
  arm_up;
  Off(OUT_BC);
  }
  
task main()
 {
  int msg;
  while(true){
   ReceiveRemoteNumber(MAILBOX1,true,msg);
  
   if(msg==SIGNALA){
   ball_catch();
   Off(OUT_BC);
   SendResponseNumber(MAILBOX1,SIGNALE);   //赤いボールを掴んだことをマスター側に伝える
   }
   if(msg==SIGNALB){
   yasumi;
   ball_release();
   yasumi;
   SendResponseNumber(MAILBOX1,SIGNALF);   //赤いボールを缶に乗せたことをマスター側に伝える
   }
   if(msg==SIGNALC){
   ball_catch();
   Off(OUT_BC);
   SendResponseNumber(MAILBOX1,SIGNALG);   //青いボールを掴んだことをマスター側に伝える
   }
   if(msg==SIGNALD){
   yasumi;
   ball_release();
   yasumi;     //青いボールを缶に乗せて停止
   }
  } 
 }
**全体の流れ [#w87a75f4]

#ref(2018b-mission3 (1).png)


�.泪好拭実ΑЮ屬ぅ棔璽襪鬟�ャッチできる位置に移動しSIGNALAをスレーブに送信

�▲好譟璽崑Α�SIGNALAを受信したらボールをキャッチしSIGNALEをマスターに返信

��マスター側:SIGNALEを受信したら後退、回転して地点Gを過ぎたあたりで停止

�ぅ泪好拭実ΑД薀ぅ鵐肇譟璽垢魍�始。最初の急カーブであえて大きく回ることで地点Fまでショートカット。地点Eで停止

�ゥ泪好拭実ΑТ未鬟機璽舛垢襦�この時青いボールまでサーチしないように注意する。

�Ε泪好拭実ΑТ未棒楸瓩慧�当な位置に到着したらSIGNALBをスレーブに送信

�Д好譟璽崑Α�SIGNALBを受信したらボールを缶の上に乗せ、アームを邪魔にならないように上げてからSIGNALFをマスターに返信

�┘泪好拭実Α�地点E付近まで戻り青いボールをサーチ。見つけたらキャッチできる位置まで接近しSIGNALCをスレーブに送信

��スレーブ側:SIGNALCを受信したらボールをキャッチしSIGNALGをマスターに返信

��マスター側:青いボールを乗せる缶を探すのに有利な位置(地点K付近)まで移動し缶をサーチ。発見し接近したらSIGNALDをスレーブに送信

��スレーブ側:SIGNALDを受信したらボールを缶の上に乗せて停止


*本体、プログラムの改善点 [#wf6af1b1]

本体についてはやはり重さによって課題をこなすのに大きな支障をきたしたと感じている。その改善案としてN1N2グループの用いていたモーターに直接タイヤを取り付けず歯車を介してタイヤを回転させるという手法はとても創作的でよいと思った。また自分で思いついた案としてはNXTの配置についてもう少し後ろ寄りに設置する、可能であったならばNXTとアームの位置を入れ替えるなどの工夫ができれば重さは変わらずともタイヤにかかる負担が軽減したのではないか。

プログラムについてはライントレースのスムーズさによって缶を探す動作の始点が変わって缶を見つけられるところまで回転しない、逆に回転しすぎて青いボールを缶と間違えるなどのミスが多かった。改善案としては先に一度ボールを見つけることで回転の始点を統一するなどの工夫があったと考えた。また次にミスの多かった缶を見つけてもうまく近づけないというミスについては自分はロボットの左右バランスによるものであると考えているためロボットの改善により成功率は上がるものと考えている。稀に起こった缶を見つけられず最小値が更新されない不具合に関してはロボコン当日にアドバイスしていただいた通り一時停止を交えた回転をrepeatなどを使って行うことで缶を察知する余裕が生まれたのではないだろうか。

*感想、反省 [#y1e223df]
 
今回のロボコンでは基本点が取れず満足のいく結果とはいかなかった。反省点としてはテスト終わりの少ない時間とはいえ一人でいる時間にもどのような動きをさせるのか考える、その動きをさせるならどのようなプログラムを書くのがよいのかなどを考えていれば実際にロボットに触れる時間が少なくとも課題を成功させることができたのではないだろうか。ただ、ロボットとプログラムへの工夫は課題1,2と比べると大きく成長しており、その点に関しては自分の中では良い点だったと感じた。その努力をもう少しできていれば基本点が1点の取れないという状況を回避できたのかもしれないと思うととても悔しく感じた。

課題に関しては非常に残念な結果に終わってしまったが、半年間このロボティクス入門ゼミを続け、プログラミングの基礎を学ぶ上で自分は物事を効率的に運ばせるにはどうすればいいのかということやそれについてどのような努力をするのが最適なのかを考えることの重要性を学べたことが一番の収穫だったように感じた。自分の専門は化学なのでこの先プログラミングに触れることはあまりないかもしれないが、このゼミで得たことを様々な場面で活かせるよう努力していきたい。

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