課題2で作成したものを2枚くっつけます.
点数については
の合計40点で審査します.細かな内訳は
をご覧ください.
ロボット本体は課題2#ref(http://yakushi.shinshu-u.ac.jp/robotics/?2019a%2FMember%2FOrangestar%2FMission2);で作ったものを改良して作りました. NXTが2つ載せられるようにして,それでいてかつ小型でライントレースの際に起こる左右の揺れの影響を受けにくいようにしました.
アームもできるだけ小型化しました.モーターに直接部品をつなげて回転運動を利用してボールをつかみます.
ボールを離す動作です.先ほどと逆向きに回転させます.
アームそのものを上げ下げするためのモーターです.取り付けた理由として,今回使うプラ容器にある程度の高さがあるため,このままでは容器の中のピンポン玉が取れなくなってしまうからです.
ロボットの全体像です.コンパクトに仕上ったと思います.
A'からスタートし,まずL'にあるピンポン玉をつかみ旋回して容器に入れます. そこから直線を突っ切って容器の中のピンポン玉を掴みゴールにある容器に入れ替えます. それを2回繰り返します.(図にある赤の点線です.この点線の動作を2回繰り返します.) 最後にLにあるピンポン玉を掴みゴールにある容器に入れて終了という計画です. 今回はロボット本体とボールを掴む機構を2台のロボットに分割して制御します. 本体を制御するロボットを「親」,アームを制御するロボットを「子」と呼ぶことにします. 親のプログラムは課題2のものをベースにします.
課題2の時と同じです
光センサーが黒を認識すると左,白を認識すると右へ行くようプログラミングしてやれば左側をトレースできます.
Bluetoothでロボットを接続し,メールボックスに数字を送ってやり取りします.親側のロボットに数字を送るSendRemoteNumberというプログラムを書いて,子のほうにはメールボックスの中にこの数字があればこの動きをするというプログラムをします.
#define SIGNALON1 11 #define SIGNALOFF1 12 #define SIGNALON2 13 #define SIGNALOFF2 14 #define turn_right OnFwd(OUT_C,25);OnRev(OUT_B,15);//右折 #define turn_left OnFwd(OUT_B,25);OnRev(OUT_C,15);//左折 #define rotate_right OnFwd(OUT_C,20);OnRev(OUT_B,25);//右旋回 #define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,25);//左旋回 #define go_straight OnFwd(OUT_BC,20);//直進 #define go_straight2 OnFwd(OUT_BC,15);//ゆっくり直進 #define turn OnRev(OUT_C,25);OnFwd(OUT_B,25);Wait(1500);Off(OUT_BC);//180°旋回 #define catch OnRev(OUT_A,25);Wait(500);Off(OUT_A);//ピンポン玉をつかむ #define release OnFwd(OUT_A,25);Wait(500);Off(OUT_A);//ピンポン玉を離す #define osidasi OnFwd(OUT_BC,100);Wait(100);Off(OUT_BC);//加速してピンポン玉を押し出す #define black 20//黒の値は20 #define white 50//白の値は50 #define lightgray 40//灰白色は40 #define darkgray 28//灰黒色は28 #define turn2 OnRev(OUT_B,28);OnFwd(OUT_C,20);Wait(1500);Off(OUT_BC); #define sakittyo OnFwd(OUT_C,20);OnFwd(OUT_B,23);Wait(1150);Off(OUT_BC); #define turn3 OnRev(OUT_B,30);Wait(4800);Off(OUT_BC); #define turn4 OnRev(OUT_B,30);Wait(5200);Off(OUT_BC); #define back OnRev(OUT_C,20);OnRev(OUT_B,28);Wait(3000);Off(OUT_BC); #define osidasi OnFwd(OUT_BC,100);Wait(100);Off(OUT_BC); #define arm_down OnFwd(OUT_A,25);Wait(1500);Off(OUT_A); #define arm_up OnRev(OUT_A,35);Wait(1500);Off(OUT_A); #define center 45
まずは直進,右左折などのマシンの操作から,黒や白の値などを定義しておきます.
sub followline_L(int stop_time) { long t0=CurrentTick(); while(CurrentTick()-t0<stop_time){//現在の時刻が一定の値を超えるまで if(SENSOR_1<black){//センサーが黒の時 rotate_left;//左旋回 }else if(SENSOR_1<darkgray){//センサーが黒灰なら turn_left;//左折 }else if(SENSOR_1>lightgray){//センサーが白灰なら turn_right;//右折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<35){//明るさ35以下で go_straight;//直進 t0=CurrentTick();//時間をリセット }else{//それ以外は rotate_right;//右旋回 t0=CurrentTick();//時間をリセット } } Off(OUT_BC);//時刻が一定の値を超えると停止 Wait(1000);//1秒間停止 }
黒線n右側をライントレースするサブルーチン
sub followline_R(int stop_time) { long t0=CurrentTick(); while(CurrentTick()-t0<stop_time){//現在の時刻が一定の値を超えるまで if(SENSOR_1<black){//センサーが黒の時 rotate_right;//右旋回 }else if(SENSOR_1<darkgray){//センサーが黒灰なら turn_right;//右折 }else if(SENSOR_1>lightgray){//センサーが白灰なら turn_left;//左折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<35){//センサーが35以下なら go_straight;//直進 t0=CurrentTick();//時間をリセット }else{//それ以外は rotate_left;//左旋回 t0=CurrentTick();//時間をリセット } } Off(OUT_BC);//一定の時間を超えると停止 Wait(1000);//一秒間停止 }
右側をライントレースするサブルーチン
sub followline_R2(int stop_time) { long t0=CurrentTick(); while(CurrentTick()-t0<stop_time){//時刻がある一定の値より小さいとき if(SENSOR_1<black){//黒なら rotate_right;//右旋回 t0=CurrentTick();//時間をリセット }else if(SENSOR_1<darkgray){//灰黒色なら turn_right;//右折 t0=CurrentTick();//時間をリセット }else if(SENSOR_1>lightgray){//灰白色なら turn_left;//左折 }else if(SENSOR_1<35){//明るさ35以下で go_straight2;//ゆっくり直進 t0=CurrentTick();時間をリセット }else{//それ以外なら rotate_left;//左旋回 } } Off(OUT_BC);//停止 Wait(2000);//2秒間停止 }
白から黒へ,黒から白へ移動するためのサブルーチン
sub Blackto_White()//黒から白へ { while(SENSOR_1<darkgray){灰黒色の間 OnFwd(OUT_BC,15);//直進 } Off(OUT_BC);//停止 } sub Whiteto_Black()//白から黒まで直進 { while(SENSOR_1>darkgray){//灰黒色まで OnFwd(OUT_BC,15);//直進 } Off(OUT_BC);//停止 }
sub Whiteto_Black_R()//白から黒まで右旋回 { while(SENSOR_1>darkgray){//灰黒色まで OnFwd(OUT_C,20); OnRev(OUT_B,20);}//右旋回 Off(OUT_BC); } sub Blackto_White_R()//黒から白へ右旋回 { while(SENSOR_1<darkgray){//灰黒の間 OnFwd(OUT_C,20); OnRev(OUT_B,20);//右旋回 } Off(OUT_BC); }
sub Blackto_White_L()//黒から白へ左旋回 { while(SENSOR_1<lightgray){//薄灰のとき OnFwd(OUT_B,20); OnRev(OUT_C,20);//左に旋回 } Off(OUT_BC); }
sub Whiteto_Black_L()白から黒へ左旋回 { while(SENSOR_1>black){//黒の時 OnFwd(OUT_B,20); OnRev(OUT_C,20);//左旋回 } Off(OUT_BC); }
#define SIGNALON1 11 #define SIGNALOFF1 12 #define SIGNALON2 13 #define SIGNALOFF2 14 #define CONN 1 task main() { int msg; while(true){ ReceiveRemoteNumber(MAILBOX1,true,msg); if(msg==SIGNALON1){//メールボックスに11があるとき OnRev(OUT_A,20);Wait(1000);//アームを閉じる }else if(msg==SIGNALOFF1){//メールボックスに12があるとき Off(OUT_A);//アームを止める }else if(msg==SIGNALON2){//メールボックスに13があるとき OnFwd(OUT_A,20);Wait(1000);//アームを開く }else if(msg==SIGNALOFF2){//メールボックスに14があるとき Off(OUT_A);//アームを止める } } }
task main() { SetSensorLight(S1); RemoteStartProgram(CONN,"kodomo.nxc");//子のプログラムを遠隔でスタート followline_R(200); Blackto_White(); followline_L(150); Blackto_White_R(); followline_R2(150); SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);//子のメールボックスに11を送信 Wait(1000); arm_up; turn; SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);//子のメールボックスに12を送信 Wait(1000); followline_R(150); Blackto_White_L(); followline_L(100); Blackto_White(); Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); followline_R(150); Blackto_White(); turn2; sakittyo; arm_down; SendRemoteNumber(CONN,MAILBOX1,SIGNALON1); Wait(1000); arm_up; turn3; Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); followline_R(200); Blackto_White(); turn2; SendRemoteNumber(CONN,MAILBOX1,SIGNALON2); Wait(1000); turn3; Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); followline_R(200); Blackto_White(); turn2; sakittyo; arm_down; SendRemoteNumber(CONN,MAILBOX1,SIGNALON1); Wait(1000); arm_up; turn3; Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); Blackto_White_R(); followline_R(200); Blackto_White(); turn2; SendRemoteNumber(CONN,MAILBOX1,SIGNALON2); Wait(1500); turn4; arm_down Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); followline_L(200); Blackto_White(); followline_R(200); Blackto_White(); followline_L(200); Blackto_White(); followline_R(200); Blackto_White(); followline_L(150); Blackto_White_R(); followline_R2(125); SendRemoteNumber(CONN,MAILBOX1,SIGNALON1); Wait(1000); arm_up; turn; followline_R(100); Blackto_White_L(); followline_L(100); Blackto_White(); Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); Whiteto_Black(); Blackto_White(); followline_R(200); Blackto_White(); turn2; sakittyo; SendRemoteNumber(CONN,MAILBOX1,SIGNALON2); Wait(1000);
ロボコンの結果は2位でした.この結果はチームの力なくしては達成できませんでした.電池が少なくなり出力に影響したり,思い通りに動かないことが多々ありましたが,ここまでたどり着けて良かったと思います.