2008b

'' 課題2: 〜ライントレースロボの制作〜''

◇ 目次 ◇

課題内容

'●チームで作成したコースに沿って動くロボットを作成する●
 [条件]
 ・速さと正確さを追求すること
 ・交差点で優先側を走っていない場合には、一時停止すること
 ・前方にあるもう一台のロボットに接触した場合には停止して相手のロボットが通り過ぎる、あるいは距離が離れるのを待つこと
 ・コースを2周したら自動的に止まること

コース説明

下が今回作成したコースの全貌となります。 直線ラインが多く、光センサーの活躍の場が少なく見えますが、
コーナリングはかなり急なのでマシンが速いと脱線の可能性が大きくなります。
また左右で優先帯を変えています。

コース.JPG

交差点拡大写真

十字路.jpg

工夫点

・他のチームは優先コースの手前に線を入れることでロボットを停止させていたが、
自分たちは優先道路をロボットが認識しバックさせることで衝突を防ぐようにしている。
その代わり単純に交差を十字形にすることでバック動作などによる誤差の影響を受けにくくした。

・黒線が細めであるが、光センサーが黒線を挟み込む方式で走るマシンにしたのでセンサー間隔に余裕ができ、
軌道修正が少なくなる分マシンの高速化につながったと思う。

ライントレースロボの紹介

ロボットの全体像

全体.jpg

これが試行錯誤の末の最終的な制作ロボットです。

センサーについて

sensor.jpg

今回ライントレースロボットを作成する過程で光センサーとタッチセンサーを使用しました。
光センサーの幅は調節しやすくなっています。

・タッチセンサーは図の手前の黄色いダンパー部分に接触があるとタッチセンサーが
押されることでマシンに伝わり信号が伝わり接触・非接触を区別する仕組みです。

lightS.jpg

・光センサーは片方のランプから赤い光が照射され、物体により光の反射量に違いがあるので
それをもう片方のフォトトランジスターで感知し、黒線と白い部分を値で区別出来ます。

自分たちは始めの写真のようにセンサーをかなり低くすることでかなりセンサーの感度が良くなっています。
(高いと 明暗差:約10 → 低いと 明暗差:約20)

・制作過程・

形態

〇呂瓩倭芦鵑硫歛蠅農作したマシンをそのま使おうと四輪形態を考えた。
しかし四輪駆動では摩擦が大きく、軌道修正が多い場合スピードを追求する面で 不利と考え途中で取りやめた。

∋洋愀燭寮作を踏まえ、次に二輪駆動三点指示(いわゆる三輪車)の方式の制作に切り替えました。
さらに普通の自動車などと同じように前輪の舵をモーターにで取らせる方式を考えました。
これならば左右のタイヤの回転を止めず、軌道修正と進行が同時に行うことが出来るので速さ及びマシンの動きがなめらかになります。

過程1.jpg

しかしここで
・舵切りを行うモータの調節が難しく、舵が切れ過ぎてしまう。
・タイヤに十分な摩擦が取れない。
・マシンとセンサーとの連動が取りにくい。
などの問題の調節が取れず時間的に今回はこの方式は見送ることにしました。

最終的に写真のような前輪二つで駆動し、後輪はマシンを支えるだけの三輪車の形態にすることにしました。
タッチセンサーと共に光センサーも前方に配置するようにしてマシンがコースからずれる前に軌道修正を行うようになっています。
始めは黒線を読み取る形式にしていましたが交差点と脱線の区別が付きにくいため
白線部分を両側の光センサーで読み取る形式に変更しました。

組み立て工夫点

・ギア比最低

gear.JPG

マシンが速いとどうしてもエラーが走行中に生じてしまうため、安定走行と完走のためにと
最小と最大のギア比にしてタイヤも小さめにしました。
しかしこれを実際に走らせて見ると誤作動が全くないのに加え、軌道修正が少なくなり
結果的にマシンスピードが速くなるという結果が得られました。

move.jpg

・ロボットは制作中や持ち運びにおいて壊れ易いので、出来るだけ強固にと
ロゴを互いになるべく噛み合わせたり前後から挟み込むようにして耐久性を強めました。
しかし、下図のように電池交換時はマシンをほとんど分解せずに出来ます。

body1.jpg

プログラム

今回のプログラムで必要な要素をまとめると
1、右センサーが黒を感知したとき、右に曲がる
2、左センサーが黒を感知したとき、左に曲がる
3、両方のセンサーが白を感知した時、直進する
4、両方のセンサーが黒を感知したとき、停止する
5、タッチセンサーが入ったとき、停止する
この5つになります。よってまずはこの5つをプログラムに組み込むことにします。

プログラム第一号とその問題点

まずぱっと作った形がこれになります。

#define RUN_TIME 200//走る時間
#define L1 40//センサー1の光度
#define L3 40//センサー2の光度

task main()
{
    SetSensor(SENSOR_2,SENSOR_TOUCH);
    
    SetSensor(SENSOR_1,SENSOR_LIGHT);
    SetSensor(SENSOR_3,SENSOR_LIGHT);
    /*センサーセット。2がタッチ、1,3が光*/
    
    ClearTimer(0);
    int runtime=RUN_TIME;
    OnRev(OUT_A+OUT_C);
    
    
    while(Timer(0)<=runtime){//runtime時間中走り続ける
                             if((SENSOR_1<=L1 && SENSOR_3<=L3) || (SENSOR_2==1)){~
                                              //両方が黒線に乗るか、タッチセンサーが入ったとき
                                              //停止し、バックし、その分の時間追加で動けるようにする
                                             ClearTimer(1);
                                             Off(OUT_A+OUT_C);
                                             Wait(100);
                                             OnFwd(OUT_A+OUT_C);
                                             Wait(20);
                                             Off(OUT_A+OUT_C);
                                             Wait(100);
                                             runtime=runtime+Timer(1);//この処理時間分を走行時間にプラスする
                             }
                             else if(SENSOR_1<=L1){
                                             //センサー1のみ黒線のとき
                                             
                                             OnFwd(OUT_C);
                                             OnRev(OUT_A);
                             }
                             else if(SENSOR_3<=L3){
                                             //センサー3のみ黒線のとき
                                             
                                             OnFwd(OUT_A);
                                             OnRev(OUT_C);
                             }
                             else if(SENSOR_1>L1 && SENSOR_3>L3){
                                             //両方白線のとき
                                             
                                             OnRev(OUT_A+OUT_C);
                             }
    }
    Off(OUT_A+OUT_C);
}

工夫した点としては、タッチセンサーが入ったとき、及び交差点に入った時の停止処理です。

ClearTimer(1);
Off(OUT_A+OUT_C);
Wait(100);
OnFwd(OUT_A+OUT_C);
Wait(20);
Off(OUT_A+OUT_C);
Wait(100);
runtime=runtime+Timer(1);

上の写真を見てわかるとおり、タッチセンサーが光センサーより前に乗り出す形になっています。そのため、交差点でただ停止するだけでは、「相手に道を譲る」という目的を果たせないと思い、停止後バックししばらく待つ、という処理を組み込みました。
また、交差点での停止はともかく、タッチセンサーはいつ、何回入るかわからないため、「2週走ったら止まるようにする」という処理の時間設定に支障をきたすと思い、この一連の処理をやってる間の時間を走行時間にプラスするという処理も加えました。

しかし、このプログラムを実行させたところ、交差点で何回もこの処理に陥り、先に進まないという事態が発生しました。

えらー.gif

もちろん、一旦後退するという処理を取り除いてしまえば一件落着なのですが、ここは工夫した点として残したいと思い、後退処理を残したままこの問題の解決にとりかかりました。

問題の解決

この問題を解決するため、まず次の二つの方法をとりました。
1、交差点で停止処理後、一定時間センサーが両方黒線に乗っても停止処理を行わない
2、左折、右折の条件式の変更

1番は、停止処理の部分を以下のように書き換えることで実現させました。

if( (SENSOR_1<=L1 && SENSOR_3<=L3 ''&& (Timer(0)-tim2>30)) ''|| (SENSOR_2==1)){
ClearTimer(1);
Off(OUT_A+OUT_C);
Wait(50);
OnFwd(OUT_A+OUT_C);
Wait(70);
Off(OUT_A+OUT_C);
Wait(50);
''tim2=Timer(0);''
runtime=runtime+Timer(1);
....


太字部が主な変更点です。
これにより、一度交差点で停止処理を行ったあと、一定時間内は両方のセンサーが黒になっても停止処理を行わないようにしました。
もちろん、タッチセンサーが入った時には交差点の停止処理後か否かにかかわらず停止処理を行う必要があるため、条件式で光センサーの方にだけ判定をつけました。

次に2番は、具体的にそれぞれ条件式を次のように書き換えました。

else if((SENSOR_1<=L1)&&(SENSOR_3>=L3)){


else if((SENSOR_1>=L1)&&(SENSOR_3<=L3)){


「片方のセンサーが黒の時」という条件式に加え、「もう片方のセンサーが白の時」という処理を論理積で加えました。
これにより、交差点を横断中=両方が黒の時はこれらの曲がる処理を無視して直進するようにしました。もしこの条件式がなかったら、交差点を横断中に「センサー1のみ黒線だったら」という処理を行ってしまうため、右か左かに曲がっていってしまうことになります。


これで後退処理の問題が解決したと思われましたが、まだ解決していませんでした。まっすぐに交差点に突入できればいいのですが、少し斜めに突入してしまうと、このようになってしまいました。

えらー2.gif

今度はこの問題を解決するために、カーブの時に今までは片方のタイヤを前進、もう片方は後退させていたのを、片方のタイヤを前進、もう片方を停止させることにしました。

Off(OUT_C);
OnRev(OUT_A);
Off(OUT_A);
OnRev(OUT_C);

こうすることで、斜めに入ってしまってもカーブの時にその場で旋回するのではなく少し前進しながらのカーブになるため、交差点を乗り切ることができるようになりました。
ただしこの方法にも問題があり、急なカーブは曲がりきることができません。しかし、今回のコースのカーブはすべて曲がることが出来、しかも今回のコースのカーブが特別緩やかというわけでもないので、今回はこの方法で落ち着くことにしました。

最終的なプログラム

以上の過程を踏まえ、最終的にはこのようなプログラムになりました。

#define RUN_TIME 1500
#define L1 45
#define L3 45

task main()
{
    SetSensor(SENSOR_2,SENSOR_TOUCH);
    
    SetSensor(SENSOR_1,SENSOR_LIGHT);
    SetSensor(SENSOR_3,SENSOR_LIGHT);
    /*センサーセット。2がタッチ、1,3が光*/
    
    ClearTimer(0);
   
    int runtime=RUN_TIME,tim2=-30/*最初はTimer(0)-tim2の差を30にしたいため、初期値は-30に*/;
    OnRev(OUT_A+OUT_C);
    
    
    while(Timer(0)<=runtime){
                             if((SENSOR_1<=L1 && SENSOR_3<=L3 && (Timer(0)-tim2>30)) || (SENSOR_2==1)){
                                              //両方が黒線に乗るか、タッチセンサーが入ったとき
                                              //停止し、バックし、その分の時間追加で動けるようにする
                                             ClearTimer(1);
                                             Off(OUT_A+OUT_C);
                                             Wait(50);
                                    OnFwd(OUT_A+OUT_C);
                                    Wait(70);
                                     Off(OUT_A+OUT_C);
                                             Wait(50);
                                    tim2=Timer(0);
                                      
                                            runtime=runtime+Timer(1);
                                            
                             }
                             else if((SENSOR_1<=L1)&&(SENSOR_3>=L3)){
                                             //センサー1のみ黒線のとき
                                             //タイヤを片方ストップさせる
                                             Off(OUT_C);
                                             OnRev(OUT_A);
                                    
                             }
                             else if((SENSOR_1>=L1)&&(SENSOR_3<=L3)){
                                             //センサー3のみ黒線のとき
                                             //同じくタイヤを片方ストップ
                                             Off(OUT_A);
                                             OnRev(OUT_C);
                                    
                             }
                             else if(SENSOR_1>L1 && SENSOR_3>L3){
                             	//両方白線のとき
                                                                  
                                             //直進させる
                                             	OnRev(OUT_A+OUT_C);
                                    
                             }
                             
                       
    }
    Off(OUT_A+OUT_C);
}

・よろしければコメントをどうぞ・

  • とても詳しく、わかりやすく良いレポートです。 -- FI? 2008-12-11 (木) 14:56:21
  • たいへんよくできています。 -- なかむら? 2008-12-11 (木) 15:27:02


添付ファイル: fileshoot.jpg 146件 [詳細] fileえらー2.gif 319件 [詳細] fileえらー.gif 312件 [詳細] filemove.jpg 302件 [詳細] filelightS.jpg 344件 [詳細] filebody1.jpg 299件 [詳細] filegear.JPG 291件 [詳細] filesensor.jpg 303件 [詳細] file過程1.jpg 304件 [詳細] file全体.jpg 320件 [詳細] file十字路.jpg 302件 [詳細] fileコース.JPG 334件 [詳細] fileside.jpg 161件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-01-18 (日) 15:18:11 (3865d)