[[2013b/Member]]
* 課題 [#i79f88be]
#contents

* 課題 [#fdfbf5f1]
http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2013b%2FMission2&openfile=robocon2013b.png

「基本ルール」
-競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
-図の左下の隅からスタートする。ロボットが紙からはみ出ない範囲で可能な限りに隅に配置する。
-空き缶を集めて図の「ゴール」と書かれた円弧と直線で囲まれる領域に空き缶を運ぶ
-なるべく高く空き缶を積み上げる
-運び終わった後、あるいは積み上げた後はロボットはゴールの領域から外に出ること。また空き缶と接触していたはいけない。
-開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
-競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
-途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。

「基本得点の計算方法 (片道)」
-n段目の空き缶の点数を5n点とし、すべての空き缶の点数を合計する。
-例:7本の空き缶を3段と4段に分けて積んだ場合: (5+10+15)+(5+10+15+20)=80点

「技術点の計算方法」
以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。 

得点の目安:
-空き缶を取りにいくまでの動作 (2点)
-空き缶を掴む動作 (4点)
-空き缶をを運ぶ動作(2点)
-空き缶を積み上げる動作(5点)
-2台のRCXまたはNXTの連携の良さ(3点)
-自立型のロボットとしての形や動作の美しさ、斬新さ(2点)
-その他 (2点)
* ロボットの説明 [#ke93d7b5]
#ref(./DCIM0264.JPG,362x640,図1)
結局車体が重すぎて急カーブができないことがわかったが、下を向いている光センサはその名残である。
#ref(./DCIM0260.JPG,362x640,図2)
ディファレンシャルギアも、ライントレースのときの車体の無理な動きに対応できるように取り付けた。
#ref(./1391616426969.jpg,640x360,図3)
缶は光センサで検知してつかみ、持ち上げる。結局缶を積み上げることはできなかったが、つかんで持ち上げる機構自体は優秀で、手で缶を光センサのところまで持っていくと、4段まで積むことができた。5段目は、缶の重みで腕が缶の高さまで上がらず、積み上げられなかった。
#ref(./1391616493383.jpg,640x360,図4)
#ref(./1391616505104.jpg,640x360,図5)
缶を確実に捉えられるように、8班のような地面に接地した触覚をつければよかったかもしれない。缶を置くと、その合図にメトロイドのメロディーが流れる。
* プログラム [#k3df3af7]
あくまで、予定であった理想のプログラムであり、本番はこのようにうまくはいかなかった。


ライントレース側のプログラム
 #define OPEN 1
 #define GO 2
 #define PUT 3
 #define BACK 4
 #define THERESHOLD 47
 #define HIPOWER 3
 #define LOWPOWER 2
 #define set_power_H SetPower(OUT_AC,HIPOWER);
 #define THERESHOLD 47 // 閾値
 #define HIGHPOWER 3 // 直進用パワー
 #define LOWPOWER 2 // カーブ用パワー
 #define set_power_H SetPower(OUT_AC,HIGHPOWER);
 #define set_power_L SetPower(OUT_AC,LOWPOWER);
 #define go_forward set_power_H; OnRev(OUT_AC);
 #define turn_left1 set_power_L;\
   OnFwd(OUT_A); OnRev(OUT_C);
 #define turn_left0 set_power_L;\
   OnRev(OUT_C); Off(OUT_A);
 #define turn_right0 set_power_L;\
   OnRev(OUT_A); Off(OUT_C);
 #define turn_right1 set_power_L;\
   OnFwd(OUT_C); OnRev(OUT_A);
 #define go_forward set_power_H; OnRev(OUT_AC); // 直進
 #define turn_left1 set_power_L; OnFwd(OUT_A); OnRev(OUT_C); // 左旋回
 #define turn_left0 set_power_L; OnRev(OUT_C); Off(OUT_A); // 左折
 #define turn_right0 set_power_L; OnRev(OUT_A); Off(OUT_C); // 右折
 #define turn_right1 set_power_L; OnFwd(OUT_C); OnRev(OUT_A); // 右旋回
 #define STEP 1
 #define nMAX 35
 #define short_break Off(OUT_AC); Wait(100);
 #define cross_line go_forward set_power_H;\
   OnFwd(OUT_AC); Wait(20); short_break;
 
 
 
 #define nMAX 35 // 通常のカーブとみなす時間の上限
 #define short_break Off(OUT_AC); Wait(100); // 小休止
 #define cross_line go_forward set_power_H; OnFwd(OUT_AC); Wait(20); short_break; // 交差点通過 
 task main()
 {
   SetSensor(SENSOR_1,SENSOR_LIGHT);
   SetSensor(SENSOR_3,SENSOR_LIGHT);
   int nOnline=0; 
  SetSensor(SENSOR_1,SENSOR_LIGHT);
  SetSensor(SENSOR_3,SENSOR_LIGHT);
  int nOnline=0;         
 
  ClearTimer(1);
 
   ClearTimer(1);
 
   while (FastTimer(1) <= 500) {
     go_forward;
     if (SENSOR_3 > 48) {
     SendMessage(OPEN);
     Off(OUT_AC);
    }
     until (Message() == GO);
     go_forward;
  while (FastTimer(1) <= 500) {
    go_forward;                 // 最初の缶へは直進で向かう
    if (SENSOR_3 > 48) {     // 缶を発見 
    SendMessage(OPEN);      // アームを動かすように指示
    Off(OUT_AC);
   }
    until (Message() == GO);   // アームの動作が終了したら
    go_forward;         // 再び直進
  }
 
   ClearTimer(0);
  ClearTimer(0);
 
 
   while (true) {
       if (SENSOR_1 < THERESHOLD -4) {
       turn_right1;
       } else {
         if (SENSOR_1 < THERESHOLD -2) {
           turn_right0;
       } else if (SENSOR_1 < THERESHOLD +2) {
           go_forward;
       } else if (SENSOR_1 < THERESHOLD +4) {
           turn_left0;
       } else {
          turn_left1;
       }
     if (SENSOR_3 > 48) {
    SendMessage(OPEN);
  while (true) {
    while (FastTimer(0) < nMAX) {  
      if (SENSOR_1 < THERESHOLD -4) {
        turn_right1;
        } else {
          if (SENSOR_1 < THERESHOLD -2) {
            turn_right0;
        } else if (SENSOR_1 < THERESHOLD +2) {
            go_forward;
        } else if (SENSOR_1 < THERESHOLD +4) {
            turn_left0;
        } else {
            turn_left1;
        }             // ライントレース
    ClearTimer(0);
     }
    Wait(STEP);
    }
    turn_left1; Wait(nMAX*STEP);
    cross_line;           // 交差点を判別・通過
    nOnline++;          // カウンタを進める
    PlaySound(SOUND_CLICK);
    ClearTimer(0);
   
    if (SENSOR_3 > 48) { 
    SendMessage(OPEN);       // 缶を発見
    Off(OUT_AC);
    }
 
    if (nOnline == 8) {
      OnFwd(OUT_A);
      OnRev(OUT_C);
      Wait(300);
      SendMessage(PUT);
       }
 
    until (Message() == GO);
    if (nOnline == 8) {           //交差点を8回判別したとき、ロボットは左側のコースを1周し、GOALの位置に到達(黒線の左側を走るため、右側のエリアに繋がる丁字路も交差点とみなしている。)
    OnFwd(OUT_A);
    OnRev(OUT_C);  // ロボットの向きを調整
    Wait(70);
    SendMessage(PUT);  // 缶を置くように指示
  }
 
  while (FastTimer(0) < nMAX) {
 
    until (Message() == GO);    // アームの動作が終了したら
 
  while (FastTimer(0) < nMAX) {              // ライントレース再開
    if (SENSOR_1 < THERESHOLD -4) {
      turn_right1;
      } else {
        if (SENSOR_1 < THERESHOLD -2) {
          turn_right0;
      } else if (SENSOR_1 < THERESHOLD +2) {
          go_forward;
      } else if (SENSOR_1 < THERESHOLD +4) {
          turn_left0;
      } else {
          turn_left1;
       }
      ClearTimer(0);
     }
    Wait(STEP);
    }
    turn_left1; Wait(nMAX*STEP);
    cross_line;
    cross_line;         // 交差点を判別・通過
    nOnline++;
    PlaySound(SOUND_CLICK);
    ClearTimer(0);
 
    if (SENSOR_3 > 48) {
    SendMessage(OPEN);
    if (SENSOR_3 > 48) {    // 缶を発見
    SendMessage(OPEN);     // アームを動かすように指示
    Off(OUT_AC);
    }
 
    until (Message() == BACK);
    until (Message() == BACK);  // 缶が置かれたら、少し後退して終了
    OnRev(OUT_AC);
    Wait(100);
 
    } 
 }

アーム側のプログラム
 #define OPEN 1
 #define GO 2
 #define PUT 3
 #define BACK 4
 #define PowerA SetPower(OUT_A,0);
 #define PowerB SetPower(OUT_A,7);
 #define PowerC SetPower(OUT_C,0);
 #define PowerD SetPower(OUT_C,10);
 #define PowerA SetPower(OUT_A,0);   // アームを開ける為のパワー
 #define PowerB SetPower(OUT_A,7);   // アームを閉じ、缶を掴み続ける為のパワー
 #define PowerC SetPower(OUT_C,0);   // アームを下ろすのと、アームを上で固定する為のパワー
 #define PowerD SetPower(OUT_C,10);  // アームを上げる為のパワーアームの開閉用モーターはA、昇降用モーターはCに接続。
 
 task main()
 {
  ClearMessage();
  while (true) {
    PowerC; OnFwd(OUT_C);
    until (Message() == OPEN);
    PowerA; OnRev(OUT_A); 
    PowerC; OnFwd(OUT_C);  // アームを上に固定する為、常にモーターを上に回す
    until (Message() == OPEN); // 缶を発見したら
    PowerA; OnRev(OUT_A);  // アームを開く
    Wait(40);
    PowerC; OnRev(OUT_C);
    PowerC; OnRev(OUT_C);  // アームを下ろす
    Wait(90);
    PowerB; OnFwd(OUT_A);
    PowerB; OnFwd(OUT_A);  // アームを閉じる
    Wait(40);
    PowerD; OnFwd(OUT_C);
    PowerD; OnFwd(OUT_C); // アームを上げる
    Wait(160);
    SendMessage(GO);
    PowerC; OnFwd(OUT_C);
    until (Message() == PUT);
    PowerC; OnRev(OUT_C);
    SendMessage(GO);     // ライントレースを再開するように指示
    PowerC; OnFwd(OUT_C);  // 再びアームを上に固定し続ける
    until (Message() == PUT);  // GOALに到着したら
    PowerC; OnRev(OUT_C);  // アームを下ろす
    Wait(50);
    PowerA; OnRev(OUT_A);
    PowerA; OnRev(OUT_A);  // アームを開く
    Wait(40);
    SendMessage(BACK);
    SendMessage(BACK);  // 少し後退するように指示
    }
   Wait(10); 
 }
* 苦労した点 [#a2bc6503]
ライントレースは、片方のタイヤを動かさずにもう片方のタイヤのみを動かすカーブ(turn_left(right)0)をなくし、両方のタイヤを互いの逆に回転させるカーブ(turn_left(right)1)と前進のみにすると、一応できるようになったが、これは定位置で動かなくなる恐れがあり、あまり生かせなかった。
* 反省 [#uea6120a]
ソフト面のプログラムは、班員のearthがよくやってくれた。ハードのロボットがきちんと組み立てば、彼のプログラムはきちんと役に立ったはずだ。それだけに、ライントレースが常にできるぐらいに軽いロボットが作れなかったのは非常に悔しい。授業ではプログラムのことしか教わることができないので、レゴの組み立てに関することは勉強不足になってしまったかもしれない。



トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS