目次
#contents
*今回の課題について [#j95b5819]
#ref(2015b/Member/kei/Mission2/2015b-mission2.png,ルート)
今回の課題はルートA→BまたはルートB→Aをうまくライントレースすることである。&br;

ルートA→B:A地点 → P直進 → Q直進 → Q右折 → P右折 → Q左折 → P左折 → B地点&br;
ルートB→A:B地点 → P右折 → Q右折 → P左折 → Q左折 → Q直進 → P直進 → A地点&br;&br;

今回の課題はただライントレースをするだけでなく交差点での動作が重要である。&br;
今回、私はルートB→Aを担当します。&br;
[[2015年後期/課題2:http://yakushi.shinshu-u.ac.jp/robotics/?2015b%2FMission2]]
*ロボットの構造について [#v6451296]
今回はロボットは基本的にテキストに乗っているベースの型でやることになっているので割愛します。
#ref(2015b/Member/kei/Mission2/IMG_4889(1).JPG,50%);
*プログラミングについて [#d1fffe12]
今回は交差点をどう認識し、ラインをトレースするとき線のどちら側をトレースするかを重視して組んだ。
また、できるだけ早くゴールできるようにする工夫もした。

**定義部分 [#a7a7053c]
***定義部分の解説 [#w387b37b]
この部分では主に三つの事を定義している。一つは黒と白を見分けるための色の閾値とスピードである。二つ目はライントレースを行うための動作である。三つ目は交差点での動作である。下の三つの定義がそれにあたる。
  //課題:交差点で1秒停止、コースB		B地点→P右折→Q右折→P左折→Q左折→Q直進→P直進→A地点

  #define BLACK 35	                     //これ以下は濃い黒
  #define WHITE 50	                     //これ以上は白
  #define LowSPEED 25
  #define HighSPEED 30
  #define Go OnFwd(OUT_AB,HighSPEED);	     // 直進
  #define Go_left OnFwd(OUT_B,LowSPEED);Off(OUT_A);
  #define Go_right OnFwd(OUT_A,LowSPEED);Off(OUT_B);
  #define turn_left OnFwd(OUT_B,LowSPEED);OnRev(OUT_A,HighSPEED);
  #define turn_right OnFwd(OUT_A,LowSPEED);OnRev(OUT_B,HighSPEED);
  #define STEP 1
  #define Chokushin Off(OUT_AB);Wait(1000);Go;Wait(700);break;
  #define Usetu Off(OUT_AB);Wait(1000);turn_right;Wait(700);Go;Wait(300);break;
  #define Sasetu Off(OUT_AB);Wait(1000);turn_left;Wait(500);Go;Wait(300);break;
----

**sub関数部分(交差点での動作) [#b9b87472]

  sub KOUSATEN(int counter) {
    switch (counter) {
        case 0: Usetu;
        case 1: Usetu;
        case 2: Sasetu;
        case 3: Sasetu;
        case 4: Chokushin;
        case 5: Chokushin;
        default: Wait(1);
    }
  }
***交差点での動作の解説 [#v0c861df]
このsub関数で交差点での動作を決定している。下のMain関数で交差点の数を数える部分があり、そこで交差点に来るたびにsub関数を実行し、最後にcounterという変数に1を加えることで再びsub関数に入った時次の動作を行うことができるようになっている。交差点での動作は上で定義してあるとおりである。

**Main関数 [#fcde30a2]

  task main() {
    SetSensorLight(S1);
    int counter = 0;
    int counter1 = 0;
    int counter2 = 0;
    Off(OUT_AB);
    Wait(1000);
    while (true) {
        if (SENSOR_1 < BLACK) {		       //濃い黒のとき&br;

***Main関数の解説�� [#j518088b]
今までに通った交差点の数が0、1、5、6のどれかであるときかつ濃い線の上にいるときにこれを実行する。この時はラインの右側にいるので左方向へ進む。そしてcounter1に1を加える。これによって濃い線の上にいる時間をカウントいている。このcounter1が一定以上の値になった時に交差点であると認識している。

            if (counter == 0 || counter == 1 || counter == 5 || counter == 6) {
                Go_left;								//左へ
                counter1++;
----
***Main関数の解説�� [#ife210e1]
今までに通った交差点の数が二つであるときかつ濃い黒線の上であるときにこれを実行する。&br;
ここではcounter2という変数を別に用意してcounter2の値が一定以下の時にcounter1の値を初期化している。逆の場合はcounter1に1を加える。二つ関数を用意している理由はcounter1の値が250以上の時に交差点と認識するようになっているが三つ目の交差点前ではそれではうまくいかなかったためである。
            } else if (counter == 2) {
                Go_right;								//右へ
                counter2++;
                if (counter2 < 5000) {
                	counter1 = 0;
                } else {
                	counter1++;
                }
----
***Main関数の解説�� [#g54d2652]
今までに通った交差点の数が3の時かつ黒い線の上であるときにこの動作を行う。ここでもcouter1にこの動作を行うたびに1を加える。
            } else if(counter == 3) {
            	Go_right;
            	counter1++;
----
***Main関数の解説�� [#nf2ac057]
通った交差点の数が上記以外すなわち4の時かつ黒い線の上のときにこの動作を行う。これも同様にcounter1に1を加える。
            } else {
                turn_right;
                counter1++;
----
***Main関数の解説�� [#pbcda0ed]
ここでは上で数え続けたcounter1が250を超えたときの動作である。250を超えた場合は交差点であると判断して動作を行う。具体的には上で記したsub関数を実行する。最初はcounterの値は0であるから上のSub関数では右折を行うようになっている。そしてcounterに1を加える。これが今までに通った交差点の数に該当する。そしてcounter1の値を初期化することでまたライントレースに戻る。ただしラインの右側か左側かでライントレースでの動きが逆になるためそれぞれの交差点を通過後の動作が用意されている。
            } if (counter1 > 250) {
            	KOUSATEN(counter);
            	counter++;
            	counter1 = 0;
            }
----
***Main関数の解説�� [#hf79f6b3]
BLACKよりは明るいがWHITEより暗い場所は境界線付近であると判断する。境界線付近では前進をすることによって少しでもタイムを縮められるように工夫をしている。
        } else if (SENSOR_1 < WHITE) {	   //境界付近なら
            Go;							   //直進
            counter1 = 0;
----
***Main関数の解説�� [#x35f0106]
ここは白い部分での動作なので線を見失ってから線を探す動作を行うところである。上の黒線上での動作同様にラインの右側か左側かで動作が異なるのでそれぞれの交差点を通過した後で動作が異なるようになっている。
        } else {					       //白のとき
            if (counter == 0 || counter == 1) {
            	Go_right;							//右へ
            	counter1 = 0;
            } else if (counter == 2 || counter == 3) {
            	turn_left;							//左へ
            	counter1 = 0;
            } else if (counter == 5 || counter == 6){
            	Go_right;
            } else {
            	turn_left;
            	counter1 = 0;
            }
        }
        Wait(STEP);
    }
  }
----
***まとめ [#s181151b]
このプログラムでは基本的に黒い線の上にいるときにcounter1に1を加える動作を繰り返し、一定以上になったら交差点であると判断して右折、左折、直進のどれかを行いcounterに1を加える。counterは今までに通った交差点の数を記録する変数である。

**プログラムの工夫点 [#w7514f8b]
今回のプログラムでの工夫点は交差点の数を数えてその数に応じてサブルーチンの挙動を変えたことである。
また二回目の交差点を回った後で誤作動が起きないように関数でカウントすることをした。
さらに交差点を越えた時にカーブの外側をライントレースするように移動をしカーブを曲がる時に片方のタイヤだけ回すか両方を回すかまた、白と黒の時の回転方向を変えることも行った。
また二回目の交差点を回った後は誤作動が起きないように別の関数でカウントすることをした。
さらに交差点を越えた時にできるだけカーブの外側をライントレースするように移動をしカーブを曲がる時に片方のタイヤだけ回すか両方を回すかまた、白と黒の時の回転方向を変えることも行った。

*感想と考察 [#u19249aa]
**考察 [#ze267323]
今回の課題での最後までの成功率はあまり高くなかった。タイムも大体3分ぐらいであった。成功率が低い要因の一つに紙を折り曲げてしまったことがあると思う。もし次の機会があったら紙を丸めるなどの工夫をしたい。
**感想 [#p7482e50]
今回の課題では本当は5段階でラインを認識して滑らかに動くようにしかたかったが紙を折り曲げてしまったことと線の濃さが不均一であったため不可能であった。次の機会があればそこを改善しプログラムもより改善して早くゴールできるようにしたい。またこのミッションの後半で電池が減ってきてうまく動かなくなり交換をしたら逆に動きすぎてまた調整し直すことになりとても苦労した。次の課題は時間ではなくモーターの回転などを利用したプログラムしていきたいと思う。回転数で制御すれば移動距離が変わらないためである。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS