ロボットの説明

黒い線の進行方向向かって左側の境界を走行する。ボールはアームではさみこみゴールまで運ぶ。最初のT字路を右折、次の交差点を直進し、A→B,A→Cのルートを走行する。

2015a-mission2.png
open.jpg

アームが開いている状態

close.jpg

アームが閉じている状態
モーターの回転の方向を90°変換するために十字のギヤを使用した。

18643.jpg
18644.jpg

プログラムの説明

赤外線センサーを用い、入射した赤外線の反射強度を取得することにより、ロボットが黒い線のどの辺を走行しているか判断する。 ロボットはコース上を、
1)線の外側
2)線の境界上
3)線の上
の三種類として認識する。進行方向向かって左側の境界上を移動させるので、ロボットの場所によりそれぞれ
1)右にシフト
2)直進
3)左にシフト
しながら進んでいく。基本的にはwhileループで1[ms]ごとにセンサーの値を取得し、上記の動作を繰り返す。T字路、交差点、ゴール地点では上記の動作とは別の専用のタスクを割り込ませる。 センサーの値は0から100の整数値で与えられる。数値が大きいほど反射強度が高い。 A→CとA→Bでは、交差点での処理とゴール後の処理が若干違うだけで基本的には同じである。
交差点の判定は、スタートからの経過時間と黒の線上にいる時間[ms]によって判定している。1ループ1[ms]に設定している為、黒の処理に入ったときに黒カウンタnをインクリメントする。nの次元は[ms]となる。マシンの処理速度に対して1[ms]は十分に遅いと考えられるので、whileループ内の処理にかかる時間は無視できると考えた。交差点に到達する前にも、長時間黒の上に滞在するポイントが存在したので、それらを省くためにCurrentTick()関数を用いてプログラム開始からの時間を条件に補助的に採用している。
ボールキャッチ処理は完全にスタート時からの秒数に依存している。これはプログラムの汎用性を下げる要因となるのであまり良い処理だとは言えない。
ボールキャッチ用の処理とゴール後のシュートの処理はtask()として定義してtask main()のなかから呼び出している。後で気づいたのだが、task main()のなかで呼び出された他のtask()は、task main()内のそれ以降の行の指示と平行に実行されるようである。今回のプログラムではたまたま動作に矛盾は生じなかったが、動作の並行処理を防ぐために#defineで定義して実行させたほうがよさそうだ。
以下にプログラムの詳細を記述する。

処理や定数の定義(共通)

#define BLACK 36
#define WHITE 48
#define SPEED 25
#define go_forward OnRev(OUT_BC,SPEED);
#define turn_left OnRev(OUT_B,SPEED);Off(OUT_C);
#define turn_left2 OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED);
#define turn_right Off(OUT_B);OnRev(OUT_C,SPEED);
#define STEP 1 //センサーのデータの取得頻度を1[ms]に設定

サブルーチン

ボールをキャッチする動作

task ball_catch(){ //ボールキャッチ
	OnFwd(OUT_A,SPEED);
	Wait(1000);
	Off(OUT_A);
}

ボールをゴールにシュートする動作 A→Bの場合

task shoot(){
	turn_right;
	Wait(1000);
	go_forward;
	Wait(300);
	Off(OUT_B);
	Off(OUT_C);
	OnRev(OUT_A,SPEED);
	Wait(1000);
	Off(OUT_A);
}

A→Cの場合

task shoot(){
	turn_left;
	Wait(800);
	go_forward;
	Wait(300);
	OnRev(OUT_A,SPEED);
	Wait(1000);
	Off(OUT_A);
}

メインタスク

変数の初期化

task main(){
	SetSensorLight(S3);
	int n=0; //黒の上にいる時間を計測するための変数
	int flg1=0; //交差点通過前=0 交差点通過後=1
	int flg2=0; //ゴール判定用のフラグ
	int flg3=0; //ボールキャッチ前=0 ボールキャッチ後=1
	long t0=CurrentTick();


ループさせるメインタスク。ゴール判定用のフラグが立つまで繰り返す。

	while(flg2==0){
		if(CurrentTick()-t0>7500 && flg3==0){ //ボールキャッチ
			start ball_catch;
			flg3=1; //ボールキャッチ用のフラグを立てる
		}else if(SENSOR_3 < BLACK){ //黒の上なら
			turn_left;
			n++; //黒カウンタインクリメント
			if(n>1200 && CurrentTick()-t0>9000 && flg1==0){ //交差点用の処理
				Off(OUT_BC);
				n=0; //黒カウンタリセット
				flg1=1; //交差点通過フラグをたてる

A→Bの場合

                                turn_left2; //左折
				Wait(700);

A→Cの場合

				go_forward; //交差点突破(直進)
                               Wait(1000);

以下共通

			}else if(n>1400 && flg1==1){
				flg2=1; //ゴール判定用のフラグをたてる
			}

	        }else if(SENSOR_3 < WHITE){ //境界線上ならば
			go_forward;
                        n=0; //黒カウンタリセット
		}else{ //それ以外(白)なら
			turn_right;
                        n=0; //黒カウンタリセット
		}
		Wait(STEP); //1[ms]間待つ。1サイクル1[ms]に設定
	}

ゴール判定後にシュートさせるサブルーチンを呼び出す。

	start shoot;
}

問題点

  • サブルーチンの呼び出しや交差点の処理などを、スタート時からの経過時間に頼って判定しているので、限定されたコースしか走行できない。また電池の消耗により、同じ経過時間でも進む速度に差が発生するので、そのつど定数の書き換えをしなければならない。
  • 場所の認識数が3パターンだけなのでなめらかに移動できない。
  • センサーと車軸が離れている為、センサーが交差点やT字路を認識してもタイヤはまだその地点よりかなり後方にいるので、処理にラグが発生する。

改善案

  • 色の識別数を増やし、行動の種類を増やす。
  • 車軸とセンサーの距離を小さくする

添付ファイル: file18644.jpg 95件 [詳細] file18643.jpg 117件 [詳細] fileclose.jpg 103件 [詳細] fileopen.jpg 97件 [詳細] file2015a-mission2.png 101件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-08-10 (月) 17:58:52