- 追加された行はこの色です。
- 削除された行はこの色です。
目次
#contents
*[[課題の説明>2014a/Mission1]] [#ofbcff9d]
*メンバー [#tbb423e0]
-bgpat: 主にプログラム担当
-只の某: 主にロボット作成担当
-bgpat: 主にプログラム担当 スタート→ゴール
-只の某: 主にロボット作成担当 ゴール→スタート
*コースの作成 [#b0a98824]
&ref(2014a/Member/bgpat/Mission1/course.png,400x300);
このような画像ファイルを作成して何枚かのA4用紙に分けて印刷し、台紙に貼り付けました。
薄い部分は黒いペンで塗りつぶしました。
*ロボット本体 [#i40141cf]
**ドライブベース [#i6612d7b]
**アーム [#i7d72672]
*プログラム [#xe5408e4]
**定数の定義 [#rc89c212]
コースやロボットによって値は異なります。
/* トレースのスピード */
#define SPEED_HIGH 40
#define SPEED_MEDIUM 30
#define SPEED_LOW 25
#define SPEED_ZERO 0
/* 直角の制御 */
#define TURN_COUNT_MAX 300
#define GO_COUNT_MAX 150
/* アームの制御 */
#define BALL_DISTANCE 9
#define BALLBAR_TIME 100
#define BALLBAR_DOWN 100
#define BALLBAR_UP 1000
#define BALLBAR_WAIT 1000
#define BALLBAR_SPEED 50
**関数の定義 [#fabca395]
コードの簡略化のための関数です。
/*
* 左右のモーターを回す
* スピードが正のときは前、負のときは後に回す
*/
void On(int leftSpeed, int rightSpeed){
if(leftSpeed > 0){
OnFwd(OUT_C, leftSpeed);
}else{
OnRev(OUT_C, -leftSpeed);
}
if(rightSpeed > 0){
OnFwd(OUT_A, rightSpeed);
}else{
OnRev(OUT_A, -rightSpeed);
}
}
/* 赤外線センサーの値を5段階(0〜4)で返す */
bool Light(){
if(SENSOR_3 < 40){
return 0;
}else if(SENSOR_3 < 44){
return 1;
}else if(SENSOR_3 < 48){
return 2;
}else if(SENSOR_3 < 52){
return 3;
}else{
return 4;
}
}
/* 止まる */
void Stay(){
Off(OUT_AC);
}
/* 前へ進む */
void GoForward(){
On(SPEED_HIGH, SPEED_HIGH);
}
/* 左へ進む */
void GoLeft(){
On(SPEED_ZERO, SPEED_MEDIUM);
}
/* 右へ進む */
void GoRight(){
On(SPEED_MEDIUM, SPEED_ZERO);
}
/* 左回転 */
void TurnLeft(){
On(-SPEED_LOW, SPEED_LOW);
}
/* 右回転 */
void TurnRight(){
On(SPEED_LOW, -SPEED_LOW);
}
/* 後ろへ戻る */
void Back(){
On(-SPEED_HIGH, -SPEED_HIGH);
}
/* 左後へ戻る */
void BackLeft(){
On(SPEED_ZERO, -SPEED_MEDIUM);
}
/* 右後へ戻る */
void BackRight(){
On(-SPEED_MEDIUM, SPEED_ZERO);
}
/* ボールを見つけるとtrueを返す */
bool checkBall(){
if(SensorUS(S1) <= BALL_DISTANCE){
return true;
}
return false;
}
/* ボールを覆う */
/* ボールを拾う */
void catchBall(){
OnFwd(OUT_B, BALLBAR_SPEED);
Wait(BALLBAR_TIME);
Wait(BALLBAR_DOWN);
Float(OUT_B);
Wait(BALLBAR_WAIT);
}
/* ボールを離す */
void releaseBall(){
OnRev(OUT_B, BALLBAR_SPEED);
Wait(BALLBAR_TIME);
Wait(BALLBAR_UP);
Float(OUT_B);
Wait(BALLBAR_WAIT);
}
**メイン関数 [#j9bbb92a]
task main(){
/* 回転数を記録するための変数 */
int turnCount = 0;
/* 曲がりながら進んだ回数を記録するための変数 */
int goCount = 0;
/* 直角の回数 */
int nCorner = 0;
/* ボールを認識した回数 */
int ballCount = 0;
/* センサー類を初期化 */
SetSensorLowspeed(S1);
SetSensorLight(S3);
while(true){
while(nCorner < 5){
Wait(1);
/* ボールを拾う処理 */
/* 直角1回目と2回目の間で、まだボールを拾っていない場合 */
if(nCorner == 1 && ballCount >= 0){
/* ボールを認識したら */
if(checkBall()){
PlayTone(880, 100);
/* 1秒間ボールを認識すれば */
if(ballCount++ > 10){
/* ボールを拾う */
catchBall();
ballCount = -1;
}
/* ボールを認識している間はトレースを一時停止 */
Stay();
Wait(99);
continue;
}else{
ballCount = 0;
}
}
/* トレース */
switch(Light()){
/* 明るさレベル0のとき */
case 0:
TurnLeft();
if(turnCount < 0 || goCount < 0){
turnCount = 0;
goCount = 0;
}
turnCount++;
break;
/* 明るさレベル1のとき */
case 1:
GoLeft();
if(turnCount < 0 || goCount < 0){
turnCount = 0;
goCount = 0;
}
goCount++;
break;
/* 明るさレベル2のとき */
case 2:
GoForward();
break;
/* 明るさレベル3のとき */
case 3:
GoRight();
if(turnCount > 0 || goCount > 0){
turnCount = 0;
goCount = 0;
}
goCount++;
break;
/* 明るさレベル4のとき */
case 4:
TurnRight();
if(turnCount > 0 || goCount > 0){
turnCount = 0;
goCount = 0;
}
turnCount++;
break;
}
/* 直角判定 */
/* もし回転数が多く直進回数が少なければ */
if(turnCount > TURN_COUNT_MAX && goCount < GO_COUNT_MAX){
PlayTone(440, 100);
switch(nCorner++){
/* 1,2,4回目の直角のとき */
case 0:
case 1:
case 3:
/* 交差点を渡る */
TurnRight();
Wait(turnCount * 3);
Off(OUT_AC);
Wait(100);
GoForward();
Wait(100);
break;
/* 5回目の直角のとき */
case 4:
/* 向きを訂正して */
/* ボールを離す */
break;
}
turnCount = 0;
goCount = 0;
}
}
}
**解説 [#k0f87237]
***トレース [#f99fefa4]
明るさを0から4の5段階に分けて、0と4のときはその場で回転、1と3のときは曲がりながら進む、2のときは直進するようします。
直角を判断するために回転した回数と曲がりながら進んだ回数をそれぞれ変数に記録しています。
回転した回数が多く、直進した回数は少ないときに直角と判断します。
交差点を超えるために直角の回数を数えます。
スタート→ゴールの場合は1,2,4回目の直角は交差点、3回目は直角コーナー、5回目はゴールとなります。
交差点と判断すると向きを戻して直進して交差点を渡ります。
直角コーナーはそのままで曲がってくれるのでプログラムは不要です。
ゴールの場合は向きを戻し、ボールをシュートしてループを抜けます。
***ボール [#ec9fadc9]
超音波センサーがボールを見つけるとアームを下ろします。
ただし、超音波センサーの誤動作も考えられるので、ボールを見つけたときにはトレースを中断して、1秒間連続で認識し続けたらボールがあると認識するようにしました。
*感想 [#n5075af2]
なかなか思っている通りに動かず苦労しました。特に値の調整が大変でした。