[[2013b/Member]]~ ~ jogio氏、dtb氏、wei氏とのグループで作業を行った。 ~ *ロボット [#v9b0bb2d] まずはロボットの全体像をご覧いただきたい。~ 駆動部としては安定感を狙ってキャタピラを使用した。~ &ref(2013b/Member/bs/Mission2/robo.jpg);~ ~ RCXは車体後部に2個を縦に並べて積んでいる。~ 2個のRCXの間は、PCからプログラムを送信する時のために少し空間が設けてある(緑で囲われた部分)。~ &ref(2013b/Member/bs/Mission2/basea.jpg);~ **缶に関する機構 [#v925a08b] このロボットにおける缶を収集・運搬する物理的機構のすべては、写真の赤で囲われた部分に集中している。~ &ref(2013b/Member/bs/Mission2/robo.jpg);~ すなわち、モーター部(下の写真)と、本体のモーター受けである。~ &ref(2013b/Member/bs/Mission2/mortor.jpeg);~ モーター部のハサミによって缶をつかみ、モーター部ごと上昇して缶を持ち上げる。~ **センサ [#x2813402] このロボットは3個の光センサを搭載している。~ うち2個はライントレース用(赤で囲われた部分)、残り1個は缶探知用(黄で囲われた部分)である。~ &ref(2013b/Member/bs/Mission2/sens1a.jpg);~ ~ 上から見た図~ &ref(2013b/Member/bs/Mission2/sensor2a.jpg);~ *プログラム [#pefc0b4d] プログラムの方針と共にdtb氏作のソースコードを掲載する。掲載に際して、改行等において若干の変更を行った。~ プログラムの方針と共にdtb氏作のソースコードを掲載する。掲載に際して、改行の変更、コメントの加筆修正などを行った。~ なお、これらのプログラムは未完成であるため方針通り正常に動作することはないが、参考として掲載する。~ **本体のプログラム [#o51dd8fb] 本体(モーター部でない部分)は、ライントレースと、缶を発見しその時々に応じた命令をモーター部を制御するRCXへ送る作業を担当する。~ ライントレースは、コースを9つの部分として扱う(下図の丸数字)。缶を6つ拾う(その順番は缶の近くにあるローマ数字)~ &ref(2013b/Member/bs/Mission2/robocon2013be.png,80%);~ #define left_kuro 28 //左側の光センサが黒とみなす最大の値 #define right_kuro 34 //右側の光センサが黒とみなす最大の値 #define left_sen 38 //右側の光センサが線上とみなす値 #define right_sen 43 //左側の光センサ線上とみなす値 #define sekkin 40 //缶が接近したときの値 #define HIPOWER 7 //強い力 #define LOWPOWER 5 //弱い力 #define set_power_H SetPower(OUT_AC,HIPOWER); //モーターを強い力に設定 #define set_power_L SetPower(OUT_AC,LOWPOWER); //モーターを弱い力に設定 #define senkai_left set_power_L;OnRev(OUT_A);OnFwd(OUT_C); //左旋回 #define senkai_right set_power_L;OnRev(OUT_C);OnFwd(OUT_A); //右旋回 #define go_forward set_power_H;OnFwd(OUT_AC); //前進 #define back set_power_L;OnRev(OUT_AC); //後退 #define CROSS(t,p,q) set_power_L;go_forward;Wait(t);senkai_left;Wait(p);senkai_left;Wait(q); //T字路や交差点を渡る時のプログラム #define STEP 1 //ライントレースで判断された動作を0.01秒間続ける。 #define STEP 1 //ライントレースで判断された動作を10ミリ秒間続ける。 #define SAIDAI 3 //T字路や交差点付近で、ある状況を3回続けて感知したらT字路・交差点と判断 #define short_break Off(OUT_AC);Wait(80); //小休憩 #define counter3 PlaySound(SOUND_CLICK); //交差点を渡る前に3回鳴らす #define GO 1 //もうひとつのRCXからこのメッセージが送られてきたらこのRCXのプログラムが再始動する #define HOLD 2 //1つ目の缶を持ち上げる動作を、もうひとつのRCXに命令するメッセージ #define TUMU_UP 3 //1つ目の缶を2つ目の缶に積みその後2つ目の缶を持ち上げる動作を、もうひとつのRCXに命令するメッセージ #define TUMU 4 //1・2目の缶を3つ目の缶に積み3つ目の缶を挟む動作を、もうひとつのRCXに命令するメッセージ #define HOLD 2 //1つ目の缶を持ち上げる動作を、もうひとつのRCXに命令するメッセージ #define TUMU_UP 3 //1つ目の缶を2つ目の缶に積みその後2つ目の缶を持ち上げる動作を、もうひとつのRCXに命令するメッセージ #define TUMU 4 //1・2目の缶を3つ目の缶に積み3つ目の缶を挟む動作を、もうひとつのRCXに命令するメッセージ #define HASAMI 5 //ハサミを広げる動作をもうひとつのRCXに命令するメッセージ sub line_race() //普通の黒線を走るプログラム { if(SENSOR_1<=left_kuro){ if(SENSOR_3<=right_kuro){go_forward;} else if(SENSOR_3<=right_sen){senkai_left;} else{senkai_left;} } else if(SENSOR_1<=left_sen){ if(SENSOR_3<=right_kuro){senkai_right;} else if(SENSOR_3<=right_sen){go_forward;} else{senkai_left;} } else{ if(SENSOR_3<=right_kuro){senkai_right;} else if(SENSOR_3<=right_sen){senkai_right;} else{go_forward;} } Wait(STEP); } sub before_cross_line_1() //T字路付近の黒線を走るプログラム { int nOnline=0; while (nOnline < SAIDAI){ if(SENSOR_3<=right_kuro){ if(SENSOR_1<=left_kuro){go_forward;} else if(SENSOR_1<=left_sen){senkai_right;} else{senkai_right;} nOnline++; } else{ if(SENSOR_3<=right_sen){ if(SENSOR_1<=left_kuro){senkai_left;} else if(SENSOR_1<=left_sen){go_forward;} else{senkai_right;} } else{ if(SENSOR_1<=left_kuro){senkai_left} else if(SENSOR_1<=left_sen){senkai_left;} else{go_forward;} } nOnline=0;} Wait(STEP); } } sub before_cross_line_2() //T字路付近の黒線を走るプログラム { int nOnline=0; while (nOnline < SAIDAI){ if(SENSOR_1<=left_kuro){ if(SENSOR_3<=right_kuro){go_forward;} else if(SENSOR_3<=right_sen){senkai_left;} else{senkai_left;} nOnline++; } else{ if(SENSOR_1<=left_sen){ if(SENSOR_3<=right_kuro){senkai_right;} else if(SENSOR_3<=right_sen){go_forward;} else{senkai_left;} } else{ if(SENSOR_3<=right_kuro){senkai_right;} else if(SENSOR_3<=right_sen){senkai_right;} else{go_forward;} } nOnline=0;} Wait(STEP); } } sub before_cross_line_3() //T字路or十字路付近の黒線を走るプログラム { int nOnline=0; while (nOnline < SAIDAI){ if(SENSOR_1<=left_kuro&&SENSOR_3<=right_kuro){go_forward;nOnline++;} else if(SENSOR_1<=left_sen&&SENSOR_3<=right_sen){go_forward;nOnline++;} else if(SENSOR_1<=left_kuro){ if(SENSOR_3<=right_sen){senkai_left;} else{senkai_left;} nOnline==0; } else if(SENSOR_1<=left_sen){ if(SENSOR_3<=right_kuro){senkai_right;} else{senkai_left;} nOnline==0; } else{ if(SENSOR_3<=right_kuro){senkai_right;} else if(SENSOR_3<=right_sen){senkai_right;} else{go_forward;} nOnline==0; } Wait(STEP); } } task main(){ SetSensor(SENSOR_1,SENSOR_LIGHT);//左側の光センサー SetSensor(SENSOR_2,SENSOR_LIGHT);//缶の判断用光センサー SetSensor(SENSOR_3,SENSOR_LIGHT);//右側の光センサー int nCross=0; while(nCross<=8){ if(nCross==0){ senkai_right;Wait(50); go_forward; until(SENSOR_3<=left_sen); senkai_left;Wait(60); //ここでラインの上に乗っかる while(SENSOR_2>=sekkin){line_race();} Off(OUT_AC); while(Message() != GO){SendMessage(HOLD);Wait(40);} //もうひとつのRCXが缶をつかむ&上に持ち上げる senkai_left;Wait(410); nCross++; } else if(nCross==1){ while(SENSOR_2>=sekkin){line_race();} Off(OUT_AC); while(Message() != GO){SendMessage(TUMU_UP);Wait(40);} //もうひとつのRCXが缶を積む&上に持ち上げる ClearTimer(0); while(FastTimer(0)<300){line_race();} before_cross_line_1(); CROSS(50,0,0); nCross++; } else if(nCross==2){ while(SENSOR_2>=sekkin){line_race();} Off(OUT_AC); while(Message() != GO){SendMessage(TUMU);Wait(40);} //もうひとつのRCXが缶を積む ClearTimer(0); while(FastTimer(0)<830){line_race();} before_cross_line_3(); CROSS(150,0,0); senkai_right;Wait(130); Off(OUT_AC); while(Message() != GO){SendMessage(HASAMI);Wait(40);} //もうひとつのRCXがハサミを広げる back;Wait(100); senkai_right;Wait(235); go_forward;Wait(150); nCross++; } else if(nCross==3){ ClearTimer(0); while(FastTimer(0)<1000){line_race();} before_cross_line_2(); CROSS(50,150,0); nCross++; } else if(nCross==4){ ClearTimer(0); while(FastTimer(0)<200){line_race();} before_cross_line_3(); CROSS(50,0,150); nCross++; } else if(nCross==5){ while(SENSOR_2>=sekkin){line_race();} Off(OUT_AC); while(Message() != GO){SendMessage(HOLD);Wait(40);} //もうひとつのRCXが缶をつかむ&上に持ち上げる ClearTimer(0); while(FastTimer(0)<1600){line_race();} before_cross_line_3(); go_forward;Wait(50); CROSS(50,0,0); nCross++; } else if(nCross==6){ while(SENSOR_2>=sekkin){line_race();} Off(OUT_AC); while(Message() != GO){SendMessage(TUMU_UP);Wait(40);} //もうひとつのRCXが缶を積む&上に持ち上げる while(SENSOR_2>=sekkin){line_race();} Off(OUT_AC); while(Message() != GO){SendMessage(TUMU);Wait(40);} //もうひとつのRCXが缶を積む ClearTimer(0); while(FastTimer(0)<300){line_race();} before_cross_line_1(); go_forward;Wait(50); senkai_right;Wait(150); CROSS(50,0,150); nCross++; } else if(nCross==7){ ClearTimer(0); while(FastTimer(0)<200){line_race();} before_cross_line_3(); go_forward;Wait(50); senkai_right;Wait(150); CROSS(50,0,150); nCross++; } else if(nCross==8){ ClearTimer(0); while(FastTimer(0)<1000){line_race();} before_cross_line_3(); CROSS(50,0,0); senkai_right;Wait(100); Off(OUT_AC); while(Message() != GO){SendMessage(HASAMI);Wait(40);} //もうひとつのRCXがハサミを広げる back;Wait(500); nCross++; } } stop main; //動作停止 stop main; //動作停止 } **モーター部のプログラム [#lc2f5974] モーター部は、本体からの命令に従い缶をつかみ、持ち上げる。また命令完了後は本体に再始動命令を送る。~ このロボットは缶を3つ単位で積むことになっている。その手順は次の通りである。括弧内はその動作に対応する、本体からの命令である。~ ��1つ目の缶を見つけ、つかんで持ち上げておく。(HOLD)~ ��2つ目の缶を見つけ、1つ目の缶を上に乗せ、2つ目の缶ごと持ち上げる(TUMU_UP)~ ��1つ目の缶を見つけ、つかみ持ち上げる。(HOLD)~ ��2つ目の缶を見つけ、1つ目の缶を上に乗せ、2つ目の缶ごとつかみ持ち上げる(TUMU_UP)~ ��3つ目の缶を見つけ、1・2つ目の缶を上に乗せ、下の3つ目の缶をつかむ(TUMU)~ �ぅ粥璽襪謀�達したら、これらを離す(HASAMI)~ ~ ちなみに、 #define GO 1 //このメッセージを送ると、もう一つのRCXが再始動する #define HOLD 2 //このメッセージを受け取ると、1つ目の缶を持ち上げる動作をする #define TUMU_UP 3 //このメッセージを受け取ると、1つ目の缶を2つ目の缶に積んで2つ目の缶を持ち上げる動作をする #define TUMU 4 //このメッセージを受け取ると、1・2つ目の缶を3つ目の缶に積んで3つ目の缶を挟む動作をする #define HOLD 2 //このメッセージを受け取ると、1つ目の缶を持ち上げる動作をする #define TUMU_UP 3 //このメッセージを受け取ると、1つ目の缶を2つ目の缶に積んで22つ目の缶を持ち上げる動作をする #define TUMU 4 //このメッセージを受け取ると、1・2つ目の缶を3つ目の缶に積んで3つ目の缶を挟む動作をする #define HASAMI 5 //このメッセージを受け取ると、ハサミを広げる動作をする #define hasamu OnRev(OUT_A);Wait(50);Off(OUT_A); //ハサミを閉じる #define hirogeru OnFwd(OUT_A);Wait(50); //ハサミを広げる #define up OnRev(OUT_C);Wait(150);Off(OUT_C); //エレベータを上げる #define down(t) OnFwd(OUT_C);Wait(t);Off(OUT_C); //エレベータを下げる #define go_sin PlaySound(SOUND_UP); //GOというサインを出したとき、分かりやすいよう音を鳴らす sub send_go(){ //GOというサインを出すサブルーチン ClearTimer(0); while(FastTimer(0)<=200){SendMessage(GO);Wait(5);} } task main(){ int n=1; while(true){ ClearMessage(); SetPower(OUT_A,4); SetPower(OUT_C,5); if(n==0){ //HOLD,TUMU_UPの際に、自重で下がるモーター部を定期的に引き上げる SetPower(OUT_C,1);OnRev(OUT_C);Wait(100);Off(OUT_C);Wait(100); } if(Message() == HOLD){ //1つ目の缶を持ち上げる if(Message() == HOLD){ //1つ目の缶を持ち上げる n=0; hasamu; up; go_sin; send_go(); } else if(Message() == TUMU_UP){ //1つ目の缶を2つ目の缶に積んで2つ目の缶を持ち上げる else if(Message() == TUMU_UP){ //1つ目の缶を2つ目の缶に積んで2つ目の缶を持ち上げる n=0; down(20); hirogeru; down(130); hasamu; up; go_sin; send_go(); } else if(Message() == TUMU){ //1・2目の缶を3つ目の缶に積んで3つ目の缶を挟む else if(Message() == TUMU){ //1・2目の缶を3つ目の缶に積んで3つ目の缶をつかむ down(20); hirogeru; down(130); hasamu; go_sin; send_go(); n=1; } else if(Message() == HASAMI){ //ハサミを広げる hirogeru; go_sin; send_go(); n=1; } } } *反省点 [#c12a9203] ・時間不足~ ロボットを作ることに時間を費やした結果、プログラムがほとんど完成せず、ロボコンではまともに動かすこともできなかった。~ ロボットを作る際に、缶をつかんだ状態のモーター部が停止した時に自重で下がる、ロボットが重くキャタピラが動かないなどのトラブルに見舞われ、その対処に時間を取られた。~ 付け加えれば、筆者が寝落ちして集まりに参加できなかったことを原因と考えるのも不可能ではないが、筆者のグループに対する貢献度から言えばあまり有力な説とは言えない。