[[2013b/Member]]
*ロボットについて [#e3f487db]
-課題内容を聞いてかなり屈曲したコースだっったので車幅を小さくしてロボットの移動をコンパクト化することが必要だと思った。初期の設計では車幅が大きかったので歯車を縦に並べる設計になった。それと同時に二輪になったのでカーブに強くなった。そして駆動輪が前輪になったので動きがスムーズなったと思う。
センサーについてはロボットのボディーとなるべく近づけることによってロボットの通った道を正確に伝えることが必要だと知ったので、車輪のすぐ前に取り付けられる設計になった。

*課題内容 [#w649b3fa]
-交差点をきちんと認識し、正しく判断して通過できるようにする。
-確実に一周できるようにする。スタート地点から出発して元にもどるようにする。
-空き缶を交差点から10cm以上離した線上に起き、それを一旦どけて再び元の位置にもどすように改良する。
-1個の空き缶でうまくいったら、2個の空き缶でやってみる。
&ref(2013b/Member/trtr/Mission1/IMG_1527.jpg,400*300,ロボット内部);
←ロボットの内部

+モーターを縦に取り付けて、歯車をつなぎ前輪に動力を伝えた。←スムーズに曲がるために車幅を狭くとるため。
+凸型の部品をロボットの裏に取り付けた。←ロボットや床が傷つかないようにするため。&動きがスムーズになるため。[後輪の役割]
+アームは車体のコンパクトさ故に自然とコンパクトかつ安定したももを作らなければならなかった。試行錯誤した結果今回の設計に落ち着いた。ホイールの前においたギアからアームまでの間にウォームギアを入れ回転を抑えることにより缶をゆっくりつかむことで安定性が生まれた。初期設計ではギアを2つ使う構造だったので中心から少しずれたところにアームがあったがクランク機構を使って中心の来るようにした。

*課題の難所 [#w649b3fa]
&ref(2013b/Member/trtr/Mission1/robotics-2013a-mission1_3.jpg,371*345,コース図);

-赤く丸した交差点をきちんと認識し、正しく判断して通過できるようにする。僕は右側を交差点1、左側を交差点2とした。通常のライントレースでは交差点で曲がってしまう可能性が高いので、そこでのロボットの判断を正しい方向に持っていくためのプログラムをくまなくてはならなかった。今回のプログラムではロボットに交差点だと気づかせないような騙し騙しのプログラムになってしまったが、渡りきれたので、まあ。よしとする。
-青くマークしたところのカーブは急なので、ロボットがコースを見失わないようにすることが必要。この点に関してはロボットのコンパクトさとプログラムの基準値を細かくしたことでさほど苦労せずにクリアした。
-空き缶を交差点から10cm以上離した線上に起き、それを一旦どけて再び元の位置にもどすように改良する。ロボットにこの動作をさせるのは思っていたよりも大変なことだった。人間ならつかむ強さを調整できるが、ロボットはつかむスピード、時間ででしかコントロールできない。その限られた条件で制御するには正確なプログラムを組んであげるしかないので丁寧に調節した。


*プログラミングについて [#cb56ff11]
-定数について
 #define THRESHOLD 45
 #define HP 7
 #define MP 4
 #define HP 5
 #define LP 2
 #define set_power_H SetPower(OUT_AC,HP);//両輪高速のマクロ
 #define set_power_L SetPower(OUT_AC,LP);//両輪低速のマクロ
 #define STEP 1//一回の判断で待つ時間
 #define go_fwd SetPower(OUT_AC,HP);OnFwd(OUT_AC);//前進 
 #define turn_left2 SetPower(OUT_C,HP);SetPower(OUT_A,LP);/
 OnFwd(OUT_C);OnRev(OUT_A);//左旋回
 #define turn_right2 SetPower(OUT_A,HP);SetPower(OUT_C,LP);/
 OnFwd(OUT_A);OnRev(OUT_C);//右旋回
 #define turn_left1 SetPower(OUT_C,HP);OnFwd(OUT_C);//右回り(強)
 #define turn_right1 SetPower(OUT_A,HP);OnFwd(OUT_A);//左回り(強)
 #define turn_left0 SetPower(OUT_C,LP);OnFwd(OUT_C);//左回り
 #define turn_right0 SetPower(OUT_A,LP);OnFwd(OUT_A);//右回り
 #define short_break Off(OUT_AC);Wait(200);
 #define CROSS_TIME 800//光センサが交点を横断するのに必要な時間
 #define time1 1600//スタートから交差点1まで
 #define time2 300//交差点1の始まりから終わりまで
 #define time3 500//交差点2の始まりから終わりまで
 #define time4 900//ゴールまで
 #define arm_open SetPower(OUT_B,LP);OnRev(OUT_B);Wait(50);Off(OUT_B);//アームを開く
 #define arm_close SetPower(OUT_B,LP);OnFwd(OUT_B);Wait(50);Off(OUT_B);//アームを閉じる

-サブルーチンについて

缶を掴んでから旋回してから前進し元の場所に缶を置きまたライントレースを行うまでのプログラム。アームの開閉の時間が大きすぎるとアームがロボット本体にあたってしまい、小さすぎると右腕と左腕があたってしまうのでそこの調節に苦労した。
 sub can_move ()//缶を運ぶ動作
 {arm_close;go_fwd;Wait(150);turn_left2;Wait(150);arm_open;turn_right2;Wait(150);}

通常のライントレーサーをするプログラム。細かいカーブにも対応できるように5段階な分けてプログラムを組んだ。基本的にはラインとの右の境界線を走るようにした。
 sub linetracer ()//ライントレーサー
 {
       if(SENSOR_1 = 0)
       if(SENSOR_2 < THRESHOLD-7) {turn_left2}
       else if(SENSOR_2 < THRESHOLD-5) {turn_left0}
       else if(SENSOR_2 < THRESHOLD+3) {go_fwd}
       else if(SENSOR_2 < THRESHOLD+5) {turn_right0}
       else    {turn_right2}
       Wait(STEP);
        PlaySound(SOUND_UP);
 }

交差点1を進むためのプログラム。この交差点では左のラインに入りやすいことがわかったので、交差点で曲がらないように右折と直進のみにした。
 sub linecross1 ()//交差点1を渡る動作
 {  
     if(SENSOR_2 < THRESHOLD+3) {go_fwd}
     else    {turn_right2}
     Wait(STEP);
        short_break;
        PlaySound(SOUND_UP);
 }
交差点2を進むためのプログラム。交差点1と同様に交差点で曲がらないように左折と直進のみにした
 sub linecross2 ()//交差点2を渡る動作
 {
       if(SENSOR_2 < THRESHOLD-7) {turn_left2}
       else if(SENSOR_2 < THRESHOLD-5) {turn_left0}
       else if(SENSOR_2 < THRESHOLD+5) {go_fwd}
       else    {turn_right2}
       Wait(STEP);
            short_break;
            PlaySound(SOUND_DOWN);
 }

-プログラムの本体
 task main()
 {//0
  SetSensor(SENSOR_2, SENSOR_LIGHT);
  SetSensor(SENSOR_1,SENSOR_TOUCH);
  ClearTimer(0);
スタートから交差点1までは通常のライントレーサーを行う。ここまでのコースは角度が小さいカーブがあるが元のプログラムもそれに対応したものになっているため通常のライントレーサーを行う。
  while(FastTimer(0) <= time1)
    { linetracer () }
       
交差点1を進むためのプログラム。
  ClearTimer(0);
  while(FastTimer(0) <= time2)
    { linecross1 () }
交差点2を進むためのプログラム。    
  ClearTimer(0);
  while(FastTimer(0) <= time3)
    { linecross2 () }
交差点2を越えて直線に突き当たりそこで缶を処理してゴールまで進むプログラム。
  ClearTimer(0);
  While(FastTimer(0) <= time4)
     { linetracer ();
       if (SENSOR_1==1){ can_move () }
 }//0

*改訂版 [#x71602f8]
 #define THRESHOLD 45
 #define HP 5
 #define LP 2
 #define STEP 1//一回の判断で待つ時間
 #define B_COUNTER 5//黒が続く回数の基準
 #define W_COUNTER 5//白が続く回数の基準
 #define TIMER0 800//標準モードから特殊モードに切り替わるための時間
 #define go_fwd SetPower(OUT_AC,HP);OnFwd(OUT_AC);//前進
 #define back SetPower(OUT_AC,HP);OnFwd(OUT_AC);//後退
 #define turn_left2 SetPower(OUT_C,HP);SetPower(OUT_A,LP);OnFwd(OUT_C);OnRev(OUT_A);//左旋回
 #define turn_right2 SetPower(OUT_A,HP);SetPower(OUT_C,LP);OnFwd(OUT_A);OnRev(OUT_C);//右旋回
 #define turn_left0 SetPower(OUT_C,LP);OnFwd(OUT_C);//左回り
 #define turn_right0 SetPower(OUT_A,LP);OnFwd(OUT_A);//右回り
 #define short_break Off(OUT_AC);Wait(200);
 #define time1 2450//スタートから交差点1まで
 #define time2 3050//交差点1の始まりから終わりまで
 #define time3 3700//交差点2の始まりから終わりまで
 #define time4 5500//交差点2からゴールまで
 #define arm_open SetPower(OUT_B,LP);OnRev(OUT_B);Wait(50);Off(OUT_B);//アームを開く
 #define arm_close SetPower(OUT_B,LP);OnFwd(OUT_B);Wait(50);Off(OUT_B);//アームを閉じる
 #define nMAX 6//カウンターの上限

 sub crossing()//交差点を渡るサブルーチン
 {SetPower(OUT_AC,HP);OnFwd(OUT_AC);Wait(CROSS_TIME);}
 sub turn_left2()//標準左回転サブルーチン
 {SetPower(OUT_C,HP);SetPower(OUT_A,LP);OnFwd(OUT_C);OnRev(OUT_A);}
 sub turn_right2()//標準右回転サブルーチン
 {SetPower(OUT_A,HP);SetPower(OUT_C,LP);OnFwd(OUT_A);OnRev(OUT_C);}
 sub turn_left1()//標準左折サブルーチン
 {SetPower(OUT_C,HP);OnFwd(OUT_C);}
 sub turn_right1()//標準右折サブルーチン
 {SetPower(OUT_A,HP);OnFwd(OUT_A);}
 sub go_forward()//標準直進サブルーチン
 {SetPower(OUT_AC,HP);OnFwd(OUT_AC);}
 sub turn_left0()//特殊時左折サブルーチン
 {SetPower(OUT_C,LP);OnFwd(OUT_C);}
 sub turn_right0()//特殊時右折サブルーチン
 {SetPower(OUT_A,LP);OnFwd(OUT_A);}
 sub turn_left-1()//特殊時左回転サブルーチン
 {SetPower(OUT_C,MP);SetPower(OUT_A,LP);OnFwd(OUT_C);OnRev(OUT_A);}
 sub turn_right-1()//特殊時右回転サブルーチン
 {SetPower(OUT_A,MP);SetPower(OUT_C,LP);OnFwd(OUT_A);OnRev(OUT_C);}
 sub can_move ()//缶を運ぶ動作  {arm_close;go_fwd;Wait(150);turn_left2;Wait(150);arm_open;back;Wait(150)turn_right2;Wait(150);}

 sub linetracer ()//ライントレーサー
 {
       if(SENSOR_1 == 0)//タッチセンサーが触れない時
       if(SENSOR_2 < THRESHOLD-7) {turn_left2}
       else if(SENSOR_2 < THRESHOLD-5) {turn_left0}
       else if(SENSOR_2 < THRESHOLD+3) {go_fwd}
       else if(SENSOR_2 < THRESHOLD+5) {turn_right0}
       else    {turn_right2}
       Wait(STEP);
        PlaySound(DOUBLE_UP);
 }

 sub line_cross ()
  {
             int nOnline=0; //続けて黒になった回数 始めを0とする
		while (nOnline < nMAX){ //続けて黒になった回数がMAX以内
			if (SENSOR_2 < THRESHOLD -5) { turn_right0; nOnline++; }
			else 
			{ 	if (SENSOR_2 < THRESHOLD -3) {turn_right0}
				else if (SENSOR_2 < THRESHOLD +4) {go_fwd} 
				else if (SENSOR_2 < THRESHOLD +7) {turn_left0}
				else {turn_left0}
			nOnline=0//カウンタをリセット
			}
		Wait(STEP);
		}
		short_break; PlaySound(SOUND_UP);
		go_fwd;//交差点を渡る
		nOnline=0;//カウンタをリセット
  }

 task main()
 {//0
 SetSensor(SENSOR_1, SENSOR_TOUCH);
 SetSensor(SENSOR_2,SENSOR_LIGHT);
 int N=0;
 int Nbkc=0;//何回黒が続いたかを計るカウンタ(number black counter)
 int Nwhc=0;//何回白が続いたかを計るカウンタ(number white counter)
 int Ncros=0;//交差点を通った回数を数えるカウンタ(number cross)
 while(true)//カッコの後の数はそのカッコが区切る階数
  {//1
  while(SENSOR_1=0)
    {//2
    while(N=0)//標準(緩やかなカーブに対応)
      {//3
      if (SENSOR_2<THRESHOLD-8){//4
        turn_right2();
        Nwhc=0;
      }else if(SENSOR_2<THRESHOLD-3){//4
        turn_right1();
        Nwhc=0;
      }else if(SENSOR_2<THRESHOLD){//4
        go_forward();
        Nwhc=0;
      }else if(SENSOR_2<THRESHOLD+3){//4
        turn_left1();
        Nwhc=0;
      }else{//4
        turn_left2();
        Nwhc++;
         if(Nwhc>W_COUNTER){//5
          ClearTimer(0);
             }//5
        }//4
      Wait(STEP);
      }//3
 while (FastTimer(0)>TIMER0)//特殊(急なカーブにも対応)
      {//3
      N=1;
      while(Nbkc<B_COUNTER)
        {//4
        if(SENSOR_2<THRESHOLD-8){//5
          turn_right-1();
          Nbkc++;
          }else{//5
            if(SENSOR_2<THRESHOLD-3){//6
              trun_right0();
            }else if(SENSOR_2<THRESHOLD+3){//6
              turn_left0();
            }else{//6
              turn_left-1();
              }//6
          Nbkc=0;
            }//5
        Wait(STEP);
        }//4
      short_break;
      turn_left-1();
      Wait(B_COUNTER*STEP);
      crossing();
      Nbkc=0;
      Ncros++
 SetSensor(SENSOR_2, SENSOR_LIGHT);
 SetSensor(SENSOR_1,SENSOR_TOUCH);
 ClearTimer(0);
 int nOnline=0;
 while(FastTimer(0) <= time1){ linetracer (); }
 ClearTimer(0);
 while(FastTimer(0) <= time2){ linecross (); }
 ClearTimer(0);
 while(FastTimer(0) <= time3){ linecross (); }
 ClearTimer(0);
 While(FastTimer(0) <= time4){
       linetracer ();
       if (SENSOR_1==1){ can_move (); }
      }
 Float(OUT_AC);//ゆっくり止まる}//0

 if(Ncros=2){//3.5
       TIMER0= 200;//必入力
       Cleartimer0;
       N=0;
      }//3.5
      }//3 while(FastTimer(0)>TIMER0)
    }//2 while(SENSOR_1=0)
  SetPower(OUT_AC,MP);
 OnRev(OUT_AC);
 Wait(BACK_TIME);
 OnFwd(OUT_A);
 Wait(TURN_TIME1);
 SetPower(OUT_C,HP); 
 OnFwd(OUT_AC);
 Wait(TURN_TIME2);
 SetPower(OUT_A,MP);
 OnRev(OUT_C);
 Wait(TURN_TIME1);
 }//1 while(true)
 }//0 task main

*工夫した点 [#n5c580e9]
-サブルーチンや定数を使いプログラムをコンパクト化した。
-カウンターでなくタイマーを使い毎回の動作を安定化した。
-PlaySoundを使いプログラミングの区切りをわかりやすくした。
-ロボットの構造に関してはこだわったつもりだ。機能性、見た目、製作時間共に他のチームに引けを取らないと思う。

*反省点 [#h0eedaec]
-交差点についてはまだ工夫できると思う。
-カウンターをうまく使いこなせなかった。

*全体を通しての感想 [#q1a39891]
-理想的なロボットを作るには、どんな働きをさせるために、どんな設計をして、どんなプログラムをするかによって全部決まってしまう。人間のようにその場にあった動きができない。僕は今回のプログラムで何度かロボットに苛ついてしまったけれどそれは制御できない人が悪くてロボットのせいではない。したがって、設計やプログラムをどれだけ丁寧にやるかどんな知識や発想をもってやるかがとても大事だと学んだ。今回は自分の納得したものにできなかったが、次回はより工夫したロボットを作りたい。


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