[[2019a/Member]] #contents *課題3:ボール運搬ロボット [#w05fb60a] ピンポン玉または青と赤のボールを運搬して、所定の容器の中に入れる。 #ref(2019a/Member/www/Mission3/ko-su'.jpg,40%) **フィールドの説明 [#i12fef37] -フィールドは課題2で使用した紙を使用する。 -生協のお弁当の四角いプラ容器2つをそれぞれ円内に置き、片方に玉を2個入れる。 -残りの2個の玉は課題2と同じ位置に置く。その際、ゴムタイヤやプレートの上に置いてもよい。 -プラ容器には色をつけたり文字や記号を書いてもよい。 -プラ容器は両面テープ等でフィールドに固定してもよい。 -2枚の紙の境界にはそれぞれ幅1cm、合計2cmの黒線を描いてもよい。 **ルール [#p6d1295d] -競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。 -図のA地点または(および)A'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。 -開始の合図から5秒以内にスタートボタンを押す作業を完了すること。 -競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。 -途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 -競技終了後、ロボットが、ゴールのプラ容器に触れていてはいけない。 -競技終了後、もともと玉が入っていたプラ容器が、ゴールのプラ容器に触れていてはいけない。 ルールについて詳しくは[[こちら>2019a/Mission3]]。 *ロボットの説明 [#ibcf3892] ロボットの全体像は下の写真である。前は黄色いパーツがついているほうで、RISが乗っているほうが後ろだ。 #ref(2019a/Member/www/Mission3/zentai.jpg,50%) ロボットはアームと足回りの2つの部分に分けられる。以下でそれぞれについて説明する。 **アームの説明 [#ebc42135] ***1.シーソー部分 [#t49d56da] アーム部分が重たいため、パワーを出すために6枚のギアを使用した。 &ref(2019a/Member/www/Mission3/udegia'.jpg,60%); &ref(2019a/Member/www/Mission3/udegia_zu.jpg,40%); ***2.ピンポン球をキャッチする部分 [#tc4c2348] アームの前と後ろの重さのバランスをとるために後ろにモーターを取り付けた。 #ref(2019a/Member/www/Mission3/kyatti'.jpg,60%) 後ろから動力を持ってくるために2か所で歯車を直角につけて、回転方向を変化させている。~ &ref(2019a/Member/www/Mission3/tenogia.jpg,60%); &ref(2019a/Member/www/Mission3/tenogia''.jpg,60%); また、下の写真のように歯車を取り付けて、パワーが出るようにした。 #ref(2019a/Member/www/Mission3/tenogia'.jpg,60%) 下の写真の ↓ は、ピンポン玉が逃げないようにするためのものだ。 #ref(2019a/Member/www/Mission3/otete.jpg,60%) ***3.ベルトコンベア部分 [#fb0c816f] ピンポン玉を拾った後、機体の上部にピンポン玉を乗せる役割をする。 #ref(2019a/Member/www/Mission3/konbea.jpg,60%) ピンポン玉をコンベアで奥に送り、最大3つまで収納できるようになっている。 #ref(2019a/Member/www/Mission3/syunou.jpg,60%) 下の画像の ↓ の部分でコンベアをピンポン玉に押し付け、ピンポン玉が途中で止まることを防止した。 #ref(2019a/Member/www/Mission3/sutoppaa.jpg,60%) ベルトコンベアは片方が回転すればピンポン玉が収納できるので、片方のみ回転する。~ コンベアを回転させるためのギアは、下の写真のように取り付けた。 #ref(2019a/Member/www/Mission3/konbea1.jpg,60%) **足まわりの説明 [#qa382d2f] #ref(2019a/Member/www/Mission3/risokiba''.jpg,70%) 上の写真のようにタイヤの上にRISを2台並べておいた。 赤外線送受信部をくっつけて通信を行えるようにした。 裏側 #ref(2019a/Member/www/Mission3/ashiura''.jpg,60%) 課題2と同様、タイヤは全部で3輪で、前輪2つが駆動輪、後輪1つは摩擦を減らすために、ゴムを外したホイールのみを取り付けた。~ 光センサーは、タイヤの中心に近いところに取り付けた。 *経路の説明 [#a6325bd5] 車体が重たく、ガタガタ揺れると壊れそうだったので、極力ライントレースをしないように経路を考えた。 **1つ目のピンポン玉を入れるまでの経路 [#l050ad9c] #ref(2019a/Member/www/Mission3/michi1.jpg,30%) スタートしてから2本の黒い線を横切って、3本目の黒い線を認識したら、ライントレースを開始する。~ 上の図にあるようにしばらく進んだら、ピンポン玉を取り、その場で90度回転してピンポン玉をリリパックの中に入れる。 **2つ目のピンポン玉を取るまでの経路 [#idf09ed4] #ref(2019a/Member/www/Mission3/michi2.jpg,30%) 少し下がった後に90度回転し、リリパックに当たらないように移動した。~ 3本の黒い線を横切り、ここでもリリパックに当たらないよう、斜めに移動。~ 4本目の黒い線を横切った後、ライントレースを開始し、ピンポン玉をつかむ。 **リリパックの中のピンポン玉を取るまでの経路 [#z3e7b023] #ref(2019a/Member/www/Mission3/michi3.jpg,30%) アームがリリパックの端に引っ掛かり、ピンポン玉がとれなくなることを防止するため、90度回転した後、少し下がってから、ピンポン玉をつかむようにした。 **3つのピンポン玉を入れるまでの経路 [#b356303a] #ref(2019a/Member/www/Mission3/michi4.jpg,30%) さらに下がり、90度回転する。~ 2本目の黒い線で停止、少し前進してリリパックにピンピン玉を入れる。 *プログラムの説明 [#s935091c] **共通するプログラム [#k04979a2] 2台のRISで通信を行うために、以下のようにマクロを定義をした。 #define signal_catch 1 #define signal_release 2 #define signal_end 3 **アームのプログラム [#p5ab606a] ***サブルーチン [#pf8a95cb] -ピンポン玉を取る untilを最初に書き入れることで、信号を受信してから動くようにした。 sub CATCH() { ClearMessage(); until(Message()==signal_catch); OnFwd(OUT_B);Wait(30);Off(OUT_B);Wait(100);// 下がる SetPower(OUT_A,2); OnRev(OUT_A);Wait(90);Off(OUT_A);Wait(100);// 掴む OnRev(OUT_B);Wait(50);Off(OUT_B);Wait(100);// 上がる OnFwd(OUT_A);Wait(90);Off(OUT_A);Wait(100);// 手を元に戻す OnFwd(OUT_C);Wait(200);Off(OUT_C);Wait(100);// 奥へ送る SendMessage(signal_end); } -ピンポン玉をリリパックに入れる sub release() { ClearMessage(); until(Message()==signal_release); OnFwd(OUT_B);Wait(30);Off(OUT_B);Wait(100);// 下がる OnRev(OUT_C);Wait(200);Off(OUT_C);Wait(100);// 前へ送る OnRev(OUT_B);Wait(50);Off(OUT_B);Wait(100);// 上がる SendMessage(signal_end); } ***メインプログラム [#ge4f37c2] アームのメインプログラムは以下の通り。 task main() { ClearMessage(); CATCH(); //L'のピンポン玉を取る release(); //リリパックに入れる CATCH(); //Lのピンポン玉を取る CATCH(); //リリパック内のピンポン玉を取る(1個目) CATCH(); //リリパック内のピンポン玉を取る(2個目) ClearMessage(); //(*) until(Message()==signal_release); OnFwd(OUT_B);Wait(30);Off(OUT_B);Wait(100); //アームを下げる OnRev(OUT_C);Wait(200);Off(OUT_C);Wait(100); //ピンポン玉を前へ送る OnRev(OUT_BC);Wait(50);Off(OUT_BC);Wait(100); //アームを上げながらピンポン玉を送る SendMessage(signal_end); } (*)以下のプログラムは基本的にはサブルーチンの release() と同じだが、アームを上げる際にもコンベアを動かしている。一番最後は複数のピンポン玉をリリパック内に入れる必要があるが、release() だとピンポン玉が全部箱に入る前に、動作が終わってしまう。また、先に入ったピンポン玉に邪魔をされてピンポン玉が全部出ないという問題を解決するためにアームを上げながらコンベアを動かすようにした。 **足回りのプログラム [#q4126503] ***マクロ・グローバル変数 [#fdbdfa50] -光センサーの値 #define black 40 //真っ黒 #define gray_black 44 //黒 #define gray 47 //灰 #define gray_white 50 //白 #define white 60 //真っ白 -基本的な動作 #define go_ahead OnFwd(OUT_AC); //前に進む #define turn_left OnFwd(OUT_A);Off(OUT_C); //左に曲がる #define turn_right OnFwd(OUT_C);Off(OUT_A); //右に曲がる #define circling_left OnRev(OUT_C);OnFwd(OUT_A); //左旋回する #define circling_right OnRev(OUT_A);OnFwd(OUT_C); //右旋回する -グローバル変数 int t; ***サブルーチン [#yf71ea61] 下にライントレースに使用したサブルーチンを示す。 sub follow_line()// 右側トレース時間 { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); while(FastTimer(0)<t){ if(SENSOR_2<black){circling_right;} //真っ黒なら右旋回せよ else if(SENSOR_2<gray_black){turn_right;} //黒なら右に曲がれ else if(SENSOR_2<gray){go_ahead;} //灰なら直進せよ else if(SENSOR_2<gray_white){turn_left;} //白なら左に曲がれ else if(SENSOR_2<white){circling_left;} //真っ白なら右旋回せよ } Off(OUT_AC);Wait(100); //1秒止まれ } コース取りの関係上交差点認識をする必要がないため、グローバル変数tを使って指定した秒数だけ動いて止まるようにしている。 ***メインプログラム [#p926cb48] 以下が足のメインプログラムである。 task main() { ClearMessage(); // A'スタート while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); //白なら進む while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); //黒なら進む while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); t=90;follow_line();//調整 Wait(100); SendMessage(signal_catch); // L'のピンポン玉を掴む命令を送る ClearMessage(); until(Message()==signal_end); circling_left;Wait(102);Off(OUT_AC); //左に90°旋回 SendMessage(signal_release); // 1つ目のピンポン玉を箱に入れる命令を送る ClearMessage(); until(Message()==signal_end); OnRev(OUT_AC);Wait(30);Off(OUT_AC); //後ろに下がる circling_left;Wait(102);Off(OUT_AC); //左に90°旋回 while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); //白なら進む while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); //黒なら進む while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); turn_right;Wait(100); //右に曲がる while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); //白なら進む while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); //黒なら進む t=150;follow_line();//調整 SendMessage(signal_catch);// Lのピンポン玉を掴む命令を送る ClearMessage(); until(Message()==signal_end); circling_left;Wait(102);Off(OUT_AC); //左に90°旋回 OnRev(OUT_AC);Wait(23);Off(OUT_AC); //後ろに下がる SendMessage(signal_catch); //リリパックの中のボールを掴む(1個目) ClearMessage(); until(Message()==signal_end); Wait(100); SendMessage(signal_catch); //リリパックの中のボールを掴む(2個目) ClearMessage(); until(Message()==signal_end); OnRev(OUT_AC);Wait(90);Off(OUT_AC); //後ろに下がる circling_left;Wait(102);Off(OUT_AC); //左に90°旋回 while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100);//白なら進む while(SENSOR_2<gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100);//黒なら進む while(SENSOR_2>gray){OnFwd(OUT_AC);}Off(OUT_AC);Wait(100); go_ahead;Wait(15);Off(OUT_AC); //前に進む SendMessage(signal_release); ClearMessage(); until(Message()==signal_end); OnRev(OUT_AC);Wait(100);Off(OUT_AC); //リリパックから離れるために少し後ろに下がる } *反省・感想 [#tb6dfd41]