上図の黄色の缶をできるだけ多くGOALと書かれているエリアに置くと高得点が得られる。この際、n段目詰まれた缶の得点は5n点となる。†まずどのようなロボットで、どんなプログラムで缶を積むかを考えた。経て変わったが、最終的に固まった方針は以下のとおりである。最初期の段階ではフィールド上の9つの缶全てを使い、3×3の塔を建設するつもりだった。缶を拾いに行く順番は下記のとおりである。(アラビア数字→アルファベット→ローマ数字)初期理想案しかしプログラム面で時間が足りない見通しとなり、最終的にSTART近傍の3つの缶を使って塔を建てることになった。その手順が下図である最終案プログラミングの方向としては、段階をカウントするための変数(nFase)を設定し、その値に応じてラインのどちらをトレースするか、缶を探知した時にどうするかなどを変えていくことにした。今回ハードウェア作成は主に他のメンバーたちがやってくれた。†このロボットの最大の特徴は、このアームの形状である。下部に設置されたプレートが缶の下のくびれた部分をすくい取り、左右から缶をホールドするだけでなく、下から缶を支えられるためどんなに激しく動いてもずり落ちたり飛び出したりすることはない。設計上は缶を3つ積んだ状態で持ち続けることができる。弱点としては、アームが重くなってしまったことで水平を保ちにくくなってしまったことがある。その点は黄色の輪ゴムで張力を発生させ、傾きを最小限に抑えることができた。二台のNXT本体をL字に配置し、極力空間の無駄をなくすとともにボディ全体の剛性が増した。アームが伸びた時でも重心が安定しているのもこのレイアウトの利点と言える。†その他の点で大まかに工夫されている点は以下のとおり超音波センサの精度を向上させるために、センサは縦置きにしている増大したアーム・車体重量を動かすためにギアを多用している前進することで缶がバンパーの中央に固定されるように形状を工夫し、さらにその直上にアームを設置することで、そのまま缶を積むことが可能になった。走行用プログラムはマスター、缶を掴むプログラムはスレーブが担当した。OnFwdSync(BOTH,SPEED2,100);//時計回りに旋回。OnRL(-SPEED1,SPEED1);//時計回りに旋回。音波探知用にスピードを落としている。"arm1.rxe"//アームを開き、つかむ準備をするプログラムを定義しなおした。1000//ゴールの交差点に止まったあと、ゴール中央を向くための回転に必要な時間。523//音程C、E、Gを指定。//走行駆動系のギア比(24:8)。r)//引数r[cm]だけ進むのに必要な回転角を導くマクロ。MAXCross)//右側の光センサを使ってライントレースを行いつつ、引数MAXCrossの分だけ交差点を感知するサブルーチン。交差点の判定は左右の光センサが同時に閾値を下回ったことで行う。MAXCross)//同じく左側の光センサによるライントレースと同時に交差点判定を行う{nCross=0;while(nCross<MAXCross){until((SL<=THRESHOLD)&&(SR<=THRESHOLD)){traceL();Wait(STEP);}nCross++;PlaySound(SOUND_UP);until((SL>THRESHOLD)&&(SR>THRESHOLD)){go_forward;Wait(STEP);}}}上記二つの交差点判定プログラムは机上の空論に終わった。原因としては、交差点以外でもカーブで2つのセンサが反応してしまうこと、仮に交差点を認識してもそこから両方のセンサを白の部分へ導けないことがあること、などが挙げられる。catch()//持っている缶を新しい缶の上に載せ、掴み、また持ち上げる一連の動作。{angleB=GetAngle(RANGE4);RotateMotor(BOTH,SPEED1,-angleB);//缶をホルダーの中に押しこむために少し前進するPlayTone(262,400);//ネット上で見つけたメロディー。後述出典参照Wait(500);PlayTone(294,400);Wait(500);PlayTone(300,400);Wait(500);PlayTone(294,400);Wait(500);RemoteStartProgram(CONN,arm_down);//スレーブにアームを開かせるWait(5000);ReceiveRemoteNumber(MAILBOX1,true,msg);if(msg==SIGNALON){PlaySound(SOUND_CLICK);}else{PlaySound(SOUND_FAST_UP);}angleA=GetAngle(RANGE2);RotateMotor(BOTH,SPEED2,angleA);//アームの伸びに合わせ後退するRemoteStartProgram(CONN,arm_up);//スレーブに缶を掴ませるPlayTone(DO,120);Wait(150);//達成感のあるメロディー。一回ごとに半音ずつ上昇させたかったPlayTone(MI,120);Wait(150);PlayTone(SO,120);Wait(150);PlayTone(DO*2,240);Wait(300);PlayTone(SO,120);Wait(150);PlayTone(DO*2,360);Wait(450);Wait(10000);if(msg==SIGNALON){PlaySound(SOUND_CLICK);}else{PlaySound(SOUND_FAST_UP);}RotateMotor(BOTH,SPEED2,-angleA+angleB);//つかむ動作の開始点まで戻る。build()//ゴールで缶を載せるだけのプログラム。今一度、缶を掴む順番を載せておく。main()//スタートからゴールまでの一連の流れを記述したプログラム{SetSensorLight(S1);SetSensorLight(S2);SetSensorLowspeed(S3);nFase=0;//第0段階開始(ラインに乗るまで)msg=SIGNALOFF;until(BluetoothStatus(CONN)==NO_ERR);find_line();start_traceR();nFase++;//第一段階開始(一つ目の缶をつかむまで)while(SS>RANGE1){traceR();Wait(STEP);}Off(BOTH);catch();nFase++;//第二段階開始(2つ目の缶をつかむまで)while(nFase<3){until(SS<RANGE3)//缶を感知するまで回転し続ける{u_turnRCW;Wait(STEP);}while(SS>RANGE1)//感知したらホルダーに格納されるまで前進{go_forward;Wait(STEP);}Off(BOTH);catch();nFase++;}while(nFase<4)//第三段階開始(3つ目の缶を格納するまで){until(SS<RANGE3+3){u_turnRCW;Wait(STEP);}u_turnCW;Wait(200);Off(BOTH);while(SS>RANGE1){go_forward;Wait(STEP);}Off(BOTH);//3つ目の缶は掴まず、ホルダーで抱えたまま進み、ゴールで缶を2つ載せるnFase++;//第四段階開始(缶をゴールに運び、塔を建てるまで)}until((SR<THRESHOLD)||(SL<THRESHOLD))//反転し、ライントレースに戻る{u_turnRCW;}find_line();start_traceL();search_crossL(2);//2つ目の交差点を過ぎたところで停止、缶を下ろすOff(BOTH);build();go_back;Wait(3000);u_turnRCW;Wait(BUILD_RAG);}コース上の缶に番号をつけ、その順番でプログラムが進むよう設計した。具体的には、変数nFaseを設定し、缶を掴む動作が繰り返されるたびにnFaseに1を足していきフェイズが進行する仕組みである。便宜上whileをつかってnFaseの値の真偽を判断しているが、繰り返しを前提にしているものではない。当初は4つの缶を積み上げる計画だったが、時間の都合で最終的に3つの缶を積み上げた塔を建てることを目指した。いう意図でプログラムはできているが、一度も最後まで行けたことはない。理由として、缶から缶までの移動を周囲の影響を受けやすい超音波センサを用いたこと、ライントレースの制度が低くさらに交差点の判定がうまく機能しなかったことが挙げられる。いずれにせよプログラムの練り上げに圧倒的に時間が足りなかったことは否定しようのない事実である。main(){until(BluetoothStatus(CONN)==NO_ERR);RotateMotorEx(OUT_BC,15,450,0,true,true);Wait(1000);RotateMotor(OUT_A,30,48);Wait(1000);PlaySound(SOUND_FAST_UP);Wait(1000);RotateMotorEx(OUT_BC,40,-450,0,true,true);Wait(1000);SendResponseNumber(MAILBOX1,SIGNALON);}アームの開閉角度48度と昇降角度450度の調整には最後まで時間を使ったところでもある。先述した通り、圧倒的に練り上げが足りなかった。原因として考えられるのは、無駄に複雑なプログラムを組もうとして一度に大量の書き換えを行い、閾値の調整や変数の設定などの基本的なことを怠ったことだ。2つの光センサによる交差点の判定を試みたが、全くうまく行かなかった。理由は先述したとおりだ。今となっては前半のような、単一の光センサでも変数のカウントによって交差点を判別できるプログラムを構築したほうが信頼性が高いと思える。ハードに頼ってソフト開発を怠った典型だ。†アイデアは尽きなかったが、完成できたものは一つもなかった。最後までやり遂げずとも、とりあえず動くところまで根気を出して調整する努力が必要だった。ハードウェア開発に比べ、ソフトウェア開発は延べ時間が足りなかった。結局最後まで想定した動きを実現させることができず、プログラミングの重要さ、ハードとソフトのバランスの大切さを実感した。完成はせずとも、今回は創造的で個性的なメンバーがそろったので非常にクリエイティブな開発になった。この経験はなかなか得られないものだと思う。今一度メンバーに感謝したい。ありがとうございました。