課題2について †メンバー紹介 †今回は、4人で課題に取り組むことになった。ここに参加メンバーを記しておく。 ・kiyomizu(私) ・suiden ・ ・ryu-abe 課題2の内容 †まず、課題2の内容やルールを確認したいと思う。今回は、ロボットコンテストをクラス全体で行うとのことでルールが前回の課題1より増え、新たに評価基準も設けられている。すべてをここに記すとレポートが煩雑になると考えられるため、以下に大まかなルールや内容のみ記しておく。 内容 1.下図のスタート地点にロボットの機体を置き、プログラムを実行する。(これ以降、機体に触れてはならない。) 2.図の左半分に置かれている紙コップ(番号が1から順に振られているもの)を右半分へ運搬する。 3.右半分に置かれている紙コップに、2で運搬してきた紙コップを重ねる。 4.どのような出来だったのか評価を受ける。 図1、課題2のコース ・ルール補足 (注2*紙コップは通常の使用をする際に置く向きとは、逆向き{幅の広い方が下}に置かれている。紙コップを10cm以上動かしてしまった場合得点は0となる。) (注3*評価は、まずコップを重ねる正確さ{同じ番号に重ねることができれば10点、番号が1つずれたならば2点、番号が2つずれたか重ねることができなかったならば0点}の得点{これを基本得点とする}を審判が決める。次に、そのロボットの動作や機体の美しさなどを他の全てのチームが20点満点で評価しその平均点{これを技術点とする}を求める。これら基本得点と技術点の合計点により評価を数値化し各チームで競い合う。) 上を見て、やるべきことを考えたところ、やはり課題1の時と同じように2段階の作業が必要であることがわかった。 ロボットの制作 †課題2をクリアするための能力を持ったロボットを作る †さて、課題2をクリアするためにどのような能力が必要であろうか。私たちのグループは次の5つの能力が必要であると結論を出した。 ・移動する能力 ・紙コップを検知する能力 ・紙コップをつかむ能力 ・紙コップを持ち上げる能力 ・紙コップを重ねる能力 <移動する能力>…紙コップを移動させ重ねるという課題であるが、フィールドがそこそこ広いので機体をスタート地点に置いたまま、なんらかの手段で(ロボットの腕をバカ長く作りそれを使って紙コップを操作するなど)課題達成を目指すというのは、無理があるだろうということになり、できるだけコンパクトかつフィールド上を動き回れる機体を制作しようということになった。図1がロボットの土台部分で、ここに機体の移動を司る車輪などが搭載されている。(また、部分的にライントレースが必要だと考えられたので土台部分にすでに光センサーが取り付けられている。) <紙コップを検知する能力>…紙コップを検知する能力であるが、3つの案が挙がった。 図2、コップの模様 <紙コップをつかむ、持ち上げる、重ねる能力>…開発初期段階では、つかむ能力と持ち上げる能力を別々にする案が出たが、コンピュータ同士の通信が必要となる(モーターの都合上、2台のコンピュータを使う必要が出てくるため)ので複雑になると考えられるこちらに対し、つかむ能力と持ち上げる能力を1つのモーターで賄うことが可能な機構が制作されたため、より簡単にできることをわざわざ複雑にする必要はないとの結論に至り、結果的に図3のような機構を採用することになった。 この機構の原型は私の制作したものである。が、少々大きすぎ、重すぎたため後にも述べているがロボットの異常な動作の原因になったと考えられ、suiden氏による軽量化を経て図3のようなすっきりとした形状になった。 図3、つかむ機構(まずモーターが付いている歯車が動き、1のアームが動く。次に2の歯車が効力を発揮しコップを持ち上げる。) 図4−1コップをつかみ 図4−2コップを持ち上げる そんなこんなでできたのがこのロボット(図5)である。(実は、先にも述べた通り1回ロボットの機体も大幅に改修した結果ダイエットをし、このようになった。) 図5、完成機体 プログラムの制作 †課題2をクリアするために必要なプログラムを組む †ロボットの機体ができたので、プログラムを組む。先ほど盛り込んだ機能を問題なく使えるようにすることを目指して組むことになった。したがって、あまり余計なものを足さないことに重きを置いている。 ・移動するプログラム ・ライントレースをするプログラム (先に機体を組むときに言及されていたある程度のライントレースが必要ではないかという意見から) ・コップを識別するプログラム ・コップをつかむ、保持する、持ち上げる、重ねるプログラム <移動するプログラム>…ライントレースのみで移動すると移動中に紙コップを引っかける、コップの識別をした後に決定される進むルートで最短距離をとることができないなど好ましくないこと(得点を下げること)が多発しかねないので、ある程度の手動での移動調整が必要であると考えた。 <ライントレースをするプログラム>…モーターの出力調整のみで移動していくと必ず何らかのずれ(主にコースのずれ)が生じるため、正確な移動を実現するためにはライントレースが必要であり、今回の課題でもこの難題に挑むこととなった。 図6、ロボットの進む軌道 <コップを識別するプログラム>…紙コップに模様をつけそれを光センサーで読み取り識別するというプログラムを制作することになった。紙コップにつける模様を工夫することによって比較的容易にできるのではという考えのもとにこのプログラムを組むことになったが、私達のチームの中でだれもうまく考えつかず、紙コップ識別機能が実装されることはなかった。したがって、我々のロボットはその位置を紙コップの数字に依存することなく進路を決定することになっている。 <コップをつかむ、保持する、持ち上げる、重ねるプログラム>…すでに組立て段階で、つかむ、保持する、重ねることのプログラムは、モーターを回転させるだけで可能なように工夫して作ってあるので、容易に組むことができた。 実際に組んだプログラム †これらをもとに実際に組んだプログラムがこれである。(注4*実際にプログラムを組んだのは私ではないので、その点に十分留意されたし。{suiden氏が組んだものである。})
これから下が実際に行う動作のプログラムである。 task main() //紙コップを離す動作の関数の定義// { SetSensorLight(S2); //光センサー(紙コップ検知用)の接続先指定// SetSensorLight(S3); //光センサー(ライントレース用)の接続先指定// int nOnline = 0; //後々使う交差点判定のときの数を定義+現在その値は0と指定// int nPoint = 0; //通過した交差点の数カウンターの定義+現在その値は0と指定// 1の部分(図8参照){手動の動作} OnFwdSync(OUT_BC,60,0);Wait(2000);Off(OUT_BC); //ここから OnFwdSync(OUT_BC,75,-100);Wait(450);Off(OUT_BC);Wait(1000); OnFwdSync(OUT_BC,60,0);Wait(1200);Off(OUT_BC); catch(); {A地点のコップをつかむ} OnFwdSync(OUT_BC,60,0);Wait(700); OnFwdSync(OUT_BC,60,-100);Wait(500);Off(OUT_BC);Wait(1000);ここまで、 スタート地点からA地点の紙コップをつかむまでの動作(この部分は私が作った。)// long t0 = CurrentTick(); //現在の時間をとる// 2の部分{ライントレース} while (CurrentTick() - t0 < 3000) { //最初からの経過時間が3秒以内ならば、以下を実行// if (SENSOR_3 > THRESHOLD +2) { //[*1]ライントレースをするために線の上に乗せる調整の動作// OnFwd(OUT_B,40); } else { Off(OUT_BC); } Wait(STEP); } while (nPoint <= 1) { //通過した交差点の数がある数以下ならば以下を実行// while (nOnline < nMAX){ //横に曲がる判定の数が異常ではない場合、以下の関数を実行しろ// if (SENSOR_3 < THRESHOLD -10) { //もしセンサーの値がある値より小さければ右へ旋回// turn_right1; nOnline++; //横(右)に曲がる数を数えるカウンターに+1// } else { if (SENSOR_3 < THRESHOLD -5) { //でない状況で、もしセンサーの値がある値より小さければ右へ曲がれ// turn_right0; } else if (SENSOR_3 < THRESHOLD +2) {//でない状況で、もしセンサーの値がある値より小さければまっすぐ進め// OnFwdSync(OUT_BC,30,0); } else if (SENSOR_3 < THRESHOLD +8) {//でない状況で、もしセンサーの値がある値より小さければ左へ曲がれ// turn_left0; } else { //でない状況で、もしセンサーの値がある値より小さければ左へ旋回// turn_left1; } nOnline=0; //横(右)に曲がる数を数えるカウンターにをリセット// } Wait(STEP); //判断時間と黒い線に沿うための動作時間の合計の指定// } short_break; //時間調整のための小休止// turn_left1; Wait(nMAX*STEP); cross_line; //交差点を渡れ// nPoint++; //通過した交差点の数カウンターの値に+1// nOnline=0; //横(右)に曲がる数を数えるカウンターにをリセット//[*2] } while (nPoint == 2) { //通過した交差点の数がある数と同じならば// OnFwdSync(OUT_BC,30,0);Wait(1500);Off(OUT_BC); Wait(1000);Wait(1000); //ここから OnFwdSync(OUT_BC,-30,0);Wait(500);Off(OUT_BC); release(); {1の位置でAのコップを重ねる} OnFwd(OUT_C,-30);Wait(200); OnFwdSync(OUT_BC,-60,0);Wait(900);Off(OUT_BC); catch(); {アームが2の位置で引っかからないよう閉じる} OnFwdSync(OUT_BC,75,-100);Wait(900);Off(OUT_BC);ここまで、Aのコップを重ねる動作と そのための機体の位置調整と2にあるコップにアームを引っかけないための動作// nPoint++; } long t1 = CurrentTick(); //t1に開始から今までの時間を保存// while (CurrentTick() - t1 < 3000) {//シュート後の時間がある値以下だったら// if (SENSOR_3 > THRESHOLD +2) { //ここから OnFwd(OUT_C,40); } else { Off(OUT_BC); } Wait(STEP); ここまで、次の場所への機体の位置の移動(手動)// } while (nPoint <= 6) { //通過した交差点の数がある数以下だったら// while (nOnline < nMAX + 50){ //ここから if (SENSOR_3 < THRESHOLD -10) { turn_left1; nOnline++; } else { if (SENSOR_3 < THRESHOLD -5) { turn_left0; } else if (SENSOR_3 < THRESHOLD +2) { OnFwdSync(OUT_BC,30,0); } else if (SENSOR_3 < THRESHOLD +8) { turn_right0; } else { turn_right1; } nOnline=0; } Wait(STEP); } short_break; turn_right1; Wait(nMAX*STEP); cross_line; nPoint++; nOnline=0; ここまで、[*1]から[*2]と同じ// } while (nPoint == 7) { //今まで通過した交差点の数がある数だったら// OnFwdSync(OUT_BC,75,100);Wait(300);Off(OUT_BC);Wait(1000);// OnFwdSync(OUT_BC,-60,0);Wait(900);Off(OUT_BC); OnFwdSync(OUT_BC,75,100);Wait(200);Off(OUT_BC);Wait(1000); release(); {先ほど閉じたアームを開く} OnFwdSync(OUT_BC,60,0);Wait(1000);Off(OUT_BC);Wait(1000); catch(); {ここでBのコップをつかむ} nPoint++; OnFwdSync(OUT_BC,60,0);Wait(500);Off(OUT_BC);Wait(1000); ここまで、機体の位置調整とBのコップをつかむ動作// } long t2 = CurrentTick(); //t2に現在の時間を保存// while (CurrentTick() - t2 < 5000) { //直前の動作が終了してからの時間がある値より小さければ、 以下の動作を実行// if (SENSOR_3 > THRESHOLD +2) { //ここから OnFwd(OUT_B,-20);OnFwd(OUT_C,50); } else { Off(OUT_BC); } Wait(STEP); //ここまで、ライントレースのための位置調整// } while (nPoint == 8) { //今まで通過した交差点の数がある数だったら// while (nOnline < nMAX){ //ここから if (SENSOR_3 < THRESHOLD -10) { turn_left1; nOnline++; } else { if (SENSOR_3 < THRESHOLD -5) { turn_left0; } else if (SENSOR_3 < THRESHOLD +2) { OnFwdSync(OUT_BC,30,0); } else if (SENSOR_3 < THRESHOLD +8) { turn_right0; } else { turn_right1; } nOnline=0; } Wait(STEP); } short_break; turn_right1; Wait(nMAX*STEP + 600); cross_line; OnFwd(OUT_BC,30);Wait(200); nPoint++; nOnline=0; ここまで、[*1]から[*2]と同じ// } long t3 = CurrentTick(); //t3に開始から今までの時間を保存// while (CurrentTick() - t3 < 18000) { //直前の動作が終了してからの時間が ある値より小さければ、以下の動作を実行// if (SENSOR_3 < THRESHOLD -10) { //ここから turn_right1; } else { if (SENSOR_3 < THRESHOLD -5) { turn_right0; } else if (SENSOR_3 < THRESHOLD +2) { OnFwd(OUT_BC,30); } else if (SENSOR_3 < THRESHOLD +8) { turn_left0; } else { turn_left1; } Wait(STEP); ここまで、[*1]から[*2]と同じ (ただし、交差点系統の関数は抜く)// } } OnFwdSync(OUT_BC,75,-100);Wait(1000);Off(OUT_BC);Wait(1000);//位置調整// while (nPoint == 9) { //今まで通過した交差点の数がある数だったら// while (nOnline < nMAX){ //ここから if (SENSOR_3 < THRESHOLD -10) { turn_left1; nOnline++; } else { if (SENSOR_3 < THRESHOLD -5) { turn_left0; } else if (SENSOR_3 < THRESHOLD +2) { OnFwdSync(OUT_BC,30,0); } else if (SENSOR_3 < THRESHOLD +8) { turn_right0; } else { turn_right1; } nOnline=0; } Wait(STEP); } short_break; turn_right1; Wait(nMAX*STEP); cross_line; nPoint++; nOnline=0; ここまで、[*1]から[*2]と同じ// } while (nPoint == 10) { //今まで通過した交差点の数がある数だったら// OnFwdSync(OUT_BC,30,0);Wait(800);Off(OUT_BC);Wait(1000);//ここから OnFwdSync(OUT_BC,-30,0);Wait(600);Off(OUT_BC);Wait(1000); release(); {ここでBのコップを重ねる} nPoint++; ここまでBのコップを重ねる動作とそのための位置調整// } while (nPoint == 11) { //今まで通過した交差点の数がある数だったら// OnFwdSync(OUT_BC,-60,0);Wait(1200);Off(OUT_BC); //ここから OnFwdSync(OUT_BC,75,-100);Wait(500);Off(OUT_BC);Wait(1000); OnFwdSync(OUT_BC,60,0);Wait(1800);Off(OUT_BC); catch(); {ここでCのコップをつかむ} nPoint++; ここまでCのコップをつかむ動作と そのための位置調整// } while (nPoint == 12) { //今まで通過した交差点の数がある数だったら// OnFwdSync(OUT_BC,75,-100);Wait(1000);Off(OUT_BC);Wait(1000);//ここから OnFwdSync(OUT_BC,60,0);Wait(2500);Off(OUT_BC); OnFwdSync(OUT_BC,-30,0);Wait(600);Off(OUT_BC);Wait(1000); release(); {ここでCのコップを重ねる} nPoint++; ここまでCのコップを 重ねる動作とそのための位置調整// } } ライントレースでは最後に向いている向きが一定ではないので、ある程度重ねる際にずれが生じてしまう。 感想、反省 † 結果的に、コップを重ねることには失敗してしてしまったが、惜しいところまでいったらしく、全体で第三位に入賞することができた。私はその時都合が悪く出席することができなかったので、当日の失敗を見ることができなかったが、失敗してしまった原因の考察をしてみることにする。(どのような失敗をしてしまったのか見ていないため、反省が的外れになってしまってもどうか勘弁してください。) |