[[2018a/Member]] #contents *課題3:缶を移動させるロボットの作成 [#w551df8f] 決められた順番で決められた位置に重ねられた缶を移動する。 ~詳細はhttp://yakushi.shinshu-u.ac.jp/robotics/?2018a%2FMission3を参照。 *車体構造 [#bd50123f] 画像のような形にした。上下のRISは常に通信をしながら連携を取る。下のRISは左右車輪を制御しセンサはローテーションセンサと光センサの2つを扱う。上のRISはアームの上下とつかむ動作を制御しセンサはタッチセンサを扱う。 &ref(2018a/Member/kan777/Mission3/3_1.jpg,20%,車体全体); &ref(2018a/Member/kan777/Mission3/3_6.jpg,20%,車体全体2); **車輪 [#a6a3e9dd] 課題2と同じく2輪駆動にし、前輪をなくした。課題2と同じ形で滑らせるようにしたが今回は後ろ側も同じものを用意した。 &ref(2018a/Member/kan777/Mission3/3_2.jpg,20%,タイヤの構造); **光センサ [#k2f13bbf] センサは前輪(滑らせるところ)の少し手前の内側に2つ付けた。余っていたため精度を上げるためにも2つ付けた。 &ref(2018a/Member/kan777/Mission3/3_3.jpg,20%,センサの位置); **ローテーションセンサ [#h8a04682] ローテーションセンサは移動の距離や回転した角度を正確に測るためにタイヤにつけた。(左タイヤAと右タイヤCの二輪駆動だが1つのみなのでAのみについている。) **アーム [#o42dd092] アームの機構は課題2のクワガタのような機構を改良してしっかりとつかめるように下に拡張した。また力がかかると滑るギアを用いることで常にしめ続けられるようにして課題2のように缶が途中で離れてしまうことがないようにした。 ~アームの上下機構にはRIS特有のギアを用いた。 &ref(2018a/Member/kan777/Mission3/3_4.jpg,20%,アーム); **タッチセンサ [#s02349fe] 缶にあたったことを検知するためにタッチセンサを用いた。光りセンサを使おうとしたが外部の光で大きく値が変わってしまい調整が大変だったのでやめた。タッチセンサは画像のようにして支点とと力点を大きく話すことで軽い力で反応するようにした。また、プログラム内でも軽い力で反応するようにBOOLではなくRAWを用いた。 ~軽い力で反応するように工夫はしたがそれでも当たった時に倒れてしまうのでなるべく缶の下のほうに触るようにした。 &ref(2018a/Member/kan777/Mission3/3_5.jpg,20%,タッチセンサ); **車体考察 [#jcba4b4f] -課題2でも二輪駆動にしたがタイヤが滑ってしまう問題があった。今回は首を振るような細かい動きをしなかったので出力を下げることで対応できた。 -前回の反省点を生かしアームの機構を改良することができた。余らせてしまっていたギアも有効活用できた。 -アームの機構、タッチセンサなどあらゆる面において反省点を生かし工夫することができた。強度の面においても格段に向上した。 -全体的なバランスも良く安定した動作ができた。 *プログラム [#k6f8c1d3] **上のRISのプログラム(アーム) [#d35b023d] //上段ris sendは100番代 #define TOJIRU Wait(50);OnFwd(OUT_A);Wait(100); #define HIRAKU Wait(50);OnRev(OUT_A);Wait(30);Off(OUT_A); #define THR 1000 //缶に接近を検知するセンサのしきい値(標準1024だが24減るだけですぐに反応するようにした。 task main(){ SetSensor(SENSOR_3,SENSOR_TOUCH); SetSensorMode(SENSOR_3,SENSOR_MODE_RAW); SetPower(OUT_A,7); SetPower(OUT_C,7); ClearMessage(); SendMessage(1); //三段目Aの缶 until(201==Message()); //移動終了を受信したらアームを開きアームを移動 ageru(1); //3段目の位置までアームを移動 HIRAKU SendMessage(101); //左に90度 前進させる until(THR>SENSOR_3); //缶に接近したら SendMessage(100); //缶に接近したメッセージ TOJIRU //つかむ ageru(10); //少し上げる SendMessage(102); //少し下がって右に90度 until(202==Message()); //終了を受信1段目の高さまで下す orosu(1); SendMessage(103); //右に90度 until(203==Message()); //終了を受信 はなす HIRAKU SendMessage(104); //少し下がらせる //二段目Aの缶 until(201==Message()); //おいて左に90度行った後 ageru(2); //アームを2段目の高さに HIRAKU SendMessage(101); //左に90度 前進させる until(THR>SENSOR_3); //缶に接近したら SendMessage(100); //缶に接近したメッセージ TOJIRU ageru(10); //少し上げる SendMessage(102); //左に90度 until(202==Message()); orosu(2); //アームを1の高さにおろして SendMessage(103); //右に90度でAにある缶をどかす until(203==Message()); HIRAKU } void ageru(int a){ OnFwd(OUT_C); switch (a){ case 1: Wait(320);//1から3段目の時間 270-300の間 9.1Vで320 break; case 2: Wait(130);//1から2へ 110-130 9.1Vで130 break; case 10: Wait(55);//ちょっと上げる時間 30-50 9.1Vで50 break; } Off(OUT_C); } void orosu(int b){ OnRev(OUT_C); switch (b){ case 1: Wait(200);//3から1段目の時間 170-200 9.1Vで190 break; case 2: //2から1段目へ 60-90 9.1Vで70 Wait(80); break; case 3: Wait(60);//2から1.5へ 40-60 9.1Vで60 break; case 20: Wait(20);//ちょっと下げる時間 20-50 9.1Vで40 break; } Off(OUT_C); Wait(100); } **下のRISのプログラム(タイヤ) [#wd871573] //下段ris sendは200番代 #define TURNL Wait(80);OnFwd(OUT_C);OnRev(OUT_A);ClearSensor(SENSOR_2);until(SENSOR_2>=41);Off(OUT_AC); //40で曲がり過ぎるときがある #define TURNR Wait(80);OnFwd(OUT_A);OnRev(OUT_C);ClearSensor(SENSOR_2);until(SENSOR_2<=-41);Off(OUT_AC); #define FOR Wait(80);OnFwd(OUT_AC);ClearSensor(SENSOR_2);until(SENSOR_2<=-23);Off(OUT_AC); //缶を置くときに少し前に進む #define BACK Wait(80);OnRev(OUT_AC);ClearSensor(SENSOR_2);until(SENSOR_2>=23);Off(OUT_AC); //缶を置くときに少し前に進んだ分戻る #define FCAN Wait(80);OnFwd(OUT_AC);ClearTimer(0);until(100==Message());Off(OUT_AC);time=Timer(0)*10; //接近の知らせを受けるまで前進 その時間をtimeに記録 int time; int time;//define FCANで使用 task main(){//下のRIS用、移動と回転 SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensor(SENSOR_2,SENSOR_ROTATION); SetSensor(SENSOR_3,SENSOR_LIGHT); SetSensorMode(SENSOR_1,SENSOR_MODE_RAW); SetSensorMode(SENSOR_3,SENSOR_MODE_RAW); SetPower(OUT_A,2); SetPower(OUT_C,2); ClearMessage(); until(1==Message()); //移動開始 //53センチ前進 OnFwd(OUT_AC); ClearSensor(SENSOR_2); until(SENSOR_2<=-165); Off(OUT_AC); TURNL //左に90度旋回 //真ん中まで前進 OnFwd(OUT_AC); Wait(180); until(SENSOR_1>777||SENSOR_3>777);//中央の黒い十字ラインを読んで止まる Wait(10); Off(OUT_AC); //移動終わり PlaySound(SOUND_DOUBLE_BEEP); Wait(100); //三段目Aの缶Bの1段目に(この時Bにある缶を全部倒す) SendMessage(201); until(101==Message()); TURNL //左に向く(A位置に向く) Wait(50); FCAN //缶を見つけるまで前進 until(102==Message()); OnRev(OUT_AC); //見つけるまで進んだ分戻る Wait(time); Off(OUT_AC); TURNR //右に向く SendMessage(202); //1段目の高さにおろす until(103==Message()); Wait(80); TURNR //右に向きBの缶を倒す OnFwd(OUT_A);OnRev(OUT_C);ClearSensor(SENSOR_2);until(SENSOR_2<=-5);Off(OUT_AC);//ずれを調整 FOR SendMessage(203); //缶を置く until(104==Message()); BACK //2段目Aの缶をAの1段目へ(この時Aの1段目の缶を押してどかす) TURNL //左に向く SendMessage(201); //アームを開けて2段目へ until(101==Message()); //終了を受信 TURNL //左に向く FCAN //缶まで前進 until(102==Message()); //掴み終わったら TURNL //左に向く SendMessage(202); //1段目の高さに卸させる until(103==Message()); //終了を受信 TURNR //右に向いてAの一段目缶を押しのける BACK BACK SendMessage(203); //置かせる } **プログラム説明 [#cd9df6dd] 当初は以下の戦略を実行するつもりだった。プログラムも完成しているが量が多くなるので割愛する。やめた理由としては、90度回転するのが少しずれていると何度も繰り返すうちにずれてしまってうまくいかなかったからである。前日に実験した時にはD地点に2段の缶を作り移動するというところまでは成功した。(C地点についてはうまくいかなかった。) プログラムは長くなるので割愛するが以下当初の予定の説明のみのせる。 プログラムは長くなるので割愛するが以下に当初の予定の説明のみのせる。 &ref(2018a/Member/kan777/Mission3/map.png,50%,map); ~説明上、上のマップのようにG地点の上の位置をCとしG地点の下の位置をDとする。 ~また、わかりづらかったのでY地点をAとしてX地点をBとしてある。 プログラムの流れは +直進し左折して中心まで移動する +A地点3段目からC地点1段目へ缶を移動 +B地点3段目からD地点1段目へ缶を移動 +A地点2段目からD地点2段目へ缶を移動 +D地点の缶をA地点へ移動(この時A地点にある缶は無視して押しのける) +B地点2段目からC地点2段目へ缶を移動 +C地点の缶をB地点へ移動(この時B地点にある缶は無視して押しのける) +終了 ~となっていた。 -今回実際に使ったプログラムはこれの一部を取り出し少し変えて確実に6点を取りに行くものにした。 以下、実際に今回使ったプログラムについて説明する。 +直進し左折して中心まで移動する +A地点3段目からB地点1段目へ缶を移動 +A地点2段目からA地点1段目へ缶を移動 ~となっている。 ~とても短いプログラムにして誤差を減らした。 それでも、誤差はあったのでプログラム内コメントにあるように時間で制御しているところは特にテストを繰り返し実測値を集め直前で最適な値をすぐに見つけられるようにした。 -タッチセンサは少しの力で反応するようにRAWを用いた。 -いろいろなところ(特にタイヤの動作転換するところ)にWaitを挟むことで誤差を減らそうと試みた。 -ローテーションセンサの誤差を減らすためなるべくゆっくり動くようにタイヤの力は2にした。 -逆にアーム関連は緩まないようにフルパワーにした。 ***Defineの説明。 [#m3f8cb86] -TOJIRU アームを閉じる -HIRAKU アームを開く -TURNL ローテーションセンサーを用いてちょうど90度左に曲がる -TURNR ローテーションセンサーを用いてちょうど90度右に曲がる -FOR 缶を置くときにすこし前に進む -BACK FORの分戻る -FCAN 缶を見つけるまで前進する。上段risからタッチセンサに反応があったという知らせを受けるまで前進し続ける。(反応があった知らせはすべて100番のメッセージを送っている) また、変数timeに見つけるまでにかかった時間を記録することでそれを逆再生すれば元の位置に戻れるようにした。 ***サブルーチンの説明。 [#u933b2ca] -ageru アームを上げるサブルーチン なんの動作なのかわかりやすくするために用意した。当初の予定があった都合上使っていないものも入っている。 与えられた値に応じた動作をする。 具体的には、 ~1が1から3段目に上げる動作 ~2が1から2段目に上げる動作 ~10がつかんだ後に少し浮かせるために上げる動作 ~となっている。 -orosu ageru()の逆のアームを下げるサブルーチン 具体的には、 ~1が3から1段目に下げる動作 ~2が2から1段目に下げる動作 ~10がおろすときにしっかりと置くように下げる動作 ~となっている。 **プログラム考察 [#i8afa142] -メッセージを多用することでながれが分かりにくくなることが懸念されたが、あえて同じ動作をなんども繰り返し書くことで流れを追っていけるようなプログラムを書くことができた。 -タイヤのずれなどいろいろな問題があり調整がすごい大変になりそうだったが、サブルーチンを活用して調整しなければいけないところをプログラム内でまとめることで調整がしやすかった。ローテーションセンサがあったことで多少は調整する量を減らせた。 -協力、分担してやらなければならない課題だったので調整すべきパーツをサブルーチンで分けた。 -確実に点を取りに行くプログラムにしたためとても短くシンプルなものとなった。車体に左右される部分が多く設計の重要性を感じた。 -タイヤにローテーションセンサを用いたことで光センサの仕事があまりなかったが余っている貴重なセンサ類を活用することはできた。 -車体構造的な問題や場所が変わるため外部からの光による誤差問題で厳しく断念したがアームに光りセンサを複数付ければうまく缶を見つけられそうだと感じた。 *全体を通して [#i460de7d] -何度やっても違う動作をしたりさっきまでうまくいっていたのに些細なことでうまくいかなくなったりととても大変だった。プログラムの言うものが無意味に感じた。しかし、今回の課題3ではローテーションセンサを使ったことで電圧による誤差はあったものの制度が格段に向上し「制御」することができた。 -課題3までの課題2や課題1の反省点をしっかりと生かし反映することができたと思う。 -微調整に追われプログラムが汚くなってしまったが、微調整だらけのプログラムにしてはきれいにまとまっていると思う。 -課題1課題2ともに満足のいく結果ではなかったので最後にうまく動作させることができてよかった。 -課題3が終わるまでに8.6V程度で電池を毎回交換していたら80本以上もの電池を使ってしまった。最近のデバイスは精度だけでなく省電力面においても優れているのだなと思った。 -調整に追われ金土日と丸3日使ったが終わらず、日曜日から疑似ロボコン当日の月曜の朝5時まで作業が続いて大変だった。センサ類の重要性やアクチュエータの不確定さを身をもって実感した。 -