2019b/Member

目次

課題3:ボール運搬ロボット

青と赤のボールを運搬して、空き缶の上に載せる。

2019b-mission2.png

ルール

  • 競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
  • 図のA地点または(および)A'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。
  • 開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
  • 競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
  • 途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
  • 競技終了後、ロボットが、空き缶に触れていてはいけない。

計画

今回の課題では、ボールを掴むロボットと缶を掴むロボットの二台に分け、中央で缶にボールを乗せて、元の位置に戻すように計画した。(私は缶を掴むロボットを担当した)

また、2人1組になってそれぞれ別のロボットを担当し、効率よく進められるように努めた。

ロボットの説明

今回は缶を掴むロボットとボールを掴むロボットの二台を用いた。

ボールを掴むロボット

IMG_1494.jpeg

このロボットはC,E,Fにあるボールを掴み、I付近で缶を掴むロボットに渡すことができるようにつくった。

IMG_1493.jpeg

三つ目のモーターをボールを掴むアームの部分に用い、うまく歯車が合うように調節した。また、アームはボールの下のほうを掴むように高さを定め、ボールをすくい上げるような形にした。

IMG_1489.jpeg

光センサーの調子が少し良くない時があったので、光センサーをできるだけ固定し、地面からの高さが一定になるようにした。また、超音波センサーが缶を感知する距離が6cmより小さい値では反応せず、缶を掴むには少し遠かったので、センサー自体の位置をできるだけ缶から遠くなるよう調節した。

缶を掴むロボット

IMG_1495.jpeg

C',E',F',にある缶を取って、I付近でボールを掴むロボットからボールを受け取り、缶を元の位置に戻すようにつくった。空き缶の位置は上部についている超音波センサーではかり、取れるようにした。

IMG_1496.jpeg

アームが缶を離す際、開きすぎてアームがタイヤに接触することがあったため、開きすぎないようにストッパーのようなものを取り付けた。また、缶がアームから離れないようにアームの形をくの字にした。

プログラミングの説明

ボールを掴むロボット

定義

#define THRESHOLD 52
#define SPEED_H 35
#define SPEED_L 25
#define onRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
#define go_forward onRL(SPEED_L,SPEED_L);
#define turn_left1 onRL(SPEED_H,-SPEED_H);
#define turn_left0 onRL(SPEED_H,0);
#define turn_right0 onRL(0,SPEED_H);
#define turn_right1 onRL(-SPEED_H,SPEED_H);
#define STEP 1
#define nMAX 140
#define short_break Off(OUT_BC);Wait(1000);
#define cross_line onRL(SPEED_L,SPEED_L);Wait(1000);
#define u_turnl1 
OnRev(OUT_BC,SPEED_L);Wait(200);RotateMotorEx(OUT_BC,SPEED_H,angle2,-100,true,true);
#define u_turnr1 
OnRev(OUT_BC,SPEED_L);Wait(1400);RotateMotorEx(OUT_BC,SPEED_H,angle1,100,true,true);
#define u_turnl2 
OnRev(OUT_BC,SPEED_L);Wait(1200);RotateMotorEx(OUT_BC,SPEED_H,angle2,-100,true,true);
#define u_turnr2 
OnRev(OUT_BC,SPEED_L);Wait(1000);RotateMotorEx(OUT_BC,SPEED_H,angle2,100,true,true);
float GetAngle(float d)
{
const float diameter = 5.5;
const float distance=12;
float ang = (distance*d)/diameter;
return ang;
}

交差点認識

sub follow_stop() //交差点で止まる
{
SetSensorLight(S4);
int nOnline=0;
int cross=0;
while(cross<1){
while(nOnline<nMAX){
if(SENSOR_4<THRESHOLD-15){
turn_right1;
nOnline++;
}else{
if(SENSOR_4<THRESHOLD-7){
turn_right0;
}else if(SENSOR_4<THRESHOLD+7){
go_forward;
}else if(SENSOR_4<THRESHOLD+15){
turn_left1;
}else{
turn_left0;
}
nOnline=0;
}
Wait(STEP);
}
short_break;
cross++;
}}
sub follow_line1() //右トレースして直進
{
SetSensorLight(S4);
int nOnline=0;
int cross=0;
while(cross<1){
 while(nOnline<nMAX){
 if(SENSOR_4<THRESHOLD-15){
 turn_right1;
 nOnline++;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_right0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_left1;
 }else{
 turn_left0;
}
nOnline=0;
}
Wait(STEP);
}
short_break;
turn_left1;Wait(nMAX*STEP);
cross_line;
nOnline=0;
cross++;
}}
sub follow_line2() //左トレースして直進
{
SetSensorLight(S4);
int nOnline=0;
int cross=0;
while(cross<1){
 while(nOnline<nMAX){
 if(SENSOR_4<THRESHOLD-15){
 turn_left1;
 nOnline++;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_left0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_right1;
 }else{
 turn_right0;
}
nOnline=0;
}
Wait(STEP);
}
short_break;
cross_line;
nOnline=0;
cross++;
}}

課題2と同じように交差点を認識するようにした。

ボールを掴む

sub catch_balll()//左トレース
{
SetSensorLight(S4);
SetSensorLowspeed(S1);
int catch=0;
while(catch<1){
 while(SensorUS(S1)>=6.1){//ここの()の中身で、超音波センサーと缶の距離が6.1cm以上になるまで以下のプログラミングを続けるようにした。
  if(SENSOR_4<THRESHOLD-15){
  turn_left1;
  }else{
  if(SENSOR_4<THRESHOLD-7){
  turn_left0;
  }else if(SENSOR_4<THRESHOLD+7){
  go_forward;
  }else if(SENSOR_4<THRESHOLD+15){
  turn_right0;
  }else{
  turn_right1;
}}
Wait(STEP);
 }
short_break;
OnFwd(OUT_A,-22);
Wait(2000);
Off(OUT_A);
catch++;
}}
sub catch_ballr()//右トレース
{
SetSensorLight(S4);
SetSensorLowspeed(S1);
int catch=0;
while(catch<1){
 while(SensorUS(S1)>=6.2){
 if(SENSOR_4<THRESHOLD-15){
 turn_right1;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_right0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_left1;
 }else{
 turn_left0;
 }}
 Wait(STEP);
 }
 short_break;
 OnFwd(OUT_A,-22);
 Wait(2000);
 Off(OUT_A);
 catch++;
 }}

超音波センサーが缶を感知するまで黒線をライントレースし、缶を感知したらアームを閉じるようにプログラミングした。

ライントレース後、曲がる

sub follow_liner() //右トレースで右折
{
SetSensorLight(S4);
int nOnline=0;
int cross=0;
while(cross<2){
 while(nOnline<nMAX){
 if(SENSOR_4<THRESHOLD-15){
 turn_right1;
 nOnline++;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_right0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_left1;
 }else{
 turn_left0;
}
nOnline=0;
}
Wait(STEP);
}
short_break;
turn_right1;
Wait(1000);
nOnline=0;
cross++;
}}
sub follow_linel() //左トレースして左折
{
SetSensorLight(S4);
int nOnline=0;
int cross=0;
while(cross<2){
 while(nOnline<nMAX){
 if(SENSOR_4<THRESHOLD-15){
 turn_left1;
 nOnline++;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_left0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_right1;
 }else{
 turn_right0;
 }
 nOnline=0;
 }
 Wait(STEP);
 }
short_break;
turn_left1;
Wait(800);
nOnline=0;
cross++;
}}

課題2と同じように交差点を判断し、交差点を認識するまでライントレースをして、交差点を認識した後は右左折するようにプログラミングした。

ボールを離す

sub catch_releaser()//右トレース
{
SetSensorLight(S4);
SetSensorLowspeed(S1);
int catch=0;
while(catch<1){
 while(SensorUS(S1)>=6.2){
 if(SENSOR_4<THRESHOLD-15){
 turn_right1;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_right0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_left1;
 }else{
 turn_left0;
 }}
Wait(STEP);
}
short_break;
OnFwd(OUT_A,20);
Wait(500);
Off(OUT_A);
catch++;
}}
sub catch_releasel()//左トレース
{
SetSensorLight(S4);
SetSensorLowspeed(S1);
int catch=0;
while(catch<1){
 while(SensorUS(S1)>=6.2){
 if(SENSOR_4<THRESHOLD-15){
 turn_left1;
 }else{
 if(SENSOR_4<THRESHOLD-7){
 turn_left0;
 }else if(SENSOR_4<THRESHOLD+7){
 go_forward;
 }else if(SENSOR_4<THRESHOLD+15){
 turn_right1;
 }else{
 turn_right0;
}}
Wait(STEP);
}
short_break;
OnFwd(OUT_A,20);
Wait(500);
Off(OUT_A);
catch++;
}}

I付近で待っているもう一方のロボットが掴んでいる缶を認識するまでライントレースし、缶を認識したらアームを開くようにプログラミングした。

main関数

task main()
{
int angle1 = GetAngle(90);
int angle2 = GetAngle(60);
catch_balll();
u_turnl2;

Cのボールを掴みUターン

follow_stop();
OnFwd(OUT_BC,25);
Wait(200);

I付近で受け渡しするため、右トレースに切り替え

catch_releaser();
Wait(6000);

ボールを離して待機

u_turnl1;
Wait(500);
OnFwd(OUT_BC,25);
Wait(100);

Uターンして左トレースに切り替え

follow_liner();
catch_ballr();
u_turnr1;

Fのボールを掴みUターン

follow_line2();

受け渡しのために右トレースに切り替え

catch_releaser();
Wait(10000);

ボールを離して待機

u_turnl2;
Wait(500);
OnFwd(OUT_BC,25);
Wait(100);

Uターンして左トレースに切り替え

follow_stop();
turn_right1;
Wait(1000);
follow_line1();
follow_stop();
turn_right1;
Wait(1000);
catch_ballr();
u_turnr1;

Eまでたどり着き、ボールを掴んでUターン

follow_line2();
follow_line2();
catch_releaser();
}

I付近でボールを離して終了。

缶を掴むロボット

定義

#define WHITE 56    // 白色
#define GWHITE 48   // 白灰色
#define GBLACK 40   // 黒灰色
#define BLACK 34    // 黒色
#define SPEED_H 47  // ハイスピード 
#define SPEED 43    // ノーマルスピード
#define SPEED_L 40  // ロースピード
#define STEP 1
#define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
#define go OnFwdSync(OUT_BC,SPEED_H,0);               // 直進
#define gofwd OnFwdSync(OUT_BC,SPEED_L,0);            // 直進(スロー)
#define left_rotation_s OnRL(SPEED,-SPEED);           // 高速左回転
#define left_rotation OnRL(SPEED_L,-SPEED_L);         // 左回転
#define turn_left Off(OUT_C);OnFwd(OUT_B,SPEED);      // 左旋回 
#define turn_right Off(OUT_B);OnFwd(OUT_C,SPEED);     // 右旋回
#define right_rotation OnRL(-SPEED_L,SPEED_L);        // 右回転
#define right_rotation_s OnRL(-SPEED,SPEED);          // 高速右回転
float GetAngle(float d)
{
 const float diameter = 5.45;
 const float pi=3.1415;
 const float distance=12.1;
 float ang = (distance*d)/diameter;
 return ang;
}
void turnR(long u)
{
 int angle = GetAngle(u);
 RotateMotorEx(OUT_BC,SPEED,angle,100,true,true);
} 
void turnL(long l)
{ 
 int angle = GetAngle(l);
 RotateMotorEx(OUT_BC,SPEED,angle,-100,true,true);
}
void back(long b)
{
 RotateMotorEx(OUT_BC,-SPEED,b,0,true,true);
}

交差点認識

void follow_line(long q)//左トレース
{
 SetSensorLight(S3);
 long t0;
 t0 = CurrentTick();
  while(CurrentTick()-t0 < q){
  if(SENSOR_3 <= BLACK){
  left_rotation
  }else if((BLACK < SENSOR_3) && (SENSOR_3 < GBLACK)){
  turn_left
  t0 = CurrentTick();
  }else if((GBLACK <= SENSOR_3) && (SENSOR_3 <= GWHITE)){
  go
  t0 = CurrentTick();
  }else if((GWHITE < SENSOR_3) && (SENSOR_3 < WHITE)){
  turn_right
  t0 = CurrentTick();
  }else if(WHITE <= SENSOR_3){
  right_rotation
 t0 = CurrentTick();
}
Wait(STEP);
}
Off(OUT_BC);
}
void follow_lineR(long p) //右トレース
{
 SetSensorLight(S3);
 long t0;
 t0 = CurrentTick();
  while(CurrentTick()-t0 < p){
  if(SENSOR_3 <= BLACK){
  right_rotation
  }else if((BLACK < SENSOR_3) && (SENSOR_3 < GBLACK)){
  turn_right
  t0 = CurrentTick();
  }else if((GBLACK <= SENSOR_3) && (SENSOR_3 <= GWHITE)){
  go
  t0 = CurrentTick();
  }else if((GWHITE < SENSOR_3) && (SENSOR_3 < WHITE)){
  turn_left
  t0 = CurrentTick();
  }else if(WHITE <= SENSOR_3){
  left_rotation
  t0 = CurrentTick();
}
Wait(STEP);
}
Off(OUT_BC);
}

課題2と同じように交差点を認識するようにプログラミングした。

一定時間までライントレース

void follow_line_for_intersection(long t)//左トレース
{
SetSensorLight(S3);
long t0;
t0 = CurrentTick();
 while(CurrentTick()-t0 < t){
 if(SENSOR_3 <= BLACK){
 left_rotation_s
 }else if((BLACK < SENSOR_3) && (SENSOR_3 < GBLACK)){
 turn_left
 }else if((GBLACK <= SENSOR_3) && (SENSOR_3 <= GWHITE)){
 go
 }else if((GWHITE < SENSOR_3) && (SENSOR_3 < WHITE)){
 turn_right
 }else if(WHITE <= SENSOR_3){
 right_rotation
}
Wait(STEP);
}
Off(OUT_BC);
}
void follow_line_for_intersectionR(long y) //右トレース
{
SetSensorLight(S3);
long t0;
t0 = CurrentTick();
while(CurrentTick()-t0 < y){
 if(SENSOR_3 <= BLACK){
 right_rotation_s
 }else if((BLACK < SENSOR_3) && (SENSOR_3 < GBLACK)){
 turn_right
 }else if((GBLACK <= SENSOR_3) && (SENSOR_3 <= GWHITE)){
 go
 }else if((GWHITE < SENSOR_3) && (SENSOR_3 < WHITE)){
 turn_left 
 }else if(WHITE <= SENSOR_3){
 left_rotation
 }
Wait(STEP);
}
Off(OUT_BC);
}

t秒経過するまでライントレースするようにプログラミングした。

アームの開閉

void open()
{
 OnFwd(OUT_A,30);
 Wait(400);
 Off(OUT_A);
}
void close()
{
 OnRev(OUT_A,30);
 Wait(700);
 Off(OUT_A);
}

C',E',F'で缶を掴む

void followC()
{
SetSensorLowspeed(S2);
SetSensorLight(S3);
 while(true){
 int s=SensorUS(S2);
 if(s<15){ //超音波センサーが15を下回る値をとったら、一時停止してアームを閉じる
 Off(OUT_BC);
 Wait(300);
 close();
 int tenkan = GetAngle(70);
 RotateMotorEx(OUT_BC,SPEED,tenkan,100,true,true);
 break;
  }else{ //ifの条件を満たさない場合、以下のライントレースのプログラミングを実行する
  if(SENSOR_3<BLACK){
  RotateMotorEx(OUT_BC,SPEED,2.0,-50,true,true);
  }else if(SENSOR_3<GBLACK){
  OnFwd(OUT_B,70);
  Off(OUT_C);
  }else if(SENSOR_3<GWHITE){
  OnFwd(OUT_BC,100);
  Wait(10);
  Off(OUT_BC);
  }else if(SENSOR_3<WHITE){
  Off(OUT_B);
  OnFwd(OUT_C,70);
  }else if(SENSOR_3>=WHITE){
  RotateMotorEx(OUT_BC,SPEED,5.0,70,true,true);
 }}}}
void followF()
{
SetSensorLowspeed(S2);
SetSensorLight(S3);
 while(true){
 int s=SensorUS(S2);
 if(s<15){
 Off(OUT_BC);
 Wait(300);
 close();
 back(120);
 turnR(66);
 break;
 }else{
 if(SENSOR_3<BLACK){
 RotateMotorEx(OUT_BC,SPEED,2.0,-50,true,true);
 }else if(SENSOR_3<GBLACK){
 OnFwd(OUT_B,70);
 Off(OUT_C);
 }else if(SENSOR_3<GWHITE){
 OnFwd(OUT_BC,100);
 Wait(10);
 Off(OUT_BC);
 }else if(SENSOR_3<WHITE){
 Off(OUT_B);
 OnFwd(OUT_C,70);
 }else if(SENSOR_3>=WHITE){
 RotateMotorEx(OUT_BC,SPEED,5.0,70,true,true);
}}}}
void followE()
{
SetSensorLowspeed(S2);
SetSensorLight(S3);
while(true){
 int s=SensorUS(S2);
 if(s<15){
 Off(OUT_BC);
 Wait(300);
 close();
 back(120);
 turnR(50);
 break;
 }else{
 if(SENSOR_3<BLACK){
 RotateMotorEx(OUT_BC,SPEED,5.0,70,true,true);
 }else if(SENSOR_3<GBLACK){
 Off(OUT_B);
 OnFwd(OUT_C,70);
 }else if(SENSOR_3<GWHITE){
 OnFwd(OUT_BC,100);
 Wait(10);
 Off(OUT_BC);
 }else if(SENSOR_3<WHITE){
 OnFwd(OUT_B,70);
 Off(OUT_C);
 }else if(SENSOR_3>=WHITE){
 RotateMotorEx(OUT_BC,SPEED,2.0,-50,true,true);
}}}}

各缶の位置まで近いづいたとき、超音波センサーが缶に反応するまでライントレースするようにプログラミングした。

main関数

task main()
{
RotateMotorEx(OUT_BC,SPEED_H,180,0,true,true);
follow_line_for_intersection(10000);
follow_line(200);
follow_line_for_intersection(1000);
follow_line(200);
follow_line_for_intersection(1500);

C付近までたどり着く

followC();                                    
follow_line_for_intersection(750);
follow_line(150);
RotateMotor(OUT_C,SPEED,150);
turnR(40);
RotateMotorEx(OUT_BC,SPEED_L,60,0,false,true);
follow_line_for_intersection(1000);
follow_line(200);
follow_line_for_intersection(3000);
Wait(10000);

Cで缶を掴んだ後、Iまで移動し待機

RotateMotor(OUT_C,-SPEED,330);
RotateMotorEx(OUT_BC,SPEED_L,70,0,false,true);
turnL(40);
follow_lineR(135);
RotateMotor(OUT_C,SPEED,70);
follow_line_for_intersection(1000);
follow_line(180);
follow_line_for_intersection(1000);
follow_line(180);
back(120);
open();

Iでボールを受け取った後、Cまで移動し缶を離す

back(160);
turnR(130);
RotateMotorEx(OUT_BC,SPEED_L,40,0,false,true);
follow_line_for_intersection(2000);

F付近まで移動

followF();                                    
follow_line_for_intersection(1000);
follow_line(200);
follow_line_for_intersection(3000);
Wait(9000);

Fで缶を掴んだ後、I付近で待機

RotateMotor(OUT_C,-SPEED,330);
RotateMotorEx(OUT_BC,SPEED_L,70,0,false,true);
turnL(40);
follow_lineR(140);
follow_line_for_intersectionR(1000);
follow_lineR(140);
RotateMotor(OUT_C,SPEED_H,90);
follow_line(160);
back(120);
open(); 

I付近でボールを受け取った後、Fまで移動し缶を離す

back(150);
turnL(77);
RotateMotorEx(OUT_BC,SPEED_L,50,0,false,true);
follow_line_for_intersectionR(1000);
follow_lineR(140);
follow_line_for_intersectionR(2000);

E付近まで移動

followE();                                   
follow_line_for_intersection(1500);
follow_line(160);
RotateMotor(OUT_C,SPEED,75);
follow_line_for_intersection(500);
follow_line(160);
follow_line_for_intersection(3000);
Wait(15000);

Eで缶を掴んだ後、Iまで移動し待機

RotateMotor(OUT_C,-SPEED,330);
RotateMotorEx(OUT_BC,SPEED_L,70,0,false,true);
turnL(40);
follow_lineR(150);
follow_line_for_intersectionR(1500);
follow_lineR(160);
RotateMotorEx(OUT_BC,SPEED_L,65,0,false,true);
RotateMotor(OUT_B,SPEED,30);
follow_line_for_intersectionR(1000);
follow_lineR(150);
follow_line_for_intersectionR(1750);
follow_lineR(140);
back(120);
turnL(15);
open();               
back(300);
}

I付近でボールを受け取った後、Eまで移動し缶を離し、缶から離れて終了。

反省点と感想

今回の課題では、ボールを掴むロボットのアームの部分をつくるのが難しく、大変だった。また、光センサーの値の変動が激しく、ロボットの動きが同じプログラミングでも違う挙動をしてしまい、調整するのに苦労した。

本番の日は、直前の調整まではうまくいって3つのボールを運ぶことができていたが、本番ではボールを1つしか運ぶことができず、残念であった。このような結果になってしまったが、班のメンバーと協力して効率よく活動できたので良い経験になったと思う。

最後にこのゼミでは、自分の所属する学科では学ぶことができないことを学ぶことができ、とても良い経験だった。また、ロボットをつくり、プロブラミングすることの大変さがよくわかり、この仕事に携わっている人たちはとてもすごいと感じた。この講義で得たことを活かしてこれからも努力していきたい。


添付ファイル: fileIMG_1496.jpeg [詳細] fileIMG_1489.jpeg [詳細] fileIMG_1493.jpeg [詳細] fileIMG_1494.jpeg [詳細] fileIMG_1495.jpeg [詳細] file2019b-mission2.png [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-02-15 (土) 23:59:29