R3R4(2班) 課題3 ミニロボコン 目次 #contents *課題内容(ミニロボコン) [#zff4a973] **課題:空き缶運搬ロボット [#q04b5c7a] 空き缶を分別して所定の場所に運ぶ。 #ref(./kadai3.png,90%,課題図) フィールドの説明 -フィールドは課題2で使用した紙を使用する。 -2種類の空き缶(Aタイプ,Bタイプ)をそれぞれ3個づつ用意し、円XにABA、円YにBABとなるように3段づつ積み上げる。 -空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。 **ルール [#v605283e] 基本ルール -競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。 -図のA地点または(および)A'地点からスタートする。ただし接地している部分はそれぞれの領域内-に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。 -Aタイプの空き缶を円Y内に、Bタイプの空き缶を円X内に運ぶ。 -開始の合図から5秒以内にスタートボタンを押す作業を完了すること。 -競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。 -途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 基本得点の計算方法 -運んだ空き缶の数×3点 -空き缶を積み重ねて置くことができば場合、2段目の空き缶一つにつき2点加算、3段目の空き缶一つにつき3点加算する。 -円内からはみ出している場合、半分以下なら1点減点、半分以上なら2点減点。 -間違った円内に空き缶を置いた場合は、1個につき1点減点。 -間違った円内の2段目に空き缶を置いた場合は1個につき3点減点、その上にある空き缶は0点 技術点の計算方法 -以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。 得点の目安: -空き缶を探し取りにいくまでの動作 (3点) -空き缶を掴む動作 (3点) -空き缶を運ぶ動作 (2点) -空き缶を置く動作 (2点) -空き缶を積む動作 (3点) -2台のRCXまたはNXT、EV3の連携の良さ(2点) -自立型のロボットとしての形や動作の美しさ、斬新さ(2点) -その他 (3点) **各係 [#qc6e5d98] -司会・審判 (2人)・司会進行、開始・終了の合図と基本得点の計算 -得点の集計係 (1人)・技術点を集計する -採点の報告係 (各チーム1人)・採点した点数を集計係に連絡する *機体説明 [#v8384b4e] #ref(./kitaiab.jpg,90%,親と子) 親機と子機と命名しました。2台で協力するところや大きさ的に決めました。途中で2回行われる抱擁は感動モノ。 **機体1(子機) [#w934251b] #ref(./kitaib1.jpg,90%,モータ使用箇所) モータA,Bで左右のタイヤを回す。モータCでアームを動かす。アームは両方同時に動くように歯車を設置する。(大変だった) #ref(./kitaib2.jpg,90%,機構) -赤枠、缶の1段目を支えるように3/4方向(横と後ろ、すなわち前方を除く範囲)を囲う。 -青枠、缶の2段目をつかむ 缶の詰みあがった高さと相談する。 #ref(./kitaib3.jpg,90%,使われ方) 上図の様に1段目を支え、2段目をつかむ。 **機体2(親機おやき) [#k6c75f89] #ref(./kitaia2.jpg,90%,つかむ箇所) 子機とつかむ機構は同じでモータBが動くと両側のアームが同時に締まるようにできている。 #ref(./kitaia3.jpg,90%,使われ方) 子機と形はほとんど同じで掴んだ時に1,2段目の缶を支え、3缶目だけをつかむ。(子機は1段目を支え、2段目だけをつかむ) *戦略 [#hb757405] **方針 [#a84ac806] RISでは珍しい機体を2台つくり、そしてお互いの連携で高得点を目指す。 高得点を目指すには -すべての缶を入れる -2台で連携する -移動、つかむ、積む、運ぶ これらを行うものを考えた。 **案(アイデア) [#za6ebc11] 移動では機体がライントレースするものなので課題2を参考。つかむ、積むは同時に考えた。親機が3段目をつかみながら子機が2段目をつかみ下がることで、親機にはつかんでいる3段目と残っているいる1段目がある。そこで3段目の缶をはなすことで3段目の位置から1段目の缶に乗り2段目の位置に積むことが出来る。積んだ1、2段の缶を運ぶだけという形をとる。 #ref(./senryaku.jpg,90%,抱擁) 緑縁のように親機(右)と子機(左)でしっかり2、3段目をつかむ。 まるで親子の抱擁に見えませんか? #ref(./senryaku1.jpg,90%,子離れ) 子機が後ろに下がる。 #ref(./senryaku2.jpg,90%,老後) 親機、子機が缶をはなすと見事に2段の積まれた缶と1段だけの缶が同じ色に分けられることができる。 #ref(./senryaku3.jpg,90%,缶の加工) 積まれた缶を引っ張り抜くときに缶同士ができるだけ影響しないように缶特有の上下のへこみをなくすため紙を貼る。さらに摩擦力をできるでけ減らすためにビニールを表面に貼った。缶の加工に頑張りすぎてしまった。(しかしこれをしないと成功しない) #ref(./senryaku5.jpg,30%,ルート) 缶を置いたり運んだりするのに最適なルートが上記だと考えた。移動する際に関係ない缶に当たらないことも重要である。 -・オレンジ線(時間で動く)・青、緑線(子機がライントレースで動く)・赤線(親機がライントレースで動く)・黄色範囲(交差点認識)・ピンク(スタート)・紫(ゴール) -左下スタートが子機、右下スタートが親機 *プログラムについて [#jfae31c8] 親機と子機でプログラムを書いた人が違うので書き方も違う **親機 [#wa343a73] ***define [#v599ea6c] #define turn_left Off(OUT_AC);OnFwd(OUT_A);OnRev(OUT_C);Wait(2);Off(OUT_AC); #define turn_right Off(OUT_AC);OnFwd(OUT_C);OnRev(OUT_A);Wait(2);Off(OUT_AC); #define run_left Off(OUT_AC);OnFwd(OUT_A);Wait(2);Off(OUT_AC); #define run_right Off(OUT_AC);OnFwd(OUT_C);Wait(2);Off(OUT_AC); #define arm_open Off(OUT_B);OnRev(OUT_B);Wait(20);Off(OUT_B); #define arm_close Off(OUT_B);OnFwd(OUT_B); #define turn_left_free OnFwd(OUT_A);OnRev(OUT_C); #define turn_right_free OnFwd(OUT_C);OnRev(OUT_A); #define turn_left_small OnFwd(OUT_A); #define turn_right_small OnFwd(OUT_C); turn_left,turn_left_freeは両方のタイヤを回転させて左へ曲がる.turn_leftはライントレースするサブルーチンの中でのみ機能し,turn_left_freeはどこでも使えるプログラムとなっている. turn_left_small,run_leftはタイヤ1つだけ回転し回転の内側のタイヤは止まっている.そうすることで大きく旋回することができる.turn_left_smallはどこでも使えるプログラムであるが,run_leftはサブルーチンの中のみで機能するプログラムとなっている. 右に曲がる,turn_right,turn_right_free,turn_right_small,run_rightも上記と同様. arm_openで空き缶を掴むためのアームを開き,arm_closeでアームを閉じ,空き缶を掴む. ***subルーチン [#zfd807c2] sub follow_line_right(){ClearTimer(0); while(FastTimer(0)<18) if(SENSOR_2<38){ turn_right; // センサー2が黒を認識したら,右へ曲がる }else if(SENSOR_2<42){ run_right;ClearTimer(0); // センサー2がグレーっぽい黒を認識したら,大きく右へ曲がる }else if(SENSOR_2<47){ OnFwd(OUT_AC);ClearTimer(0); // センサー2がグレーを認識したら,まっすぐ進む }else if(SENSOR_2<50){ run_left;ClearTimer(0); // センサー2がグレーっぽい白を認識したら,大きく左へ曲がる }else if(SENSOR_2<55){ turn_left;ClearTimer(0); // センサー2が白を認識したら,左へ曲がる }} 上のサブルーチンは黒線の右側をライントレースするプログラムとなっている.センサー2が0.18秒以上黒を認識したら,上のサブルーチンから外れ,次のプログラムへと行く. sub follow_line_left(){ClearTimer(0); while(FastTimer(0)<18) if(SENSOR_2<38){ turn_left; // センサー2が黒を認識したら,左へ曲がる }else if(SENSOR_2<42){ run_left;ClearTimer(0); // センサー2がグレーっぽい黒を認識したら,大きく左へ曲がる }else if(SENSOR_2<47){ OnFwd(OUT_AC);ClearTimer(0); // センサー2がグレーを認識したら,まっすぐ進む }else if(SENSOR_2<50){ run_right;ClearTimer(0); // センサー2がグレーっぽい白を認識したら,大きく右へ曲がる }else if(SENSOR_2<55){ turn_right;ClearTimer(0); // センサー2が白を認識したら,右へ曲がる }} 上のプログラムは黒線の左側をライントレースするプログラムとなっている.センサー2が0.18秒以上黒を認識したら,上のサブルーチンから外れ,次のプログラムへと行く. ***task mainについて [#l73eda2c] task main() { OnFwd(OUT_AC); Wait(200); Off(OUT_AC); // A'からHに向かって進む(黒線まで) SetSensor(SENSOR_2,SENSOR_LIGHT); follow_line_left(); // Hまで黒線左側をライントレース turn_right_small; Wait(90); turn_right_free; Wait(15); Off(OUT_AC); // HからIに方向転換 follow_line_left(); // HからIに進む 黒線左側をライントレース Off(OUT_AC); Wait(300); // "こき"の動きとの時間合わせ 少しIで待つ turn_right_free; Wait(10); Off(OUT_AC); // Yに体が向くように少し方向転換 OnFwd(OUT_AC); Wait(40); // IからYまで直進 Off(OUT_AC); arm_close; // 缶を掴む Wait(1000); // 相手が2段目の空き缶を抜くまで待機 arm_open; // 3段目の空き缶をアームを放すことで1段目の空き缶の上に乗せる OnFwd(OUT_AC); Wait(25); Off(OUT_AC); // 缶をがっちり抱える turn_right_small; Wait(110); Off(OUT_AC); // Yで右に90°方向転換 OnFwd(OUT_AC); Wait(30); // 黒線左側をライントレースできるように円から抜ける Off(OUT_AC); follow_line_left(); // 黒線左側をライントレースし,Gまで進む turn_left_small; Wait(30); turn_left_free; Wait(35); // Gで左へ曲がる Off(OUT_AC); Wait(1500); // "こき"が通り過ぎるまで待つ OnFwd(OUT_AC); Wait(120); Off(OUT_AC); // 缶をおいていく OnRev(OUT_AC); Wait(120); // Gに戻る turn_right_free; Wait(70); Off(OUT_AC); // 右に回転して軌道に戻る follow_line_left(); // ライントレース Off(OUT_AC); Wait(300); // "こき"の動きとの時間合わせ turn_right_free; Wait(10); Off(OUT_AC); // 少し右に曲がることでXに体を向ける. OnFwd(OUT_AC); Wait(20); // 空き缶まで行く Off(OUT_AC); Wait(100); // "こき"との時間合わせ arm_close; // 缶を掴む Wait(500); // 相手が2段目の空き缶を抜くまで待機 arm_open; // 3段目の空き缶をアームを放すことで1段目の上に乗せる OnRev(OUT_AC); Wait(120); Off(OUT_AC); Wait(100); // XからG辺りまで後退 turn_right_free; Wait(75); Off(OUT_AC); Wait(200); // 右へ曲がる OnFwd(OUT_AC); Wait(200); Off(OUT_AC); Wait(200); // 直進 turn_left_free; Wait(75); Off(OUT_AC); Wait(200); // 左へ曲がる OnFwd(OUT_AC); Wait(260); Off(OUT_AC); Wait(200); // A'で空き缶を抱える turn_left_free; Wait(85); Off(OUT_AC); Wait(200); // A'で左へ曲がる OnFwd(OUT_AC); Wait(100); Off(OUT_AC); // 空き缶をXに置く OnRev(OUT_AC); Wait(100); Off(OUT_AC); // Xで少し後退 Off(OUT_AC); //終了 } **子機 [#c61ecec3] ***define [#me2920e9] #define THRESHOLD 48 //基準(中間値)となる光の値(定数) #define CROSSTIMER 6 //黒線を6回検知で止まるという値 #define GO OnFwd(OUT_AC); //まっすぐ進む #define BACK OnRev(OUT_AC); //後ろ #define turn_left OnFwd(OUT_A);Off(OUT_C); //左回り #define turn_right Off(OUT_A);OnFwd(OUT_C); //右回り #define turn_hleft OnFwd(OUT_A);OnRev(OUT_C); //右旋回 #define turn_hright OnRev(OUT_A);OnFwd(OUT_C); //左旋回 #define STEP 1 //0.01秒(if内で使用) #define tunoTIME 200 //アームを動かす時間 ***subルーチン [#madf572d] 黒<THRESHOLD-7<黒灰<THRESHOLD-3<灰<THRESHOLD+3<白灰<THRESHOLD+7<白 sub traceLstop() //L(左)をトレースして黒灰を6回検知して止まる(白の時旋回をする)〔4方向〕 { int n=0; while(n<CROSSTIMER){ if(SENSOR_2<THRESHOLD-3){ turn_left;n++; }else{ if(SENSOR_2<THRESHOLD+3){ GO; }else if(SENSOR_2<THRESHOLD+7){ turn_right; }else{ turn_hright; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); } sub traceRstop() //R(右)をトレースして黒灰を6回検知して止まる(白の時旋回をする)〔4方向〕 { int n=0; while(n<CROSSTIMER){ if(SENSOR_2<THRESHOLD-3){ turn_right;n++; }else{ if(SENSOR_2<THRESHOLD+3){ GO; }else if(SENSOR_2<THRESHOLD+7){ turn_left; }else{ turn_hleft; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); } sub traceSLstop() //L(左)をトレースして黒灰を6回検知して止まる(ただし白の時旋回をしない)〔3方向〕 { int n=0; while(n<6){ if(SENSOR_2<THRESHOLD-3){ turn_left;n++; }else{ if(SENSOR_2<THRESHOLD+3){ GO; }else{ turn_right; }n=0; } Wait(STEP); } PlaySound(SOUND_DOWN); }// 黒で旋回そして止まるためのカウントにすると止まりきらなくなるので黒灰で曲がりそしてカウントにすることで安全に止まってくれる。よって5方向にするのではなく4方向にする STEPはif内の動作を1回あたり0.01秒行うための時間 各if終了後に音楽を入れることで交差点の判断の有無を確認しやすくする subを用いたdefine #define STOPGOr while(SENSOR_2<THRESHOLD+7){GO;} traceRstop();//黒線を飛び越え黒線の右をたどる #define STOPGOl while(SENSOR_2<THRESHOLD+7){GO;} traceLstop();//黒線を飛び越え黒線の左をたどる ***task mainについて [#ad0dcd96] task main() { SetPower(OUT_B,3); //モータBの力を3にする SetSensor(SENSOR_2,SENSOR_LIGHT); //センサーを2に設定 GO;Wait(80); //地点Aの抜け出し traceLstop(); Off(OUT_AC);Wait(350); //C交差点止まる GO;Wait(20); turn_hright;Wait(110); traceRstop(); Off(OUT_AC);Wait(10); //K交差点止まる turn_hleft;Wait(15); //つかむため軌道修正 Off(OUT_AC);Wait(200); GO;Wait(90);Off(OUT_AC); //X缶の位置まで進む OnFwd(OUT_B);Wait(tunoTIME);Off(OUT_AC);Wait(100); //缶をつかむ BACK;Wait(180); Off(OUT_AC);Wait(600); //後ろに下がる OnRev(OUT_B);Wait(tunoTIME);Off(OUT_B); //缶をはなす GO;Wait(180);Off(OUT_AC); //缶をはなす位置まで移動 while(SENSOR_2>THRESHOLD-7){BACK;}; //K地点の黒線まで下がる turn_hleft;Wait(50);while(SENSOR_2>THRESHOLD-7){turn_hleft;}; //CKの右側をトレースできるように旋回 traceRstop(); //CKの右トレース GO;Wait(30); turn_hright;Wait(100); traceRstop(); //Cの右直線のトレース turn_right;Wait(185); Off(OUT_AC);Wait(10); while(SENSOR_2>THRESHOLD-7){GO;}; //Eの右直線の末端まで進む GO;Wait(40); while(SENSOR_2>THRESHOLD-7){turn_hright;}; Off(OUT_AC);Wait(400); GO;Wait(80);Off(OUT_AC);Wait(150); //Yの缶の位置まで進む OnFwd(OUT_B);Wait(tunoTIME);Off(OUT_AC);Wait(200); //缶をつかむ BACK;Wait(90); turn_hleft;Wait(85);Off(OUT_AC);Wait(100); OnRev(OUT_B);Wait(tunoTIME);Off(OUT_B);Wait(30); //缶をはなす GO;Wait(165);BACK;Wait(165);Off(OUT_AC);Wait(50); //缶をはなして後ろへいく turn_hright;Wait(90);Off(OUT_AC);Wait(100); GO;Wait(180); traceSLstop(); //FG間の左トレース turn_right(20); traceLstop(); //GL間を左トレース turn_hright;Wait(20);Off(OUT_AC);Wait(50); //缶を置く位置を調整 GO;Wait(50);Off(OUT_AC);Wait(100); //缶を置く while(SENSOR_2>THRESHOLD-5){BACK;};Off(OUT_AC);Wait(100); OnFwd(OUT_B);Wait(20); turn_hright;Wait(45); GO;Wait(110);while(SENSOR_2>THRESHOLD-7){GO;}; //KC間まで進む GO;Wait(25); turn_hright;Wait(50); traceRstop(); //Cまで右トレース OnRev(OUT_B);Wait(30);Off(OUT_ABC);Wait(100); STOPGOl; //C、直角(Dの上)間を左トレース Wait(20); STOPGOr; //直角、D間の右トレース turn_hleft;Wait(20); //缶を置く位置を調整 GO;Wait(30); //缶を置く Off(OUT_ABC);Wait(100); //終了!! } *結果 [#m23e724e] **結果(動画サイトも) [#q00aee69] ロボコンの全体の順位は皆のおかげもあって3位、得点は5点。今回の戦略では(積み缶+単缶)×2で22点の高得点ポテンシャルを持っていた。しかしやはり不安定性(電圧、動きが割と速い)により失敗してしまった。練習でも最高得点は3点という感じだった。 今回は親機が最初の交差点認識を把握できなかったことで失敗に終わった。子機は完璧に動いた。正直言って悔しい。アイデアもよかったのですが、それさえも披露できなかった。 練習の動画であるが動きだけでも伝えたいと思う。 https://youtu.be/Pok_ylCWW7A **原因 [#daedfcbb] -戦略上難しいとしている高い位置からの缶の落下、そして着地。これは運要素が強く、缶がこけてしまうこともあった。缶を加工したりしたがなお厳しかった。ロボットに加える部品数も足りなく完璧にできなかった。 -電圧による効果によっての進み具合の変化。これを防ぐことは難しいのでそのたびにプログラムを書き換えた。 -動きの速いこと(動きの荒さ)からくる誤差。時間で動くときに大きく影響。歯車の不足によって倍率を下げられなかった。 -場所による光の加減で光センサーのとらえ方の違い。練習の時同じ場所でやりつつけたため本番までこの要素に気づけなかった。 -2台の調子が合わないことしか起きない。どちらも正確性があればよかった。 練習では子機の方が失敗率が高かったのだが、本番では完璧な走りを見せてくれたのでチーム驚きだった。親機がまさかの最初のライントレースで失敗したのは光の加減だと考えられる。 **感想 [#yf6f965c] このロボコンで技術が高まり成長できたことを本当にうれしく思う。高校の時、プログラミングやそれに合うロボットを作ることなどをやることが出来なかったことをここで出来本当に幸せを感じた。授業内容課題はとても楽しく一番というほどだったがとにかく時間と根気が必要で大変がった。つらかった。ロボットは言うことを聞いてくれない、プログラミングがよくわからない、課題が難しい。(自分のスキルが低いだけ)しかしやっていくうちになんとなく形もできて、課題に対し完璧ではないが立ち向かえるようになれた。ロボットに関して可愛く面白い、天才っていうのができて愛着も湧く。プログラミングも分かれば楽しく、本当に数学みたいで理解できれば応用にすることもできたりして感動もある。各課題で10番教室でわざわざ集まって遅くまで残って警備員に怒られてなど相方と頑張った思い出さえできてしまった。最終課題は本番前、徹夜までして仕上げた。(仕上がってはないか)子機は完璧な演技をしたが、最後のモチーフとして親子の抱擁シーンを皆に見せれなかったことが本当に無念だった。ではあるものの自分を含めて本当に皆さんお疲れでした。自分は機械ロボット学科なのでこれからの勉強に少しでも役立てれたらいいと思う。