2014a/Member 目次
yokkun
sakar
sugaken
arara
2台のロボットで紙コップを収集し、同じ番号の書かれている紙コップに重ねる フィールドの説明◦フィールドは課題1で使用した紙を2枚つなぎ合わせる (詳細な図面は課題1を参照のこと)。
◦図の右半分の黄色い地点には、その数字と同じ数字が書いてある紙コップが置かれている。 また左半分のA,B,Cの地点にも1から3までの数字が書かれている紙コップが置かれているが、 どのコップをどの地点に置くかは直前にサイコロを振って決める。
基本ルール
◦競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
◦図の右上のスタートエリアからスタートする(課題1と同じ)。接地している部分がスタートエリア内に入って入ればよい。
◦図の左半分にある紙コップを集めて、それぞれ右半分にある同じ番号の紙コップに重ねる。
◦右半分の紙コップは10cm内の移動は認める
◦開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
◦競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
◦途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 :基本得点の計算方法
◦同じ番号の紙コップに重ねることができれば、1組で10点
◦番号が1違いの紙コップに重ねれば、1組で2点
◦番号が2違いの紙コップに重ねれば、1組で0点
◦最終的な紙コップの位置が10cm以上動いた場合は、その1組の点数を半分にする 技術点の計算方法以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチームが20点満点で採点し、その平均点を求める。 得点の目安: ◦紙コップを取りにいくまでの動作 (2点)
◦紙コップを掴む動作 (4点)
◦紙コップをを運ぶ動作(3点)
◦紙コップを重ねる動作(4点)
◦2台のRCXまたはNXTの連携の良さ(3点)
◦自立型のロボットとしての形や動作の美しさ、斬新さ(2点)
◦その他 (2点)
ドライブベースは最初本体二つが通信しやすいように平行に横に並べていたがそれだとトラックみたいにとても大きなドライブベースになってしまい曲がらなかったり前に進まなかったりライントレースをしなかったりしたのでコンパクトにするために本体二つを直角につなげることによりロボットがスムーズに動いてくれたし、通信もしっかりしてくれたので本体を二つにつなげるドライブベースにしました。
センサーはライントレースをするセンサーはドライブベースが重いのでミスが減るようにドライブベースのすぐ近くにつけた。紙コップを感知するセンサーはアームがでかくて感知し間違えることがあったのでなるべくロボットの前につけた。
アームは一度に挟んで持ち上げることのできるアームにしました。構造としては最初アームが閉じるようにモーターが回りアームが閉じると閉じるためのギアが回らなくなりアームが上がるようにギアが回る仕組みとなっている。また最初は一つのモーターで動かしていたがアームが紙コップを持つ場所であったりバッテリーの減少などにより紙コップを持ち上げることができなくなることがあったのでモーターを二つでアームを稼働させることにより毎回安定して紙コップを持ち上げることができた。
Aにとりに行ってそこにおいてあったコップが1,2,3のどれなのかを識別してそれをもうひとつの紙コップの場所に運び積み重ねるというプログラムにしました。自分たちは通信してアームと本体が連動して動くようにしました。
定義
#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
・ライントレースのサブルーティン
課題1で三段階に分けてうまくいかなかったので五段階にしました。
sub line_trace(tim) { SetSensor(SENSOR_2, SENSOR_LIGHT); //ライントレース用の光センサー int nonline=0; ClearTimer(1); while(Timer(1) <= tim){ if (SENSOR_2 < SKIT-6){ turn_left1; } else if (SENSOR_2 < SKIT-3) { //しきい値よりも6低いと左旋回 turn_left0; //しきい値よりも3低いと左折 } else if (SENSOR_2 < SKIT+3) { //しきい値よりも3高いと右折 go_forward; //しきい値よりも6高いと右旋回するが、 } 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); //紙コップ識別用の光センサー go_forward; //4.3秒前に進む Wait(430); line_trace(800); //ライントレースを8秒行う 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); //8秒前に進む 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); //1秒後ろに下がる Wait(100); turn_left1; //3秒左に旋回 Wait(30); OnFwd(OUT_AC); //3秒前進 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); //8秒前進 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); //8秒前進 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); //8秒前進 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); //8秒前進 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; //2秒前進 Wait(200); turn_left0; //2秒左折 Wait(200); line_trace(); //ライントレース until(SENSOR_3 > JUDGE+6); Off(OUT_AC); //停止 go_back(100); //1秒下がる 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); //8秒前進 Wait(80); ClearTimer(0); ClearMessage(); } } }
・アームに関するプログラム 定義
#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() { 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); } }
・ドライブベースが最初通信を一番しやすいように組み立てたらとてもでかくなってしまい、スムーズに動かなくなったので本体を直角につけてコンパクトにした。
・センサーの位置を変えた。ライントレースをするセンサーはライントレースがスムーズにできるようにドライブベースになるべく近づけて、紙コップを識別するセンサーはアームが大がかりなものになってしまったためになかなかセンサーが感知しなかったのでコードがギリギリ届くところまでセンサーを前につけた。
・途中で軽さを重視しすぎて最小限のブロックで作ったらアームが紙コップを上げる際やライントレースをする際の左右運動をする際にこわけてしまったりしたので最小限のブロックで頑丈になるようにした。
・ドライブベースの重心が後ろにあることによりあえて二輪にして後ろは最初なめらかなブロックをつけていたが逆にそこ一点に重さが集中して地面にたいする圧力が大きくなってしまったのであえて平らで広いただのブロックだけにすることで圧力が分散してスムーズに動いた。
・アームのモーターはもともと一つであったが紙コップをつかむ場所のずれやバッテリーの減少などが原因であがったりあがらなかったりと安定しなかったのでモーターを二つつけた。
・本体の二つがしっかり通信するようにどちらも表を向けて直角につけた。
・ライントレースでカーブの時に安定するように値の違いを五段階に分けた。
・アーム一つで紙コップをキャッチして上げることができるアームを作ったことにより紙コップが安定してつかめ移動できるようになった。
・アームはもともと左右どちらとも先っぽにタイヤをつけていたが右側だけを棒をたしてながくすることにより多少ずれてもその棒が紙コップをひっかけてくれて安定してキャッチできた。
・最初の練習段階では本体二つがしっかり通信してくれていたがちゃんとしたプログラムを入れるとうまく通信してくれなかった。その考えられる原因として第一にプログラムを一行書くごとにちゃんと作動するか確認しなかったからであると思う。そのためにどこまで正常にうごいているか間に音を鳴らして確認すればちゃんとしたプログラムができたと思う。
・ドライブベースに関してもう少し工夫してアームの乗せる位置やアームの部品を考えればモーターを二つも使わなくても一つでいけたかもしれない。
プログラムはとても難しいものだと思った。一つでも間違っているとエラーが出てしまったりちゃんと作動してくれないのでとても繊細だと思った。けれどこの授業を通してプログラムの基礎がわかり、少しプログラムというものに興味をもつことができた。
今後この授業のおかげでプログラムをやってない人よりかは一歩リードできているのでこの授業を糧にプログラムもしっかりがんばっていきたい。