課題2の内容とルール

各チームで次のようなコースを作成し、コースを2周するロボットを製作せよ。

  • 黒い線の幅は15〜25mmの範囲で一定にすること
  • 交差点が3箇所以上あること
  • 直角のコーナーを2箇所以上設置すること
  • 近道を2箇所 (直角のコーナーをショートカットしてもよい)
  • スタート地点にはコースに直角に横5cmのラインを描く

ただし、

  • 速さと正確さを追求すること
  • 2周目はスタート地点の直前で自動的に止まること
  • 近道を選択するプログラムとそうでないプログラムを2人で分担して作成すること

ロボットの概要

本体はモーターを2つ並べて小型化している。大部分はモーターが占めている。

kannsei.JPG

モーターに直接ついているギアは8枚歯で、それに40枚歯を組み合わせている。

taiya.JPG

駆動輪は2つなので後ろにキャスターをつけた。

kyasuta.JPG

センサの位置は前。鍵の手のパーツを使い、取り付けている。上下、左右自由に位置を変えることができる。

sensa.JPG

製作過程

小回りできるように、タイヤ間をできるだけ短くした。

初めはモーターに直接タイヤをつけていたが、動かしてみると速すぎたので、ギアを組み合わせることにした。

キャスターは摩擦を少なくするため、床と接する面が小さいタイヤを選んだ。

プログラム

条件設定について

センサーとラインの位置関係
2つのセンサーはラインを挟むように配置している。
2つのセンサが認識するパターン
{白,白} {黒,黒} {白,黒} {黒,白} の4つ。
コース上で予想される状況
  • 直線: {白,白}
  • 右カーブ: {白,黒}
  • 左カーブ: {黒,白}
  • 右折: {白,黒}
  • 左折: {黒,白}
  • 交差点: {黒,黒}
  • 点線との分岐
    line.JPG

実線のみ(伊藤)

  /*2周にかかる時間*/
  #define run_time 650
  /*タイマー*/
  ClearTimer(0);
task main()
{
     /*センサの指定*/
    SetSensor(SENSOR_1,SENSOR_LIGHT);
    SetSensor(SENSOR_3,SENSOR_LIGHT);   
     /*ライントレース(65秒以内の間)*/
    while (Timer(0)<=run_time)
     {
        if ((SENSOR_1>40)&&(SENSOR_3>40))      //{白,白}:直進
          {
            OnFwd(OUT_A+OUT_C);
          }
        if ((SENSOR_1<40)&&(SENSOR_3>40))      //{黒,白}:左に方向転換
          {
            Off(OUT_A);
            OnFwd(OUT_C);
          }
        if ((SENSOR_1>40)&&(SENSOR_3<40))      //{白,黒}:右に方向転換
          {
            Off(OUT_C);
            OnFwd(OUT_A);
            Wait(8);                  //工夫※
          }
        if ((SENSOR_1<40)&&(SENSOR_3<40))      //{黒,黒}:直進
          {
           OnFwd(OUT_A+OUT_C);
           PlaySound(SOUND_CLICK) ;	//音、{黒,黒}の度鳴らす
          }
      }
    Off(OUT_A+OUT_C);
}

まず、センサーが2つあること、センサーは閾値以下もしくは閾値以上の2パターン(黒or白)を判断すること、と考えた。 そのため2×2=4つの場合分けをした。 {白,白}{黒,白}{白,黒}{白,黒}の4つの場合についての動きをそれぞれifで書いた。

whileの条件式は{黒,黒}を認識した回数を示す変数によって決めようと初めは考えていた。そのために{黒,黒}を認識するごと音を鳴らし、回数のカウントをしやすくしてみた。しかし、これだけだと{黒,黒}を70回目に認識した瞬間、つまり交差点で止まっていしまう。そのため最終的にはタイマーを使って2周にかかる時間である65秒間whileの条件式にした。

工夫※右折で失敗することが多かったので、{白,黒}:右に方向転換の場合にのみWaitを使って右に回りやすくした。この時間が短すぎると効果がないし、逆に長すぎると点線との分岐点などで右に曲がってしまう。何度か試し、一番失敗の少なくなる時間を選んだ。

点線を選択(山本)

#define THRESHOLD 40		                                 //閾値の値を40にする
int cross ;				                         //変数を定義する(4回使うので4つ必要)
int across ;
int go_across ;
int cross_a ;
sub lead ()							 //サブルーチンで定義する
{	
	SetSensor(SENSOR_1, SENSOR_LIGHT);			 //右のセンサを1につなぐ
	SetSensor(SENSOR_3, SENSOR_LIGHT);			 //左のセンサを3につなぐ
	OnFwd(OUT_A+OUT_C);
	until ((SENSOR_3 < THRESHOLD));	//センサ3が黒を判断するまで直進する(点線のところまで)
		Off(OUT_A+OUT_C);				 //いったん止まる
		Wait(70);
		Off(OUT_C);
		OnFwd(OUT_A);				         //点線のルートに入る
		Wait(55);
		OnFwd(OUT_A+OUT_C);
		Wait(25);
		Off(OUT_A+OUT_C);
		Wait(70);
	go_across = 1;
	while (go_across <= 2){			                //変数の値が2になるまでライントレースする
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 > THRESHOLD))	// 黒線上にいるときは直進する
	{	OnFwd(OUT_A+OUT_C);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 > THRESHOLD))	//左にずれたときは右に修正する	
	{	Off(OUT_A);
		OnFwd(OUT_C);
		}
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 < THRESHOLD))	//右にずれたときは左に修正する
	{	OnRev(OUT_C);
		OnFwd(OUT_A);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 < THRESHOLD))	//交差点では直進する
	{	OnFwd(OUT_A+OUT_C);
		go_across = go_across +1 ;		        //交差点を通る度に変数の値が1増える
		}
	}
		Off(OUT_A+OUT_C);
		Wait(50);
		Off(OUT_C);
		OnFwd(OUT_A);
		Wait(95);
	cross = 1;
	while (cross <= 12) {			               //変数の値が12になるまでライントレースする
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 > THRESHOLD))		
	{	OnFwd(OUT_A+OUT_C);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 > THRESHOLD))		
	{	Off(OUT_A);
		OnFwd(OUT_C);
		}
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 < THRESHOLD))		
	{	Off(OUT_C);
		OnFwd(OUT_A);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 < THRESHOLD))		
	{	OnFwd(OUT_A+OUT_C);
		cross =cross +1 ;
		}
	}
		Off(OUT_A+OUT_C);				//点線のルートに入る
		Wait(70);
		Off(OUT_C);
		OnFwd(OUT_A);
		Wait(25);
		OnFwd(OUT_A+OUT_C);
		Wait(30);
		Off(OUT_A+OUT_C);
		Wait(70);
	across = 1;
	while (across <= 2){			                //変数の値が2になるまでライントレースする
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 > THRESHOLD))		
	{	OnFwd(OUT_A+OUT_C);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 > THRESHOLD))	
	{	Off(OUT_A);
		OnFwd(OUT_C);
		}
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 < THRESHOLD))
	{	Off(OUT_C);
		OnFwd(OUT_A);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 < THRESHOLD))
	{	OnFwd(OUT_A+OUT_C);
		across = across +1 ;			        //交差点を通る度に変数が1増える
		}
	}
		Off(OUT_A+OUT_C);
		Wait(70);
		Off(OUT_C);
		OnFwd(OUT_A);
		Wait(95);
		Off(OUT_A+OUT_C);
		Wait(70);
}						                //ここまでがサブルーチンで定義される
task main()
	{
		lead ();					//サブルーチン
		cross_a = 1 ;
	while (cross_a <= 9) {
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 > THRESHOLD))	// 黒線上にいるとき直進する
	{	OnFwd(OUT_A+OUT_C);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 > THRESHOLD))	//右にずれたとき左に修正する	
	{	Off(OUT_A);
		OnFwd(OUT_C);
		}
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 < THRESHOLD))	//左にずれたとき右に修正する
	{	Off(OUT_C);
		OnFwd(OUT_A);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 < THRESHOLD))	//交差点は直進する
	{	OnFwd(OUT_A+OUT_C);
		cross_a =cross_a + 1;
		}
	}
		Off(OUT_A+OUT_C);			        //スタート地点に戻る(1周終わり)
		Wait(70);
		OnFwd(OUT_A+OUT_C);
		Wait(30);
		Off(OUT_A+OUT_C);
		Wait(70);
		lead ();						//サブルーチン
		ClearTimer(0);                    	        // Timer(0) をリセットする
   while ( Timer(0) <= 40){		           //4秒間ライントレースする(少し手前で止まらせる)
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 > THRESHOLD))		
	{	OnFwd(OUT_A+OUT_C);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 > THRESHOLD))		
	{	Off(OUT_A);
		OnFwd(OUT_C);
		}
	if ((SENSOR_1 > THRESHOLD) && (SENSOR_3 < THRESHOLD))		
	{	Off(OUT_C);
		OnFwd(OUT_A);
		}
	if ((SENSOR_1 < THRESHOLD) && (SENSOR_3 < THRESHOLD))		
	{	OnFwd(OUT_A+OUT_C);
		}
	}
		Off(OUT_A+OUT_C);				 //終わり
}

交差点と点線とを判断するために変数を使いました。交差点を通過する度に変数を1ずつ増やしていき、一定の値を越えた後のセンサ3が黒の時そこが点線(近道)だと判断しました。また2周目にゴール手前で止まらなければいけなかったので、単純にrepeatすることができないので、1周目と2周目で同じ部分を繰り返すためにsubを使いました。そして、最後はタイマを使って4秒間ライントレースしてゴール手前で止まるようにしました。

反省

伊藤

whileの条件式となる{黒,黒}の認識した回数を数えるために、音を鳴らすことにした。一個の交差点につき、1回音が鳴ると考えていたのだが、実際にやってみると一回交差点を通過するごとに3、4回音が鳴った。考えていたことと違っていたので驚いた。音を利用することでプログラムがどのように判断したのかが分かり、おもしろいと思った。

最終的なプログラムは、4つのifによる場合分けと走行時間の指定、という単純なものになってしまった。回転センサや変数を有効に使えればよかったかなというのが反省点です。ただ、交差点を数えたり回転センサで距離をはかったりしていないので、他のコースでもある程度走れるのではないかと思う。

山本

点線を判断するためにマシンの位置を伝えるが一番苦労した。最初は回転センサを使ってみようとしたが、うまく使うことができず、結局変数を使って交差点を数えて位置情報を伝えることにした。また、走らせる度に異なった走りをするので、修正するのも困難だった。

何度も失敗して途中くじけそうになったが、試行錯誤を繰り返して思い通りに走らせることができた時はとても気持ちよかった。

コメント欄

  • コースの分析やロボットの説明は良いと思います。ただ、プログラムについては改善できる点がいくつかあります。ライントレースをする部分が何度も出たりしているので、もっと簡潔にできるかもしれません。また、細かいことですが、光センサの定義の位置にも注意できます。また、説明も何のための変数か等をはっきりさせましょう -- FI? 2010-12-17 (金) 17:33:26
  • よく説明がされています -- TAKA? 2010-12-24 (金) 16:28:36


添付ファイル: fileline.JPG 382件 [詳細] filetaiya.JPG 283件 [詳細] filekyasuta.JPG 380件 [詳細] filekannsei.JPG 358件 [詳細] filesensa.JPG 282件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2010-12-24 (金) 16:28:36 (3166d)