目次
#contents
*課題について [#o42b2683]
**課題2概要 [#gf5dd8fa]
図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成せよ。詳しくは[[課題2>2017a/Mission2]]を参照。
自分はE地点右折コースを選択。
*ロボットについて [#d95c8b9b]
#ref(./image1.JPG,40%,ロボット 全体図)
↑ロボットの全体図
今回はこのような簡単なロボットを製作した。
#ref(./image3.JPG,40%,ロボット 分解図)
↑ロボットの大部分を外した場合このようになる
**工夫した点 [#a975ae52]
・ロボットの全体図を見れば分かるが、とてもシンプルでコンパクトな形だ。なぜこのような形にしたかというと、今回の課題において正確なライントレースが必要とされるからだ。
�.札鵐機爾肇織ぅ笋竜�離(回転半径)をできるだけ短くした。
このことによって光センサーの動きを小さくし、コースアウトをする確率を軽減させた。
�∈険Δ離織ぅ笋竜�離を短くした。
小回りを利かせた。
�C鰐未噺�センサーの距離を短くした。
正確なセンサー値を得るためである。
#ref(./image5.JPG,40%,ロボット)
↑のように地面すれすれまで近ずけた。
�せ戮┐鯢佞韻拭�
車体が後ろに傾くのを防ぐためである。
#ref(./image4.JPG,40%,支え)
*プログラム紹介 [#b69d1fd3]
今回はプログラミングが大事となる課題であった。それぞれについて説明しておこう。
**定数について [#w2bdbd1a]
/*数値代入系*/
# define TMAX 28 //黒い線を28/100秒以上通過すると「交差点」または「急カーブ」と判断する。
/*動作制御系*/
# define forward OnFwd(OUT_AC); //直進
# define back OnRev(OUT_AC); //後退
# define t_left OnRev(OUT_A);OnFwd(OUT_C); //左旋回
# define left Off(OUT_A);OnFwd(OUT_C); //左回転
# define t_right OnFwd(OUT_A);OnRev(OUT_C); //右旋回
# define right OnFwd(OUT_A);Off(OUT_C); //右回転
# define KOUON PlaySound(SOUND_UP); //高音を鳴らす。
# define TEION PlaySound(SOUND_DOWN); //低音を鳴らす。
**マクロについて [#s87779e5]
# define tomaru(t) Off(OUT_AC);Wait(t); //t/100秒停止をする。
# define power(s) SetPower(OUT_AC,s); //モーターのパワーを変換する。
**ライントレースについて [#u41482a0]
ただ単にプログラムを作成すると膨大な量を書く必要があるため、「右ライントレース」と「左ライントレース」の2つのプログラムをsub関数内に書き、main関数の簡略化を行った。このことによってmain関数がとても簡単に書くことができた。
/*グローバル変数*/
int n=0;
交差点、急カーブに何回通過したかをカウントする。変数nはmain関数にも使用するため、グローバル変数としておく。
/*右ライントレース*/
sub migi(){
while(FastTimer(0)<TMAX){ //交差点・急カーブの判断を行うためwhileの条件式にTMAXを使用。
if(SENSOR_1<40){ //計測値が閾値40以下の場合、右旋回
OnFwd(OUT_A);OnRev(OUT_C);
}else if(SENSOR_1<42){ //計測値が閾値40~42の場合、右回転
OnFwd(OUT_A);Off(OUT_C);
}else if(SENSOR_1<52){ // 計測値が閾値42~52の場合、直進
OnFwd(OUT_A);OnFwd(OUT_C);
}else if(SENSOR_1<55){ //計測値が閾値52~55の場合、左回転
Off(OUT_A);OnFwd(OUT_C);
} else { //計測値が閾値55以上の場合、左旋回
OnRev(OUT_A);OnFwd(OUT_C);
}
if(SENSOR_1>40){ //計測値が閾値40以上の場合、タイマーをリセット
ClearTimer(0);
}
}
n++; //今何回目の交差点・急カーブなのかをカウント
}
/*左ライントレース*/
sub hidari(){
while(FastTimer(0)<TMAX){ //交差点・急カーブの判断を行うためwhileの条件式にTMAXを使用。
if(SENSOR_1<40){ //計測値が閾値40以下の場合、左旋回
OnRev(OUT_A);OnFwd(OUT_C);
}else if(SENSOR_1<42){ //計測値が閾値40~42の場合、左回転
Off(OUT_A);OnFwd(OUT_C);
}else if(SENSOR_1<52){ //計測値が閾値42~52の場合、直進
OnFwd(OUT_A);OnFwd(OUT_C);
}else if(SENSOR_1<55){ //計測値が閾値52~55の場合、右回転
OnFwd(OUT_A);Off(OUT_C);
} else { //計測値が閾値55以上の場合、右旋回
OnFwd(OUT_A);OnRev(OUT_C);
}
if(SENSOR_1>40){ //計測値が閾値40以上の場合、タイマーをリセット
ClearTimer(0);
}
}
n++; //今何回目の交差点・急カーブなのかをカウント
}
まず、自分のプログラムには欠点がある。それは、右ライントレースは左折する時、カウントできないということだ(これは左ライントレースをする場合も当てはまる)。なぜかというとタイマーは閾値40以上だとリセットされるため、外側が白色(閾値55以上)だとリセットされ続けwhile関数から脱出することができずカウントすることができないのである。
もし、E地点直進コースなら左折だけなので左ライントレースのみで完走させることが可能であった。しかし、E地点右折コースの場合、右折・左折両方あるため左ライントレースだけでなく右ライントレースも必要となる。
**main関数について [#p96285ee]
sub関数でライントレースの仕方をプログラムしたのでmain関数では主に、sub関数から出た場合(交差点、丁字路、直角コーナに差し掛かった場合)の処理を行っている。
また、各交差点、丁字路、直角コーナについてそれぞれ� 銑�の通し番号を振る。番号については以下の写真を参考にせよ。
#ref(./image7.JPG,20%,計画図)
↑青で書かれた番号がそれぞれの通し番号である。作る前に自分で考えて作った計画図なので汚い。
task main(){
power(0);
SetSensor(SENSOR_1,SENSOR_LIGHT);
ClearTimer(0);
while(n<=13){
変数nが13以下の場合、while関数内に存在する。
**� 銑┐泙� [#qd6001cb]
� ̄�折
if(n==0){ //�,涼�字路
migi();
KOUON; //高音を鳴らす
t_left;Wait(10);
forward;Wait(40); //左車線へ移動
ClearTimer(0); //タイマーをリセットする
}
�,任蓮�丁字路を認識した後10/100秒左旋回した後40/100秒直進させる。これにより、左車線(左側の白と黒の境)へスムーズに移動することができる。なぜ左車線へ移動したかというと次の丁字路で左折する必要があり、右ライントレースだと効率よく移動できないからだ。最後にこれらの処理時間をリセットさせて左ライントレースのsub関数へ入る。
��一時停止+左折
else if(n==1){ //�△涼�字路
hidari();
back;Wait(20);
tomaru(80); //一時停止
TEION; //低音を鳴らす
t_left;Wait(30);
forward;Wait(50); //次の左車線へ移動
ClearTimer(0); //タイマーをリセットする
}
�△任蓮�丁字路を認識した後、一時停止してから30/100秒左旋回し50/100秒直進させ次の左車線へ移動させる。なぜ同じ左車線なのに処理を行ったかというと、処理しなければ黒線上にTMAX以上存在してしまい、変数nがカウントする可能性があるからだ。
�D梢�
else if(n==2){ //��の丁字路
hidari();
KOUON; //高温を鳴らす
t_right;Wait(15);
forward;Wait(50); //次の左車線へ移動
ClearTimer(0); //タイマーをリセットする
}
��では、丁字路を認識した後、15/100秒右旋回し、50/100秒直進させる。このことにより、スムーズに次の左車線へ移動できる。
�ず言�
else if(n==3){ //�い涼�字路
hidari();
KOUON; //高音を鳴らす
t_right;Wait(15);
forward;Wait(50); //次の右車線へ移動
ClearTimer(0); //タイマーをリセットする
}
�い任蓮�丁字路を認識した後、15/100秒右旋回し、50/100秒全身して次の右車線へ移動する。ここでなぜ右車線に変更したのかというと次の�イ慮鮑硬世砲鰐簑蠅呂覆い�、この後の円型の道路のライントレースにおいて、左ライントレースだと黒線上にTMAX以上存在してしまい変数nがカウントされる可能性があるのに対し、右ライントレースではこのような問題が生じることがないからだ。右ライントレースにすることで問題が生じにくくなるのだ。
�グ貉�停止+直進
else if(n==4){ //�イ慮鮑硬�
migi();
tomaru(80); //一時停止
TEION; //低音を鳴らす
t_left;Wait(25);
forward;Wait(50); //次の右車線へ移動
ClearTimer(0); //タイマーをリセットする
}
�イ任蓮�交差点を認識した後、一時停止してから25/100秒左旋回し50/100秒直進して次の右車線に移動する。右車線にすることによるメリットは�い農睫世靴拭�
�Π貉�停止+直進
else if(n==5){ //�Δ慮鮑硬�
migi();
tomaru(80); //一時停止
TEION; //低音を鳴らす
t_left;Wait(25);
forward;Wait(50); //次の右車線へ移動
ClearTimer(0); //タイマーをリセットする
}
�Δ蓮↓イ汎韻絃豺腓覆里覇韻現萢�をする
�П�折
else if(n==6){ //�Г猟廠僖魁璽�
migi();
KOUON; //高音を鳴らす
t_right;Wait(50);
forward;Wait(50);
right;Wait(15); //次の右車線へ移動
ClearTimer(0); //タイマーをリセットする
}
�Г任蓮�直角コースと認識した後、50/100秒右旋回し50/100秒直進する。このままだと黒線上をTMAX以上いて変数nがカウントされてしまう可能性があるのでこの処理に加え15/100秒右回転する。
�┻泪�ーブ
else if(n==7){ //�┐竜泪�ーブコース
migi();
forward;Wait(15);
t_right;Wait(70);
forward;Wait(30);
right;Wait(50);
t_right;Wait(80); //変数nがカウントされない所まで移動
ClearTimer(0); //タイマーをリセットする
}
�┐任狼泪�ーブに差し掛かるので、一度変数nがカウントされた後、変数nがカウントされない所まで移動するよう処理する。
**��〜��まで [#zb53621a]
��〜��の行動はよく見ると� 銑い旅堝阿帆瓦�一緒であることを認識してほしい。つまりプログラムも全く一緒にすればよい。
��右折
else if(n==8){ //��の直角コース
migi();
KOUON; //高音を鳴らす。
t_left;Wait(10);
forward;Wait(40); //次の左車線へ移動
ClearTimer(0); //タイマーをリセットする
}
行動は��と�‘韻犬覆里妊廛蹈哀薀爐眛韻犬任△襦�
��一時停止+左折
else if(n==9){ //��の丁字路
hidari();
back;Wait(20);
tomaru(80); //一時停止
TEION; //低音を鳴らす
t_left;Wait(30);
forward;Wait(50); //次の左車線へ移動
ClearTimer(0); //タイマーをリセットする
}
行動は��と��同じなのでプログラムも同じである。
��直進
else if(n==10){ //��の丁字路
hidari();
KOUON; //高音を鳴らす
t_right;Wait(15);
forward;Wait(50); //次の左車線へ移動
ClearTimer(0); //タイマーをリセットする
}
行動は��と�F韻犬覆里妊廛蹈哀薀爐眛韻犬任△襦�
��左折
else if(n==11){ //��の丁字路
hidari();
KOUON; //高音を鳴らす
t_right;Wait(15);
forward;Wait(50); //次の右車線へ移動
ClearTimer(0); //タイマーをリセットする
}
行動は��と�て韻犬覆里妊廛蹈哀薀爐眛韻犬任△襦�
**��〜��まで [#cda6b226]
��右折
else if(n==12){ //��の直角コース
migi();
KOUON; //高音を鳴らす
t_right;Wait(50);
forward;Wait(50); //次の右車線へ移動
ClearTimer(0); //タイマーをリセットする
}
��では、直角コースと認識した後、50/100秒右旋回し、50/100秒直進させ次の右車線へ移動させる。なぜ右車線かというと、この先の急カーブにおいて左ライントレースだと黒線上にTMAX以上存在して変数nがカウントされる可能性があるのに対し、右ライントレースだとこのような問題が起きないからだ。
��直進
else if(n==13){ //��の直角コース
migi();
KOUON; //高音を鳴らす
t_left;Wait(25);
forward;Wait(250); //スタート地点へ移動
}
��では、直角コースと認識した後、25/100秒左旋回し、250/100秒直進させスタート地点へ移動させる。
}
n(変数)が14とカウントされたのでwhile関数から脱出。
Off(OUT_AC); //停止させる
}
完成!!
*反省・感想 [#ta686651]
今回はプログラミンングがメインの課題であった。sub関数が分からない状態からのスタートだったので初めはとても焦ったけれども、今ではこの課題があったおかげで様々なことを学ぶことができたので感謝している。反省する点は丁字路や直角コースのsub関数から出た後の処理をもう少し正確にして、完走する確率を上げるべきだったことだけである。他に反省する所は特にない。