#contents *課題概要 [#j1be51d4] 今回の課題はピッチャーロボットとバッターロボットが所定の位置からスタートし、所定の位置につき、ピッチャーが投げたボールをバッターが打ってゴールにいれることで点をとる。その得点と観客がつけた技術点の平均との合計を競うというものである。 詳しいルールを知りたい方はこちら→[[2016b/Mission3]] 今回の課題はピッチャーロボットとバッターロボットが所定の位置からスタートし、所定の位置につき、ピッチャーが投げたボールをバッターが打ってゴールにいれることで点をとる。その得点と観客がつけた技術点の平均との合計を競うというものである。 詳しいルールを知りたい方はこちら→([[2016b/Mission3]]) *ピッチャー [#o0c1b59c] **機体 [#zbb559c9] 機体のメインはボールの発射機構である。私の班はボールを転がすことで発射する機構にした。この機構をつくるにあたって1番苦労したのは、ボールをいれて運ぶための場所である。このロボットではボールを転がすためにボールを入れる場所を高くする必要があった。しかし、あまりに高すぎるとバランスが悪くなるのでそれを防ぐために横に広く作った。しかし、これだとボール同士が干渉し、ボールが出てこなくなったため、細かい部品を中に取り付けることでつまらないようにした。 &ref(2016b/Member/suzukaze/Mission3/DSC_0067[1].JPG,10%,ボール入れる場所); また、ボールを機体の真ん中を転がす機構にしたため、センサー等は機体の横に取り付けた。それによりライントレースは難しくなったため、今回は使わないことにした。 **プログラム [#ca91d0bb] defineは方向転換とセンサ−用の直進と角度制御用の直進、それと発射装填を用意した。 #define TURNR(A) RotateMotorEx(OUT_BC,40,A,100,true,true);Wait(1000);//右に曲がる #define TURNL(L) RotateMotorEx(OUT_BC,40,L,-100,true,true);Wait(1000);//左に曲がる #define TYOKUSIN OnFwdSync(OUT_BC,40,0); //直進する #define CM(K) RotateMotorEx(OUT_BC,40,20.47315*K,0,true,true);Wait(1000);//K(cm)直進 #define HASSYA RotateMotor(OUT_A,-90,90);Wait(1000);RotateMotor(OUT_A,-90,-90);//ボールを発射、装填 サブルーチン(BASYO)はライトセンサーでラインを検知してそれを超えるものである。 sub BASYO()//ラインを検知して超えるプログラム { SetSensorLight(S1); TYOKUSIN; until(SENSOR_1<35); Off(OUT_BC); Wait(500); CM(5); Wait(500); } プログラムの流れとしては、まずゴールにぶつからないように向きを変え、角度制御により直進、そこで向きを変え、ラインを3回超えるまで進む、そうすると投球位置を過ぎるので後退して位置調整、その後、方向転換してバッターの方を向き通信を開始するという流れになっている。通信が始まってからについては通信([[#g7b8458f]])で詳しく説明する。 task main() { int SIREI;//子機からの信号を入れる場所 TURNR(110); CM(36); TURNR(150); repeat(3){ //ラインを3回超えるまで BASYO(); } CM(-13);//位置の調節のためバック TURNR(130); until(BluetoothStatus(1)==NO_ERR);//通信 RemotePlayTone(1,440,1000);//通信 Wait(1000); RemoteStartProgram(1,"DAGEKI.rxe");//通信 while(SIREI<12){ ReceiveRemoteNumber(MAILBOX1,true,SIREI);//通信 if(SIREI==11){ PlaySound(SOUND_CLICK); Wait(200); HASSYA; SIREI=0;//通信 } } } 最初は超音波センサーを使ったバッターの検知等も試したが正確な検知ができず、角度制御で場所を指定した方が正確に向きを合わせられたので今回は角度制御で場所、向きをバッターに合わせた。 *バッター [#nd60736e] 私は基本的にピッチャーを担当したのでバッターにはあまり詳しくない。バッターについて詳しく知りたい方はこちら→([[2016b/Member/sennokiseki/Mission3]])([[2016b/Member/mamedeppo/Mission3]]) **機体 [#p88534ec] 私たちの班ではボールをキャッチしてから発射する方法をとった。そのためにアームを取り付けた。これをタイミングよく下げることでボールをキャッチし、上げることで発射される。1度完全に勢いを消せるのでキャッチできればかなり正確にゴールを狙える。 &ref(2016b/Member/suzukaze/Mission3/DSC_0071[1].JPG,10%,アーム); こちらも超音波センサーを使わず、ライトセンサーのみとなっている。 **プログラム [#s29b8532] ここではバッターが最初の位置から位置に着くまでのプログラムを説明する。通信が始まってからのプログラムは通信([[#g7b8458f]])で説明する。流れとしてはまず、角度制御である程度進み、ライントレースをすることで最終位置に近づき、最後の調整でピッチャーの方を向く。 defineは角度制御、ライントレースともに必要なのでそのためのカーブ、旋回、直進を準備。他にもライントレースの時間や1部の位置調節がある。 #define go_straight(t) RotateMotor(OUT_BC,50,t); //角度制御直進 #define go_nonstop OnFwd(OUT_BC,50); //直進 #define turn(t) RotateMotorEx(OUT_BC,60,t,100,true,true);//角度制御ターン #define turn_right OnFwd(OUT_B,40); //右カーブ #define turn_right_slow OnFwd(OUT_B,40); OnRev(OUT_C,30); //時計回りに回転 #define turn_left OnFwd(OUT_C,40); //左カーブ #define turn_left_slow OnFwd(OUT_C,40); OnRev(OUT_B,30); //反時計回りに回転 #define go_line OnFwd(OUT_BC,40); //ライントレース用直進 #define FOLLOW_TIME 5000 #define SASETSU OnRev(OUT_BC,50); Wait(400); Off(OUT_BC); OnFwd(OUT_C,50); Wait(1500); Off(OUT_C);//ライントレース前の向き、位置調整 ライントレース用のプログラム。黒の濃さによって曲がり方を変えている他、ライントレースの時間も制御している。 sub FOLLOW_LINE()//ライントレース { long t0=CurrentTick(); while(CurrentTick()-t0<FOLLOW_TIME){ if(SENSOR_3<=38){ turn_right; }else if(SENSOR_3<=45){ turn_right_slow; }else if(SENSOR_3<=50){ go_line; }else if(SENSOR_3<=59){ turn_left_slow; }else{ turn_left; } } Off(OUT_BC); } ライントレースを始める場所まで移動、その後、位置調整する。 sub BEGIN()//ライントレースを始めるまでの向き、位置調整 { Wait(1500); turn(120); //障害物回避 go_straight(1300); PlaySound(SOUND_CLICK); go_nonstop; until(SENSOR_3<=40);//ラインを検知 Off(OUT_BC); PlaySound(SOUND_CLICK); Wait(1000); SASETSU; //ライントレース位置を調整 } ライントレースの後に所定の位置に着き、ピッチャーの方を向くところ sub READY()//最後の位置、向き調整 { go_straight(500); OnRev(OUT_BC,50); until(SENSOR_3<=40); Off(OUT_BC); PlaySound(SOUND_CLICK); Wait(1000); turn(20); go_straight(400); turn(-70); PlaySound(SOUND_UP); } 上記サブルーチンを順番通り繋げたもの task main() { SetSensorLight(S3); BEGIN(); FOLLOW_LINE(); READY(); } *通信 [#g7b8458f] ここでは通信の開始、つまりボールを投げて打つところのプログラムを説明する。まず、今回はRemoteStartProgramというプログラムを使った。これは相手のプログラムを開始させるプログラムである。なので親機であるピッチャーのプログラムはピッチャーの項目で説明したプログラムに含まれているが、バッターのプログラムはバッターの位置に着くためのプログラムとは別のプログラムである。ここからは親機と子機の動きを起こる順番に説明するため、どちらのプログラムかわかりにくくなると思うので注意してほしい。 defineとしてボールの発射装填(ピッチャー)、ボールのキャッチ(バッター)、ボールの発射(バッター)、向きの調節(バッター)を準備した。 #define HASSYA RotateMotor(OUT_A,-90,90);Wait(1000);RotateMotor(OUT_A,-90,-90);//ボールを発射、装填(ピッチャー) #define CATCH Wait(500);RotateMotor(OUT_A,70,45);Wait(1000);ボールのキャッチ(バッター) #define UTU RotateMotor(OUT_A,-90,45);Wait(1000);ボールの発射(バッター) #define TURN(s,t) RotateMotorEx(OUT_BC,40,s,t,true,true);Wait(1000);向き調整(バッター) まず、親機であるピッチャーが子機の通信が準備できるまで待機、その後、子機のプログラムを開始させる。 until(BluetoothStatus(1)==NO_ERR);//子機と通信ができるまで待機 RemotePlayTone(1,440,1000);//子機の音を出させる Wait(1000); RemoteStartProgram(1,"DAGEKI.rxe");//子機のプログラムを開始させる 開始するプログラム int x=1;//回数を計るために定義 task main() { UTU;//アームを上げておく while(x<6){ BATTING();//下で説明 } SendRemoteNumber(0,MAILBOX1,12);//親機のプログラムを終了させる } サブルーチンの中身1部抜粋 sub BATTING() { SendRemoteNumber(0,MAILBOX1,11);//親機に指令を出す Wait(1500);//キャッチのタイミング調整 CATCH; if(x==1){ TURN(80,100);//ゴールに向きを合わせる UTU; TURN(80,-100);//元の向きに戻る x = x+1;//次のゴールを狙うための操作 子機が親機に指令を出すことで親機が動く while(SIREI<12){ ReceiveRemoteNumber(MAILBOX1,true,SIREI);//子機からの指令を受け取ってしまう if(SIREI==11){ //指令によりifのなかに入る PlaySound(SOUND_CLICK); Wait(200); HASSYA; SIREI=0;//必要かどうか不明 上記の繰り返し(バッター) } else if(x==2){ TURN(95,-100); UTU; TURN(95,100); x = x+1; } else if(x==3){ TURN(40,100); UTU; TURN(40,-100); x = x+1; } else if(x==4){ TURN(45,-100); UTU; TURN(45,100); x = x+1; } else { TURN(45,-100); UTU; TURN(45,100); x = x+1; } } *まとめ [#kf28480a] 位置に着くところや通信のプログラムはかなりよくできたと思うがボールの発射速度が遅く、バッターがキャッチできないことも多かった。ボールを転がすならもう少し高い位置から転がしてスピードをあげるべきだったと思う。