Tomo
Naoyoshi
Yabu
Kurityan
2台のロボットで空き缶を収集し、ゴールに空き缶になるべく高く積み上げる。
コースと缶の配置は下の図のようになっている。
Naoyoshi とYabuはロボットのプログラミングを担当しTomoとYabuはロボットの作成を担当した。
マスター
#define RIGHT OUT_B #define LEFT OUT_C #define BOTH OUT_BC #define SPEED1 35 #define SPEED2 SPEED1*2 #define OnRL(speedR,speedL) OnRev(RIGHT,speedR);OnRev(LEFT,speedL); //ギアの都合で正転と逆転が反対 #define go_forward OnRevSync(BOTH,SPEED2,0); //左右のタイヤの移動距離をシンクロさせて前進 #define go_back OnFwdSync(BOTH,SPEED2,0); //後退 #define turn_left1 OnFwdSync(BOTH,SPEED2,100); //時計回りに旋回。3つ目の引数100は旋回率(右のモータと左のモータの回転角度が100%異なる) #define turn_left0 OnRL(SPEED2,0); //左折 #define turn_right0 OnRL(0,SPEED2); //右折 #define turn_right1 OnFwdSync(BOTH,SPEED2,-100); //半時計回りに旋回 #define u_turnCW OnRL(-SPEED1,SPEED1); //時計回りに旋回。音波探知用にスピードを落としている。 #define u_turnRCW OnRL(SPEED1,-SPEED1); //半時計回りに旋回 #define THRESHOLD 45 #define RANGE1 7 //ライントレース中に缶をつかむ動作に移行するための距離 #define RANGE2 19.8 //アームを伸ばした時の缶までの距離 #define RANGE3 23 //回転しながら #define RANGE4 5 //前方に感知した缶をバンパーのホルダーに押しこむのに必要な距離 #define STEP 1 #define SR SENSOR_2 #define SL SENSOR_1 #define SS SensorUS(S3) #define CONN 1 #define arm_down "arm1.rxe" //アームを開き、つかむ準備をするプログラムを定義しなおした。特にアームをダウンさせるわけではない #define arm_up "arm2.rxe" //アームの降下→握り→上昇の一連の動作を定義しなおした #define BUILD_RAG 1000 //ゴールの交差点に止まったあと、ゴール中央を向くための回転に必要な時間。 #define DO 523 //音程C、E、Gを指定。hiCはCの二倍で対応 #define MI 659 #define SO 784 #define SIGNALON 11 //Mail受信用 #define SIGNALOFF 12 #define LATIO 3 //走行駆動系のギア比(24:8)。距離の算出に必要
int nFase,angleA,angleB,msg,nCross;
float GetAngle(float r) //引数r[cm]だけ進むのに必要な回転角を導くマクロ。ギア比考慮済み { const float diameter=5.45; const float pi=3.1415; float ang=r/(diameter*pi)*360.0*LATIO; return ang; }
sub find_line() //黒線を見つけるまで前進し、左右両方のセンサが線を検知するまで角度を調整するサブルーチン { until((SL<=THRESHOLD)&&(SR<=THRESHOLD)) { if((SL>THRESHOLD)&&(SR>THRESHOLD)) { go_forward; } else if((SL>THRESHOLD)&&(SR<=THRESHOLD)) { turn_right0; } else { turn_left0; } Wait(STEP); } }
sub start_traceR() //左右の光センサが先に乗った状態から右方向にライントレースを開始するためのサブルーチン { until(SL>THRESHOLD) { turn_right0; } PlaySound(SOUND_CLICK); Off(BOTH); }
sub start_traceL() //左右の光センサが先に乗った状態から左方向にライントレースを開始するためのサブルーチン { until(SR>THRESHOLD) { turn_left0; } PlaySound(SOUND_CLICK); Off(BOTH); }
sub traceR() //右側の光センサを使ってライントレースを行うモード { if(SR<THRESHOLD-4) { turn_right1; } else if(SR<THRESHOLD) { turn_right0; } else if(SR<THRESHOLD+4) { go_forward; } else if(SR<THRESHOLD+7) { turn_left0; } else { turn_left1; } }
sub traceL() //左側の光センサを使ってライントレースを行うモード { if(SL<THRESHOLD-4) { turn_left1; } else if(SL<THRESHOLD) { turn_left0; } else if(SL<THRESHOLD+4) { go_forward; } else if(SL<THRESHOLD+7) { turn_right0; } else { turn_right1; } }
sub search_crossR(int MAXCross) //右側の光センサを使ってライントレースを行いつつ、引数MAXCrossの分だけ交差点を感知するサブルーチン。交差点の判定は左右の光センサが同時に閾値を下回ったことで行う。 { nCross=0; while(nCross<MAXCross) { until((SL<=THRESHOLD)&&(SR<=THRESHOLD)) { traceR(); Wait(STEP); } nCross++; PlaySound(SOUND_UP); until((SL>THRESHOLD)&&(SR>THRESHOLD)) { go_forward; Wait(STEP); } } }
sub search_crossL(int MAXCross) //同じく左側の光センサによるライントレースと同時に交差点判定を行う { nCross=0; while(nCross<MAXCross) { until((SL<=THRESHOLD)&&(SR<=THRESHOLD)) { traceL(); Wait(STEP); } nCross++; PlaySound(SOUND_UP); until((SL>THRESHOLD)&&(SR>THRESHOLD)) { go_forward; Wait(STEP); } } }
sub catch() //持っている缶を新しい缶の上に載せ、掴み、また持ち上げる一連の動作。 { angleB=GetAngle(RANGE4); RotateMotor(BOTH,SPEED1,-angleB); //缶をホルダーの中に押しこむために少し前進する PlayTone(262,400); //ネット上で見つけたメロディー。特に意味はない。 Wait(500); PlayTone(294,400); Wait(500); PlayTone(300,400); Wait(500); PlayTone(294,400); Wait(500); RemoteStartProgram(CONN,arm_down); //スレーブにアームを開かせる Wait(5000); ReceiveRemoteNumber(MAILBOX1,true,msg); if(msg==SIGNALON) { PlaySound(SOUND_CLICK); } else { PlaySound(SOUND_FAST_UP); } angleA=GetAngle(RANGE2); RotateMotor(BOTH,SPEED2,angleA); //アームの伸びに合わせ後退する RemoteStartProgram(CONN,arm_up); //スレーブに缶を掴ませる PlayTone(DO,120);Wait(150); //達成感のあるメロディー。一回ごとに半音ずつ上昇させたかった PlayTone(MI,120);Wait(150); PlayTone(SO,120);Wait(150); PlayTone(DO*2,240);Wait(300); PlayTone(SO,120);Wait(150); PlayTone(DO*2,360);Wait(450); Wait(10000); if(msg==SIGNALON) { PlaySound(SOUND_CLICK); } else { PlaySound(SOUND_FAST_UP); } RotateMotor(BOTH,SPEED2,-angleA+angleB); //つかむ動作の開始点まで戻る。 }
sub build() //ゴールで缶を載せるだけのプログラム。最後まで使われなかった { PlayTone(262,400); Wait(500); PlayTone(294,400); Wait(500); PlayTone(524,400); Wait(500); PlayTone(294,400); Wait(500); RemoteStartProgram(CONN,arm_down); Wait(10000); go_back; Wait(2000); Off(BOTH); nFase++; }
task main() //スタートからゴールまでの一連の流れを記述したプログラム { SetSensorLight(S1); SetSensorLight(S2); SetSensorLowspeed(S3); nFase=0; //第0段階開始(ラインに乗るまで) msg=SIGNALOFF; until(BluetoothStatus(CONN)==NO_ERR); find_line(); start_traceR(); nFase++; //第一段階開始 (一つ目の缶をつかむまで) while(SS>RANGE1) { traceR(); Wait(STEP); } Off(BOTH); catch(); nFase++; //第二段階開始(2つ目の缶をつかむまで) while(nFase<3) { until(SS<RANGE3) //缶を感知するまで回転し続ける { u_turnRCW; Wait(STEP); } while(SS>RANGE1) //感知したらホルダーに格納されるまで前進 { go_forward; Wait(STEP); } Off(BOTH); catch(); nFase++; } while(nFase<4) //第三段階開始(3つ目の缶を格納するまで) { until(SS<RANGE3+3) { u_turnRCW; Wait(STEP); } u_turnCW; Wait(200); Off(BOTH); while(SS>RANGE1) { go_forward; Wait(STEP); } Off(BOTH); //3つ目の缶は掴まず、ホルダーで抱えたままゴールで缶を2つ載せる nFase++; //第四段階開始(缶をゴールに運び、塔を建てるまで) } until((SR<THRESHOLD)||(SL<THRESHOLD)) //反転し、ライントレースに戻る { u_turnRCW; } find_line(); start_traceL(); search_crossL(2); //2つ目の交差点を過ぎたところで停止、缶を下ろす Off(BOTH); build(); go_back;Wait(3000); u_turnRCW;Wait(BUILD_RAG); }
スレイブ1
#define SIGNALON 11 #define SIGNALOFF 12 #define CONN 0
task main() { until(BluetoothStatus(CONN)==NO_ERR); RotateMotor(OUT_A,20,-48); Wait(1000); PlaySound(SOUND_FAST_UP); Wait(2000); SendResponseNumber(MAILBOX1,SIGNALON); }
スレイブ2
#define SIGNALON 11 #define SIGNALOFF 12 #define CONN 0
task main() { until(BluetoothStatus(CONN)==NO_ERR); RotateMotorEx(OUT_BC,15,450,0,true,true); Wait(1000); RotateMotor(OUT_A,30,48); Wait(1000); PlaySound(SOUND_FAST_UP); Wait(1000); RotateMotorEx(OUT_BC,40,-450,0,true,true); Wait(1000); SendResponseNumber(MAILBOX1,SIGNALON); }
今回はロボットキッドを二つ合わせて使って下の写真のような一つのロボットを作った。
下の図のように動いて缶を詰めるようにロボットを作成した。
この動作を繰り返して4個の缶を積むことを目標とした。
工夫点1
最初はアームをモーターに直接つけていたのだが、それだとアームが重くて動かなかったり、パワー全開で動いて缶を吹っ飛ばしてしまったりしていた。なので下の写真のようにモーターに小さいギア、アームに大きいギアを付けて回すことにした。これにより、アームを力強くアームを上げ下げできるようになった。
工夫点2
タイヤも力強くゆっくり動かすためにモーターに小さいギア、タイヤに大きいギアを付けて動かした。(下の写真参照) 工夫点2 タイヤも力強くゆっくり動かすためにモーターに小さいギア、タイヤに大きいギアを付けて動かした。
工夫点3
光センサを二つ付けてラインを挟むようにして課題1のときよりもライントレースをしやすくした。(下の写真参照)
工夫点3 光センサを二つ付けてラインを挟むようにして課題1のときよりもライントレースをしやすくした。
工夫点4
アームの缶を掴む部分と缶を持ち上げる部分の接着が弱く傾いていたので輪ゴムで補強した。(下の写真参照) 工夫点4 アームの缶を掴む部分と缶を持ち上げる部分の接着が弱く傾いていたので輪ゴムで補強した。
工夫点5 缶を掴む部分は一番下に底をつけて缶を落ちないようにして他のチームとは違って輪ゴムやタイヤを全く使わなかった。
工夫点5
缶を掴む部分は一番下に底をつけて缶を落ちないようにして他のチームとは違って輪ゴムやタイヤを全く使わなかった。(下の写真参照)
ロボットの制作に関しては移動するための車体の部分にパーツを使いすぎてしまった点が問題だった。缶を積み上げることができていたロボットはアームの部分がしっかりと出来ていた。車体の部分の構造をもっとシンプルにしてアームの部分をしっかりと作るべきだった。
課題2ではロボットを作るのも大変だったが、それ以上にチームで目標を達成することが大変だった。みんなの考えに行き違いなどがあってなかなか作業が進まないこともあった。次にこのような事がある時はみんなの考えを共有し、作るもののイメージを一致させて作業できるようにしたい。またロボット本体と同じくらいプログラミングも大切であることを学んだ。