#contents * 課題3 [#w6a4e981] #ref(2015b/Member/cst321/Mission3/2015b-mission3.png,80%,図); 今回の課題は基本的一つ目のロボットがボールをもって、カンに打ったあとに、 二つ目のロボットがボールをGOALBまでに回収するという課題です。 こちらのチームはRISを使っているので、超音波センサーがないため、光センサーに頼るしかないので、カンの上にランタンを置きました。 そして、RISを使うチームは中央線を越えても大丈夫という規定もありました。 ** 課題の一番難しいところ [#v3aeba10] 言うのは結構簡単だが、実際には難しい。 まず、シュートロボットはどのぐらい歩けば、ボールをキャッチすればいいかという問題が生じる。加えて、歩いてくれても、その時間と路程が不安定なので、いつキャッチするかを把握するのがとても難しいです。 そして、一つ目のボールをシュートした後に、どうやって、二つ目のボールを捕まえに行けばいいかがとても難しい。シュートする場所が固定できないと、二つ目のボールを捕まえるのが無理です。 キャッチロボットの場合は、カンに当たった後のボールはどこに跳ね返ってあるかを把握するのが難しい。ボールの可能性がある居場所多すぎて、ロボットの行方がどうやって設定すればいいかわかりません。 * キャッチロボットとシュートロボット [#s19bb27d] #ref(2015b/Member/cst321/Mission3/all.JPG,20%,今回のロボット); **シュートロボット [#d53f6c66] シュートロボットでは体が小さく、軽く、簡単にしました。それはプログラミングをしやすくするからです。体が小さく簡単だと、動きの誤差も少なくなるだろうと思いました。 &ref(2015b/Member/cst321/Mission3/openhand.JPG,10%,準備動作); &ref(2015b/Member/cst321/Mission3/closehand.JPG,10%,キャッチ動作); キャッチ動作は写真のように見えます。 詳しいモターの使い方になると下の写真を見てください。 #ref(2015b/Member/cst321/Mission3/handmotor.JPG,20%,キャッチモター); 写真のように、三つもギアでも使ってしまいました。 それはモターが下設置したため、アームに届くには三つのギアが必要でした。 三つのギアも使ったため、モターに一定の力をかけてしまったので、いい例ではありません。 シュートするためアームの下に小さい壁を作りました。 アームを持ち上げる同時に、その壁がボールにぶつかって、シュートを行う。 #ref(2015b/Member/cst321/Mission3/front.JPG,10%,小さい緑の壁); 次に紹介するのはシュートロボットは三つのセンサーも使っています。 それはライントレース用の光センサーとランタンの探知用光センサーと回転センサー。 まず回転センサーの使用を紹介します。 #ref(2015b/Member/cst321/Mission3/rotation.JPG,10%,回転センサー); 誤差が一番少ないと判断し、歩いた距離を測るのに回転センサーを使いました。 時間で距離を測ったら、ロボットのバッテリーに影響されやすいので、不安定です。 そして、シュートの方向を測定するには、ランタンの光の探知がいるので、ロボットの上に光センサーをつけました。 #ref(2015b/Member/cst321/Mission3/openhand.JPG,10%,準備動作); 最後にライントレースはいつも通り、ロボットの下に着けました。(写真を忘れたので申し訳ございません。) **キャッチロボット [#ac4a51d4] #ref(2015b/Member/cst321/Mission3/catchmotor.JPG,20%,キャッチロボット); キャッチロボットでは掃除機という概念をもって作りました。つまり大きい範囲を踏まえて、回収することです。その車輪を24/7でずっと内側で回し続けます。そうすると、触ったボールをすぐ中に吸い込みます。 そして、ロボットの二つ側に、この透明な棒を加えて、ロボットが回るときに、ボールが出ないようにしました。 #ref(2015b/Member/cst321/Mission3/down.JPG,20%,透明な棒); この棒はボールを逃がさない役割を持って、同時に、左右のボールを回収する役割も持っています。 センサーの場合は、このロボットはライントレースをするしかないので、ライントレース用の光センサーをしたにつけました。 * シュートプログラミング [#f84c599e] ボールはすでに固定している場所があるので、ボールを探すのが必要がありませんが、ボールのところまでへ行って、捕まえるのが必要です。アームが小さいので、さらに正確度を上げる必要になります。ですから、回転センサーを使って、その移動した距離を計ることにしました。 //black = 43 < 48 < white = 52 //SENSOR_2 トレース //SENSOR_3 物体探索 //TIMER(0) トレース //TIMER(1) 光探索 /*パワー設定*/ #define power(s) SetPower(OUT_A+OUT_C,s); /*ライントレース用*/ #define shiki 48 #define tomaru(t) Off(OUT_AC);Wait(t); #define FWD OnFwd(OUT_AC); #define BACK OnRev(OUT_AC); #define LEFT_t OnRev(OUT_A); OnFwd(OUT_C); #define LEFT Off(OUT_A); OnFwd(OUT_C); #define RIGHT_t OnRev(OUT_C); OnFwd(OUT_A); #define RIGHT Off(OUT_C); OnFwd(OUT_A); #define TMAX 20 /*アーム*/ #define open(t) OnFwd(OUT_B);Wait(t);//玉を扱う機構 #define close(t) OnRev(OUT_B);Wait(t);Off(OUT_B); #define stop_B Off(OUT_B); /*光とシュート*/ #define SUN 50//ランタンの輝度を表す数値 #define shoot power(2);open(15);Wait(10);close(15); これはスタートラインからのライントレースプログラムです。 /*赤球までのトレース*/ sub trace_0(){ power(2); ClearSensor(SENSOR_1); while(1){ if (SENSOR_2 < shiki -7){ LEFT_t; } else if (SENSOR_2 < shiki -4){ LEFT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ RIGHT; } else { RIGHT_t; } if(SENSOR_1 > 335){ power(3); close(50); ClearSensor(SENSOR_1); break; } } } ボールを捕まえてから、交差点で右へ回って、ライントレースをして、カンを近づく行動です /*ボールを捕まえてからのライントレース*/ sub trace_1(){ ClearSensor(SENSOR_1); close(10); Off(OUT_B); power(2); while(1){ if (SENSOR_2 < shiki -7){ LEFT_t; } else if (SENSOR_2 < shiki -4){ LEFT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ RIGHT; } else { RIGHT_t; } if(SENSOR_1 > 62){ tomaru(10); break; } } } sub trace_2(){ power(1); ClearSensor(SENSOR_1); while(1){ if (SENSOR_2 < shiki -7){ RIGHT_t; } else if (SENSOR_2 < shiki -4){ RIGHT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ LEFT; } else { LEFT_t; } if(SENSOR_1 > 44){ power(3); close(50); ClearSensor(SENSOR_1); break; } } } sub trace_3(){ power(2); ClearSensor(SENSOR_1); while(1){ close(1); Off(OUT_B); if (SENSOR_2 < shiki -7){ RIGHT_t; } else if (SENSOR_2 < shiki -4){ RIGHT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ LEFT; } else { LEFT_t; } if(SENSOR_1 > 110){ power(3); close(50); ClearSensor(SENSOR_1); break; } } } シュートのプログラムは一周を回るようにして、その中で一番明るいほうに戻って、シュートをするように設定されます /*シュート*/ sub LIGHT(){ PlaySound(SOUND_UP); int sun_MAX = 0; int sensor_MAX = 0; close(20); ClearSensor(SENSOR_1); power(1); while(SENSOR_1 < 85){ RIGHT_t; if(SENSOR_3 > sun_MAX){ sun_MAX = SENSOR_3; sensor_MAX = SENSOR_1; } } tomaru(10); LEFT_t; until(SENSOR_1 < sensor_MAX); tomaru(10); } #ref(2015b/Member/cst321/Mission3/tracemap.png,80%,路線図); 図のようにtrace0からtrace3までの動きはどこで行われるかを示されています task main(){ /*回転センサ*/ SetSensor(SENSOR_1,SENSOR_ROTATION); /*トレース用センサ*/ SetSensor(SENSOR_2,SENSOR_LIGHT); /*探索用センサ*/ SetSensor(SENSOR_3,SENSOR_LIGHT); FWD;Wait(150); trace_0();//向かう tomaru(50); trace_1();//赤玉持ち LIGHT(); shoot; tomaru(20); ClearSensor(SENSOR_1); RIGHT_t; until(SENSOR_1 > 28); tomaru(10); ClearSensor(SENSOR_1); FWD; until(SENSOR_1 > 26); Off(OUT_B); FWD; until(SENSOR_2 < 48); open(7); Off(OUT_B); trace_2(); tomaru(10); FWD;Wait(100); trace_3(); tomaru(10); LIGHT(); shoot; trace_1(); } * キャッチプログラミング [#oecaddc4] ボールを探すのが難しいので、ボールを探さないまま、全てのラインに沿って「掃除」すればいいだろうと私たちが考えました。ですから、回収範囲を大きくして、二回ライントレースを行うことにしました。 そして、LOADINGという指示は、掃除機のようにボールを吸い込む動きです。 RELEASEという指示は、ボールを排出する動きです。 startimeは、交差点かどうかを判定せずにライントレースする時間です。 基本的に、ライントレースのプログラミングなので、特徴がありません。 int startime=300; #define CHECKCROSSTIME 25 #define fwd(OUT) Off(OUT);OnFwd(OUT) #define rev(OUT) Off(OUT);OnRev(OUT) #define TURNLEFT fwd(OUT_AC) #define LEFT Off(OUT_C);fwd(OUT_A) #define TURNRIGHT rev(OUT_AC) #define RIGHT Off(OUT_A);rev(OUT_C) #define STRAIGHT rev(OUT_C);fwd(OUT_A) #define BACK fwd(OUT_C);rev(OUT_A) #define ISNOTCROSS FastTimer(0) <= CHECKCROSSTIME || FastTimer(1) <= startime #define RELEASE rev(OUT_B); #define LOADING fwd(OUT_B); sub trace(){ ClearTimer(0); while(ISNOTCROSS){ if(FastTimer(1) < startime){ ClearTimer(0); } if(52 <= SENSOR_1){ TURNRIGHT; }else if(50 <= SENSOR_1){ RIGHT; }else if(41 <= SENSOR_1){ STRAIGHT; }else if(39 <= SENSOR_1){ LEFT; }else { TURNLEFT; } if(39 <= SENSOR_1) ClearTimer(0); } Off(OUT_AC); ClearTimer(0); Wait(100); } /* 直進する */ sub go_straight(){ STRAIGHT; Wait(30); ClearTimer(1); } /* 左折する */ sub turn_left(){ ClearTimer(1); ClearTimer(0); } /* 右折する */ sub turn_right(){ ClearTimer(1); while(ISNOTCROSS){ if(FastTimer(1) >= startime){ ClearTimer(0); ClearTimer(1); break; } if(53 <= SENSOR_1){ TURNLEFT; }else if(50 <= SENSOR_1){ LEFT; }else if(47 <= SENSOR_1){ STRAIGHT; }else if(44 <= SENSOR_1){ RIGHT; }else { TURNRIGHT; } } TURNLEFT; Wait(10); Off(OUT_AC); ClearTimer(0); ClearTimer(1); } task main(){ SetSensor(SENSOR_1,SENSOR_LIGHT); ClearTimer(0); LOADING; go_straight(); trace(); go_straight(); Off(OUT_AC); Wait(2300); ClearTimer(1); startime=900; trace(); startime=300; //turn_left();// //trace(); go_straight(); trace(); go_straight(); //turn_left(); trace(); go_straight(); startime=1400; trace(); startime=300; TURNRIGHT; Wait(10); Off(OUT_AC); RELEASE; Wait(300); BACK; Wait(100); TURNRIGHT; Wait(40); LOADING; ClearTimer(0); trace(); turn_left(); startime=900; trace(); startime=300; //turn_left();// //trace(); go_straight(); trace(); go_straight(); trace(); go_straight(); startime=1400; trace(); startime=300; TURNRIGHT; Wait(10); Off(OUT_AC); RELEASE; Wait(300); go_straight(); Wait(10); Off(OUT_ABC); } * 今までできなかったところ [#p7dd4717] キャッチの方のボールが探せない方法を「掃除機」の概念で何とか解決しましたが、シュートの方のズの図のようにそのPOINT Xの場所が固定できません。回転センサーにより生じる誤差だと考えられます。 そのPOINT Xの固定がさえできなければ、青いボールが捕まりません。結局、赤いボールしか打てません。 本番で、3回をやらせていただきましたが、一回目と二回目が完全に失敗で、やっと三回目は青いボールまでを捕まえて、シュートできるようになりました。 * 感想 [#k6a241ba] 今までやった課題と違って、この課題は4人の協力がなければ、きっとできないと思います。 4人で討論して、徹夜まで課題を何とか完成しました。本当にうれしいです。 私はプログラミングの方に意見とチェックすることしかやっていませんが、ロボットの構造の方は精一杯やりました。 悔しいですが、私はプログラミングの方が上手だと言えません。