2017a/Member

課題内容

 今回の課題は、光センサを使用して図のコースを指定の経路で走るという内容である。

 詳しい内容は2017a/Mission2を参照してほしい。

コースの図

走行コース

 「E地点直進コース」と「E地点右折コース」の内、「E地点右折コース」を走るロボットを作成したため、以下の順番で走行するようになっている。

 E→P→Q→R→T→T→H→G→S→P→Q→F→E→A

ロボット本体

 ロボット本体はできるだけシンプルかつコンパクトな形状を目指して作成した。

ロボット全体の写真

 ロボット本体を組み立てるのに当たって、できるだけ小回りがきくようなロボットにしようと考えた。そこで、タイヤの間隔を極力狭くし、モーター2つとギアの幅だけにすることで旋回半径をできるだけ小さくしている。
 また、はじめはセンサーとタイヤとの距離を少し遠く配置していたのだが、必ずHーG地点間のS字カーブやEーF地点間のカーブで旋回しきれずにコースアウトしてしまい、正しくラインをトレースしてくれなかった。そこで、センサとタイヤの距離をできるだけ短くし、より正確に黒線に沿って走行できるようにもしている。

タイヤとセンサの距離の説明

プログラム

定数・マクロ・グローバル変数 定義

/*---------- 定数・マクロ 定義 -----------*/
/* 閾値設定 */
#define LINE_BLACK 38					//黒
#define THRESHOLD_LOW 40				//閾値最小(黒より)
#define THRESHOLD_HIGH 47				//閾値最大(白より)
#define LINE_WHITE 49					//白

/* 動作 */
#define FOWORD OnFwd(OUT_AC);				//直進
#define BACK OnRev(OUT_AC);				//後退
#define STOP Off(OUT_AC);				//停止
#define TURN_LEFT OnFwd(OUT_C); OnRev(OUT_A);		//左旋回
#define TURN_RIGHT OnFwd(OUT_A); OnRev(OUT_C);		//右旋回
#define CURVE_LEFT OnFwd(OUT_C); Off(OUT_A);		//左折
#define CURVE_RIGHT OnFwd(OUT_A); Off(OUT_C);		//右折

/* 交差点判定用の時間 */ 
#define TIME_MAX_N	26				//T→G間以外での交差点判定までの時間
#define TIME_MAX_TG	33				//T→G間での交差点判定までの時間

/*----------- グローバル変数 定義 ----------*/
int timer = 0;						//黒反応時間
int time_max = 0;					//交差点判定用

 『動作』のマクロについてはプログラムのコメント文で説明できていると思うので省略する。
 また、"TIME_MAX_N"と"TIME_MAX_TG"、"timer"、"timer_max"は交差点を判断するときに使用している。これらの詳しい説明はサブルーチンとメインタスクのところでしているので、ここでは省略する。

 閾値設定

 ライントレースをする際に、黒線と白線が境界できっちり分かれているわけではなく、どちらでもない中間の範囲が存在する。そこで、どこからが黒でどこからが白なのか、またその境目の範囲の中で中央はどこになるのかを"LINE_BLACK"、"THRESHOLD_LOW"、"THRESHOLD_HIGH"、"LINE_WHITE"という4つを定義し、黒から白の間を5つに分けることで判別している。

閾値説明図

サブルーチン

 サブルーチンは、ラインをトレースするためのものを"Follow_Line_R()"と"Follow_Line_L()"として左右で設定している。また、交差点の判断もここで行っている。

/*---------- ラインの右側を走行 ----------*/
sub Follow_Line_R()
{
	while(timer < time_max){
		if(SENSOR_2 > LINE_WHITE){
			TURN_LEFT;
			ClearTimer(0); 
		}
		else if(SENSOR_2 > THRESHOLD_HIGH){
			CURVE_LEFT;
			ClearTimer(0); 
		}
		else if(SENSOR_2 > THRESHOLD_LOW){
			FOWORD;
			ClearTimer(0);
		}
		else if(SENSOR_2 > LINE_BLACK){
			CURVE_RIGHT;
			ClearTimer(0);
		}
		else{
 			TURN_RIGHT;
		}	
		timer = FastTimer(0);
	}
	timer = 0;
}

/*---------- ライン左側を走行 ----------*/
sub Follow_Line_L()
{
	while(timer < time_max){
		if(SENSOR_2 > LINE_WHITE){
			TURN_RIGHT;
			ClearTimer(0); 
		}
		else if(SENSOR_2 > THRESHOLD_HIGH){
			CURVE_RIGHT;
			ClearTimer(0); 
		}
		else if(SENSOR_2 > THRESHOLD_LOW){
			FOWORD;
			ClearTimer(0);
		}
		else if(SENSOR_2 > LINE_BLACK){
			CURVE_LEFT;
			ClearTimer(0);
		}
		else{
 			TURN_LEFT;
		}	
		timer = FastTimer(0);
	}
	timer = 0;
}

 ラインのトレース

 定数・マクロのところで説明したように、閾値によって黒と白とその境目を5つに分けているため、それぞれの場所に応じて動作を設定している。光センサの値が"THRESHOLD_LOW"から"THREHOLD_HIGH"の間は、境目の中央になるため左右どちらのサブルーチンでも「直進」するようになっている。"THRESHOLD_LOW"より小さい場合と"THRESHOLD_HIGH"より大きい場合は左右で動作が逆になってはいるが、"LINE_BLACK"や"LINE_WHITE"を超えるまでは「タイヤを片方停止してのターン」、超えたら「片方は正転、反対側は逆転しての旋回」を行うようにしている。

動作説明図

 交差点判断

 交差点に差し掛かるとき、光センサは長い間黒を認識していることになる。そこで、光センサの値が"LINE_BLACK"より小さい(黒色を検知している)間タイマーで時間を計測し、変数"timer"にその値を渡す。この"timer"の値を"time_max"の値(メインタスクで設定)と比較し、大きい場合はループから抜けることで交差点を判断している。

メインタスク

 メインタスクは、大きく分けて光センサとモーターのパワーの設定とラインをトレースする動作部分の2つに分けられる。動作部分についてはプログラムの下で説明する。

/*---------- メインタスク ----------*/
task main()
{
      /*	光センサ・モータパワー 設定	*/ 
	SetSensor(SENSOR_2 , SENSOR_LIGHT);
 	SetPower(OUT_AC , 3);

      /*	動作部分	*/
// A地点→E地点 ---------------------------------------- 
	time_max = TIME_MAX_N;

	Follow_Line_R();

	// E地点 到達
	// SOUND_UP & 右折
	PlaySound(SOUND_UP);
	TURN_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// E地点→P地点 ----------------------------------------
	Follow_Line_R();

	// P地点 到達 (一時停止)
	// SOUND_DOWN & 左折
	PlaySound(SOUND_DOWN);
	STOP;
	Wait(100);
	TURN_LEFT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// P地点→Q地点 ----------------------------------------
	Follow_Line_L();

	// Q地点 到達
	// SOUND_DOWN & 直進(効率化のため右折による横断)
	PlaySound(SOUND_UP);
	CURVE_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// Q地点→R地点 ----------------------------------------
	Follow_Line_L();

	// R地点 到達
	// SOUND_UP & 左折
	PlaySound(SOUND_UP);
	TURN_LEFT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// R地点→T地点 ----------------------------------------
	Follow_Line_L();

	// T地点 到達(一時停止)
	// SOUND_DOWN & 直進
	PlaySound(SOUND_DOWN);
	STOP;
	Wait(100);
	FOWORD;
	until(SENSOR_2 > THRESHOLD_HIGH);

// T地点→T地点 ----------------------------------------
	time_max = TIME_MAX_TG;

	Follow_Line_L();
	// T地点 到達(一時停止)
	// SOUND_DOWN & 直進(ライン右側へ移動)
	PlaySound(SOUND_DOWN);
	STOP;
	Wait(100);
	CURVE_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);
	until(SENSOR_2 < THRESHOLD_LOW);
	until(SENSOR_2 > THRESHOLD_HIGH);

// T地点→H地点 ----------------------------------------
	Follow_Line_R();

	// H地点 到達
	// SOUND_UP & 右折
	PlaySound(SOUND_UP);
	CURVE_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// H地点→地点G ----------------------------------------
	Follow_Line_R();

	// G地点 到達
	// SOUND_UP & 直進
	PlaySound(SOUND_UP);
	FOWORD;
	until(SENSOR_2 > THRESHOLD_HIGH);

// G地点→S地点 ----------------------------------------
	time_max = TIME_MAX_N;

	Follow_Line_L();

	// S地点 到達(一時停止)
	// SOUND_DOWN & 左折
	PlaySound(SOUND_DOWN);
	STOP;
	Wait(100);
	TURN_LEFT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// S地点→P地点 ----------------------------------------
	Follow_Line_L();

	// P地点 到達
	// SOUN_UP & 直進(効率化のために右折による横断)
	PlaySound(SOUND_UP);
	CURVE_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// P地点→Q地点 ----------------------------------------
	Follow_Line_L();

	// Q地点 到達
	// SOUND_UP & 左折(ライン右側へ移動)
	PlaySound(SOUND_UP);
	CURVE_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);

// Q地点→F地点 ----------------------------------------
	Follow_Line_R();

	// F地点 到達
	// SOUND_UP & 左折(直進によってライン横断)
	PlaySound(SOUND_UP);
	FOWORD;
	until(SENSOR_2 > THRESHOLD_HIGH);

// F地点→E地点 ----------------------------------------
	Follow_Line_L();

	// E地点 到達
	//(直進による横断)
	FOWORD;
	until(SENSOR_2 > THRESHOLD_HIGH);

// E地点→A地点 ----------------------------------------
	Follow_Line_L();

	// A地点 到達
	// ライン横断後、A地点内で停止
	PlaySound(SOUND_DOWN);
	CURVE_RIGHT;
	until(SENSOR_2 > THRESHOLD_HIGH);
	FOWORD;
	Wait(70);
	STOP;
//ゴール
}

 動作部分

 基本的には、次の動作の繰り返しで走行している。

  ("time_max"の設定)
  .薀ぅ鵑留Δ發靴は左を走行
  交差点到達時に音を鳴らし、指定がある場合には一時停止
  8鮑硬世魏C

 『"time_max"の設定』に関しては、T地点からG地点まで範囲以外の場所では"TIME_MAX_N"を設定している。T地点からG地点までの間は円の内側や急カーブを走行し"TIME_MAX_N"よりも大きな値を設定しないとコースアウトしてしまうため"TIME_MAX_TG"を設定している。そのため"time_max"の設定は、スタート時と1回目のT地点通過時、G地点通過時の3回のみ行っている。

まとめ

 今回の課題は閾値の値と交差点判断のための時間の両方の設定によって走行の具合が大きく変わってしまった。そのため、不具合を調整しようとして片方を変更してしまうと変更前は綺麗に動いていたはずの箇所がおかしくなってしまうことがよくあり、両方の値を変更しながら理想の値を探すのが難しかったように思う。
 また、交差点を横断するときに、できるだけ複雑な動きは避けてシンプルな動作で横断できるように工夫した。しかし、1つずつの動作はシンプルだが各交差点ごとに動きを変えてしまっているため、メインタスクが長くなってしまった。もう少し工夫してサブルーチンなどでまとめることができればよかったと思う。


添付ファイル: file閾値説明図.jpg 42件 [詳細] file動作説明図.jpg 50件 [詳細] fileタイヤ・センサ距離.jpg 46件 [詳細] fileロボット全体.jpg 36件 [詳細] file課題2 コース.jpg 57件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-07-07 (金) 22:31:30