[[2018b/Member]]
#contents
*課題3:ボール運搬ロボット [#rdd1cd26]
&size(20){&color(#166){青};};と&size(20){&color(#911){赤};};のボールを運搬して、それぞれ所定の350ml缶の上に乗せる。
**フィールド説明 [#aa075881]
#ref(7.png)
-フィールドは課題2で使用した紙を使用する。
-350ml缶(中が入っていても空でよい)は逆さまにして使い、ロボットのスタート直後にサイコロを振って出た目の番号の位置に置く。
-その番号の次の番号のところにもダミーの缶を置くことができる。ただし6の目が出た場合は6の位置と25cm以上離れていない場所ならどこに置いてもよいものとする。距離は缶と缶のもっとも近い部分で測る。
-空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。
-赤と青のボールは、図のように所定の場所に置いておく。その際、キットに含まれない小さな輪ゴムを使用するものとする。
**ルール [#z38e9872]
-基本ルール
--競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
--図のX地点または(および)Y地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。
--赤いボールを図のピンクのいずれかに置いた缶に、青いボールを図の水色のいずれかに置いた缶に、それぞれ乗せる。
--開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
--競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
--途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。

-基本得点の計算方法
--ボールを一つ乗せればそれぞれ10点、二つとも乗せればボーナス点としてさらに10点。
--ダミーの缶を設置した上で、正しい缶に乗せれば、それぞれさらに6点加点する。
--ボールを目的の缶に当てることができれば、それぞれ4点。
--ボールを同じ領域内の間違った缶に乗せた場合は、それぞれ6点。
--ボールを同じ領域内の間違った缶に当てた場合は、それぞれ2点。
--ボールを違う領域内の缶に乗せた場合は、それぞれ2点。
--ボールを違う領域内の缶に当てた場合は、0点。
--目的の缶をもとの位置(直径7cmの円)から少し出してしまった場合は1点減点、半分以上出してしまった場合は2点または取得した得点の半分のいずれか少ないほうを減点、その缶を完全にだしてしまったときは点数を半分にする。
--ダミーの缶がもとの位置から移動しても減点はしない。

-技術点の計算方法~

以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。
得点の目安: 
--ボール探し取りにいくまでの動作 (3点)
--ボール掴む動作 (3点)
--ボールを運ぶ動作 (2点)
--ボールを缶に置く動作 (2点)
--2台のNXT、EV3の連携の良さ(2点)
--自立型のロボットとしての形や動作の美しさ、斬新さ(2点)
--その他 (3点)

*ロボットについて [#jb55a7f5]
**全体像 [#j16816c7]
#ref(IMG_E5087.JPG)

#ref(pindome.png)

***説明(工夫した点や反省点など) [#t29cb7f5]
車体は前後に長く、参考書のサンプルの形からあまりかけ離れないように製作した。それにより常に安定した走りができるようにした。また、アームや各センサ、車体の動きを邪魔しないようにコードを余ったパーツで束ねられるようにした。
**マスター側:車輪、各センサー [#q5cb6c85]
#ref(IMG_E5087.JPG)

#ref(IMG_E5082.JPG)

#ref(IMG_E5085.JPG)

***説明(工夫した点や反省点など) [#vc39e62e]
モータを回転させて動かすタイヤ2つとその後方に車体のバランスを保ちながら車体の動きに合わせて動く小さなタイヤ1つの合計3つのタイヤで走る、参考資料のサンプルと同じ形に製作した。サンプルと同じ形であることで動きに安定感がある。
また前方に光センサーを2つ取り付けることでライントレース や交差点判断をより簡単に正確に出来るように製作した。しかしながら課題1.2で用いた光センサー1つでのライントレース のプログラムを課題3でも応用できるのではないかという案がチームで出て、結局右側の光センサーは光る飾りとなってしまった。
車体後方のアームの下、アームの動きを邪魔しないギリギリのところに超音波センサーを取り付け、ボールや缶をできる限り正確に探索し近づけるようにした。しかしながら超音波センサーの値が実際に定規で測った値と異なっており、調整するのが大変だった。
**スレーブ側:ボールを持ち上げて、缶に置くアーム [#bde72a97]
#ref(arm.png)
***説明(工夫した点や反省点など) [#z937e3d2]
人間がボールを拾い上げる動きをモデルとしてモータ2つを、ボールをつかみ缶に乗せる(手)と手を上下に動かす(腕)とそれぞれ役割を分けてプログラムを簡単に作れるように構成した。車体の重心の位置やバランス、アームと超音波センサーは同じ方向につけたいなどの理由からアームは車体の後方に取り付けたが、ボールを拾う時やボールをつかんで持ち上げた後などに180度回転する手間が増えてしまった。
*自分のチームが考えたコース取り [#n6e15f3b]
#ref(7_LI (2).jpg)

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

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

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

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

ゥ泪好拭実ΑТ未鬟機璽舛垢襦この時青いボールまでサーチしないように、回転を行う時間に注意。

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

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

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

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

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

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

*プログラミング [#n544807e]
**マスター側(車輪、各センサー) [#d3e2325b]

***定義やマクロ[#q58b36bd]
#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);
***サブルーチン関数やインライン関数 [#zac78d14]
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);
  }
 }
***メインのプログラム [#rfeb0cf5]
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;       //停止
  }
 }
}
**スレーブ側(アーム) [#wab3a823]
***定義やマクロ#define POWER 50 [#ie242c4f]
#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
***サブルーチン関数やインライン関数 [#vc3683a4]
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);
 }
***メインのプログラム [#iecfd0d7]
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;     //青いボールを缶に乗せて停止
  }
 } 
}

*車体やプログラムに関する反省点や改善点 [#z63059ba]
車体についてはやはり重さによって課題をこなすのに大きな支障をきたしたと感じている。その改善案としてN1N2グループの用いていたモータに直接タイヤを取り付けず歯車を介してタイヤを回転させるという手法はとても創作的でよいと思った。また自分で思いついた案としてはNXTの配置についてもう少し後ろ寄りに設置する、可能であったならばNXTとアームの位置を入れ替えるなどの工夫ができれば重さは変わらずともタイヤにかかる負担が軽減したのではないか。
プログラムについてはライントレースのスムーズさによって缶を探す動作の始点が変わって缶を見つけられるところまで回転しない、逆に回転しすぎて青いボールを缶と間違えるなどのミスが多かった。改善案としては先に一度ボールを見つけることで回転の始点を統一するなどの工夫があったと考えた。また次にミスの多かった缶を見つけてもうまく近づけないというミスについては自分はロボットの左右バランスによるものであると考えているためロボットの改善により成功率は上がるものと考えている。稀に起こった缶を見つけられず最小値が更新されない不具合に関してはロボコン当日にアドバイスしていただいた通り一時停止を交えた回転をrepeatなどを使って行うことで缶を察知する余裕が生まれたのではないだろうか。
*感想 [#t517c12c]
基本点が0点で終わってしまったことはかなり残念だが、芸術点として10.8点を獲得し総合4位になれたことはとても嬉しく感じた。テスト期間でチームのメンバー間の都合が合わず頻繁に集まることはできなかったが、あらかじめ次の集合までにお互いにやることを決め、時間が限られる中、効率よく進めることができた点はとてもよかった。

私は繊維学部 機械・ロボット学科なのでこの先今回のゼミのようなプログラミングの授業があるかとは思いますが、プログラミングの知識やさまざまな課題に対するアプローチの仕方、作業をより効率的に行うにはどうしたら良いかなどをあらかじめ後期の半年間を通して学ぶことが出来たのはかなり将来のためになったと感じている。これからも自分の専門をより深く学び、世の中の役に立つロボットを開発したいという自分の夢に向かって努力し続けていきたい。

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