青と赤のボールを運搬して、空き缶の上に載せる。
今回の課題では、ボールを掴むロボットと缶を掴むロボットの二台に分け、中央で缶にボールを乗せて、元の位置に戻すように計画した。(私は缶を掴むロボットを担当した)
また、2人1組になってそれぞれ別のロボットを担当し、効率よく進められるように努めた。
今回は缶を掴むロボットとボールを掴むロボットの二台を用いた。
このロボットはC,E,Fにあるボールを掴み、I付近で缶を掴むロボットに渡すことができるようにつくった。
三つ目のモーターをボールを掴むアームの部分に用い、うまく歯車が合うように調節した。また、アームはボールの下のほうを掴むように高さを定め、ボールをすくい上げるような形にした。
光センサーの調子が少し良くない時があったので、光センサーをできるだけ固定し、地面からの高さが一定になるようにした。また、超音波センサーが缶を感知する距離が6cmより小さい値では反応せず、缶を掴むには少し遠かったので、センサー自体の位置をできるだけ缶から遠くなるよう調節した。
C',E',F',にある缶を取って、I付近でボールを掴むロボットからボールを受け取り、缶を元の位置に戻すようにつくった。空き缶の位置は上部についている超音波センサーではかり、取れるようにした。
アームが缶を離す際、開きすぎてアームがタイヤに接触することがあったため、開きすぎないようにストッパーのようなものを取り付けた。また、缶がアームから離れないようにアームの形をくの字にした。
#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付近で待っているもう一方のロボットが掴んでいる缶を認識するまでライントレースし、缶を認識したらアームを開くようにプログラミングした。
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); }
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); }}}}
各缶の位置まで近いづいたとき、超音波センサーが缶に反応するまでライントレースするようにプログラミングした。
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つしか運ぶことができず、残念であった。このような結果になってしまったが、班のメンバーと協力して効率よく活動できたので良い経験になったと思う。
最後にこのゼミでは、自分の所属する学科では学ぶことができないことを学ぶことができ、とても良い経験だった。また、ロボットをつくり、プロブラミングすることの大変さがよくわかり、この仕事に携わっている人たちはとてもすごいと感じた。この講義で得たことを活かしてこれからも努力していきたい。