**目次 [#s0b0810b] #contents **課題2の説明 [#cfbf6862] &ref(robocon2013a.png);~ -''概要'' --基本得点80点+技術点20点の計100点で課題2(ロボコン、Mission2)を評価 --基本得点は自分たち以外のグループ以外の一グループが採点 --技術得点は自分たち以外の全グループが採点し、その平均で決める --大雑把に書くと、6回ボールをパスして2回缶に当てれば良い -''基本ルール'' --競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。 --書き足した直線部からスタートする。 --図の上部からスタートしたロボットAがピンポン玉を取りにいく --直線部までピンポン玉を持ってくる (1) --直線部に入ってからロボットBへパスを送る (2) --ロボットBは直線部でパスを受け取る --ロボットBは直線部でパスを送る (3) --ロボットAは直線部でパスを受けとる --ロボットAは直線部でパスを送る (4) --ロボットBは直線部でパスを受け取る --ロボットBがゴールの空き缶の近くまでピンポン玉を運んで空き缶に当てる (5) (ただし黒い線で囲まれた空き缶の領域には入ってはいけない) --ロボットBはシュートをした後もう一つのピンポン玉を取りにいく --以後は、これまでのAとBの役割を反対にして、パスを繰り返し、最終的にはロボットAがもう一つのゴールにシュートする。 --開始の合図から5秒以内にスタートボタンを押す作業を完了すること。 --競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。 --途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 -''基本得点(80点)'' --ボールをつかむ ・・・ 5点 --(2)のパスが通る ・・・ 5点 --(3)のパスが通る ・・・ 10点 --(4)のパスが通る ・・・ 5点 --(5)でシュートをする ・・・ 5点 --シュートが空き缶に当たる ・・・ 10点 --反対方向も同じ -''技術得点(20点)'' --ピンポン玉を取りにいくまでの動作 (3点) --ピンポン玉を運ぶ動作(2点) --ピンポン玉をパスする動作(3点) --ピンポン玉を受ける動作(3点) --2台以上のロボットの連携の良さ(3点) --自立型のロボットとしての形や動作の美しさ、斬新さ(3点) --その他 (3点) **ロボット [#c09087d8] **プログラム [#h7f1574a] #define zone1 37 //黒線の中央の値 #define zone2 45 //黒線の中央よりやや外側よりの値 #define zone3 60 //黒線と白紙部分の境目の値 #define zone4 65 //白紙部分の値 #define SPEED 45 //ロボットの進む速さ #define LOWSPEED SPEED*0.625 //「SPEED」の0.625倍の速さ #define mae OnFwd(OUT_BC,SPEED*0.8); //「SPEED」の0.8倍の速さで前進 #define STEP 1 //一回の判定でロボが進む時間(この場合だと0.001秒間に一回処理している) #define nMAX 100 //STEP秒間に赤外線センサーの値が37以下をnMAX回出したら交差点と判断する #define SIGNAL1 11 //「打った」と宣言する信号 #define SIGNAL2 12 //「打て」と宣言する信号 #define CONN 1 //通信の時に設定するスレーブの番号(1〜3まで選べる) int p=0; //センサーが黒線の上にあるとき、pを使ってカウントし、pがnMAXの値を超えたらそこは交差点(今回は0.001秒間に一回カウント) int n=0; // int m=0; //交差点を通過した個数を数えるときにmを使う int msg=0; //相手に送るメッセージ sub migigawa(int x) //交差点をx回通過するまで右側をライントレースし続ける { while(m < x) { while(p < nMAX && m<x) { if (SENSOR_4 < zone1) { OnFwd(OUT_B,SPEED);OnRev(OUT_C,LOWSPEED); //小回りな右折 p++; } else { if (SENSOR_4 < zone2) { OnFwd(OUT_B,SPEED);Off(OUT_C); //普通の右折 } else if (SENSOR_4 < zone3) { mae; } else if (SENSOR_4 < zone4) { OnFwd(OUT_C,SPEED);Off(OUT_B); // 普通の左折 } else { OnFwd(OUT_C,SPEED);OnRev(OUT_B,LOWSPEED); //小回りな左折 } p=0; } Wait(STEP); } OnFwd(OUT_C,SPEED);OnRev(OUT_B,LOWSPEED); //小回りな左折 Wait(nMAX*STEP); OnFwd(OUT_BC,SPEED);Wait(300); p=0; m++; } m=0; } ↑「赤外線センサーの値がzone1(37)以下ならば小回りに右折し、zone1(37)〜zone2(45)ならばちょっぴり大回りに右折する。zone2〜zone3なら前進しzone3〜zone4ならちょっぴり大回りに左折。zone4〜zone5なら小回りに左折する」。''この動作''をmigigawa(x)のみで表現させている。xには整数が入り、x回交差点を通過したら''この動作''をやめるようにプログラムしてある。 sub hidarigawa(int x) //交差点をx回通過するまでライントレースし続ける { while(m < x) { while(p < nMAX && m<x) { if (SENSOR_4 < zone1) { OnFwd(OUT_C,SPEED);Off(OUT_B); // 普通の左折 p++; } else { if (SENSOR_4 < zone2) { OnFwd(OUT_C,SPEED);OnRev(OUT_B,LOWSPEED); //小回りな左折 } else if (SENSOR_4 < zone3) { mae; } else if (SENSOR_4 < zone4) { OnFwd(OUT_B,SPEED);Off(OUT_C); //普通の右折 } else { OnFwd(OUT_B,SPEED);OnRev(OUT_C,LOWSPEED); //小回りな右折 } p=0; } Wait(STEP); } OnFwd(OUT_B,SPEED);OnRev(OUT_C,LOWSPEED); Wait(nMAX*STEP); OnFwd(OUT_BC,SPEED);Wait(300); p=0; m++; } m=0; } task main () { SetSensorLight(S4); //四番ポートに赤外線センサーを設置 Wait(2000); //ロボットを置く時間 //''一回目の缶当てスタート!'' migigawa(2); //交差点を二回カウントするまでライントレース Off(OUT_BC);Wait(1000); //休憩 RotateMotor(OUT_C,-SPEED,200);RotateMotor(OUT_B,SPEED,120);Off(OUT_BC); //角度調整 mae;OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //アームで球を捕獲 mae;until(SENSOR_4 < 50);Off(OUT_BC); //黒線まで直進 OnRev(OUT_BC,SPEED);Wait(500);OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50); //後ろの黒線までバック OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);Wait(500); //旋回 OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);until(SENSOR_4 < 50); //ライントレース出来る体制に戻る hidarigawa(1); //左側をライントレースしながら交差点を一回カウント Off(OUT_BC);Wait(1000);RotateMotor(OUT_BC,-SPEED,430);Wait(1000); //打つ地点までバック RotateMotor(OUT_B,-SPEED,300);RotateMotor(OUT_C,SPEED,100);Off(OUT_BC); //角度調整 Wait(1000);SendRemoteNumber(CONN,MAILBOX1,SIGNAL1); //信号を送る OnFwd(OUT_BC,SPEED);RotateMotor(OUT_A,100,400);Off(OUT_ABC); //打つ RotateMotor(OUT_BC,-SPEED,200); //打った状態からライントレースできる体制に戻る OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);RotateMotor(OUT_BC,SPEED,50); //打った状態からライントレースできる体制に戻る OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);until(SENSOR_4 < 50); //打った状態からライントレースできる体制に戻る Off(OUT_BC);Wait(5000); //五秒待つ hidarigawa(1); //左側ライントレース交差点を一回カウント RotateMotor(OUT_BC,SPEED,100);Off(OUT_BC); //受け取る場所まで移動 RotateMotor(OUT_BC,-SPEED,10);RotateMotor(OUT_C,SPEED,550);Off(OUT_BC); //90°旋回 SendRemoteNumber(CONN,MAILBOX2,SIGNAL2); // 相手に「打て」とメッセージを送る Wait(500); //相手が打ってから球が来るまで待つ時間 OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //球を受け取る OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);Off(OUT_BC);RotateMotor(OUT_BC,SPEED,80); OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);until(SENSOR_4 < 50); //ライントレース出来る体制に戻る Off(OUT_BC);Wait(7000); //七秒待つ hidarigawa(1); //左側、交差点を一回カウント RotateMotor(OUT_BC,SPEED,50);Off(OUT_BC); //打つ地点まで移動 RotateMotor(OUT_B,-SPEED,400);Off(OUT_B);RotateMotor(OUT_C,-SPEED,20); //角度調整 SendRemoteNumber(CONN,MAILBOX3,SIGNAL1); //「打つ」と送る OnFwd(OUT_BC,SPEED);RotateMotor(OUT_A,100,400);Off(OUT_ABC); //打つ RotateMotor(OUT_BC,-SPEED,50);Off(OUT_BC); //打った時のズレを修正 //一回目の缶当て終了! //二回目の缶当てスタート RotateMotor(OUT_C,-SPEED,50); Wait(65000); //相手が準備できるまで待機 SendRemoteNumber(CONN,MAILBOX4,SIGNAL2); //「打て」と相手に送る Wait(1500);OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //球を受け取る RotateMotor(OUT_C,SPEED,50);Wait(5000); //相手が準備できるまで待つ RotateMotor(OUT_BC,-SPEED,200); RotateMotor(OUT_C,-SPEED,180);RotateMotor(OUT_B,-SPEED,380); //打つ準備をする RotateMotor(OUT_BC,SPEED,300);RotateMotor(OUT_B,SPEED,80); //打つ準備をする RotateMotor(OUT_BC,-SPEED,100); SendRemoteNumber(CONN,MAILBOX5,SIGNAL1); //「打つぞ」と相手に送る Wait(500);OnFwd(OUT_BC,SPEED);RotateMotor(OUT_A,80,400);Off(OUT_ABC); //打つ Wait(1500);OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);Off(OUT_BC);//打ってから黒線まで戻る RotateMotor(OUT_BC,SPEED,50); OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED); //ライントレース出来る体制に戻る until(SENSOR_4 < 50);Off(OUT_BC); //ライントレースできる体制に戻る migigawa(1); //目の前のT字路をカウント RotateMotor(OUT_BC,SPEED,350);RotateMotor(OUT_B,SPEED,400); //受け取る位置まで移動 RotateMotor(OUT_C,-SPEED,180);Off(OUT_BC);RotateMotor(OUT_C,-SPEED,100); //受け取り角度調整 SendRemoteNumber(CONN,MAILBOX6,SIGNAL2); //「打て」と送る Wait(1500); //球が来るのを待つ OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //球を受け取る Wait(1000);OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);Off(OUT_BC); //ライントレース出来る体制に戻る RotateMotor(OUT_BC,SPEED,50); //ライントレースできる体制に戻る! OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED);until(SENSOR_4 < 50);Off(OUT_BC); //ライントレースd(ry migigawa(1); Off(OUT_BC); RotateMotor(OUT_B,-SPEED,420); RotateMotor(OUT_A,100,400); //缶に当てる //二回目の缶当て終了! } } -RotateMotorについて --Rotatemotor(OUT_A,80,50);と打つと、「Aに接続されているモーターを80%の力で50°回転」を実行する --回す角度でモーターの動きを決められるので、電池に左右されることがない --RotateMotor(OUT_BC,80,50);のように同じ方向へ同時に動かすことはできるが、RotateMotor(OUT_B,80,50);rotateMor(OUt_C,80,50);と書いても同時に二つのモーターが動くわけではなく、接続がBのモーターを80%の力で50°回した後にCのモーターを80%,50°回すだけである --課題2をクリアするために絶対必要なコマンドであり、授業で教えるべきだ **反省 [#k139bc56] **意見 [#r8e90b9c] -ロボット同士の通信のやり方を詳しく資料に記述してほしい -RotateMotorのコマンドはほぼ必須なので、詳しく資料に記述してほしい