[[2015b/Member]] 目次 #contents *課題内容 [#g9939cd0] 課題は、ボールを離れた場所から缶に当てるロボットとボールを回収するロボットの制作です。 #ref(./2015b-mission3.png,60%,課題) *ロボットAについて [#k3ee3c7c] ロボットAは、ボールを掴んで缶に当てる動作を行います。このロボットには、モーターを3つと、光センサを2つ、角度センサを1つ使用しています。モーターのうち2つは車輪に使い、残りの1つは、ボールを掴む・弾く動作のために使っています。光センサは、ライントレース用と、缶の位置を探す用に分けて使っています。角度センサは、主に距離を測るために使っています。 #ref(./DSC_0248.JPG,60%,ロボット全体図) ↑ロボット全体図 **ボールを掴む・弾く動作 [#v79a51aa] 今回の課題では、ボールを缶に当てる動作が必要になるので、どうやってボールをとばすかということが、初めに考えられました。ボールを正確に掴むため、クワガタのようなアームにし車体を利用して、体当たりのような形で押し出す方法が考えられましたが、それではあまりに不格好だと思い、掴む・押し出すを綺麗な形で行える方法を考えました。その結果、爪のようなものを軸回転させるという方法になりました。これにより、ボール回収後も、車体から飛び出すことなく安定して運べますし、なにより、ボールを無駄な動きなく飛ばすことができます。 このロボットが完成するまで、様々な改良を加えていきました。最終的に完成させたロボットでも、動きに問題は無かったですが、ギア比等をもっとしっかり考えておくべきだったと思います。 #ref(./DSC_0250.JPG,60%,動作説明) ↑ギア側面図 *ロボットBについて [#afae0e3e] ロボットBは、缶に当たったボールを回収する動作をします。このロボットには、モーター3つと、光センサを1つ使用しています。モーターのうち2つは車輪に、残り1つは、ボール回収動作を行うために使っています。光センサは、ライントレースをするために使用しています。 制作初期は、缶に当たったボールを探すことを目標としていましたが、光センサでボールを探すことが難しいと判断したため、コース内に止まったボールを、手当り次第回収するという、成功率の高い方法をとりました。 #ref(./DSC_0249.JPG,60%,ロボット全体図) ↑ロボット全体図 **ボールを回収する動作 [#rd0d793d] ロボットBのボール回収動作は、RCXのキャタピラパーツを4つ使用して、それを常に車体中心に向かって回転するようにして、ボールを回収していくことができます。万が一、ボールが外に飛び出さないよう、柔らかい透明なパーツを車体の両サイドに取り付けています。もう一つ、このパーツを利用したことに、ロボットのキャタピラパーツが捉えられない位置にあるボールを前にはじき出し、運良く回収できるということが挙げらます。こちらの方が、本来の目的であったりします。 このロボットは、制作が発表当日に完了したということもあり、まだまだ、改良の余地はあったと思われますが、結果としてはこれで良かったのかもしれません。 #ref(./DSC_0251.JPG,60%,動作説明) ↑ギア側面図 *プログラム [#we877882] プログラムは、同チームの2人が中心になって作成してくれました。ざっくりとした説明になってしまいますので、詳細は同チームの人のページを確認してください。 **ロボットA用 [#daa1aaa3] ロボットAの基本戦略は、ボールの位置を角度センサにより正確に計測し、その場に到達したら掴む動作を行い、缶に近い場所まで移動、光センサを利用し缶の位置を特定し、ボールを弾くというような形になります。 所々、ライントレースをしたり、角度センサを利用して走行したりするため、プログラムをサブルーチンで複数組んであります。 //black = 43 < 48 < white = 52 //SENSOR_2 トレース //SENSOR_3 物体探索 //TIMER(0) トレース //TIMER(1) 光探索 /*共通機構*/ #define power(s) SetPower(OUT_A+OUT_C,s); /*ライントレース用*/ #define shiki 48 #define tomaru(t) Off(OUT_AC);Wait(t); #define FWD OnFwd(OUT_AC); #define BACK OnRev(OUT_AC); #define LEFT_t OnRev(OUT_A); OnFwd(OUT_C); #define LEFT Off(OUT_A); OnFwd(OUT_C); #define RIGHT_t OnRev(OUT_C); OnFwd(OUT_A); #define RIGHT Off(OUT_C); OnFwd(OUT_A); #define TMAX 20 /*ロボコン独自機構*/ #define open(t) OnFwd(OUT_B);Wait(t);//玉を扱う機構 #define close(t) OnRev(OUT_B);Wait(t);Off(OUT_B); #define stop_B Off(OUT_B); #define SUN 50//ランタンの輝度を表す数値 #define shoot power(2);open(15);Wait(10);close(15); /*赤球迄のトレース*/ sub trace_0() { power(2); ClearSensor(SENSOR_1); while(1){ if (SENSOR_2 < shiki -7){ LEFT_t; } else if (SENSOR_2 < shiki -4){ LEFT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ RIGHT; } else { RIGHT_t; } if(SENSOR_1 > 335){ power(3); close(50); ClearSensor(SENSOR_1); break; } } } /*赤球を放つ手前*/ sub trace_1() { ClearSensor(SENSOR_1); close(10); Off(OUT_B); power(2); while(1){ if (SENSOR_2 < shiki -7){ LEFT_t; } else if (SENSOR_2 < shiki -4){ LEFT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ RIGHT; } else { RIGHT_t; } if(SENSOR_1 > 62){ tomaru(10); break; } } } sub trace_2() { power(1); ClearSensor(SENSOR_1); while(1){ if (SENSOR_2 < shiki -7){ RIGHT_t; } else if (SENSOR_2 < shiki -4){ RIGHT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ LEFT; } else { LEFT_t; } if(SENSOR_1 > 44){ power(3); close(50); ClearSensor(SENSOR_1); break; } } } sub trace_3() { power(2); ClearSensor(SENSOR_1); while(1){ close(1); Off(OUT_B); if (SENSOR_2 < shiki -7){ RIGHT_t; } else if (SENSOR_2 < shiki -4){ RIGHT; } else if (SENSOR_2 < shiki){ FWD; } else if(SENSOR_2 < shiki +4){ LEFT; } else { LEFT_t; } if(SENSOR_1 > 110){ power(3); close(50); ClearSensor(SENSOR_1); break; } } } /*光源を探す*/ sub LIGHT() { PlaySound(SOUND_UP); int sun_MAX = 0; int sensor_MAX = 0; close(20); ClearSensor(SENSOR_1); power(1); while(SENSOR_1 < 85){ RIGHT_t; if(SENSOR_3 > sun_MAX){ sun_MAX = SENSOR_3; sensor_MAX = SENSOR_1; } } tomaru(10); LEFT_t; until(SENSOR_1 < sensor_MAX); tomaru(10); } task main() { /*回転センサ*/ SetSensor(SENSOR_1,SENSOR_ROTATION); /*トレース用センサ*/ SetSensor(SENSOR_2,SENSOR_LIGHT); /*探索用センサ*/ SetSensor(SENSOR_3,SENSOR_LIGHT); FWD;Wait(150); trace_0();//向かう tomaru(50); trace_1();//赤玉持ち LIGHT(); shoot; tomaru(20); ClearSensor(SENSOR_1); RIGHT_t; until(SENSOR_1 > 28); tomaru(10); ClearSensor(SENSOR_1); FWD; until(SENSOR_1 > 26); Off(OUT_B); FWD; until(SENSOR_2 < 48); open(7); Off(OUT_B); trace_2(); tomaru(10); FWD;Wait(100); trace_3(); tomaru(10); LIGHT(); shoot; trace_1(); } **ロボットB用 [#rdc01f14] ロボットBの基本戦略は、ライントレースする中でボールを回収していくことになります。プログラムは、課題2で組んだプログラムに、回収動作や、ロボットAと動作が被らないように停止する動作等を加えてあります。 /* 37 black 53 white */ int startime=300; #define CHECKCROSSTIME 25 #define fwd(OUT) Off(OUT);OnFwd(OUT) #define rev(OUT) Off(OUT);OnRev(OUT) #define TURNLEFT fwd(OUT_AC) #define LEFT Off(OUT_C);fwd(OUT_A) #define TURNRIGHT rev(OUT_AC) #define RIGHT Off(OUT_A);rev(OUT_C) #define STRAIGHT rev(OUT_C);fwd(OUT_A) #define BACK fwd(OUT_C);rev(OUT_A) #define ISNOTCROSS FastTimer(0) <= CHECKCROSSTIME || FastTimer(1) <= startime #define RELEASE rev(OUT_B); #define LOADING fwd(OUT_B); sub trace(){ ClearTimer(0); while(ISNOTCROSS){ if(FastTimer(1) < startime){ ClearTimer(0); } if(52 <= SENSOR_1){ TURNRIGHT; }else if(50 <= SENSOR_1){ RIGHT; }else if(41 <= SENSOR_1){ STRAIGHT; }else if(39 <= SENSOR_1){ LEFT; }else { TURNLEFT; } if(39 <= SENSOR_1) ClearTimer(0); } Off(OUT_AC); ClearTimer(0); Wait(100); } /* 直進する */ sub go_straight(){ STRAIGHT; Wait(30); ClearTimer(1); } /* 左折する */ sub turn_left(){ ClearTimer(1); ClearTimer(0); } /* 右折する */ sub turn_right(){ ClearTimer(1); while(ISNOTCROSS){ if(FastTimer(1) >= startime){ ClearTimer(0); ClearTimer(1); break; } if(53 <= SENSOR_1){ TURNLEFT; }else if(50 <= SENSOR_1){ LEFT; }else if(47 <= SENSOR_1){ STRAIGHT; }else if(44 <= SENSOR_1){ RIGHT; }else { TURNRIGHT; } } TURNLEFT; Wait(10); Off(OUT_AC); ClearTimer(0); ClearTimer(1); } task main(){ SetSensor(SENSOR_1,SENSOR_LIGHT); ClearTimer(0); LOADING; go_straight(); trace(); go_straight(); Off(OUT_AC); Wait(2300); ClearTimer(1); startime=900; trace(); startime=300; //turn_left();// //trace(); go_straight(); trace(); go_straight(); //turn_left(); trace(); go_straight(); startime=1400; trace(); startime=300; TURNRIGHT; Wait(10); Off(OUT_AC); RELEASE; Wait(300); BACK; Wait(100); TURNRIGHT; Wait(40); LOADING; ClearTimer(0); trace(); turn_left(); startime=900; trace(); startime=300; //turn_left();// //trace(); go_straight(); trace(); go_straight(); trace(); go_straight(); startime=1400; trace(); startime=300; TURNRIGHT; Wait(10); Off(OUT_AC); RELEASE; Wait(300); go_straight(); Wait(10); Off(OUT_ABC); } *結果[#s55739b0] 結果は、全4チーム中一番という結果でしたが、これには、多かれ少なかれ、運が絡んでいます。まず、ロボットAの角度センサを利用した、ボールの位置特定が、百発百中でないことがあります。赤ボールに関しては、悪くない確率で成功させられますが、青ボールに関しては、めったにできないので、諦めていたところでした。ロボットBについても、ボールの停止位置に左右される作りになっていますので、運が良かったとしか言えません。私自身は運がいい方ではないので、この結果は、チームのみんながもたらした、結果なのかもしれません。 結果は、全4チーム中一番という結果でしたが、これには、多かれ少なかれ、運が絡んでいます。まず、ロボットAの角度センサを利用した、ボールの位置特定が、正確に特定できない時があります。赤ボールに関しては、悪くない確率で成功させられますが、青ボールに関しては、めったにできないので、諦めていたところでした。ロボットBについても、ボールの停止位置に左右される作りになっていますので、運が良かったとしか言えません。私自身は運がいい方ではないので、この結果は、チームのみんながもたらした、結果なのかもしれません。 *感想 [#nf94c7f1] 終わりよければすべて良しというわけではありませんが、結果だけをみれば満足のいくものでした。今回の課題では、チーム一丸となって取り組んだものだったので、なお喜ばしいものになりました。このゼミを通して、私自身沢山のことを学ばせてもらいました。素直に楽しかったです。