クワガタのような大きなアームを装備している。
ライントレースの様子
半時計周りの空き缶運び。
ラインの右側をトレースしながら8.5秒間(空き缶を掴むまで)前進する。
↓
空き缶を掴む。
↓
ラインの左側を前進。
↓
十字路通過。
↓
ラインの左側を前進しながら3回十字路を通過する。
↓
20.5秒間ラインの左側を前進する。
↓
右旋回をして、180°機体の向きを回転させる。
↓
空き缶を置く。
↓
少しバックして、向きを前進方向に戻す。
↓
ラインの右側を前進して、ゴールに向かう。
↓
ゴール(終了)。
基本的な動作は至って簡単で、黒ラインの縁をトレースするものである。まず、ライントレースするにあたって光センサでラインの高度を読み取りながら走行するようにした。ラインの縁に差し掛かったときだけ直進するプログラムを作った。つまり、ラインの右側を走行する場合は白(紙の色)のとき左折をする。このとき黒ラインにどれだけ近いかで旋回と片輪をを軸にした回転に分割した。黒ラインから大きく離れているときは片輪を軸にした左回転。黒ラインに比較的近いときは左旋回とした。黒ラインの中に収まっているときは、黒色の濃さによって右折の度合いを判断している。黒ラインの中心部に機体が居るとき、センサーは一番小さな値を返して来る。この値に近いときは、片輪を軸とした右回転をする。中心部から外れた明るい黒(センサーの値が中心部より高い)時には、右旋回をする。
これがこのプログラムの前進部の動作原理である。
次に十字路について解説する。十字路では前進するプログラムを続けると片輪の回転を連続して繰り返すことになる。つまり、回転した分のキョリを戻ることによって十字路の中心部に戻ることになる。中心に戻った後一度前進してから前進のプログラムに切り替える。
この前進と十字路のプログラムを合わせることによってコースを完走することが出来する。
#define CENTER 45
赤外線センサーのラインを読み取った時の値。
この値は中央よりやや外側の値になっている。
#define CCC 20500
この値は走行中に4回目に通過した交差点から空き缶を離すまでの時間である。
#define SPEED_H 52 #define SPEED_L 32
この値は走行中のモーターの強度を示している。SPEED_Hは直線、SPEED_Lは急な角などで用いる。
#define turn_R Off(OUT_B); OnFwd(OUT_C,SPEED_L); #define turn_L Off(OUT_C); OnFwd(OUT_B,SPEED_L);
これは片輪を軸とした回転運動のときに使用するもの。Rが右回転、Lが左回転を示す。
#define turn_SR OnRev(OUT_B,SPEED_L); OnFwd(OUT_C,SPEED_L); #define turn_SL OnRev(OUT_C,SPEED_L); OnFwd(OUT_B,SPEED_L);
これは車体の中心を軸とした小回り重視の回転をするときに用いるものである。SRが右旋回、SLが左旋回を示す。
#define go_F OnFwd(OUT_BC,SPEED_H); #define go_b OnFwd(OUT_B,-50);OnFwd(OUT_C,-50);
直進運動に用いるものである。Fが前進、bが後進である。
#define STEP 1 #define nMAX 300
交差点を走行時に使用するものである。交差点を判断するループの1ループあたりの時間をSTEPで示し、このループ回数をnMAX回行うと交差点であるとしている。
#define short_break Off(OUT_BC);Wait(300);
交差点を判断しているループから抜けたあとの処理に問題が起きないようにするためのものである。
#define CROSS_TIME 600 #define cross OnFwd(OUT_C,SPEED_L);OnFwd(OUT_B,SPEED_L);Wait(CROSS_TIME);short_break;
これは交差点での走行の仕方を定義したものである。ここでもshort_breakを使い誤動作をなくしている。
機体は初め使っていたライントレース専門の機体を空き缶を掴めるようにするために改造した。しかし、改造に使える時間が時間が短く、大部分の構造は変更することが出来まかった。そこで、もともと機体の制御部の位置を高い位置にすることによって空き缶を掴むアーム部分を取り付けることが出来た。
十字路の進入角度が鈍角のものと鋭角のものがあり、鈍角のときに中心部に差し掛かる時間が少なくなり、十字路をうまく曲がることが出来なかった。しかし中心部分に差し掛かる時間を短くすることで十字路と認識させることができうまくいった。
初めてプログラムを書いて動かしたときは課題をうまくこなせず、中間ロボコンに挑戦することがとても不安だった。しかし、徐々に機体の性質やセンサーの感度を理解でき最終的に完走まで持っていけることが出来てよかった。全体的にぎこちなく、またうまくいったりいかなかったと不安要素がとても多いプログラムを作ってしまった。
今回のプログラミングを通してアルゴリズムを考えることも大切だが、何よりも動くものとして形にするときには、まず動くことが大切だと言うことが分かった。
今回経験を生かしたプログラミングができるよう、残りの授業を楽しみたい。
#define CENTER 45 #define CCC 20500 #define SPEED_H 52 #define SPEED_L 32 #define turn_R Off(OUT_B); OnFwd(OUT_C,SPEED_L); #define turn_L Off(OUT_C); OnFwd(OUT_B,SPEED_L); #define turn_SR OnRev(OUT_B,SPEED_L); OnFwd(OUT_C,SPEED_L); #define turn_SL OnRev(OUT_C,SPEED_L); OnFwd(OUT_B,SPEED_L); #define go_F OnFwd(OUT_BC,SPEED_H); #define STEP 1 #define nMAX 300 #define short_break Off(OUT_BC);Wait(300); #define CROSS_TIME 600 #define cross OnFwd(OUT_C,SPEED_L);OnFwd(OUT_B,SPEED_L);Wait(CROSS_TIME);short_break; #define go_b OnFwd(OUT_B,-50);OnFwd(OUT_C,-50); //右側前進 sub trace_R() { int n; while(true) { while(n < nMAX) { if(SENSOR_1 < CENTER-12) { turn_SR; n++; } else { if(SENSOR_1 < CENTER-6) { turn_R; } else if(SENSOR_1 < CENTER+6) { go_F; } else if(SENSOR_1 < CENTER+12) { turn_L; } else { turn_SL; } n=0; } Wait(STEP); } short_break; turn_SL;Wait(nMAX*STEP); cross; n=0; break; } } //左側前進 sub trace_L() { int n; while(true) { while(n < nMAX) { if(SENSOR_1 < CENTER-12) { turn_SL; n++; } else { if(SENSOR_1 < CENTER-6) { turn_L; } else if(SENSOR_1 < CENTER+6) { go_F; } else if(SENSOR_1 < CENTER+12) { turn_R; } else { turn_SR; } n=0; } Wait(STEP); } short_break; turn_SR;Wait(nMAX*STEP); cross; n=0; break; } } task main() { SetSensorLight(S1); SetSensorTouch(S3); int n=0,count = 0; long t = 0; if(t >= 0){ t = CurrentTick(); //右側前進 while(true){ if(SENSOR_1 < CENTER-9){ if(SENSOR_1 < CENTER-19){ turn_R; }else{ turn_SR; } }else if(SENSOR_1 < CENTER+2){ go_F; }else{ if(SENSOR_1 < CENTER){ turn_SL; }else{ turn_L; } } Wait(STEP); if(CurrentTick() - t > 8500){ break; } } } //空き缶を掴む short_break; OnFwd(OUT_A,-30); trace_R(); trace_L(); trace_L(); trace_L(); //左側前進 t=CurrentTick(); while(true){ while(CurrentTick()-t <= CCC) { if(SENSOR_1 < CENTER-12) { turn_SL; } else { if(SENSOR_1 < CENTER-6) { turn_L; } else if(SENSOR_1 < CENTER+6) { go_F; } else if(SENSOR_1 < CENTER+12) { turn_R; } else { turn_SR; } } } break; } //180°向きを変える turn_SR; Wait(2700); //空き缶を離す OnFwd(OUT_A,30); Wait(300); Off(OUT_A); //後方へさがる go_b; Wait(600); //元の向きに直る turn_SL; Wait(1100); Off(OUT_BC); //右側前進 while(true) { while(n < nMAX) { if(SENSOR_1 < CENTER-12) { turn_SR; } else { if(SENSOR_1 < CENTER-6) { turn_R; } else if(SENSOR_1 < CENTER+6) { go_F; } else if(SENSOR_1 < CENTER+12) { turn_L; } else { turn_SL; } n=0; } Wait(STEP); } } //ゴール }