- 履歴一覧
- 2015a/Member/Y.H/Mission2 は削除されています。
*目次 [#pdbe1a7d]
#contents
*課題について [#s030a29a]
課題2は光センサーを使ったライン・トレース・ロボットの製作。
コースは以下の通り(課題2のページより)
#ref(./コース.png,50%)
-A地点からB地点へ (P三叉路およびQ交差点はともに直進)
-B地点からA地点へ (Q交差点では直進、P三叉路では直進)
-C地点からA地点へ (Q交差点では直進、P三叉路では右折)
また、これらの経路の途中(PQ間)においたボールをゴールまで運ぶこと。三叉路および交差点では二秒間停止すること。
今回は、B地点からA地点のコースとする。
*ロボット本体について [#j1672ef1]
#ref(./image1 (2).JPG,70%)
ボールをつかむためにタッチセンサをつけると邪魔になりそうだったので、つけないことにした。
アームはモーターAで動かす。BCは移動用に使った。
アームは上からボールにかぶせる形にした。
*プログラムについて [#z4ee3701]
**ライントレース1[#k3c8fb05]
交差点や三叉路の判定にはカウンターを使うことにした。
定義
#define hikari 50 //光センサーの閾値で、これを基準にロボットの行動を分ける
#define SPEED1 55
#define SPEED 25
#define turn_left OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);
#define TURN_LEFT OnFwd(OUT_B,SPEED);
#define go_forward OnFwd(OUT_BC,SPEED1); //ロボットの行動で、小回りだと小文字とした
#define TURN_RIGHT OnFwd(OUT_C,SPEED);
#define turn_right OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED);
#define STEP 1 //ライントレースの一回の判断の時間
#define nMAX 175 //これを超えると、交差点と判断
#define pose Off(OUT_BC);Wait(200); //交差点を判断した後の二秒停止のルール
#define CROSS_TIME 200
#define cross_line OnFwd(OUT_BC,SPEED);Wait(CROSS_TIME);pose;
プログラムの本文
task main()
{
SetSensorLight(S3);
int nOnline=0;
while(true){
while(nOnline<nMAX){
if(SENSOR_3<hikari -7){ //光センサーの値が特に小さいときは
turn_right; //小回りをしてカウンターを回す
nOnline++;
}else{ //そのほかの時は
if(SENSOR_3<hikari -3){
TURN_RIGHT;
}else if(SENSOR_3<hikari +3){ //光センサーの値によりロボットの動きを変えつつ
go_forward; //ライントレースをして、カウンターはリセット
}else if(SENSOR_3<hikari +10){
TURN_LEFT;
}else{
turn_left;
}
nOnline=0;
}
Wait(STEP); //STEPの間、上の動作をする
} //ことをカウンターがnMaxに達するまで無限ループ
pose; //カウンターがnMaxに達し、交差点と判断
turn_left;Wait(nMAX*STEP); //それまでにずれた分軌道を修正
cross_line; //交差点を渡る
nOnline=0; //カウンターをリセットし、再びライントレースに戻れるようにする
}
}
**ライントレース2 [#p10a79f3]
1を参考に改良しようと思った。
結果、早くライントレースさせるためには、コースを区間に区分し、それぞれに最適化するほうがよいと思った。というのも小回りでの左右の回転では、ロボットが進まないからである。分けてしまえばその時には全く五段階である必要がなかったので、二段階か三段階にして小回りさせる数を減らした。また、直進は時々カーブの時にしかならなかったので、削った。
定義
#define hikari 50
#define SPEED 25
#define SPEED1 35
#define turn_left OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED1);
#define TURN_LEFT OnFwd(OUT_B,SPEED1);Off(OUT_C);
#define go_forward OnFwd(OUT_BC,SPEED1);
#define TURN_RIGHT OnFwd(OUT_C,SPEED1);Off(OUT_B);
#define turn_right OnRev(OUT_B,SPEED);OnFwd(OUT_C,SPEED);
#define STEP1 5
#define STEP2 2
#define nMax 70
#define curve 100
#define arm_down OnFwd(OUT_A,SPEED);Wait(300);
#define shoot OnRev(OUT_BC,SPEED);Wait(1000);\
OnRev(OUT_A,SPEED);Wait(500);\
OnFwd(OUT_BC,SPEED1);Wait(500);
プログラムの本文
task main()
{
SetSensorLight(S4);
int nOnline=0;
int nKousa=0;
int nMax_RIGHT=0;
while(nOnline<nMax){ //最初の直進
if(SENSOR_4<hikari){
TURN_RIGHT;
nOnline=0; //進行方向線の右側をなぞる
}else{
TURN_LEFT;
nOnline++;
}
Wait(STEP1);
}
turn_right;Wait(STEP1*nMax/2); //曲がり角を曲がり
go_forward;Wait(560);
until(SENSOR_4<hikari){
turn_left; //次から線の左側をなぞるようにする(次の直進の後からでもよいが、曲がったついでに)
}
turn_left;Wait(200);
nOnline=0;
while(nOnline<nMax){ //次の直進
if(SENSOR_4<hikari){
TURN_LEFT;
nOnline++; //線の左側をなぞる
}else{
TURN_RIGHT;
nOnline=0;
}
Wait(STEP1);
}
arm_down;Off(OUT_ABC);Wait(500); //交差点を判断したら
TURN_RIGHT;Wait(STEP1*nMax); //ボールをつかむ
nOnline=0;
long t0=CurrentTick();
while(CurrentTick()-t0<9000){ //左側をなぞったほうが緩くなるカーブ
if(SENSOR_4<hikari){
TURN_LEFT;
nMax_RIGHT=0;
}else{
TURN_RIGHT;
nMax_RIGHT++;
}
Wait(STEP2);
if(nMax_RIGHT>curve){
until(SENSOR_4<hikari){ //カーブの半径のほうがタイヤの回転の半径より
turn_right; //小さいので小回り
}
}
}
until(SENSOR_4<hikari){ //カーブの終わりごろに
TURN_RIGHT;
} //次から線の右側をなぞるようにする
turn_right;Wait(200);
while(nKousa<2){
while(nOnline<nMax){ //線の右側をなぞったほうが緩くなるカーブ(三叉路も、反対だと判定できなくなるため、直前の直線から右側をなぞらせる)
if(SENSOR_4>hikari){
TURN_LEFT;
nOnline=0; //線の右側をなぞる
}else{
TURN_RIGHT;
nOnline++;
}
Wait(STEP1);
}
TURN_LEFT;Wait(STEP1*nMax);Off(OUT_BC);
nKousa++;
}
shoot; //三叉路(一回目の交差点)は通過し、ゴールの周りの線を二回目の交差点と判断させてボールをシュートする
}
*感想 [#bfb90857]
プログラムの1からみれば2は早くなったのではないかとも思うが、回転半径を小さくしてロボットのブレを減らし、出力を上げればもっと速くなると思う。あるいはどちらかのタイヤと、光センサーを近づければ、回転半径が左右で異なるので、左右の出力を変えてやればまた違うのではないかと思ったが、タイヤ間の距離を縮めたほうが早そうだと思った。
本体についてはまだある。二つのタイヤよりだいぶ前に光センサーがあるので、曲がり角はきっちりライントレースをして曲がる、ということはできなかった。構造的におそらく。