2016a/Member/dragstar/Mission2
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
#contents
*制作したロボット [#mf921c4d]
図1、2に示したロボットが今回私たちがライントレースに使用したロボットです。構造としては非常にシンプルで具体的にはマニュアルに掲載されていた基礎構造の正面部分に光センサーを装着したのみとなっています。
&ref(ロボ ライントレース.jpg);
図1ライントレース用ロボット
&ref(観光センサー.jpg);
図2感光センサー
図1の赤で示した部位がセンサーで図2にはセンサーの感光部位を示しています。
機体が動いた際の衝撃でセンサーが動かないようにしっかりと固定しました。
* ライントレースコース [#g4b43e5c]
以下の図3に今回ロボットを走らせたコースを示します。
順路としては図で示した通りB⇒1⇒R⇒2⇒Q⇒3⇒Q⇒4⇒P⇒5⇒S⇒6⇒Cです。
&ref(コース順路.JPG);
図3コース順路
このコースで最も苦戦したのは交差点でした。
交差点ではカウント数を導入したり、以下に示すようなfind_lineを定義しこれらを駆使して解決しました。
#define SPEED_L 25
#define turn_right1 OnRL(-SPEED_L,SPEED_L);
#define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_C,speedL);
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC);
find_lineは、THRESHOLDで指定した明るさ以下になる地点を探して右旋回するように指定することができます。今回の課題ではこのfind_lineは大変に重宝しました。
また、今回組んだプログラムでは、ロボットはラインの左側を沿って進むので交差点で静止すると必然的に交差点を少し左折状態で静止します。ここで交差点を直進したり、右折したいときは以下に示すように右旋回とfind_lineを組み合わせました。
//右折//
#define cross_right2 turn_right2;Wait(250);Off(OUT_AC);
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC);
//直進//
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC);
#define cross_right2 turn_right2;Wait(250);Off(OUT_AC);
右折の場合は、cross_right1で大きく旋回し、直進方向のラインを越えてそこからfindlineで右折方向のラインに移るようになっています。
直進したい場合、機体交差点を少し左折した状態からcross_right2でライン上から無地の部部に移り findlineで直進方向のラインに乗るようになっています。
*交差点の判別 [#gd66e20f]
私達は、カウンタを定義してある規定のカウント数を超えると、繰り返しを停止するようなプログラムを導入して交差点を判別しました。
ここでは順路B⇒1⇒Rのプログラムを示します。
sub CROSS1() //初めの交差点までの動作サブルーチン
{
SetSensorLight(S1);
int n ; //カウンタの導入
while(n < 600) //カウンタの数が600を超えると繰り返しをやめてwhileのコマンドの外に出る
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //センサーが40以下の暗さを感知すると大きく左旋回しカウンタを1加算する。
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0; //センサーが48以下の40を下回らない暗さを感知すると左旋回する。
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward; //センサーが62以下の48を下回らない暗さを感知すると前進する。
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0; //センサーが70以下の62を下回らない暗さを感知するとする右旋回する。
}
else
{
turn_right1; //検知した暗さが70よりも明るければ大きく右旋回する。
}
}
Float(OUT_AC); //停止
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
交差点の判別法としては、交差点に差し掛かる際、ロボが左折しても暗い部分から抜け出せないことに着目しました。
このコマンドでは感知する暗さが40以下であれば、ロボは左折し続け、カウンタも加算され続けます。
交差点では、他の経路部分とは違い左折して暗い部分から抜け出そうとしてもセンサーがラインの中心線上を通過するので抜け出せません。
これによって交差点ではカウンタの加算量が他の順路よりも多くなります。
したがって、交差点に差し掛かるときのカウンタの量がwhileの外に出るカウンタ最大量近ずいていれば、ロボは確実に交差点で止まることになります。
したがって、このことを考慮にいれてカウンタ最大量を調整してやると、その道程に応じた交差点まで進み停止する命令を出すことができます。
このようなコマンドを組み合わせることで順路を進ませました。
*プログラム [#gd86e20f]
**定義 [#w6b36881]
今回サブルーチンを導入したので定義にはそれほど複雑なものは導入しませんでした。
#define THRESHOLD 55 //基準となる暗さ
#define SPEED_H 50
#define SPEED_H2 45
#define SPEED_L 25 //出力の定義
#define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_C,speedL); //左右の車輪の制御
#define go_forward OnRL(SPEED_H,SPEED_H); //前進
#define turn_left0 OnRL(SPEED_L,0); //小さく左に旋回
#define turn_left1 OnRL(SPEED_L,-SPEED_L); //大きく左旋回
#define turn_left2 OnRL(SPEED_H2,0); //左旋回
#define turn_right0 OnRL(0,SPEED_L); //小さく右に旋回
#define turn_right1 OnRL(-SPEED_L,SPEED_L); //大きく右旋回
#define turn_right2 OnRL(0,SPEED_H2); //右旋回
#define STEP 1 //ステップ数
#define cross_right1 turn_right2;Wait(600);Off(OUT_AC); //交差点を右に少し旋回
#define cross_right2 turn_right2;Wait(250);Off(OUT_AC); //交差点を右に大きく旋回
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC); //55以下の暗さの地点を探して右に回る
**B⇒1⇒R [#e509ec94]
最初の交差点に行きつくまでを記述したサブルーチンを示します。
sub CROSS1() //初めの交差点までの動作サブルーチン
{
SetSensorLight(S1);
int n ; //カウンタの導入
while(n < 600) //カウンタの数が600を超えると繰り返しをやめてwhileのコマンドの外に出る
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //センサーが40以下の暗さを感知すると大きく左旋回しカウンタを1加算する。
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0; //センサーが48以下の40を下回らない暗さを感知すると左旋回する。
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward; //センサーが62以下の48を下回らない暗さを感知すると前進する。
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0; //センサーが70以下の62を下回らない暗さを感知するとする右旋回する。
}
else
{
turn_right1; //検知した暗さが70よりも明るければ大きく右旋回する。
}
}
Float(OUT_AC); //停止
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
**R⇒2⇒Q [#x4c2d547]
RからQの交差点まで到達し、直進方向を向かせるまでのサブルーチンを示します。
sub CROSS2() //二つ目の交差点までの動作サブルーチン
{
SetSensorLight(S1);
int j ;
while(j < 6314)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
j++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right2;
find_line; //直進方向を向かせる。
j=0; //カウントリセット
}
**Q⇒3⇒Q [#q51933bd]
円周をぐるりと回る動作のサブルーチンです。
この動作はカウント数の調整が最も苦労した過程でした。
sub CROSS3() //二つ目の交差点を通り円を一周して戻る動作サブルーチン
{
SetSensorLight(S1);
int k ;
while(k < 1680)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
k++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right2;
find_line; //直進方向を向かせる
k=0; //カウントリセット
}
**Q⇒4⇒P[#y4db9a03]
sub CROSS4() //交差点Qから交差点Pまでの動作サブルーチン
{
SetSensorLight(S1);
int n ;
while(n < 900)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
**P⇒5⇒S [#j22e99e5]
sub CROSS5() //交差点Pから交差点Sまでの動作サブルーチン
{
SetSensorLight(S1);
int n ;
while(n < 1000)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
**S⇒6⇒C[#j21e99e5]
sub CROSS6() //交差点SからゴールCまでの動作サブルーチン
{
SetSensorLight(S1);
int n ;
while(n < 900)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right2;
go_forward;
Wait(600); //ゴール
n=0; //カウントリセット
}
**動作[#j21e99e8]
サブルーチンを用いたためタスクメインの中身はすっきりした形になりました。
task main()
{
CROSS1(); //B⇒1⇒R
Wait(1000); //1秒待機
CROSS2(); //R⇒2⇒Q
Wait(1000);
CROSS3(); //Q⇒3⇒Q
Wait(1000);
CROSS4(); //Q⇒4⇒P
Wait(1000);
CROSS5(); //P⇒5⇒S
Wait(1000);
CROSS6(); //S⇒6⇒C
Wait(1000);
Float(OUT_AC); //ゴールでストップ
}
*反省点と感想 [#k98aee16]
タイム 50.17s
サブルーチンの理解に時間がかかり苦戦しましたがゴールに到達できてよかったです。
反省点としては、カウンターによる経路認識しか使わなかった為サブルーチンの中身が単調になってしまったことです。今後はタイマーなども使えるようにしていきたいです。また、確実に経路を進むためにサブルーチンの中身をさらに改善できればと思っています。
終了行:
#contents
*制作したロボット [#mf921c4d]
図1、2に示したロボットが今回私たちがライントレースに使用したロボットです。構造としては非常にシンプルで具体的にはマニュアルに掲載されていた基礎構造の正面部分に光センサーを装着したのみとなっています。
&ref(ロボ ライントレース.jpg);
図1ライントレース用ロボット
&ref(観光センサー.jpg);
図2感光センサー
図1の赤で示した部位がセンサーで図2にはセンサーの感光部位を示しています。
機体が動いた際の衝撃でセンサーが動かないようにしっかりと固定しました。
* ライントレースコース [#g4b43e5c]
以下の図3に今回ロボットを走らせたコースを示します。
順路としては図で示した通りB⇒1⇒R⇒2⇒Q⇒3⇒Q⇒4⇒P⇒5⇒S⇒6⇒Cです。
&ref(コース順路.JPG);
図3コース順路
このコースで最も苦戦したのは交差点でした。
交差点ではカウント数を導入したり、以下に示すようなfind_lineを定義しこれらを駆使して解決しました。
#define SPEED_L 25
#define turn_right1 OnRL(-SPEED_L,SPEED_L);
#define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_C,speedL);
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC);
find_lineは、THRESHOLDで指定した明るさ以下になる地点を探して右旋回するように指定することができます。今回の課題ではこのfind_lineは大変に重宝しました。
また、今回組んだプログラムでは、ロボットはラインの左側を沿って進むので交差点で静止すると必然的に交差点を少し左折状態で静止します。ここで交差点を直進したり、右折したいときは以下に示すように右旋回とfind_lineを組み合わせました。
//右折//
#define cross_right2 turn_right2;Wait(250);Off(OUT_AC);
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC);
//直進//
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC);
#define cross_right2 turn_right2;Wait(250);Off(OUT_AC);
右折の場合は、cross_right1で大きく旋回し、直進方向のラインを越えてそこからfindlineで右折方向のラインに移るようになっています。
直進したい場合、機体交差点を少し左折した状態からcross_right2でライン上から無地の部部に移り findlineで直進方向のラインに乗るようになっています。
*交差点の判別 [#gd66e20f]
私達は、カウンタを定義してある規定のカウント数を超えると、繰り返しを停止するようなプログラムを導入して交差点を判別しました。
ここでは順路B⇒1⇒Rのプログラムを示します。
sub CROSS1() //初めの交差点までの動作サブルーチン
{
SetSensorLight(S1);
int n ; //カウンタの導入
while(n < 600) //カウンタの数が600を超えると繰り返しをやめてwhileのコマンドの外に出る
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //センサーが40以下の暗さを感知すると大きく左旋回しカウンタを1加算する。
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0; //センサーが48以下の40を下回らない暗さを感知すると左旋回する。
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward; //センサーが62以下の48を下回らない暗さを感知すると前進する。
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0; //センサーが70以下の62を下回らない暗さを感知するとする右旋回する。
}
else
{
turn_right1; //検知した暗さが70よりも明るければ大きく右旋回する。
}
}
Float(OUT_AC); //停止
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
交差点の判別法としては、交差点に差し掛かる際、ロボが左折しても暗い部分から抜け出せないことに着目しました。
このコマンドでは感知する暗さが40以下であれば、ロボは左折し続け、カウンタも加算され続けます。
交差点では、他の経路部分とは違い左折して暗い部分から抜け出そうとしてもセンサーがラインの中心線上を通過するので抜け出せません。
これによって交差点ではカウンタの加算量が他の順路よりも多くなります。
したがって、交差点に差し掛かるときのカウンタの量がwhileの外に出るカウンタ最大量近ずいていれば、ロボは確実に交差点で止まることになります。
したがって、このことを考慮にいれてカウンタ最大量を調整してやると、その道程に応じた交差点まで進み停止する命令を出すことができます。
このようなコマンドを組み合わせることで順路を進ませました。
*プログラム [#gd86e20f]
**定義 [#w6b36881]
今回サブルーチンを導入したので定義にはそれほど複雑なものは導入しませんでした。
#define THRESHOLD 55 //基準となる暗さ
#define SPEED_H 50
#define SPEED_H2 45
#define SPEED_L 25 //出力の定義
#define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_C,speedL); //左右の車輪の制御
#define go_forward OnRL(SPEED_H,SPEED_H); //前進
#define turn_left0 OnRL(SPEED_L,0); //小さく左に旋回
#define turn_left1 OnRL(SPEED_L,-SPEED_L); //大きく左旋回
#define turn_left2 OnRL(SPEED_H2,0); //左旋回
#define turn_right0 OnRL(0,SPEED_L); //小さく右に旋回
#define turn_right1 OnRL(-SPEED_L,SPEED_L); //大きく右旋回
#define turn_right2 OnRL(0,SPEED_H2); //右旋回
#define STEP 1 //ステップ数
#define cross_right1 turn_right2;Wait(600);Off(OUT_AC); //交差点を右に少し旋回
#define cross_right2 turn_right2;Wait(250);Off(OUT_AC); //交差点を右に大きく旋回
#define find_line turn_right1;until(SENSOR_1 < THRESHOLD);Off(OUT_AC); //55以下の暗さの地点を探して右に回る
**B⇒1⇒R [#e509ec94]
最初の交差点に行きつくまでを記述したサブルーチンを示します。
sub CROSS1() //初めの交差点までの動作サブルーチン
{
SetSensorLight(S1);
int n ; //カウンタの導入
while(n < 600) //カウンタの数が600を超えると繰り返しをやめてwhileのコマンドの外に出る
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //センサーが40以下の暗さを感知すると大きく左旋回しカウンタを1加算する。
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0; //センサーが48以下の40を下回らない暗さを感知すると左旋回する。
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward; //センサーが62以下の48を下回らない暗さを感知すると前進する。
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0; //センサーが70以下の62を下回らない暗さを感知するとする右旋回する。
}
else
{
turn_right1; //検知した暗さが70よりも明るければ大きく右旋回する。
}
}
Float(OUT_AC); //停止
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
**R⇒2⇒Q [#x4c2d547]
RからQの交差点まで到達し、直進方向を向かせるまでのサブルーチンを示します。
sub CROSS2() //二つ目の交差点までの動作サブルーチン
{
SetSensorLight(S1);
int j ;
while(j < 6314)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
j++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right2;
find_line; //直進方向を向かせる。
j=0; //カウントリセット
}
**Q⇒3⇒Q [#q51933bd]
円周をぐるりと回る動作のサブルーチンです。
この動作はカウント数の調整が最も苦労した過程でした。
sub CROSS3() //二つ目の交差点を通り円を一周して戻る動作サブルーチン
{
SetSensorLight(S1);
int k ;
while(k < 1680)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
k++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right2;
find_line; //直進方向を向かせる
k=0; //カウントリセット
}
**Q⇒4⇒P[#y4db9a03]
sub CROSS4() //交差点Qから交差点Pまでの動作サブルーチン
{
SetSensorLight(S1);
int n ;
while(n < 900)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
**P⇒5⇒S [#j22e99e5]
sub CROSS5() //交差点Pから交差点Sまでの動作サブルーチン
{
SetSensorLight(S1);
int n ;
while(n < 1000)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right1;
find_line; //右折
n=0; //カウントリセット
}
**S⇒6⇒C[#j21e99e5]
sub CROSS6() //交差点SからゴールCまでの動作サブルーチン
{
SetSensorLight(S1);
int n ;
while(n < 900)
{
if(SENSOR_1<THRESHOLD-15)
{
turn_left1;
n++; //カウント
}
else if(SENSOR_1<THRESHOLD-7)
{
turn_left0;
}
else if(SENSOR_1<THRESHOLD+7)
{
go_forward;
}
else if(SENSOR_1<THRESHOLD+15)
{
turn_right0;
}
else
{
turn_right1;
}
}
Float(OUT_AC);
PlaySound(SOUND_UP);
Wait(800);
cross_right2;
go_forward;
Wait(600); //ゴール
n=0; //カウントリセット
}
**動作[#j21e99e8]
サブルーチンを用いたためタスクメインの中身はすっきりした形になりました。
task main()
{
CROSS1(); //B⇒1⇒R
Wait(1000); //1秒待機
CROSS2(); //R⇒2⇒Q
Wait(1000);
CROSS3(); //Q⇒3⇒Q
Wait(1000);
CROSS4(); //Q⇒4⇒P
Wait(1000);
CROSS5(); //P⇒5⇒S
Wait(1000);
CROSS6(); //S⇒6⇒C
Wait(1000);
Float(OUT_AC); //ゴールでストップ
}
*反省点と感想 [#k98aee16]
タイム 50.17s
サブルーチンの理解に時間がかかり苦戦しましたがゴールに到達できてよかったです。
反省点としては、カウンターによる経路認識しか使わなかった為サブルーチンの中身が単調になってしまったことです。今後はタイマーなども使えるようにしていきたいです。また、確実に経路を進むためにサブルーチンの中身をさらに改善できればと思っています。
ページ名: