目次
・競技時間はロボットAがSTART A地点のスタートラインを横切って、ロボットBがGOAL B地点のゴールラインに達するまで、あるいは審判が続行不能と判断するまで。
・ロボットAはSTART A地点から出発し、P地点におかれた赤いボールを拾って350mlのアルミ缶に当てる。その後、ロボットBがボールを回収する。引き続き青いボールについても同様の動作を繰り返す。ロボットBはボールを回収した後、最終的にGOAL Bまでボールを運ぶ。
・アルミ缶は中身が入っているものを使う。 RISのチームはアルミ缶の上に灯台としてランタンを置く。
・ボールがアルミ缶に当たる前にロボットBがボールに触ってはいけない。
・ロボットAはセンターラインを超えては行けない。
・アルミ缶を5cm以上動かした場合は減点
以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチームが20点満点で採点し、その平均点を求める。
得点の目安:
・ボールをつかむ動作 (2点)
・ボールを運ぶ動作、ライントレースの正確さ、滑らかさ(2点)
・ボールを投げる動作・正確さ(3点)
・ボールを探す動作(3点)
・ボールを回収してゴールまで運ぶ動作(2点)
・2台のNXTの連携の良さ(2点)
・自立型のロボットとしての形や動作の美しさ、斬新さ(3点)
・その他 (3点)
上の写真はロボットA。下の写真がロボットB。ロボットAはnqcでロボットBはnxcであるので通信することはできない。音を鳴らして合図をする事も考えたが、鳴らすことが出来る音が小さすぎて合図として使うことが出来なかったので通信はしないことにした。自分はロボットBの制作、プログラミングにはほとんど関わっていない。
ロボットBは超音波センサーでボールを探す。スタート地点付近から探し、ボールが缶の裏側にある場合は回り込んでボールをつかみにいくようになっている。
以下ロボットAについて説明する。今回使ったモーターは3つ。車輪部分に2つとアームを動かすのに1つ。出来ればアーム部分をボールをつかむ動作と投げる動作に分け、それぞれに1つずつモーターを使いたかったが、旋回などを行うためにどうしても車輪部分に2つのモーターが必要だったため断念した。なので、ロボット制作の中ではボールをつかむ動作と投げる動作をどうやって1つのモーターで行うかに1番悩んだ。また、使った光センサーは2つで、それぞれライントレースとランプの方向を探すのに使った。
アーム部分で大量に棒などを固定するためのパーツが必要となったために、土台部分は出来るだけそれらの部品を使わないようにつくった。しかし、ボールを乗せる土台を付けた他はほとんどドライブベースと同じである。
ボールをつかんだり、投げたりする部分である。制作初期の段階ではボールを乗せる土台に坂を作り、アームで抑え込んでいたボールを離すと自動的にボールが前に転がっていくというものを想定していた。しかし、完成したロボットを実際に動かしてみると、ボールが転がる勢いがなさ過ぎて真っ直ぐ転がらない、紙の折り目によっては戻ってきてしまうという問題があった。そこで、ボールを抑えつける部分の後ろに新たに部品を付けることによって、アームが持ち上がると新たに付けた部品がボールを押し出すようにした。これにより、ボールの勢いの問題は解消され、強くまっすぐにボールを投げられるようになった。ただし、新たに取り付けた部品より後ろ側にボールがあると、新たな部品がボールを抑え込んでしまうため拾える範囲は多少狭まったが、そこはプログラムを正確にすることでなんとかなった。また、そのままモーターにアームを接続するとアームの上げ下げが早くなりすぎてしまうため、4つの歯車を挟み勢いを弱めている。
ライントレースのための光センサーはボールを乗せる土台に付いている。ランプの方向を探すための光センサーはとても高いところに付いているが、これはランプの高さに合わせた結果である。実験段階ではランプを缶の上に乗せていなかったためそのままアームに付けていた。しかし、缶の上に乗せてみたところ光センサーがほとんど反応せず、無理やり高さをつけたことでこのようなこととなった。光センサーを部品で囲っているのは、正面の光のみを感知し、より正確にランプの方向を知るためである。
OnFwdとOnRevが逆になっているのはモーターの接続が逆になっていたからである。
int light_max = 0; int turn_time = 500; int time_max = 0; int t = 0; int s = 0;
sub light(){ SetSensor(SENSOR_1, SENSOR_LIGHT); SetSensor(SENSOR_2, SENSOR_LIGHT); ClearTimer(0); OnFwd(OUT_A);OnRev(OUT_C); while(FastTimer(0) < turn_time){ if(SENSOR_2 > light_max){ light_max = SENSOR_2; time_max = FastTimer(0); } } Off(OUT_AC);Wait(100); OnFwd(OUT_C);OnRev(OUT_A);Wait(turn_time - time_max); Off(OUT_AC);Wait(100); }
これはランプの方向を探すためのプログラムである。最初に1回転し周囲の光の強さを測る。そのうち1番光が強かった方向までの回転時間を覚えておく。これをtime_maxとする。次に1回転するのにかかる時間からtime_maxを引き、その時間だけ逆回転する。これで1番強い光の方向を向くことが出来る。
task main(){ SetSensor(SENSOR_2,SENSOR_LIGHT); SetSensor(SENSOR_1,SENSOR_LIGHT);
SetPower(OUT_B,5);OnFwd(OUT_B);Wait(50); OnRev(OUT_AC);Wait(200); OnRev(OUT_A);OnFwd(OUT_C);Wait(100); OnRev(OUT_AC);Wait(200); Off(OUT_AC);Wait(100); SetPower(OUT_B, 1);OnRev(OUT_B);Wait(100);
最初にアームを上げる。このときモーターBをOffにしないのは、Offにするとアームが徐々に下がりボールのもとにたどり着くまでに下がりきってしまうからである。次にボールのもとまで進む。これは時間制御で行っており、初期位置で線に合わせていればほぼ確実にボールを掴むことが出来るようになっている。
OnRev(OUT_C);OnFwd(OUT_A);Wait(150); OnRev(OUT_AC);Wait(300); while(light_max < 65){ OnRev(OUT_AC);Wait(50);Off(OUT_AC); light(); } PlaySound(SOUND_CLICK); light(); SetPower(OUT_B,5);OnFwd(OUT_B);Wait(50);
最初に光センサーがランプの光を感知できるように、ある程度ランプに近づくようにしている。これは時間を決めて方向を決めているが、少し近づけば良いだけなので、回る時間の設定もその後進む時間の設定も適当である。 ある程度近づいたらサブルーチンを使って光を探し始める。サブルーチンの中で周りの光の強さを測りlight_maxを決めるが、このlight_maxが一定値を超えると再度サブルーチンを実行しボールを投げるようになっている。この部分は方向が少しズレたり、違う光の方向に向かっていったりと当日まで頭を悩ませたが、先生の光センサーを囲めばいいという助言により瞬時に解決した。
OnFwd(OUT_C);OnRev(OUT_A);Wait(150); Off(OUT_AC);Wait(100); OnRev(OUT_AC);Wait(200); OnRev(OUT_AC);until(SENSOR_1 < 41); Off(OUT_AC); PlaySound(SOUND_CLICK);Wait(100);
最初に右斜め後ろを向くように100°~150°くらい回る。その後、黒線を一本越えるように進む。越えたい線とその次の線の間の距離は大きいので(真ん中の線は黒線ではない)前の段階でランプとの距離が上手くとれていれば余裕を持って目標の線を越えることができる。なので、進む時間の設定は少し長めにしている。線を越えた後は次の黒線まで進み、ライントレースを始める。
ClearTimer(1); while(FastTimer(1) < 50){ if(SENSOR_1 > 49){ OnRev(OUT_A);OnFwd(OUT_C); } else if(SENSOR_1 > 46){ OnRev(OUT_A);Off(OUT_C); } else if(SENSOR_1 > 40){ OnRev(OUT_AC);ClearTimer(1); } else if(SENSOR_1 > 37){ OnRev(OUT_C);Off(OUT_A);ClearTimer(1); } else{ OnRev(OUT_C);OnFwd(OUT_A);ClearTimer(1); } } OnRev(OUT_A);OnFwd(OUT_C);Wait(80); OnRev(OUT_AC);Wait(150);Off(OUT_AC);Wait(100); SetPower(OUT_B,5);OnFwd(OUT_B);Wait(50); SetPower(OUT_B,1);OnRev(OUT_B);Wait(100);Off(OUT_B);
ライントレースは交差点を探すのと同じ要領で角を探す。黒線の左側をトレースし、真っ白なときは右旋回、少し白いときは右折、少し黒いときは左折、真っ黒なときは左旋回、白と黒の中間ぐらいのときは直進する。真っ白なとき以外でタイマーが、リセットされるようになっており、タイマーが一定時間以上リセットされずに続くと、そこを角だと認識する。その後時間制御でボールの方を向き少し進みボールを掴む。時間制御は角を目印にしており正確にボールの元へ進み掴むことができる。
OnFwd(OUT_A);OnRev(OUT_C);Wait(350); OnRev(OUT_AC);Wait(200); while(SENSOR_2 < 50){ OnRev(OUT_AC);Wait(50);Off(OUT_AC); light(); } PlaySound(SOUND_CLICK); light();OnRev(OUT_A);OnFwd(OUT_C);Wait(35); Off(OUT_AC);Wait(100); SetPower(OUT_B,5);OnFwd(OUT_B);Wait(50); OnFwd(OUT_AC);Wait(100); Off(OUT_AC); }
一回目にボールを当てたときとほぼ同じである。 ボールを投げた後少し下がって止まる。
今回は最後の課題ということで、今までの総まとめのような感じだった。これまで習ったことを駆使して課題をクリアするため試行錯誤するのは意外なことにとても楽しかった。自分たちのグループはnqcとnxcの異なる二種類のロボットを使ったが、自分のことばかりやってnxcを作った人には負担をかけ過ぎてしまった。もっと手伝えることがあったのではないかと思う。結果は2個目のボールを掴むところまでしかいけず、完璧ではなかったけど十分上手くいったと思うし満足できた。