- 追加された行はこの色です。
- 削除された行はこの色です。
[[2007a/MemberOnly/進行状況A]]
#counter
#contents
*今回の課題 [#ba820c16]
黒い線に沿って動くロボットを作成せよ。ただし、
1、速さと正確さを追求すること
2、交差点で優先側を走っていない場合には、一時停止すること
3、前方にあるもう一台のロボットに接触した場合には停止して,
相手のロボットが行き過ぎる、あるいは距離が離れるのを待つこと
&ref(./交差点.png);
*作戦 [#o213de30]
**課題クリアのためには? [#k263fe9d]
今回の課題のメインはライントレースです。しかし、ライントレースより厄介なのは交差点です。交差点を識別し、優先道路なら直進、違うなら一時停止しなければならないからです。この課題は、光センサーの使い方がポイントだと感じました。よって、センサーの付け方からロボットのベースを決めることにしました。
**交差点をどのようにクリアするか? [#nb90b6e9]
***センサーのつけ方 [#p24fcbb0]
ライントレースするための光センサーの取り付け方は、(僕の思いついた限り)3つあります。それぞれの長所、短所を述べたうえで、僕たちの班が選んだ取り付け方と、それを選んだ理由を説明したいと思います。
-------------------------------------------------------
&size(25){※取り付け方1};
光センサー1つを使います。もし、センサーがライン上にあれば、ロボットがラインから出るようにタイヤを動かし、センサーがラインを出たら、逆のタイヤを動かし、ラインに戻るようにします。
&ref(./センサー1.png);
&size(20){☆メリット};
ライントレースにおいてセンサーを1つしか使わないため、プログラムが簡単になります。
急なカーブもクリアすることができます。
&size(20){★デメリット};
交差点が識別できません。
---------------------------------------------------------
&size(25){※取り付け方2};
光センサー2つを使います。光センサーの間隔を2,5cm(ラインの幅)以上広げ、もし、どちらかのセンサーがライン上にきたら、モーターを調整して、もとの状態にもどすプログラムを作る。
&ref(./センサー2.png);
&size(20){☆メリット};
たいていのコースをライントレースすることが可能です。コースを脱線する恐れが、ほとんどありません。
&size(20){★デメリット};
交差点の識別が難しい。
--------------------------------------------------------
&size(25){※取り付け方3};
光センサー2つを使います。光センサーの間隔を2,5cm(ラインの幅)以内にして、もし、どちらかのセンサーがライン外にきたら、モーターを調整して、もとの状態にもどすプログラムを作る。
&ref(./センサー3.png);
&size(20){☆メリット};
交差点を認識できます。
&size(20){★デメリット};
急なカーブに対応できず、ラインを見失なってしまいます。
--------------------------------------------------------
***交差点の考察・まとめ [#q3ef10b5]
僕たちの班は、光センサーを「取り付け方3」のようにしました。理由はいたって単純。交差点をちゃんと攻略できるのは、「取り付け方3」しかないからです。ライントレースにおける「カーブ」に至っては、「取り付け方1」及び「取り付け方2」に負けています。しかし、今回の課題では、1番上の2に書いたように、交差点で優先道路でない場合、一時停止しなければなりません。「取り付け方2」では、やり方によってはできますが、1番きれいに交差点を攻略できるのは「取り付け方3」です。総合してみると、1番だと思った「取り付け方3」を採用しました。
僕たちの班は、光センサーを「取り付け方3」のようにしました。理由はいたって単純。交差点をちゃんと攻略できるのは、「取り付け方3」だと判断したからです。ライントレースにおける「カーブ」に至っては、「取り付け方1」及び「取り付け方2」に負けています。しかし、今回の課題では、1番上の2に書いたように、交差点で優先道路でない場合、一時停止しなければなりません。「取り付け方2」では、やり方によってはできますが、1番きれいに交差点を攻略できるのは「取り付け方3」です。総合してみると、1番だと思った「取り付け方3」を採用しました。
**急なカーブをどのようにクリアするか? [#zefa6442]
交差点を攻略できても、急なカーブをライントレースできないのでは、意味がありません。そこで、プログラムを工夫して、急なカーブにも対応できるようにしました。下に、元のプログラムと改善後のプログラムを書きます。
元のプログラム(左に曲がりたいとき)
OnFwd(OUT_C); //右のタイヤを回転させます
Off(OUT_A); //左のタイヤを止めます
改善後のプログラム(左に曲がりたいとき)
SetPower(OUT_A,3); //左のタイヤの出力を弱く設定
SetPower(OUT_C,7); //右のタイヤの出力を強く設定
OnFwd(OUT_C); //右のタイヤを回転させます
OnRev(OUT_A); //左のタイヤを反対の方向に回転させます
このように、曲がりたい方向にあるタイヤを進行方向に対して逆の方向に回転させるだけで、かなり曲がりやすくなります。右に曲がりたいときも、同様の方法ですることが可能です。
*コース [#k41606b7]
交差点が2つのシンプルなコースです。
&ref(./コース1.JPG);
*完成までの道のり [#pb39e867]
**過程1(土台作り) [#r3f2c075]
左右のタイヤにそれぞれモーターを1つずつ使い、土台を支えるために3つのタイヤを使いました。光センサーはロボットの前方に、下に向けて配置しました。また、タッチセンサーも前につける必要があるので、土台は後ろに重心がくるようにしました。
**過程2(タッチセンサー) [#ba910d20]
タッチセンサーはこのロボットのチャームポイントです!!
2枚の写真を見比べてください。前方の障害物にあたると、タッチセンサーが反応する仕組みになっています。
&ref(./タッチセンサー1.JPG);
&ref(./タッチセンサー2.JPG);
**過程3(光センサー) [#zce2dbdf]
このように光センサーをつけました。
&ref(./光センサー1.JPG);
**過程4(試験走行) [#z3162a60]
試験走行用のプログラムを作って走らせました。しかし、以下のような問題が発生しました。
1つ目、光センサーが床に近すぎたため、ラインと、そうでない部分を判別できなかった。
2つ目、ロボットの動きが速すぎたためすぐにラインをはずれてしまった。
3つ目、プログラムのミスで、タッチセンサーが当たっても止まらないときがあった。
このような問題が発生したため、ロボットとプログラムを組みなおす必要がありました。
**過程5(組みなおし) [#jb1addc4]
ギアの組み合わせをかえることにより、ロボットの速さを適度にすることに成功しました。また、センサーの地面からの高さと、後輪のタイヤの大きさをかえることにより、ちゃんとラインを区別してくれるようになりました。
&ref(./ギア.JPG);
*完成したロボットの説明 [#p93eba86]
&ref(./ロボット完成版.JPG);
**性能 [#j0911820]
・とても急なカーブには対応できないが、ほとんどのカーブをクリアする事ができる~
・交差点前で一時停止をきちんとできる~
・コースの完走率は今のところ80%ぐらいである~
・ただし、コースから脱線した場合、自力でコースに戻る事ができない~
**特徴 [#jd2d8b80]
・このロボットは、ほぼ、左右対称にできています。(配色もそうです)~
・タッチセンサーが他の班と比べて個性的です。~
・~
このロボットは完全に、左右対称にできています。(配色もそうです)
*プログラム [#te3dbada]
#define Dol 1047 定数を定義 「ド」の波長
#define Rel 1175 定数を定義 「レ」の波長
#define Mil 1319 定数を定義 「ミ」の波長
#define Fal 1397 定数を定義 「ファ」の波長
#define Sol 1568 定数を定義 「ソ」の波長
#define Sofl 1661 定数を定義 「ソのシャープ」の波長
#define Ram 1760 定数を定義 「ラ」の波長
#define Rafm 1865 定数を定義 「シのフラット」の波長
#define Shm 1976 定数を定義 「シ」の波長
#define Dom 2093 定数を定義 「ド、1オクターブ上」の波長
task play_music(){ //MUSIC
while (true) //この曲は「おもちゃのチャチャチャ」です
{
PlayTone(Dol,20); Wait(30);
PlayTone(Dol,20); Wait(30);
PlayTone(Dol,20); Wait(30);
PlayTone(Mil,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(60);
PlayTone(Rel,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Fal,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(90);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sofl,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Sofl,20); Wait(30);
PlayTone(Sol,40); Wait(60);
PlayTone(Shm,40); Wait(60);
PlayTone(Dom,40); Wait(120);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Fal,20); Wait(30);
PlayTone(Mil,20); Wait(30);
PlayTone(Mil,20); Wait(30);
PlayTone(Mil,20); Wait(30);
PlayTone(Fal,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Dol,80); Wait(120);
PlayTone(Fal,20); Wait(30);
PlayTone(Fal,20); Wait(30);
PlayTone(Mil,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Rel,20); Wait(30);
PlayTone(Shm,20); Wait(30);
PlayTone(Shm,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Sol,80); Wait(120);
PlayTone(Ram,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Shm,20); Wait(30);
PlayTone(Dom,20); Wait(30);
PlayTone(Dom,20); Wait(30);
PlayTone(Dom,40); Wait(60);
PlayTone(Shm,20); Wait(30);
PlayTone(Shm,20); Wait(30);
PlayTone(Shm,20); Wait(30);
PlayTone(Shm,20); Wait(30);
PlayTone(Ram,80); Wait(120);
PlayTone(Sol,20); Wait(30);
PlayTone(Sol,20); Wait(30);
PlayTone(Sofl,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Ram,20); Wait(30);
PlayTone(Sofl,20); Wait(30);
PlayTone(Sol,40); Wait(60);
PlayTone(Shm,40); Wait(60);
PlayTone(Dom,40); Wait(360);
}}
//ここからライントレースのプログラム
int k_s; //変数を用意(soundを鳴らすか鳴らさないかをきめる変数)
int s_p; //変数を用意(交差点を見分けるときに使用)
int k_p; //変数を用意(どちらに曲がっているかをあらわすために使用)
define LI 43 //光の強さの境界線を定義
int s_p; //変数を用意
sub search_pro(){ //ラインを見失ったとき用のサブルーチン
while ((SENSOR_1 > LI) && (SENSOR_3 > LI)){ //ラインが見つかるまで繰り返す
SetPower(OUT_A+OUT_C,7);
OnRev(OUT_A);OnFwd(OUT_C); 左を探す
Wait(30);
OnRev(OUT_C);OnFwd(OUT_A); 右を探す
Wait(60);
OnRev(OUT_A);OnFwd(OUT_C); ロボットの向きを元にもどす
Wait(30);
OnFwd(OUT_A+OUT_C); 直進する
repeat(7){ //7回繰り返す
Wait(10);
if (SENSOR_2 == 1) //タッチセンサーにあたったら10秒とまる
{
Off(OUT_A+OUT_C);
Wait(100);
}
}
}
}
sub s_touch() //タッチセンサーにあたったとき用の命令文(サブルーチン)
{
SetPower(OUT_A+OUT_C,7);
Off(OUT_A+OUT_C); モーターの出力をとめる
Wait(100); 10秒待つ
}
task main () {
SetSensor(SENSOR_1, SENSOR_LIGHT); //センサー1を光センサーと定義
SetSensor(SENSOR_2, SENSOR_TOUCH); //センサー2をタッチセンサーと定義
SetSensor(SENSOR_3, SENSOR_LIGHT); //センサ−3を光センサーと定義
s_p = 2 ; 変数に2を代入
s_p = 2 ; 変数に2を代入
start play_music ; //音楽を再生する
k_s =1; 変数に1を代入
while (true){
while (SENSOR_2 == 0){ //タッチセンサーが反応するまで繰り返す
while ((SENSOR_1 < LI) && (SENSOR_3 < LI)) //センサー1、3共にライン上のとき
{
SetPower(OUT_A+OUT_C,7);
OnFwd(OUT_A+OUT_C); 直進する
OnFwd(OUT_A+OUT_C); 直進する
if ( k_s == 2) {start play_music;k_s = 1;} //ライン上なら音楽再生
s_p = 1;
if (SENSOR_2 == 1) タッチセンサーが反応したら、ロボットを止める
{
s_touch();
}
}
while ((SENSOR_1 < LI) && (SENSOR_3 > LI)) //センサー1がライン上、センサー3がライン外のとき
{
if ( k_s == 2) {start play_music;k_s = 1;} //ライン上なら音楽再生
SetPower(OUT_A,3); //左のタイヤの出力を弱く設定
SetPower(OUT_C,7); //右のタイヤの出力を強く設定
OnFwd(OUT_C); //右のタイヤを回転させます
OnRev(OUT_A); //左のタイヤを反対の方向に回転させます
s_p = 1;
if(k_p ==1){
ClearTimer(2);} //右に曲がっていた時間を計っていたタイマーをリセット
k_p=2;
if (SENSOR_2 == 1) タッチセンサーが反応したら、ロボットを止める
{
s_touch();
}
}
while ((SENSOR_1 > LI) && (SENSOR_3 < LI)) //センサー1がライン外、センサー3がライン上のとき
{
SetPower(OUT_C,3); //右のタイヤの出力を弱く設定
SetPower(OUT_A,7); //左のタイヤの出力を強く設定
OnFwd(OUT_A); //左のタイヤを回転させます
OnRev(OUT_C); //右のタイヤを反対の方向に回転させます
if ( k_s == 2) {start play_music;k_s = 1;} //ライン上なら音楽再生
k_s=2;
s_p = 1;
if(k_p ==2){
ClearTimer(1);} //左に曲がっていた時間を計っていたタイマーをリセット
k_p=1;
if (SENSOR_2 == 1) タッチセンサーが反応したら、ロボットを止める
{
s_touch();
}
}
if ((SENSOR_1 > LI) && (SENSOR_3 > LI)) センサー1、3共にライン外のとき
{
if (s_p == 1){ //このパターンが交差点です
SetPower(OUT_A+OUT_C,7);
Off(OUT_A+OUT_C); いったん止まる
OnRev(OUT_A+OUT_C);
Wait(10); すこし下がる
Off(OUT_A+OUT_C); 一時停止する
stop play_music ;k_s=2; //交差点にくると、音楽の再生を停止
if (s_p == 1){ //このパターンは交差点です
SetPower(OUT_A,3);
SetPower(OUT_C,7);
Off(OUT_A+OUT_C); ロボットを停止させる
if(Timer(2) >= 20){ //2秒以上、左にカーブして交差点に入ったとき
OnRev(OUT_A); //ロボットの向きを微調整する
Wait(23);}
if(Timer(1) >=20){ //2秒以上、右にカーブして交差点に入ったとき
OnRev(OUT_C);
Wait(23);}
OnRev(OUT_A+OUT_C); //少しバックする
Wait(50);
Off(OUT_A+OUT_C); //10秒間停止する
Wait(100);
OnFwd(OUT_A+OUT_C); //交差点を横切る
repeat(14){
Wait(10);
OnFwd(OUT_A+OUT_C); 交差点を横切る
repeat(9){
Wait(10);
s_p = 2;
if (SENSOR_2 == 1) タッチセンサーが反応したら、ロボットを止める
if (SENSOR_2 == 1) タッチセンサーが反応したら止まる
{
s_touch();
} }
}else{ //コースを見失ったとき
SetPower(OUT_A+OUT_C,7);
search_pro(); サブルーチンのサーチプログラムを作動させる
}
}
}
}
}
今回の課題をこなすにあたって、プログラムは非常に重要な役割を担います。前回の書道ロボットの課題は、与えた命令通りにロボットが動くので、プログラミングは比較的やさしいものでした。しかし、今回の課題では、ロボットがセンサーによる情報を分析して動くので、予想外の動きをすることがあります。あらゆるパターンを考え、プログラミングをすることは結構難しいことでした。
*まとめ [#t3710646]
**工夫したところ [#x3d600ce]
プログラムが長くなったので、なるべく{ と } が上下に同じ位置にくるようにして、少しでもプログラムがみえやすくなるように努力した
プログラムが長くなったので、なるべく{ と } が上下に同じ位置にくるようにして、少しでもプログラムがみえやすくなるように努力した。
プログラムにおいて、変数を使用したこと。そのことにより、センサーから送られてくる情報だけでなく、現在ロボットがどのように走っているかという事をロボットに認識させることが可能になった。(何秒間、どちらにカーブしたかが分かる)
**苦労したところ [#w5d32ca7]
if文、while文をたくさん使ったため、{}が多くなりプログラムを組むのが難しかった。
最初から課題のすべてをこなすロボットを作ろうとしたので、初めて試験走行したときはライントレースさえ、してくれなかった。その後のロボット、プログラムの組みなおしは想像以上にきつかった。
**感想(制作を終えて) [#k715fb0d]
(栗山)~
今回の課題は、とても大変でした。「あと少しラインが太かったら…」となんども思いました。故に、与えられた条件の中で、初めてコースを完走できたときはとてもうれしかったです。まだ、タイヤの面で改善する余地があるので、より速く正確にコースを1周できるようにしたいです。
*コメントをどうぞ [#yc269d1d]
#comment