CENTER:&color(green,none){&size(27){ロボコン};}; **&color(lightseagreen,none){目次}; [#i787c5f0] #contents **&color(lightseagreen,none){ルール}; [#h23c405e] *迷路を抜け、四段に積まれた空き缶をゴールまで運ぶ。~ ◇基本ルール~ -- 4段に積まれた空き缶を運びだし、ゴールに入れる。 -- 競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。~ -- 2隅のコーナー(30cm四方)からスタートする。 -- スタート時のロボットは2個を越えないこと (スタート後はいくつに分裂してもかまわない)。~ -- 開始の合図から5秒以内にRCXのスタートボタンを押す作業を完了すること。~ -- 競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。~ -- 途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。~ ◇基本得点の計算方法~ -- 緑の空き缶を1個ゴールに運べば4点。~ -- 黒い空き缶(最上の空き缶)を運べば8点。~ -- 空き缶を場外に出してしまった場合は一個につきマイナス1点。~ -- 半分以上ゴールに入った空き缶だけを得点の対象とする。ただし空き缶がゴールからはみ出している場合は、マイナス1点~ ◇技術点の計算方法~ 以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について、~ 他の全てのチーム(9チーム+TAor教員)が20点満点で採点し、その平均点を求める。~ 得点の目安:~ -- 空き缶までたどり着く動作 (3点)~ -- 空き缶を運ぶ動作 (転がす・掴むなど) (4点)~ -- 空き缶をゴールに入れる動作 (2点)~ -- 2台以上のロボット、あるいは単体のロボットの場合は2台のRCXの連携の良さ(3点)~ -- 自立型のロボットとしての形や動作の美しさ、斬新さ(3点)~ -- その他 (5点)~ 詳しくは[[2008b/ロボコン]]を参照。~ **&color(lightseagreen,none){作戦}; [#dfc51fff] 1:四つ一度につかみ、縦に積んだまま一遍に持ち運ぶ。 2:とにかく走り回って缶を拾い、一つずつゴールに押し込む。 1の現実性が低そうにみられていたが、作る過程で案外の好感触を得ている。~ 2はとにかく時間制限のないことを利用して健気に動くロボットの予定。~ **&color(lightseagreen,none){使用するもの}; [#bf23e660] ***&color(limegreen,none){マシン}; [#rb4a1cc9] #ref(hakohako.jpg) ▲一個ずつの運搬用ロボ #ref(tsuno.jpg) ▲四つ一度の運搬ロボ #br ***&color(limegreen,none){プログラム}; [#rb4a1cc9] &color(red,none){4つ一気に運搬するロボットのプログラム}; void go_straight(int t ) { OnFwd(OUT_A+OUT_C); Wait(t); Off(OUT_A+OUT_C); Wait(16); } void go_back(int t ) { OnRev(OUT_A+OUT_C); Wait(t); Off(OUT_A+OUT_C); Wait(15); } void go_right(int t ) { OnFwd(OUT_A); OnRev(OUT_C); Wait(t); Off(OUT_A+OUT_C); Wait(15); } void go_left(int t ) { OnFwd(OUT_C); OnRev(OUT_A); Wait(t); Off(OUT_A+OUT_C); Wait(15); } void tozi(int t) //アームを閉じる関数 { OnRev(OUT_B); Wait(t); Off(OUT_B); Wait(15); } void hiraki(int t) //アームを開く関数 { OnFwd(OUT_B); Wait(t); Off(OUT_B); Wait(15); } #define THRESHOLD 40 //ライントレース用の閾値 #define RUN_TIME 50 //ライントレース用のタイマーの時間設定 task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensor(SENSOR_2,SENSOR_LIGHT); SetSensor(SENSOR_3,SENSOR_LIGHT); ClearTimer(0); repeat(20) { Wait(100); PlaySound(SOUND_CLICK); } PlaySound(SOUND_UP); repeat(10) { go_straight(8); } go_left(30); go_right(2); repeat(10) { go_straight(8); } Wait(50); go_right(30); go_left(2); Wait(50); while(Timer(0) <= RUN_TIME) //5秒間ライントレース { if(SENSOR_1<THRESHOLD) { OnFwd(OUT_C); OnRev(OUT_A); Wait(15); } else { OnFwd(OUT_A+OUT_C); } if(SENSOR_3<THRESHOLD) { OnFwd(OUT_A); OnRev(OUT_C); Wait(15); } else { OnFwd(OUT_A+OUT_C); } if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)) { Off(OUT_A+OUT_C); Wait(200); OnFwd(OUT_A+OUT_C); Wait(80); } else { OnFwd(OUT_A+OUT_C); } } Off(OUT_A+OUT_C); Wait(50); go_left(90); //左に向いて repeat(40) { go_straight(8); //まっすぐ進み } go_left(30); //さらに左を向き go_right(2); repeat(15) { hiraki(3); //アームを開き } repeat(20) { go_straight(8); //さらに進み } repeat(40) { tozi(3); //アームを閉じて } OnRev(OUT_B); repeat(20) { go_straight(10); //ゴール目指して進む } Wait(20); Off(OUT_B); OnRev(OUT_B); //途中慣性でアームが勝手に開かないように go_right(30); //所々でモータに信号を送る go_left(2); Wait(20); Off(OUT_B); OnRev(OUT_B); repeat(60) go_straight(8); Wait(20); Off(OUT_B); OnRev(OUT_B); go_right(30); go_left(2); Wait(20); Off(OUT_B); while(Timer(0) <= RUN_TIME) //帰りも再びライントレース { if(SENSOR_1<THRESHOLD) { OnFwd(OUT_C); OnRev(OUT_A); Wait(15); } else { OnFwd(OUT_A+OUT_C); } if(SENSOR_3<THRESHOLD) { OnFwd(OUT_A); OnRev(OUT_C); Wait(15); } else {OnFwd(OUT_A+OUT_C);} if((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)) { Off(OUT_A+OUT_C); Wait(200); OnFwd(OUT_A+OUT_C); Wait(80); } else { OnFwd(OUT_A+OUT_C); } } Off(OUT_A+OUT_C); Wait(50); OnRev(OUT_B); go_left(30); go_right(2); Wait(20); Off(OUT_B); repeat(40) { hiraki(3); //ゴールの前でアームを開き } go_straight(20); Wait(20); //急停止した衝撃で缶を倒しゴールに入れる PlaySound(SOUND_DOUBLE_BEEP); } &color(red,none){1つずつ運搬するロボットのプログラム}; //基本動作 void go_straight(int t){ OnFwd(OUT_A+ OUT_C); Wait(t); } void go_straight2(int t,int w){ go_straight(t); Off(OUT_A+ OUT_C); Wait(w); } void go_back(int t){ OnRev(OUT_A+ OUT_C); Wait(t); } void go_back2(int t,int w){ go_back(t); Off(OUT_A+ OUT_C); Wait(w); } void turn_right(int t){ OnFwd(OUT_A); OnRev(OUT_C); Wait(t); } void turn_right2(int t,int w){ turn_right(t); Off(OUT_A+ OUT_C); Wait(w); } void turn_left(int t){ OnRev(OUT_A); OnFwd(OUT_C); Wait(t); } void turn_left2(int t,int w){ turn_left(t); Off(OUT_A+ OUT_C); Wait(w); } //グローバル変数 int loopcount;//ループ数カウント用 int stopcount;//停止時間カウント用 int rot_old;//前回の回転値記憶用 int b_flag=0;//ループ脱出用フラグ int step;//各行動指定値用 //停止時間計測処理 //60ループごとに記憶していたそれ以前の回転値と現在の回転値を比較 //値が変化していなければ回転が止まっている=停止している //値が変化していた場合は前回の回転値を更新 void stopcountor(){ if(loopcount%60==0){ if(SENSOR_1==rot_old){ stopcount++; }else{ stopcount=0; } rot_old=SENSOR_1; } if(loopcount>65535){ loopcount=-1; } loopcount++; } //各行動時に一定時間停止していた場合の復帰処理 void stopcheck_L(){ stopcountor(); if(stopcount>6){ while(1){ turn_right2(5,20); rot_old++; if(rot_old>=2){ break; } } go_straight2(10,5); //go_back2(10,30); stopcount=0; ClearSensor(SENSOR_1); } } void stopcheck_R(){ stopcountor(); if(stopcount>6){ while(1){ turn_left2(5,20); rot_old--; if(rot_old<=-2){ break; } } go_straight2(10,5); //go_back2(10,30); stopcount=0; ClearSensor(SENSOR_1); } } void stopcheck_S(){ stopcountor(); if(stopcount>5){ b_flag=1; stopcount=0; ClearSensor(SENSOR_1); } } //各行動用サブルーチン sub step1_s1(){ while(!SENSOR_3){ go_straight2(20,10); //go_straight(0); stopcheck_S(); if(SENSOR_2||b_flag){ break; } } Wait(20); go_back(step); b_flag=0; Off(OUT_A+OUT_C); Wait(20); } sub step1_s2(){ ClearSensor(SENSOR_1); while(1){ go_straight2(10,5); if(SENSOR_1>step){ Off(OUT_A+OUT_C); break; } } Off(OUT_A+OUT_C); Wait(20); } sub step1_R(){ ClearSensor(SENSOR_1); while(1){ turn_right2(5,20); if(SENSOR_1>step){ break; } stopcheck_R(); } Off(OUT_A+OUT_C); } sub step1_R90(){ turn_right2(21,step); Off(OUT_A+OUT_C); } sub step1_L(){ stopcount=0; ClearSensor(SENSOR_1); while(1){ turn_left2(5,20); if(SENSOR_1<step){ break; } stopcheck_L(); } Off(OUT_A+OUT_C); } sub step1_L90(){ turn_left2(22,-step); Off(OUT_A+OUT_C); } //ほぼ指定移動 task main(){ SetSensor(SENSOR_1,SENSOR_ROTATION);//車輪回転チェック SetSensor(SENSOR_2,SENSOR_TOUCH);//ゴール地点判断 SetSensor(SENSOR_3,SENSOR_TOUCH);//壁判断 ClearSensor(SENSOR_1); //スタート地点からループ開始地点へ step=5; step1_s1(); step=5; step1_R(); step=33; step1_s2(); step=-9; step1_L(); //ループ開始 while(1){ //往路 step=5; step1_s1(); step=7; step1_R(); step=15; step1_s1(); step=-6; step1_L();+ step=5; step1_s1(); go_back(5); step=-5; step1_L(); step=5; step1_s1(); //帰路 step=-7; step1_L(); step=5; step1_s1(); step=-5; step1_L(); step=5; step1_s1(); step=6; step1_R(); step=5; step1_s1(); step=6; step1_R(); step=5; step1_s1(); step=-7; step1_L(); step=5; step1_s1(); step=-6; step1_L(); step=33; step1_s2(); step=6; step1_R(); step=10; step1_s1(); //転回 step=-7; step1_L(); step1_L(); } Off(OUT_A+OUT_C); } **&color(lightseagreen,none){制作過程}; [#l6ac6c41] ***&color(limegreen,none){マシン};[#sdddb4dd] 三つの光センサーで動作する4つまとめて運ぶマシン &color(mediumvioletred,none){ ▼『4つ一度につかみにいく』ための腕};~ #ref(tuno.jpg)~ #br &color(mediumvioletred,none){ ▼『4つ〜』進化版。安定性に欠けるが角が二本に。};~ #ref(kuwagata.jpg)~ #br &color(mediumvioletred,none){ ▼『4つ〜』安定性向上版。仰々しいが安定性は格段に上昇。};~ #ref(nihonude.jpg)~ #br &color(steelblue,none){ ▼『健気に一つずつ缶を押し込む』ためのマシン本体暫定版。};~ &color(steelblue,none){ 基本はこんな感じで、缶を囲い込むように作りいくつかのセンサを使う。};~ #ref(kenage.jpg)~ #br &color(steelblue,none){ ▼『一つずつ〜』骨格完成版。};~ #ref(kakou.jpg)~ #br &color(steelblue,none){ ▼『一つずつ〜』腕中スペース。ここに缶を収納。};~ #ref(hako.jpg)~ #br &color(steelblue,none){ ▼『一つずつ〜』センサ搭載版};~ &color(steelblue,none){ 回転センサーと2つのタッチセンサーで動作するようになっており、壁にぶつかったときと、ゴールの枠にぶつかったときに反応する。};~ #ref(sensor.jpg)~ #br ***&color(limegreen,none){動作}; [#udaa007e] #br ↓缶をつかんで保持する動作。~ #ref(douga1 4can.flc) #br **&color(lightseagreen,none){本番}; [#r538c250] #br #ref(robokon.jpg) ↑本番(二回目)の様子。~ #br ・本番では缶までたどりつけなかったが、ロボットは、回転センサを利用していったん後退するプログラムのおかげで健気に頑張ってくれたと思う。~ ・結果は8位だった。~ **&color(lightseagreen,none){反省・感想}; [#df18d7cc] まとめて運ぶために長いアームのついたロボットを作ったが、耐久度に問題があり、結局使うことができなかったのが残念だった。耐久度を上げようと努力したが、今度は重心が偏ってしまったりして、何か問題が残る形になってしまった。 回転センサーを使うと、初期位置によって誤差が生まれるので、失敗が多かった。 #br ***&color(limegreen,none){コメントをどうぞ}; [#x5253fe4] #comment