A→M→K(一時停止の後,直進)→L(ピンポン玉をつかむ)→後退→K(一時停止の後,左折)→J(一時停止の後,左折)→I(一時停止の後,直進)→H(一時停止の後,直進)→G(一時停止の後,左折)→F→E→D(一時停止の後,直進)→C(直進)→B(停止)→シュート
詳しくは,2019a/Mission2をご覧ください.
アームのところ以外はNQC本体の大きさに収まるぐらいの小柄なものにした.
三輪にし,二輪駆動にすることで小回りが利くようにした.
一つのモーターで二つのアームが動くように歯車の配置を工夫した.またなるべく小柄なものにして重量を軽くした.
ライントレースといっても線の太さが太いので線のふちの色の違いをセンサーで識別して進んでいく方法をとった.白と黒の二種類の動作のみだとライントレースする際のスムーズさが損なわれるので五種類の動作を用いた.またコースから大幅に外れたら旋回,少しずれていたら右折,左折,コースからほぼ外れていなかったら直進をする動作にした.スムーズにライントレースをするために五段階にセンサーの数値を分けるのに苦労した.
交差点はコースが直角に交わっている形状をしているのでそこが一本道のコースと違うところである.直角であるためにコースを直角にライントレースをしようとするとセンサーが黒の値を計測する時間が長くなる.この特徴を利用して交差点を判断する.具体的にはライントレースの関数(sub follow line)は黒の値を連続して一定時間(black time)以上計測しない限り動作をつづけるように設定した.この一定時間(black time)の値を設定するのも苦労した.また円形の交差点については一定時間(black time)の値を小さくして調整した.
sub follow lineとsub cross lineという関数を使って動作を実現した. まずsub follow lineを実行していき,交差点を認識したら止まる.このとき機体はコースからライントレースしかけたコース寄りに少し傾いている.その状態から直進して白を認識したら止まる.次にコースの左側をトレースしていたら右折,コースの右側をトレースしていたら左折を黒を認識するまで続ける.止まったらそのあとsub follow lineを再開する.これで交差点が渡れたことになる.
まずはプログラム中で何度も行う動きのプログラムを定義する。
int black_time=30; /交差点の判断のときに使う、黒色と判断している時間の上限を設定するもの。 #define migisenkai OnFwd(OUT_A); OnFwd(OUT_C); //機体を右旋回させる動作。 #define usetsu OnFwd(OUT_A); Off(OUT_C); //機体を右折させる動作。 #define chokushin OnFwd(OUT_A); OnRev(OUT_C); //機体を直進させる動作。 #define sasetsu Off(OUT_A); OnRev(OUT_C); //機体を左折させる動作。 #define hidarisenkai OnRev(OUT_A); OnRev(OUT_C); //機体を左旋回させる動作。 #define koutai OnRev(OUT_A); OnFwd(OUT_C); //機体を後退させる動作。
次に主にライントレースのときに使うサブルーチンを設定する。
sub follow_line() //左側の線のふちをライントレースするサブルーチンである.センサーの値と色の対応関係は黒が36未満,黒灰は36以上39未満,灰は39以上43未満,白灰は43以上47未満,白は47以上である. { SetSensor(SENSOR_2,SENSOR_LIGHT); //センサーを設定する。 while(FastTimer(0)<black_time){ //while関数を使い、連続して黒と判定した時間がblacktime以下の場合カッコの中の動作を繰り返す。 if(SENSOR_2>=47){ //センサーが読み取る値が47以上の時右旋回をする. migisenkai ClearTimer(0); }else if((SENSOR_2>=43)&&(SENSOR_2<47)){ //センサーが読み取る値が43以上,47未満の時右折をする. usetsu ClearTimer(0); }else if((SENSOR_2>=39)&&(SENSOR_2<43)){ //センサーが読み取る値が39以上43未満の時,直進をする. chokushin ClearTimer(0); }else if((SENSOR_2>=36)&&(SENSOR_2<39)){ //センサーが読み取る値が36以上39未満の時,左折をする. sasetsu ClearTimer(0); }else if(SENSOR_2<36){ //センサーが読み取る値が36未満の時,左旋回をする. hidarisenkai } } Off(OUT_AC); Wait(100); //動作をスムーズにするために入れた. ClearTimer(0); }
sub follow_line2() //右側の線のふちをライントレースするサブルーチンである.sub follow lineの黒と白,黒灰と白灰の動作を逆にしただけなのでせつめいは省略する. { SetSensor(SENSOR_2,SENSOR_LIGHT); while(FastTimer(0)<black_time){ if(SENSOR_2<36){ migisenkai }else if((SENSOR_2>=36)&&(SENSOR_2<39)){ usetsu ClearTimer(0); }else if((SENSOR_2>=39)&&(SENSOR_2<43)){ chokushin ClearTimer(0); }else if((SENSOR_2>=43)&&(SENSOR_2<47)){ sasetsu ClearTimer(0); }else if(SENSOR_2>=47){ hidarisenkai ClearTimer(0); } } Off(OUT_AC); Wait(100); ClearTimer(0); }
sub cross_line() //交差点をまっすぐ進むためのサブルーチンである. { SetSensor(SENSOR_2,SENSOR_LIGHT); while(SENSOR_2<47){ //センサーが読み取る値が47未満の場合直進する. chokushin } while(SENSOR_2>36){ //センサーが読み取る値が36より大きい場合右折をする. usetsu } Off(OUT_AC); Wait(100); ClearTimer(0); }
プログラム上ではfollow lineを入れているが,ロボットがfollow lineの動作をしてくれない時があり,follow lineの手前にcross lineを入れるとfollow lineの動作をすることが多々あった.そのcross lineの動作はライントレースに影響をきたさなかったので良しとした.このような入れ方をしているcross lineには”?”のマークを入れておいた.
task main(){ SetPower(OUT_B,1); //アームの動作のスピードを最低にした. cross_line(); //? follow_line(); //MからKまでライントレースをする. cross_line(); //Kの交差点を直進する. OnRev(OUT_C); Wait(60); Off(OUT_C); Wait(100); //Lに近づく. OnFwd(OUT_B); Wait(20);Off(OUT_B); Wait(100); //ピンポン玉をつかむ. koutai Wait(150); Off(OUT_AC); Wait(100); //Kまでバックする. cross_line(); //? follow_line(); //Kまでライントレースする. follow_line(); //Jまでライントレースする. black_time=20;follow_line(); //Iまでライントレースする. cross_line(); //Iの交差点を直進する. black_time=20;follow_line(); //Hまでライントレースする. cross_line(); //Hの交差点を直進する. follow_line(); //Gまでライントレースする. chokushin Wait(40); Off(OUT_AC); Wait(100); //少し直進をして次に線の右側をライントレースできるようにする. follow_line2(); //線の右側をDまでライントレースする. cross_line(); //Dの交差点を直進する. followline2(); //線の右側をBまでライントレースする. OnRev(OUT_B) Wait(20) Off(OUT_B); //アームを開く. hidarisenkai Wait(30) Off(OUT_AC); //機体を左旋回させながらピンポン玉をシュートする. }
ロボットを作るのにはあまり時間がかからなかったが,プログラムを完成させるのに相当な時間がかかった.一番のつまずきはsub follow lineの中にOff(OUT_AC)を入れてなかったのと一番最後にClear Timer(0)を入れていなかったことによってsub follow lineが実行されなかったか変に実行されてしまったことである.今回の課題の試行錯誤のおかげでプログラミングの理解が深まった.またプログラムを書く速さも早くなった.しかしうえでも既述したように理解不能なプログラムの動き方もあるので次回解決できる手掛かりを見つけられたらと思う.よかったところは適切な数値設定によってライントレースがスムーズにできたことである.