三つに分けることが出来る。大なり小なりそれぞれの部分で工夫があるので、順を追って説明していく。このコップを掴む機構はゼミにて松本先生がお手本として皆にお披露目した物をそのまま真似ている。大枠の仕組みには手を加えずに、それを補助する多少の工夫を付け加えたのが私たちがしたお仕事である。具体的には、先ずコップに触れて摩擦で固定するタイヤのアームからの高さを弄っている。タイヤの位置が低いと重心の位置からしてコップが回ってしまうからだ。本番で生かされることはなかったが、持ち上げたコップの縁が被せられるコップに当たり角度を垂直にしつつ被さるという仕組みもあった。画像の下部をご覧いただくと、青い光センサーの傍から左右に伸びる棒が目に入る。これは紙コップに機体が接近する際に、紙コップを光センサー及びアームの正面に誘導するの為の物だ。長すぎると紙コップに予期しない場所で当たってしまい、逆に短すぎると機能を果たさないので多少の調節を行った。それらとは別に正面の光センサーの位置も調整している。この調整というのが何処にどの様につけるのかという内容なのだが、アームにつけずにドライブベース本体から伸ばした棒につけている。その理由としては、NXTと違い超音波センサーが無いRCXでは離れた位置にある紙コップを認識する為に、光センサーを使うしかないと判断した為だ。アームに光センサーを付けると紙コップを持ち上げる際に光センサーも持ち上がってしまい前方の光を認識する機能を果たさなくなる。すると紙コップを持ち上げるまではいいのだが、その紙コップを被せる紙コップを探すの方法がライントレースと時間指定しか使えなくなってしまう。モーターとアームを繋ぐギアのちょっとした工夫。ゼミ中にも紹介されていたことだが、ギアを回す時間の指定を間違い、力が掛かりすぎてパーツが破損するのを防ぐ白いギアが噛ませてある。このギアは一定以上の力が掛かると空回りするようになっているのだ。モーターに取り付けられている螺旋状の黒いギア、ウォームギア。このウォームギアに普通のギアを噛ませると、一回転でギアの歯を一つ送り出すようになる。これによって紙コップを掴む機構がゆっくりと、尚且つ力強く動くこととなる。正面からの画像でも見えていたプーリー。この部分は機体の動き自体にはなんら影響しないのだが、人間が機体に手を加える時とても役立つ。その状況なのだが、まずこの機体のコップを掴む機構がモーター一つで動いていることが関係する。通常時はギアが動けば先端のアームが開閉するのだが、そのアームが閉じきるとギアが固定され、回転をそのままに伝えて機構が上に跳ね上がるのだ。その結果、先ずそもそもがウォームギアを取り付けているのもあって、アーム側を動かすとギアを回すのに多大な力が掛かりパーツが破損する。モーター側を回そうにも跳ね上がったアームが邪魔で解体するしかないという状況になる。そこで、モーターとウォームギアの同一軸上にプーリーを取り付けた。このプーリーの役割は跳ね上がったアームが完全にモーター近辺にくっついてしまうのを防ぎ、モーターの軸を回すのに掛かる力を軽減することだ。フィジカル・コンピューティングをするにおいてトライ&エラーは必要不可欠であり、現に私がこの機体を作るときもそうであった。失敗の度に元に戻すのを楽にするこのプーリーは小さい工夫でありながら大きな効果があったことは間違いない。機体の後部、RCX本体の下に取り付けられ重さを支えていたパーツだ。普通のタイヤではなくキャスターなのかと言うと、摩擦を出来るだけ少なくする為なのだ。前部にある一対のタイヤでこの機体は動いており、汚い書き方だが後部はケツを振るような構造になっている。前部のタイヤが動くに際して後部は左右に振られることとなるのだが、後部を支えるパーツがキャスターではなくタイヤであった場合、地面との間に強い摩擦が生まれることとなる。この摩擦はパーツに負荷を掛ける上に動きの滑らかさを阻害するので、極力排除したいものなのだ。実際に機械を動かす以上、人は摩擦と振動に頭を悩ませなければならない。モーター二つが接触している辺りドライブベースがRCXのお手本となる形と違うことが目につく。改造をした理由としては極力機体を小さくして小回りを良くし、紙コップとの無駄な接触を防ぐことがある。次にコップを持ち上げる機構の方に伸びる、光センサーのついた棒。この棒の長さ・太さの調整が容易かったのもある。長さは紙コップの判別をする光センサーの位置に影響し、太さはライントレースに使う二つの光センサーが機能するかどうかに影響するので重要だ。こちらの機体は、機体本体の構造にもプログラムにも触れていなかったので私に説明できることはない。私の親愛なる班メンバー三人のページを見ていただければ幸いである。赤色の矢印が私が作ったメイン機体、青色の矢印がサブ機体の移動経路であるとして上の図を見て頂きたい。メイン機体がコースを横に走る一本のラインを中心に動き紙コップをはめていき、サブ機が紙コップB・Cをメイン機が通るライン上に揃えていくというのが大まかな流れだ。順序立てて説明するとメイン機がコップAを運ぶサブ機がコップBを動かすメイン機がコップBを運ぶサブ機がコップCを動かすメイン機がコップCを運ぶただこれだけである。肝としては、メイン機体が紙コップの色で数字を判別の後、紙コップ2近くの交差点でルートを数字に応じて変更することだろうか。全般に同じ内容を繰り返し過ぎで頭の悪いプログラム。ライントレースをサブルーチンにするのではなく、インライン関数にして他のサブルーチンに引き込めば相当小さくなるのではなかろうか。打ち込む時点でRCXから見てマクロとインライン関数に大差がないということを知っていたならば、まだマシなプログラムを作られただろう。OnFwd(OUT_A);OnRev(OUT_C);Wait(180);Off(OUT_AC);今回は光センサー二つでラインを挟むようにしてライントレースし、尚且つ交差点判別が容易になったので右旋回と左旋回を削除した。結局右左90度に旋回することが多々あったのでそれぞれ作るべきだったのではないかと思う。OnRev(OUT_B);Wait(130);Off(OUT_B);/*グローバル変数。コップの色に応じて1〜3の値をとり、点Aからのパターン分岐を決める。number=0;グローバル変数は全てのタスクに作用するので、あまり勧められた物ではないということを聞いてはいたが、今回は変数を幾つも使う訳でもなく長いプログラムでもない、そして何よりサブルーチンを使ったことで多少なり変数を使えるタスクが複雑になることが予想されたので採用した。if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){//左側が黒turn_left1;Wait(STEP);}else{go_forward;//両方黒Wait(STEP);}}今回のプログラムの失敗、一番の間違いがこのライントレースのサブルーチン化である。サブルーチンはメインタスクとは別に起動してある物で、その都度メインタスクから繋いで使う為容量を節約できるのだが、ライントレースは0.01秒毎に行うので何度もメインタスクがアクセスをすることとなる。何よりもサブルーチンの中にサブルーチンを含むことは出来ないので、このライントレースは単体で使うしかない。これをインライン関数にしておけば他のサブルーチンに組み込んで綺麗な見た目に出来たし、容量の減少によって作業効率も良くなった筈だ。プログラムの内容としては、論理積を使って直進、右折、左折を使い分けてライン上を動く平平凡凡のライントレースだ。ここからは紙コップを掴んだ後に行うパターン分けされた運搬作業のプログラムだ。他の部分に変数"number"に数が与えられるプログラムがあるので分かりづらいかもしれないが、それぞれ変数の値は紙コップの色で与えられていて、色によって運搬するプログラムが変わる物と考えて頂ければ差支えない。イメージがしやすいように、「この機体で狙っていた動き」で使った図を何度か挟み込むこととする。if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){turn_left1;Wait(STEP);}else{go_forward;Wait(STEP);}}上のライントレースに関するサブルーチンの箇所でも書いたが、ライントレースをインライン関数にしなかった結果、このようなライントレースのプログラムがいたる所に散らばっている。何度も同じ説明はしないで以降は飛ばすので、ご了承を。ライントレースを括っている"while"の条件を日本語に起こすと「前方を向いている光センサーが平時と違う値を読み取ったらライントレースを終えなさい」といったところか。前方に光を反射するしないに関わらず物体が何かあったらライントレースを止めるようにしていて、これによって紙コップがあることを認識させる。この部分が全体のプログラムでも一番の肝で、ロボコンにて私が失敗した一番の原因でもある。go_forward;Wait(10);//紙コップに完全に接触するまで前進。そこからの位置調整も要調査Off(OUT_AC);cup_down;U_turn;紙コップを被せて再び次のコップをとる為に方向転換をしてライントレースを始める。if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){turn_left1;Wait(STEP);}else{go_forward;Wait(STEP);}}紙コップ2から一番近い交差点までを論理和でもってしてライントレースさせている。交差点から紙コップ2へ向かうのだが、車体の大きさに対して交差点から紙コップまでの距離が近いので、一先ず逆方向に進ませて距離を離してからUターンして紙コップに向かわせている。if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){turn_left1;Wait(STEP);}else{go_forward;Wait(STEP);}}go_forward;Wait(20);//紙コップに完全に接触するまで前進。そこからの位置調整も要調査Off(OUT_AC);cup_down;OnRev(OUT_AC);Wait(130);紙コップを被せた後に紙コップが揃えられる軸に戻る。if((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)){turn_left1;Wait(STEP);}else{go_forward;Wait(STEP);}}go_forward;Wait(10);while((SENSOR_1>THRESHOLD)||(SENSOR_3)>THRESHOLD){//交差点を認識するまで前進させるgo_forward;}ここでは一つの用紙中央にある交差点まで向かわせてから紙コップ3へ向かわせようとしている。後に出てくるプログラムの話ではあるが、タイマーを使った方がプログラムが綺麗に、尚且つ確実なライントレースが出来ると分かってしまっている。本来ならここも直すべきなのだが、閾値の設定にてこずり手が回らなかった。turn_right0;Wait(75);while((SENSOR_2>35)&&(SENSOR_2<47)){//紙コップを認識するまでgo_forward;}go_forward;Wait(25);Off(OUT_AC);cup_down;紙コップ3を認識するまで前進し紙コップを被せる。一枚の用紙中央の交差点まで向かったのは右方向に90度旋回し前進するだけで紙コップ3に辿り着けるため。OnRev(OUT_AC);Wait(110);while((SENSOR_1>THRESHOLD)||(SENSOR_3)>THRESHOLD){//交差点を認識するまで前進させるOnRev(OUT_AC);}turn_right0;Wait(75);}コップを被せた後は交差点まで後退して、ラインを認識後に右90度旋回をして紙コップを再び探し始める。if((SENSOR_2<47)&&(SENSOR_2>37)){number=2;}else{number=3;}//センサーの値に応じてnumberに値を入れるcup_up;U_turn;}開始からライントレースを経て紙コップを掴む、色を読み取るまでをインライン関数化したもの。何度も使う訳ではないので、インライン関数にせずにメインタスクに入れてしまえばよかった。if((SENSOR_2>35)&&(SENSOR_2<47)){number=2;}else{number=3;}//センサーの値に応じてnumberに値を入れるcup_up;U_turn;ClearTimer(0);//タイマー設置"carry_cup()"が紙コップAがあった場所を超えたところからのプログラムなので、そこまで辿り着き尚且つそこが紙コップAがかつてあった付近であると認識できるプログラムが必要になる。交差点判別回数に頼るとラインを挟んでセンサーが両方黒と判定したら交差点と認識するプログラムの都合、ラインへの角度などによって安定しなかったので、時間を使うこととした。今見直してハッキリと分かることだが、全般に雑である。プログラムの説明にもあったようにライントレースのサブルーチン化、インライン関数化が相当お粗末でプログラム全体の容量が膨れ上がっている。プログラムの説明文が尻すぼみに量が減っていっているが、これは手を抜いているのではなくライントレースが多すぎるのと同じ内容を説明しなかっただけなのだ。これだけでプログラムがダメダメなのは自明なのだが、それだけに留まらず紙コップの識別も酷い。40前後と言ったところか。これを見る分には十分に識別できそうだが、実際はここに紙コップがない通常時の値が入る。色の判別をさせるだけならば兎も角、紙コップが前方に有るかどうかすら光センサーの値から判別させるのが祟って、青い紙コップを認識させずらかった。平時の光センサーが得る値と青紙コップを捉えた時の値が近かった為だ。この光センサーによる判別は場所に成否を大きく左右される。値の調節をしきれずに大失敗するとロボコン本番のようになってしまうのだ。ここまで来るとプログラムの設計ミスとしか言いようがない。先生曰く日除けをつけてセンサーの値を安定させるべきだったようだが、それ以前に完全に固定の動きをさせて、紙コップの色を識別することのみに光センサーを使うべきだったのではないかと後悔している。悔やんでも悔やみきれない。