[[2017b/Member/masato/Mission3]] #contents *はじめに [#z6f997ac] 今回の課題では2組でチームを作り協力して行うものとなっている。通常は4人いるが、私たちのチームは3人となっている。メンバーは「masato」「onodera」「yuu」の3人チームである。 **課題3 [#w203e535] 今回の課題は紙コップとピンポン玉を別々に回収して所定の場所まで運ぶこと。 #ref(./2017b-mission3.png,100%,課題3) ***フィールドの説明 [#p57279d4] ・フィールドは課題2で使用した紙を使用する。 ・図のマジェンタの円に逆さまにした紙コップを置き、その中にピンポン玉を2つずつ入れておく。 ・図の黄色い円に紙コップを通常の向きに置き、障害物とする。直径6cmの円の外周をペンまたは鉛筆でマークしておく。 ・紙コップには色をつけたり文字や記号を書いてもよい。 ・割り箸を使って一辺が14cmの正方形を作り、X地点を中心とした円に接するように置く。 ***基本ルール [#cab19fce] ・競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。 ・図のA地点または(および)D地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。 ・ピンポン玉をX地点に運び、割り箸で正方形に囲まれた領域に入れる。 ・紙コップをY地点がある黒線に囲まれた領域に運ぶ。 ・開始の合図から5秒以内にスタートボタンを押す作業を完了すること。 ・競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。 ・途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 ***基本得点の計算方法 (片道) [#la6cab91] ・運んだピンポン玉の数×3点 ・運んだ紙コップの数×3点 ・紙コップを2つ重ねて置くことができた場合はさらに3点加算、3つ重ねて置くことができた場合は6点加算 ・障害物の紙コップに接触して一部を円の外に移動した場合は各1点減点、全部を円の外に移動した場合は各2点減点 ・例:ピンポン玉を4個運び、紙コップを3個運んだ場合で、そのうち2つの紙コップを重ねることができた場合:(4x3点) + (3x3点 + 3点) = 24点 ***技術点の計算方法 [#w73ece57] 以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。 得点の目安: ・紙コップとピンポン玉を探し取りにいくまでの動作 (2点) ・紙コップを掴む動作 (2点) ・紙コップを運ぶ動作 (2点) ・紙コップを置く (2点) ・ピンポン玉を拾う動作(2点) ・ピンポン玉を運ぶ動作(2点) ・ピンポン玉を目的に入れる動作(2点) ・2台のRCXまたはNXT、EV3の連携の良さ(2点) ・自立型のロボットとしての形や動作の美しさ、斬新さ(2点) ・その他 (2点) ([[2017b/Mission3]]を引用) **作戦 [#r2a083a5] 私たちのチームはロボットを別々に行動させるのではなく、合体させることにした。マスター側のプログラムがローバーを動かし、スレーブ側のプログラムが紙コップを掴むようにした。紙コップを掴んで運ぶ順番は以下の図の通りである。 #ref(./mappu.png,50%,作戦) スタートはAからである。 *ロボットの構造 [#kf3d3fc6] #ref(./IMG_0345.JPG,25%,ロボットの構造) #ref(./IMG_0350.JPG,25%,ロボットの構造) 構造を大雑把にいうと、3輪駆動のローバー部分の前側に紙コップを掴むためのクワガタ型のアームを取り付けた構造になっている。以下でそれぞれのパーツについて詳しく説明していく。 構造を大雑把にいうと、3輪駆動(後輪はキャスター)のローバー部分の前側に紙コップを掴むためのクワガタ型のアームを取り付けた構造になっている。以下でそれぞれのパーツについて詳しく説明していく。 **ローバー部分 [#o3066c99] #ref(./IMG_0329.JPG,15%) #ref(./IMG_0351.JPG,25%) なるべくコンパクトにしようと努力したが、本体2つに紙コップを掴むためのモーター2つを支えなければならなかっためどうしても全長は長くなってしまった。更に重さに耐えるために後ろには小さいタイヤ(摩擦を軽減するためゴムは外してある)を2つ付けて前輪に合わせて回転するようになっている。写真にはついていないが前輪側に紙コップを探すための超音波センサが縦にしてつけてある。 **アーム部分 [#f99c7e4c] #ref(./IMG_0321.JPG,15%) 当初は上から掴んで運んでいくという機構([[2017b/Member/onodera/Mission3]]で詳しく説明されている)だったが確実性の低さからクワガタ型のように横から掴む方式に変更した。 #ref(./IMG_0322.JPG,15%) ギアを3つ使いモーター1つで紙コップの掴む・離すができるようにした。写真の一番右のギアから動力がつたわるようになっている。 #ref(./pct.png,40%) 最初は上図のように掴もうとしたが途中で落としたりと安定しなかった。 #ref(./pct2.png,40%) そこで紙コップをアーム全体で覆うようにして掴んでみたところ、上手くいった。接地点が多いほうが上手く力が伝わるのだと思う。また偶然ではあったが、このように掴むことによって紙コップが若干浮くことに気が付いた。これを利用して、アームを少しだけ上げなくてもこのまま割りばしの上を通り抜け中のピンポン玉を入れることに成功した。 #ref(./IMG_0328.JPG,15%) 1つのモーターはアームの開閉をもう一つは上げ下げを制御している。 #ref(./pct3.png,40%) 最終的にはこのような形でコップを運んだ。 *プログラム [#ob261d8e] **マスター側プログラム [#scdf797b] ***マクロ [#k2e6065e] #define SPEED 55 #define SPEED_SLOW 45 #define CONN 1 //スレーブの接続番号 #define SIGNAL_CATCH 11 #define SIGNAL_RELEASE 12 #define SIGNAL_UP 13 #define SIGNAL_UP1 14 #define SIGNAL_DOWN 15 ***定義 [#c6ca5ba5] const float diameter = 5.45; //タイヤの直径。NXTのタイヤの直径は約5,45cmのためこの値。 const float track = 10.35; //タイヤのトレッド幅。トレッドとはタイヤの中心間距離。 const float pi = 3.1415; //円周率。 ***関数 [#k6ad5758] void fwdDist(float d) //引数dの分だけ前進する関数 { long angle = d/(diameter*pi)*360.0; //進むのに必要なタイヤの回転角を計算 RotateMotorEx(OUT_BC, SPEED_SLOW, angle, 0, true, true); } void turnAng(long ang) //角度ang度の時計回りの旋回するための関数。 { long angle = track/diameter * ang; //進むのに必要な回転角度を計算。 RotateMotorEx(OUT_BC, SPEED_SLOW, angle, 100, true,true); } int searchDirection(long ang) //現地点を中心として角度ang度の範囲内で回転してコップを探しコップまでの距離を測る。 { long tacho_min; int d_min = 300; long angle = (track/diameter)*ang; turnAng(ang/2); ResetTachoCount(OUT_BC); OnFwdSync(OUT_BC,SPEED_SLOW,-100); while(MotorTachoCount(OUT_B)<=angle){ if(SensorUS(S3)<d_min){ d_min = SensorUS(S3); tacho_min = MotorTachoCount(OUT_B); } } OnFwdSyncEx(OUT_BC,SPEED_SLOW,100,RESET_NONE); until(MotorTachoCount(OUT_B)<=tacho_min || SensorUS(S3)<=d_min); Wait(14); Off(OUT_BC); Wait(500); return d_min; } (配られたプリント引用) ***task main [#y6463f7c] task main() { RotateMotor(OUT_BC,35,315); Wait(1000); RotateMotor(OUT_BC,35,320); Wait(1000); //�,了罐灰奪廚亮蠢阿泙嚢圓� SendRemoteNumber(CONN,MAILBOX1,SIGNAL_CATCH); //スレーブに信号を送りコップを掴む Wait(3000); RotateMotor(OUT_C,55,180); RotateMotor(OUT_B,-55,310); Wait(1000); RotateMotor(OUT_BC,35,260); //右に旋回してから割りばしまで前進 SendRemoteNumber(CONN,MAILBOX1,SIGNAL_UP); //コップを上に持ち上げる Wait(2000); RotateMotor(OUT_C,-55,360); RotateMotor(OUT_BC,55,600); RotateMotor(OUT_B,-55,330); RotateMotor(OUT_C,55,50); RotateMotor(OUT_BC,55,900); //Y地点までコップを運ぶ SendRemoteNumber(CONN,MAILBOX1,SIGNAL_DOWN); //スレーブに信号を送りコップを降ろす Wait(1500); SendRemoteNumber(CONN,MAILBOX1,SIGNAL_RELEASE);//スレーブに信号を送りコップを離す Wait(2000); SendRemoteNumber(CONN,MAILBOX1,SIGNAL_UP); //スレーブに信号を送りアームを上げる Wait(2000); RotateMotor(OUT_BC,-55,100); OnFwd(OUT_B,55); OnFwd(OUT_C,55); Wait(1000); Off(OUT_BC); SetSensorLowspeed(S3); //2個目の紙コップを探しに行く int d = searchDirection(60); if (d > 5){ fwdDist(d-5.0); } } **スレーブ側プログラム [#x0177db3] ***マクロ [#c0e11652] #define SIGNAL_CATCH 11 //コップをキャッチする信号 #define SIGNAL_RELEASE 12 //コップを離す信号 #define SIGNAL_UP 13 //アームを上げる信号 #define SIGNAL_DOWN 15 //アームを下げる信号 ***task main [#s26e8c3d] task main() { int msg; //受け取った値を格納する変数 while(true){ /* MAILBOX1から値を受け取りmsgに格納 */ ReceiveRemoteNumber(MAILBOX1,true,msg); if (msg == SIGNAL_CATCH) { //アームを閉じる OnFwd(OUT_C,40); Wait(800); Off(OUT_C); }else{ if (msg == SIGNAL_RELEASE) { //アームを開ける RotateMotor(OUT_C,-20,38); }else if (msg == SIGNAL_UP) { //アームを上げる RotateMotor(OUT_B,-45,120); }else if (msg == SIGNAL_DOWN) { //アームを降ろす RotateMotor(OUT_B,45,94); } } } *感想 [#qabaf89b] 短い時間の中ロボットの制作に思いのほか時間がかかってしまい、残念ながら3つのコップすべてを運ぶことができなかった。もう少し時間の使い方や役割分担をはっきりとさせておけば、最後までできたのではないかと思い、とても悔しい。しかし一生懸命やったことに変わりはないし、最後まで協力しあえたチームメンバーにすごく感謝したい。