ロボットの紹介

全体像

車軸回り

はじめは三輪で小回りの聞くロボットを作ろうと考えましたが、安定性と高さを考慮してコンパクトな四輪にしました。
コンパクトながらも安定感が欲しかったので、車軸を支える点を一輪につき二箇所にしてより強固にしました。
その結果車軸周りの重さが増して、重心が低く安定感のあるロボットになりました。

車軸回り

はさみ

鋏の部分は鋏自体を大きく広くすることで挟みやすく外れにくい構造に仕上がりました。
また、うまく鋏同士が噛みあうようにしたので、持った時の安定感がより増しました。
ただ、鋏部分と本体部分の接続が弱いので簡単に壊れてしまうの欠点です。

はさみ

タッチセンサー

タッチセンサー部分は説明書の完成品を参考に作りました。
軽い缶にも反応するようにできたと思います。

タッチセンサー

コース攻略

コース攻略

反時計回り

  1. スタート直後の曲がり角を曲がるためにスタートから,泙任聾鮑硬世覆靴離薀ぅ鵐肇譟璽垢鬚靴泙后
  2. ,ら△慮鮑硬世魃曚┐襪泙任蓮交差点ありのライントレースをします。
  3. △慮鮑硬世忘討唳垢軍櫃るまでは内側を回るために交差点なしのライントレースをします。
  4. 交差点を超える直前に交差点ありのライントレースになるように初めて△魃曚┐浸からの時間指定で切り替えます。
  5. そのまま3つの交差点を越え、➂の交差点を越えた時から交差点なしのライントレースに切り替えて再び時間を計り始めます。
  6. そのままい泙膿覆澆泙后
  7. ➂からい泙任了間指定で缶を置く動作をします。
  8. そのまま交差点なしのライントレースを続けてゴールします。

プログラム

#define BLACK1 38 //最も黒い部分のしきい値
#define BLACK2 42 //そこそこ黒い部分のしきい値 
#define WHITE1 45 //そこそこ白い部分のしきい値
#define WHITE2 49 //最も白い部分のしきい値
#define HIPOWER 7
#define LOWPOWER 1
#define set_power_H SetPower(OUT_AC,HIPOWER);
#define set_power_L SetPower(OUT_AC,LOWPOWER);
#define go_fwd set_power_H; OnFwd(OUT_AC);
#define turn_left1 set_power_L; Off(OUT_A); OnFwd(OUT_C); //左に曲がる
#define turn_right1 set_power_L; OnFwd(OUT_A); Off(OUT_C); //右に曲がる
#define turn_left2 set_power_H; OnRev(OUT_A); OnFwd(OUT_C); //左に旋回
#define turn_right2 set_power_H; OnFwd(OUT_A); OnRev(OUT_C); //右に旋回
#define STEP 1
#define nMAX 4
#define short_break Off(OUT_AC); Wait(100);
#define CROSS_TIME 30 //交差点を曲がる際に進む時間
#define cross_line  set_power_L; OnFwd(OUT_AC); Wait(CROSS_TIME); short_break; //交差点を曲がる動作
#define time1 1000
#define time2 500
#define time3 2000
task main() {
 SetSensor(SENSOR_1,SENSOR_LIGHT);
 SetSensor(SENSOR_2,SENSOR_TOUCH); 
 int nOnline=0;
 int nCloss=0; //交差点を曲がった数
 ClearTimer(0);
 if(SENSOR_2 == 0) {
     OnRev(OUT_B);
    }
while(FastTimer(0) <= time1){
     if(SENSOR_2 == 1){
       OnFwd(OUT_B);
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }
                             PlaySound(SOUND_LOW_BEEP);
   while(nCloss <= 0) {
      while(nOnline < nMAX){
         if(SENSOR_1 < BLACK1) {  
       turn_right2;
	  nOnline++;
         } else {
            if (SENSOR_1 < BLACK2) {
	  turn_right1;
            } else if (SENSOR_1 < WHITE1) {
	   go_fwd;
            } else if (SENSOR_1 < WHITE2) {
	   turn_left1;
            } else {	   
         turn_left2;
            }
      nOnline=0;
        }
         Wait(STEP);  
      }
     PlaySound(SOUND_UP);
     short_break;
     turn_left1; Wait(nMAX*STEP);
     cross_line;
     nCloss++;
     nOnline=0;
    }
  } //一度交差点を曲がったら輪の内側での交差点誤認識を防ぐためしばらくライントレースのみ
ClearTimer(0); //ここでタイマーをリセットして時間のズレを減らしたい
                             PlaySound(SOUND_LOW_BEEP); 
  while(FastTimer(0) <= time2){
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }
                             PlaySound(SOUND_LOW_BEEP);
while((nCloss > 0)&&(nCloss <= 4)) {
      while(nOnline < nMAX){
         if(SENSOR_1 < BLACK1) {  
       turn_right2;
	  nOnline++;
         } else {
            if (SENSOR_1 < BLACK2) {
	  turn_right1;
            } else if (SENSOR_1 < WHITE1) {
	   go_fwd;
            } else if (SENSOR_1 < WHITE2) {
	   turn_left1;
            } else {	   
         turn_left2;
            }
      nOnline=0;
        }
         Wait(STEP);  
      }
     PlaySound(SOUND_UP);
     short_break;
     turn_left1; Wait(nMAX*STEP);
     cross_line;
     nCloss++;
     nOnline=0;
    }
  } //ここからは交差点を曲がる必要がないのでライントレースに戻す
ClearTimer(0);////ここでタイマーをリセットして時間のズレを減らしたい
                             PlaySound(SOUND_LOW_BEEP); 
while(FastTimer(0) <= time3){
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }// 缶をおくところまで時間で指定
                             PlaySound(SOUND_LOW_BEEP);
 Off(OUT_AC);   //缶を置く動作
 Wait(100);
 OnFwd(OUT_A);
 OnRev(OUT_C);
 Wait(150);
 Off(OUT_AC);
 OnRev(OUT_B);
 OnRev(OUT_AC);
 Wait(200);
 OnFwd(OUT_A);
 OnRev(OUT_C);
 Wait(150);
                             PlaySound(SOUND_LOW_BEEP);
  while(true){   //ここからゴールまでは交差点なしのライントレース
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }
}

定義

明るさのしきい値

#define BLACK1 38 //最も黒い部分のしきい値
#define BLACK2 42 //そこそこ黒い部分のしきい値 
#define WHITE1 45 //そこそこ白い部分のしきい値
#define WHITE2 49 //最も白い部分のしきい値

一番にはしきい値を定義します。
動かす場所によって明るさは変わってしまうため場所ごとに設定しなおさなければいけません。

パワーの定義

#define HIPOWER 7
#define LOWPOWER 1
#define set_power_H SetPower(OUT_AC,HIPOWER);
#define set_power_L SetPower(OUT_AC,LOWPOWER);

次にモーターを回すパワーの値を定義します。
これを変えることでロボットの進むスピードを変えられるので便利です。

よく使う動きを定義

#define go_fwd set_power_H; OnFwd(OUT_AC);
#define turn_left1 set_power_L; Off(OUT_A); OnFwd(OUT_C); //左に曲がる
#define turn_right1 set_power_L; OnFwd(OUT_A); Off(OUT_C); //右に曲がる
#define turn_left2 set_power_H; OnRev(OUT_A); OnFwd(OUT_C); //左に旋回
#define turn_right2 set_power_H; OnFwd(OUT_A); OnRev(OUT_C); //右に旋回

次にはよく使う動作をすぐに使えるようにまとめて一つのコマンドと定義します。
ライントレースでは回転の動きをよく使うのでこの回転の動作を定義しました。

交差点の定義

#define STEP 1
#define nMAX 4
#define short_break Off(OUT_AC); Wait(100);
#define CROSS_TIME 30 //交差点を曲がる際に進む時間
#define cross_line  set_power_L; OnFwd(OUT_AC); Wait(CROSS_TIME); short_break; //交差点を曲がる動作

次に交差点を渡る際の移動時間、回転時間などを定義します。
これを失敗すると交差点を誤認識したり渡りきらなかったりするので注意が必要です。

時間の定義

#define time1 1000
#define time2 500
#define time3 2000

最後に時間を使って命令を変える際の時間を定義します。
電池の消耗によって進む時間が毎回変わってしますのでここが一番苦労しました。

スタートから第一の交差点まで

task main() {
 SetSensor(SENSOR_1,SENSOR_LIGHT);
 SetSensor(SENSOR_2,SENSOR_TOUCH); 
 int nOnline=0;
 int nCloss=0; //交差点を曲がった数
 ClearTimer(0);
 if(SENSOR_2 == 0) {
     OnRev(OUT_B);
    }
while(FastTimer(0) <= time1){
     if(SENSOR_2 == 1){
       OnFwd(OUT_B);
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }
                             PlaySound(SOUND_LOW_BEEP);
   while(nCloss <= 0) {
      while(nOnline < nMAX){
         if(SENSOR_1 < BLACK1) {  
       turn_right2;
	  nOnline++;
         } else {
            if (SENSOR_1 < BLACK2) {
	  turn_right1;
            } else if (SENSOR_1 < WHITE1) {
	   go_fwd;
            } else if (SENSOR_1 < WHITE2) {
	   turn_left1;
            } else {	   
         turn_left2;
            }
      nOnline=0;
        }
         Wait(STEP);  
      }
     PlaySound(SOUND_UP);
     short_break;
     turn_left1; Wait(nMAX*STEP);
     cross_line;
     nCloss++;
     nOnline=0;
    }
  }

まず、スタートしてから数秒間は交差点を認識しないただのライントレースを行います。
これは急な角を曲がるときに何らかのトラブルで交差点と判断して逆走しないためです。
ここからある時間が過ぎると交差点を認識するライントレースへと切り替わります。
この切り替える時間が難しく、交差点直前の急カーブを交差点と誤認識してしまうトラブルが多発しました。

mission1-1.jpg

第一の交差点から第二の交差点へ

ClearTimer(0); 
                             PlaySound(SOUND_LOW_BEEP); 
  while(FastTimer(0) <= time2){
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }
                             PlaySound(SOUND_LOW_BEEP);

まずは第一の交差点を渡った瞬間にタイマーを一度リセットします。
これによってスタートから計り続けるよりも誤差が格段に減ります。
第一の交差点を渡ってからしばらくの間は交差点を判断しないただのライントレースに戻します。
これは円の内側を進むときに交差点を判断するままにしておくと交差点の誤認識を繰り返してしまうからです。
よってそれを防ぐために第一の交差点からほぼ直線の場所まで時間指定でライントレースをします。
この時間がまたシビアで、交差点の誤認識が相次ぎ苦労しました。

mission1-2.jpg
mission1-3.jpg

第二の交差点から最後の交差点まで

while((nCloss > 0)&&(nCloss <= 4)) {
      while(nOnline < nMAX){
         if(SENSOR_1 < BLACK1) {  
       turn_right2;
	  nOnline++;
         } else {
            if (SENSOR_1 < BLACK2) {
	  turn_right1;
            } else if (SENSOR_1 < WHITE1) {
	   go_fwd;
            } else if (SENSOR_1 < WHITE2) {
	   turn_left1;
            } else {	   
         turn_left2;
            }
      nOnline=0;
        }
         Wait(STEP);  
      }
     PlaySound(SOUND_UP);
     short_break;
     turn_left1; Wait(nMAX*STEP);
     cross_line;
     nCloss++;
     nOnline=0;
    }
  }

第二の交差点からは円の外側を常に走ることになるので交差点有のライントレースで最後の交差点まで進むことができます。
時間指定を使うことがないのでここはスムーズに行けました。

mission1-4.jpg

最後の交差点から缶を缶を置く場所まで

ClearTimer(0);
                  PlaySound(SOUND_LOW_BEEP); 
while(FastTimer(0) <= time3){
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }

ここからはかなり長めの時間指定ライントレースです。
ここからは交差点を曲がる必要がないので通常のライントレースに戻しました。
ここでの誤差が一番激しく、缶を置く位置がいつもずれてしまいました。

mission1-5.jpg

缶を置く動作からゴールまで

 Off(OUT_AC);   
 Wait(100);
 OnFwd(OUT_A);
 OnRev(OUT_C);
 Wait(150);
 Off(OUT_AC);
 OnRev(OUT_B);
 OnRev(OUT_AC);
 Wait(200);
 OnFwd(OUT_A);
 OnRev(OUT_C);
 Wait(150);
                             PlaySound(SOUND_LOW_BEEP);
  while(true){   //ここからゴールまでは交差点なしのライントレース
     } if(SENSOR_1 < BLACK1) {
       turn_right2;
     } else if (SENSOR_1 < BLACK2) {
       turn_right1;
     } else if (SENSOR_1 < WHITE1) {
       go_fwd;
     } else if (SENSOR_1 < WHITE2) {
       turn_left1;
     } else {
	turn_left2;
	}
     Wait(STEP);
   }
}

缶を置くのは「180度回転する→はさみを離す→そのままバックする→180度回転する」といういたってシンプルな命令です。
180度ピッタリに回転するのはなかなか難しく、最後までうまくいきませんでした。
缶を置いてからは通常のライントレースでゴールします。

mission1-6.jpg

苦労した点

  • 輪の内側を走る際に交差点と認識して一回転してしまうので、それを改善する方法を考えるのが大変だった。
  • 缶が軽いのでタッチセンサーがなかなか反応しなかった。
  • 時間を計るときに、バッテリーの残量によって速さが変わってしまうのでちょうどいい時間を見つけられなかった。

感想

履修当初に想像していたよりもずっと大変で驚きました。
チームで集まろうとしてもなかなか予定が合わずにしっかりと時間が取れなかったのが残念です。
課題2ではうまくできるように頑張りたいと思います。


添付ファイル: filemission1-6.jpg 164件 [詳細] filemission1-5.jpg 172件 [詳細] filemission1-4.jpg 170件 [詳細] filemission1-3.jpg 510件 [詳細] filemission1-2.jpg 188件 [詳細] filemission1-1.jpg 176件 [詳細] filezentai.jpeg 174件 [詳細] filesyatai.jpeg 178件 [詳細] filesensor.jpeg 172件 [詳細] filehasami.jpeg 182件 [詳細] filerobo1.jpg 179件 [詳細]

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