・4段に積まれた空き缶を運びだし、ゴールに入れる。
・競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
・2隅のコーナー(30cm四方)からスタートする。
・スタート時のロボットは2個を越えないこと (スタート後はいくつに分裂してもかまわない)。
・開始の合図から5秒以内にRCXのスタートボタンを押す作業を完了すること。
・競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
・途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
・基本得点は、半分以上ゴールに入った空き缶のみ得点の対象になる。
・技術点は、以下の方法で計算する。
・空き缶までたどり着く動作 (3点)
・空き缶を運ぶ動作 (転がす・掴むなど) (4点)
・空き缶をゴールに入れる動作 (2点)
・2台以上のロボット、あるいは単体のロボットの場合は2台のRCXの連携の良さ(3点)
・自立型のロボットとしての形や動作の美しさ、斬新さ(3点)
・その他 (5点)
図のように走行する。
アームについて
・最初は黒いレゴパーツを使い作成したが、重くなりすぎることが判明。棒パーツをつなげて軽いアームに作りなおした。
・アームの下部(一番下の缶をつかむ部分)と上部(一番上の缶をつかむ部分)にゴムを渡し、缶をがっちりキャッチできるようにした。
アームを持ち上げる機構について
・ギロチン台のような形のこの機構は、最初は接続が甘く取れやすかったが、がっちり補強した結果、最終的にはロボットの中で一番頑丈な機構になった。
・持ち上げる時は、ベースではなくこの機構の上部をつかんで全体をぶら下げるように持たなければならない(ベースを持つと外れます)。
・アームが缶をつかんだ時に持ち上げられるか試してみたところ、モーター1つでは無理だったので、モータ−2つをギアで接続して2倍の動力で持ち上げるようにした。
・ゴールに入れるための持ち上げの高さも足りなかったので、パーツを継ぎ足してより高く上がるように改良した。
↑モーターを2つ使用した。
・まず缶を運ぶロボットをどのようにすればいいのかわからなかった。ロボットを1つにするのか2つにするのかで悩んだ。
・アームの部分が前方に出ているため、前後のバランスがなかなかうまくいかなかった。 アームがどうしても前に傾いてしまい、補強に苦労した。
・持ち上げる構造にモーター2つが必要になったことで、後からモーターを付け加えたので、レゴパーツやギアの組み合わせに苦労した。
・アームの高さ、モーターの数、光センサー、補強のパーツなど、あとから修正しなければいけないことに気付いた点が多く、パーツの組み合わせに苦労した。
上のプログラム(アームの開閉と上下)
task main() { SetPower(OUT_C,7); //モーターのパワーを7にする OnFwd(OUT_B); //2つのモーターを使って OnRev(OUT_C); //アームを上げる Wait(1900); OnRev(OUT_A); //円に差し掛かったあたりでアームを開く Wait(500); OnRev(OUT_B); //アームを下ろす OnFwd(OUT_C); Wait(50); Off(OUT_B+OUT_C); Wait(100); OnFwd(OUT_A); //アームを閉じて缶をつかむ Wait(50); OnFwd(OUT_B); //アームを上げて缶を持ち上げる OnRev(OUT_C); Wait(2500); OnRev(OUT_B); //ゴールの前にきたのを見計らって OnFwd(OUT_C); //アームを下ろして缶を置く Wait(50); Off(OUT_B+OUT_C); Wait(100); OnRev(OUT_A); //アームを開く Wait(20); Off(OUT_A); }
下のプログラム(ロボット全体の移動)
#define THRESHOLD 40 #define RUNTIMEA 60 #define RUNTIMEB 65 task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); //センサー1と2は SetSensor(SENSOR_2,SENSOR_LIGHT); //光センサー int n; //変数nを設定する Wait(100); //アームを持ち上げるため停止して待つ OnRev(OUT_A+OUT_C); //スタート位置から前進する Wait(250); Float(OUT_A+OUT_C); OnFwd(OUT_A); //右に曲がる OnRev(OUT_C); Wait(95); Float(OUT_A+OUT_C); OnRev(OUT_A+OUT_C); //ライン付近まで前進する Wait(410); OnFwd(OUT_C); //少し左を向く Wait(70); Float(OUT_A+OUT_C); OnRev(OUT_A+OUT_C); //右側の光センサーが黒色を感知して until(SENSOR_2<THRESHOLD); //2つのセンサーがラインをまたぐまで前進する Off(OUT_A+OUT_C); //いったん止まる Wait(100); ClearTimer(0); while(Timer(0)<=RUNTIMEA) //タイマーがRUNTIMEA以下のとき実行 { if(SENSOR_1>THRESHOLD){ //両方の光センサーが if(SENSOR_2>THRESHOLD){ //白を感知したとき OnRev(OUT_A+OUT_C); //前進 } else{ //右の光センサーだけ黒を感知したとき Off(OUT_A); //右に回転 OnRev(OUT_C); } } else{ //左の光センサーだけ黒を感知したとき if(SENSOR_2>THRESHOLD){ OnRev(OUT_A); //左に回転 Off(OUT_C); } else{ //両方の光センサーが黒を感知したとき OnRev(OUT_A+OUT_C); //前進 } } } OnRev(OUT_A); //斜め左の缶の方向を向く OnFwd(OUT_C); Wait(75); OnRev(OUT_A+OUT_C); //少し前進してライン上から離れる Wait(20); n=0; //nを0にする while(n<2){ //nが2以下のとき実行 if(SENSOR_1>THRESHOLD){ //両方の光センサーが if(SENSOR_2>THRESHOLD){ //白を感知したとき OnRev(OUT_A+OUT_C); //前進 } else{ //右の光センサーだけ黒を感知したとき OnRev(OUT_C); //左に回転 Off(OUT_A); } } else{ //左の光センサーだけ黒を感知したとき if(SENSOR_2>THRESHOLD){ OnRev(OUT_A); //右に回転 Off(OUT_C); } else{ //両方の光センサーが黒を感知したとき n=n+1; //変数nに1を加える Off(OUT_A+OUT_C); //勢いを抑えるために一旦停止 Wait(10); OnRev(OUT_A+OUT_C); //前進してラインを超える Wait(25); } } } while(n<3){ //nが3以下のとき実行 if(SENSOR_1>THRESHOLD){ //両方の光センサーが if(SENSOR_2>THRESHOLD){ //白を感知したとき OnRev(OUT_A+OUT_C); //前進 } else{ //右の光センサーだけが黒を感知したとき OnRev(OUT_C); //左に回転 Off(OUT_A); } } else{ //左の光センサーだけが黒を感知したとき if(SENSOR_2>THRESHOLD){ OnRev(OUT_A); //右に回転 Off(OUT_C); } else{ //両方の光センサーが黒を感知したとき n=n+1; //変数nに1を加える Off(OUT_A+OUT_C); //停止する } } } OnRev(OUT_A+OUT_C); //停止した位置から少し前進して Wait(10); //缶をつかめる位置まで移動 Off(OUT_A+OUT_C); //アームが缶をつかみ持ち上げる Wait(920); //動作が終了するまで待つ OnRev(OUT_A+OUT_C); //回転するときにアームが障害物に Wait(40); //当たらないように少し前進する OnRev(OUT_A); //回転して行きに進んできた方向を向く OnFwd(OUT_C); Wait(210); Float(OUT_A+OUT_C); OnRev(OUT_A+OUT_C); //前進して円を抜ける Wait(200); until(SENSOR_2<THRESHOLD); //右の光センサーが黒を感知したとき OnFwd(OUT_A); //右に回転してライン上に OnRev(OUT_C); Wait(40); ClearTimer(0); //タイマーを0にリセットする while(Timer(0)<=RUNTIMEB) //タイマーがRUNTIMEB以下のとき実行 { if(SENSOR_1>THRESHOLD){ //両方の光センサーが if(SENSOR_2>THRESHOLD){ //白を感知したとき OnRev(OUT_A+OUT_C); //前進 } else{ //右の光センサーだけが黒を感知したとき Off(OUT_A); //右に回転 OnRev(OUT_C); } } else{ //左の光センサーだけが黒を感知したとき if(SENSOR_2>THRESHOLD){ OnRev(OUT_A); //左に回転 Off(OUT_C); } else{ //両方の光センサーが黒を感知したとき OnRev(OUT_A+OUT_C); 前進 Off(OUT_A); } } } OnFwd(OUT_A+OUT_C); //少し後退する Wait(50); OnRev(OUT_A); //少し左を向く OnFwd(OUT_C); Wait(45); OnRev(OUT_A+OUT_C); //前進する Wait(150); OnRev(OUT_A); //もう一度左に向きを変える OnFwd(OUT_C); Wait(40); OnRev(OUT_A+OUT_C); //ゴールの前まで前進 Wait(100); Float(OUT_A+OUT_C); //停止して終了 }
・ロボットのサイズが大きくなってしまったため、ポイントごとに前進や回転の時間を微調整しながら完成させました。缶をつかんだ後に、少し前進してから回転して戻る部分は、ロボットの大きさを考えて付け足しました。
・上下のロボットで通信を使わなかったため、それぞれの動くタイミングが合うように工夫していきました。
・缶の周りに描かれている円をうまく利用して、缶の正面を向き、距離もあわせて止まるように考えて作ることができました。変数を使って調整することで、ミスなく進むようなりました。
・ロボットのサイズが大きく、木の障害物をよける部分で苦労した。
・ライントレースを時間で調整したため、微妙な誤差で失敗してしまうことが多く、細かい調整に苦労した。
・微調整のために何度も何度も走らせる必要があり、時間が掛かった。
・走らせるごとに電池の消耗による誤差も生じてきて、さらに調整が必要になった。ギリギリまで調整しなければいけなくて大変だった。
基本点20点、技術点17.8点、合計37.8点で1位
4つ全ての缶を運びきって優勝できたことに大満足です!
優勝賞品のロボットがとてもかわいいです。
何より結果を出すことができたのが良かったです。時間が掛かりながらも、全員でアイデアを出し合って、協力しながらやることができました。
もっと工夫したロボットを作ることができたと思う。例えば…
・回転センサーを使って正確な距離を進むロボットを作る
・タッチセンサーを距離の基準とするように使う
・2つのRCXで通信を使ってタイミングを合わせる
・サブルーチンを使ってプログラミングを短く、わかりやすいものにする
etc...
改善できるポイントはまだまだあったと思います。
もっと効率よく作業をすすめていければよかったと感じました。
コメントをどうぞ。