[[2014a/MemberOnly/進行状況]] 目次 #contents #contens *メンバー [#hc4d637b] sugaken sakar yokkun arara *課題の説明 [#yadae02a] &ref(2014a/Member/sugaken/Mission2/2014a-mission2.png,70%); 2台のロボットで紙コップを収集し、同じ番号の書かれている紙コップに重ねる **フィールドの説明 [#e32bb62c] ◦フィールドは課題1で使用した紙を2枚つなぎ合わせる (詳細な図面は課題1を参照のこと)。 ◦図の右半分の黄色い地点には、その数字と同じ数字が書いてある紙コップが置かれている。また左半分のA,B,Cの地点にも1から3までの数字が書かれている紙コップが置かれているが、どのコップをどの地点に置くかは直前にサイコロを振って次のように決める。 *ロボットの説明 [#dbe2e552] **ロボット全体 [#rc54d7e4] &ref(2014a/Member/sugaken/Mission2/IMG_0351[1].jpg,30%); &ref(2014a/Member/sugaken/Mission2/IMG_0352[1].jpg,30%); 今回のロボット今までに培ってきたことをなるべく多く詰め込んだ物にできるように努力しました。 初めに考えていたロボットは、黄色い本体を二つ通信部分が向き合うように縦にならべたものをドライブベースの上に乗せた形でしたが、それだと重くなりすぎてしまいうまくライントレースできないという問題がおきました。なのでパーツをなるべく少なくしさらに小型化できるように考えた結果、写真のようなロボットになりました。黄色い本体の通信部分は直角にしても通信が可能だということが分かったことが大きな小型化を可能にしたと思います。また黄色の本体を固定するのになるべく少ないパーツで行えたことは軽量化できたポイントだと思います。このロボットならしっかりとライントレースもできるようになった。 **ドライブベース [#g19144f7] &ref(2014a/Member/sugaken/Mission2/IMG_0353[1].jpg,30%); 今回のドライブベースは2輪の物にしました。写真からもわかるようにライントレースをするための光センサーをタイヤ近づけたことと、タイヤ同士の距離を短くしたことで正確なライントレースと小回りのきくロボットになったと思います。ちなみに写真の左側に写っている光センサーは紙コップを色で識別するために付けられたものです。このセンサーについての工夫点はなるべくセンサーを前方に出すように取り付けたことです。結果としてセンサーのコードの長さいっぱいまで前に出すことができたので色の識別が安定するようになりました。 **アーム [#u0c65c43] &ref(2014a/Member/sugaken/Mission2/IMG_0354[1].jpg,30%); アームは一方向にギアを回すだけでアームを開いた状態から閉じて持ち上げることまでできる物にしました。講義の中で教授が参考として見せていただいたものをもとに作りました。とてもよいアームができましたがモーターが一つではアームを動かすことができなかったので二つのモーターで動かすことができるようにアームを改良しました。二つのモーターの回転向きをそろえることが結構苦労したことだと思います。 *プログラム [#h8e7d289] 今回は黄色い本体二つのそれぞれに違うプログラムをいれて、通信機能を使って行うことにしました。今回作ったのはAのコップを初めに取りに行って123のどこかに重ねるまでのプログラムを作りました。 **ロボットの動きに関するプログラム [#yd1a53cd] 定義 #define CUPA1 111 #define CUPA2 112 #define CUPA3 113 #define GOFOR 200 #define GOBACK 201 #define ARMUP 202 #define ARMDOWN 203 #define GOA1 121 #define GOA2 122 #define GOA3 123 #define SKIT 45 //トレースのしきい値 #define JUDGE 45 //紙コップ判断のしきい値 #define HIGHPOWER 7 #define LOWPOWER 1 #define set_power_H SetPower(OUT_AC,HIGHPOWER);//速度を速める #define set_power_L SetPower(OUT_AC,LOWPOWER);//速度を落とす #define turn_left1 set_power_L;\ OnFwd(OUT_A); OnRev(OUT_C); //左旋回 #define turn_left0 set_power_L;\ OnFwd(OUT_A); Off(OUT_C); //左折 #define turn_right0 set_power_L;\ OnFwd(OUT_C); Off(OUT_A); //右折 #define turn_right1 set_power_L;\ OnFwd(OUT_C); OnRev(OUT_A); //右旋回 #define go_forward set_power_H; OnFwd(OUT_AC); //直進 #define go_back(s) OnRev(OUT_AC); Wait(s); Off(OUT_AC); //後進s秒間 #define STEP 1 //ライントレースの判断時間 #define noMAX 30 //右に行き過ぎた時、転回の最大回数 #define NOSTEP 200 //右に行き過ぎた時、左に戻るための時間 #define SENDTIME 300ライントレースのサブルーティン sub line_trace(tim) { SetSensor(SENSOR_2, SENSOR_LIGHT); //ライントレース用の光センサー int nonline=0; ClearTimer(1); /*しきい値よりも6低いと左旋回 しきい値よりも3低いと左折 しきい値よりも3高いと右折 しきい値よりも6高いと右旋回するが、 右旋回をしすぎて逆方向に行きそうであれば左旋回して戻る*/ while(Timer(1) <= tim){ if (SENSOR_2 < SKIT-6){ turn_left1; } else if (SENSOR_2 < SKIT-3) { turn_left0; } else if (SENSOR_2 < SKIT+3) { go_forward; } else { if(SENSOR_2 < SKIT+6) { turn_right0; } else { while (nonline < noMAX){ turn_right1; nonline++; } turn_left1; Wait(noMAX*STEP*NOSTEP); } nonline=0; } Wait(STEP); } } メインタスク task main() { SetSensor(SENSOR_3, SENSOR_LIGHT); //紙コップ識別用の光センサー /*下のコースに行ったあとライントレースをしながらA地点に行く 紙コップが黒ければ()CUPA1 紙コップが灰色なら()CUPA2 紙コップが白ければ()CUPA3 というメッセージを送る*/ go_forward; Wait(430); line_trace(800); while(true){ Aから1の場合 if (SENSOR_3 < JUDGE-7){ Off(OUT_AC); ClearTimer(0); ClearMessage(); while((Message() != 1)||(FastTimer(0)<SENDTIME)){ SendMessage(CUPA1); } if(Message() == 1){ //メッセージの通信に成功したらピッと鳴り、失敗したらブーと鳴る PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); } until(Message() == GOFOR); SendMessage(2); OnFwd(OUT_AC); Wait(80); ClearTimer(0); ClearMessage(); while((Message() != 3)||(FastTimer(0)<SENDTIME)){ SendMessage(ARMUP); } if(Message() == 3){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); } ClearMessage(); while(true){ if(Message() == GOA1){ SendMessage(4); OnRev(OUT_AC); Wait(100); turn_left1; Wait(30); OnFwd(OUT_AC); Wait(300); line_trace(); until(SENSOR_3 < JUDGE-7); Off(OUT_AC); go_back(100); ClearTimer(0); ClearMessage(); while((Message() != 5)||(FastTimer(0)<SENDTIME)){ SendMessage(ARMDOWN); } if(Message() == 5){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message() == GOBACK); SendMessage(6); OnFwd(OUT_AC); Wait(80); ClearTimer(0); ClearMessage(); } Aから2の場合 else if(SENSOR_3 < JUDGE-3){ Off(OUT_AC); ClearTimer(0); ClearMessage(); while((Message() != 1)||(FastTimer(0)<SENDTIME)){ SendMessage(CUPA2); } if(Message() == 1){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); } until(Message() == GOFOR); SendMessage(2); OnFwd(OUT_AC); Wait(80); ClearTimer(0); ClearMessage(); while((Message() != 3)||(FastTimer(0)<SENDTIME)){ SendMessage(ARMUP); } if(Message() == 3){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); } ClearMessage(); while(true){ if(Message() == GOA2){ SendMessage(4); line_trace(); until(SENSOR_3 < JUDGE-2); Off(OUT_AC); go_back(100); ClearTimer(0); ClearMessage(); while((Message() != 5)||(FastTimer(0)<SENDTIME)){ SendMessage(ARMDOWN); } if(Message() == 5){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message() == GOBACK); SendMessage(6); OnFwd(OUT_AC); Wait(80); ClearTimer(0); ClearMessage(); } Aから3の場合 else if(SENSOR_3 > JUDGE+5){ Off(OUT_AC); ClearTimer(0); ClearMessage(); while((Message() != 1)||(FastTimer(0)<SENDTIME)){ SendMessage(CUPA3); } if(Message() == 1){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); } until(Message() == GOFOR); SendMessage(2); OnFwd(OUT_AC); Wait(80); ClearTimer(0); ClearMessage(); while((Message() != 3)||(FastTimer(0)<SENDTIME)){ SendMessage(ARMUP); } if(Message() == 3){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); } ClearMessage(); while(true){ if(Message() == GOA3){ SendMessage(4); go_forward; Wait(200); turn_left0; Wait(200); line_trace(); until(SENSOR_3 > JUDGE+6); Off(OUT_AC); go_back(100); ClearTimer(0); ClearMessage(); while((Message() != 5)||(FastTimer(0)<SENDTIME)){ SendMessage(ARMDOWN); } if(Message() == 1){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message() == GOBACK); SendMessage(6); OnFwd(OUT_AC); Wait(80); ClearTimer(0); ClearMessage(); } } } **アームに関するプログラム [#zb0a04e3] #define CUPA1 111 #define CUPA2 112 #define CUPA3 113 #define GOFOR 200 #define GOBACK 201 #define ARMUP 202 #define ARMDOWN 203 #define GOA1 121 #define GOA2 122 #define GOA3 123 #define HIGHPOWER 7 #define LOWPOWER 1 #define CATCHPOWER 4 #define set_power_H SetPower(OUT_AC,HIGHPOWER);// #define set_power_L SetPower(OUT_AC,LOWPOWER); // #define set_power_C SetPower(OUT_B,CATCHPOWER);// #define STEP 1 #define SENDTIME 300 メインタスク task main() { /*CUPA1が送られてきたらコップをとって1の場所へ CUPA2が送られてきたらコップをとって2の場所へ CUPA3が送られてきたらコップをとって3の場所へ*/ ClearMessage(); OnRev(OUT_AC); Wait(1200); Off(OUT_AC); while(true){ Aから1の場合 if(Message() == CUPA1){ SendMessage(1); OnFwd(OUT_AC); Wait(50); ClearTimer(0); ClearMessage(); while((Message() != 2)||(FastTimer(0)<SENDTIME)){ SendMessage(GOFOR); } if(Message() == 2){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMUP); SendMessage(3); OnRev(OUT_AC); Wait(150); ClearTimer(0); ClearMessage(); while((Message() != 4)||(FastTimer(0)<SENDTIME)){ SendMessage(GOA1); } if(Message() == 4){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } until(Message()==ARMDOWN); SendMessage(5); OnFwd(OUT_AC); Wait(150); ClearTimer(0); ClearMessage(); while((Message() != 6)||(FastTimer(0)<SENDTIME)){ SendMessage(GOBACK); } if(Message() == 6){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMUP); SendMessage(7); OnRev(OUT_AC); Wait(150); Aから2の場合 }else if(Message() == CUPA2){ SendMessage(1); OnFwd(OUT_AC); Wait(50); ClearTimer(0); ClearMessage(); while((Message() != 2)||(FastTimer(0)<SENDTIME)){ SendMessage(GOFOR); } if(Message() == 2){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMUP); SendMessage(3); OnRev(OUT_AC); Wait(150); ClearTimer(0); ClearMessage(); while((Message() != 4)||(FastTimer(0)<SENDTIME)){ SendMessage(GOA2); } if(Message() == 4){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } OnRev(OUT_B); Wait(800); } until(Message()==ARMDOWN); SendMessage(5); OnFwd(OUT_AC); Wait(150); ClearTimer(0); ClearMessage(); while((Message() != 6)||(FastTimer(0)<SENDTIME)){ SendMessage(GOBACK); } if(Message() == 6){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMUP); SendMessage(7); OnRev(OUT_AC); Wait(150); Aから3の場合 }if(Message() == CUPA3){ SendMessage(1); OnFwd(OUT_AC); Wait(50); ClearTimer(0); ClearMessage(); while((Message() != 2)||(FastTimer(0)<SENDTIME)){ SendMessage(GOFOR); } if(Message() == 2){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMUP); SendMessage(3); OnRev(OUT_AC); Wait(150); ClearTimer(0); ClearMessage(); while((Message() != 4)||(FastTimer(0)<SENDTIME)){ SendMessage(GOA3); } if(Message() == 4){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMDOWN); SendMessage(5); OnFwd(OUT_AC); Wait(150); ClearTimer(0); ClearMessage(); while((Message() != 6)||(FastTimer(0)<SENDTIME)){ SendMessage(GOBACK); } if(Message() == 6){ PlaySound(SOUND_CLICK); }else{ PlaySound(SOUND_LOW_BEEP); } Wait(50); until(Message()==ARMUP); SendMessage(7); OnRev(OUT_AC); Wait(150); } } まず説明のためにロボットの動きに関するプログラムを「動プ」とし、アームに関するプログラムを「腕プ」とします。 このロボットは初めに動プにしたがってAのコップのところへ行きます。この時腕プにしたがってアームを上げっぱなしで行きます(コップの色を識別するため)コップAについたら色を識別します。(識別は動プで行います)今回は1のコップだとします。識別したら次のような手順でコップを持ち上げて運んで行きコップを重ねます。 動プ 腕プ 停止したのちCUPA1を送信 → CUPA1を受信 ↓ GOFOR受信後に前進 ← GOFOR送信 ↓ ARMUPを送信 → ARMUP受信後、コップを持ち上げる ↓ GOA1受信後、コップ1へ向かう ← GOA1を送信 ↓ 着いたらARMDOWNを送信 → ARMDOWN受信後、アームを下げる ↓ GOBACK受信後、後進 ← GOBACKを送信 Aが2の場合や3の場合でも基本的には上のように通信をしていくようにプログラムを作りました。 *妥協案プログラム [#y069a344] こちらのプログラムは、ライントレースも通信もしない、コップを重ねる事だけに重点をおいたものである そのため、非常にシンプルかつ初歩的なプログラムとなった さらに、Aの位置にあるコップが1番のコップであると仮定された限定的なプログラムである **妥協案の動く方向に関するプログラム [#h906670b] 定義 #define HIGHPOWER 7 //HIGHPOWERの値を7に設定 #define LOWPOWER 1 //LOWPOWERの値を1に設定 #define set_power_H SetPower(OUT_AC,HIGHPOWER);//速度を速める #define set_power_L SetPower(OUT_AC,LOWPOWER);//速度を落とす #define turn_left1(p) set_power_L;\ OnFwd(OUT_A); OnRev(OUT_C); Wait(p); //左旋回 #define turn_left0(q) set_power_L;\ OnFwd(OUT_A); Off(OUT_C); Wait(q); //左折 #define turn_right0(r) set_power_L;\ OnFwd(OUT_C); Off(OUT_A); Wait(r); //右折 #define turn_right1(s) set_power_L;\ OnFwd(OUT_C); OnRev(OUT_A); Wait(s); //右旋回 #define go_forward(t) set_power_H; OnFwd(OUT_AC); Wait(t); //直進 #define go_back(u) OnRev(OUT_AC); Wait(u); Off(OUT_AC); //後進s秒間 メインタスク task main() { turn_right1(165); go_forward(290); turn_left1(140); go_forward(320); turn_left1(120); go_forward(310); turn_left1(30); Off(OUT_AC); Wait(100); go_forward(50); Off(OUT_AC); } 1.スタート地点から右旋回をして真下を向き、Aのコップと横並びになる位置まで前進 2.左旋回をした後、Aの位置のコップに向かって前進 3.2番と3番のコップにぶつからない位置で左旋回をしたあとに前進 4.1番のコップの手前まで来たら、コップの方向を向いて1秒間停止(このときアームを上げる) 5.そのまま0.5秒間前進して(このときアームを下げてコップを重ねる)、停止 **妥協案のアームに関するプログラム [#ve0949bd] 妥協案のプログラムは上記のプログラムがうまくいかなかったので、とりあえずコップをつかんで置きに行く簡単なプログラムを作ろうということで作ったものです。このプログラムはライントレースせずに、時間ですべてを生制御している物です。 定義 #define t1 165 #define t2 290 #define t3 140 #define t4 320 #define t5 120 #define t6 310 #define t7 30 #define UPTIME t1+t2+t3+t4+t5+t6+t7 //ロボットが1番のコップの位置につくまでの時間 メインタスク task main() { Wait(UPTIME); OnFwd(OUT_AC); Wait(150); Off(OUT_AC); OnRev(OUT_AC); Wait(150); Off(OUT_AC); } 1.ロボットが1番のコップの手前まで来るまで待つ 2.アームを上げてAの位置から持ってきたコップをつかむ 3.アームを下げて1番のコップの上にAの位置のコップを重ねる *まとめ [#v2d0a2eb] 今回はロボット製作にしっかりと時間をかけて納得のいくものを作れたと思います。初期に考えていたものより小型化や軽量化するようにパーツを減らしたり、黄色い本体の付け方を工夫できないかと試行錯誤することが楽しかったです。 プログラムは通信がうまくいかずにコップを重ねることができませんでした。プログラムの考え方はよかったと思いますが、タスクの優先順位をつけることが出来なかったことが失敗の原因だと思いました。 ロボコン本番には帰省をしていて参加できませんでしたが、チームのメンバーのがんばりのおかげで6位になることができました。是非上位のチームのプログラムやロボットを見てみたいと思いました。