*課題とルール [#icc3e4e6]

http://yakushi.shinshu-u.ac.jp/robotics/?plugin=ref&page=2013a%2FMission2&src=robocon2013a.png

基本ルール
-競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
-書き足した直線部からスタートする。
-図の上部からスタートしたロボットAがピンポン玉を取りにいく
-直線部までピンポン玉を持ってくる (1)
-直線部に入ってからロボットBへパスを送る (2)
-ロボットBは直線部でパスを受け取る
-ロボットBは直線部でパスを送る (3)
-ロボットAは直線部でパスを受けとる
-ロボットAは直線部でパスを送る (4)
-ロボットBは直線部でパスを受け取る(5)
-ロボットBがゴールの空き缶の近くまでピンポン玉を運んで空き缶に当てる (5) (ただし黒い線で囲まれた空き缶の領域には入ってはいけない)
-ロボットBはシュートをした後もう一つのピンポン玉を取りにいく
-以後は、これまでのAとBの役割を反対にして、パスを繰り返し、最終的にはロボットAがもう一つのゴールにシュートする。
-開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
-競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
-途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。

-基本得点の計算方法 (片道)
-ボールをつかむ ・・・ 5点
-(2)のパスが通る ・・・ 5点
-(3)のパスが通る ・・・ 10点
-(4)のパスが通る ・・・ 5点
-(5)でシュートをする ・・・ 5点
-シュートが空き缶に当たる ・・・ 10点
-;反対方向も同じ
-技術点の計算方法以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。
-得点の目安: 
-ピンポン玉を取りにいくまでの動作 (3点)
-ピンポン玉を運ぶ動作(2点)
-ピンポン玉をパスする動作(3点)
-ピンポン玉を受ける動作(3点)
-2台以上のロボットの連携の良さ(3点)
-自立型のロボットとしての形や動作の美しさ、斬新さ(3点)
-その他 (3点)



*ロボットの紹介 [#fda08ed8]

-今回作ったロボットはパスとキャッチを一つの機構で出来るように回転できるアームとした。


-下図のようにオレンジ色の向きのアームが回転する事により転がってきたボールをキャッチして、青色の向きに回転する事によりボールを打ってパスする。

&ref(2013a/Member/free/Mission2/16.jpg,640×480);

-最初にアームを作った際に、アームがボールに引っかかってしまったので、図の赤丸の部分に出っ張りを付けてボールが奥まで転がらないようにした。

&ref(2013a/Member/free/Mission2/15.jpg,640×480,写真1);

-さらに、緑で囲った部分のように先を広げることにより、横に逸れてしまったパスが来ても対応できるようにした。

&ref(2013a/Member/free/Mission2/17.jpg,640×480);

-アームの打つ部分にはタイヤを用いた。

-必要な部分のみを付けたため、他の班よりも小型の車体にすることができた。

-しかしモーターを前に出したために、前が重くなってしまいバランスがあまり良くない事が欠点でもある。

-以降、プログラムの説明で下図の赤線部を「ルート1」。青線部を「ルート2」とする。

&ref(2013a/Member/free/Mission2/20.png,621×477);

-㊟本来往復しなければならないが今回は都合上、片道分のプログラムのみである。



*ルート1のプログラム [#yd3f9353]

 #define BLACK_01 27
 #define BLACK_02 35
 #define WHITE_01 50
 #define WHITE_02 60
 #define SPEED 30
 #define go_forward OnFwd(OUT_AC,SPEED); //前進
 #define turn_right OnRev(OUT_A,SPEED);OnFwd(OUT_C,SPEED); //急右折
 #define turn_left OnFwd(OUT_A,SPEED);OnRev(OUT_C,SPEED); //急左折
 #define right Off(OUT_A);OnFwd(OUT_C,SPEED); //右折
 #define left OnFwd(OUT_A,SPEED);Off(OUT_C); //左折
 #define STEP 1
 #define CENTER 45
 #define CCC 14000
 #define SPEED_H 45
 #define SPEED_L 25
 #define turn_R Off(OUT_A); OnFwd(OUT_C,SPEED_L);
 #define turn_L Off(OUT_C); OnFwd(OUT_A,SPEED_L);
 #define turn_SR OnRev(OUT_A,SPEED_L); OnFwd(OUT_C,SPEED_L);
 #define turn_SL OnRev(OUT_C,SPEED_L); OnFwd(OUT_A,SPEED_L);
 #define go_F OnFwd(OUT_AC,SPEED_H);
 #define nMAX 250
 #define short_break Off(OUT_AC);Wait(400);
 #define CROSS_TIME 400
 #define cross_line OnFwd(OUT_A,SPEED_L);OnFwd(OUT_C,SPEED_L);Wait(CROSS_TIME);short_break;
 #define cross OnFwd(OUT_C,SPEED_L);OnFwd(OUT_A,SPEED_L);Wait(CROSS_TIME+200);short_break;
 #define go_b OnFwd(OUT_A,-40);OnFwd(OUT_C,-40);
 #define catch OnFwd(OUT_B,33);Wait(600);Off(OUT_B);
 #define throw OnRev(OUT_B,80);Wait(1000);Off(OUT_B);
///////////////////////////////////////////////////////////////////left////////////////////////////////////////////////////////////////////

 sub right_n()  // 線の右側をライントレースするサブルーチン
 {	
	if (SENSOR_1<BLACK_01) {turn_left;}
	else if (SENSOR_1<BLACK_02) {left;}
	else if (SENSOR_1<WHITE_01) {go_forward;}
	else if (SENSOR_1<WHITE_02) {right;}
	else {turn_right;}Wait(STEP);
 }
//////////////////////////////////////////////////////////////////cross_L//////////////////////////////////////////////////////////////

 sub trace_R( // 線の右側をライントレースするサブルーチン(交差点判断あり)
 {
 int n;
 while(true){
 while(n < nMAX){ //交差点判断
	if(SENSOR_1 < CENTER-12) {
	     turn_SL;
	n++;
	} else {
	if(SENSOR_1 < CENTER-6) {
	     turn_L;
	} else if(SENSOR_1 < CENTER+6) {
	     go_F;
	} else if(SENSOR_1 < CENTER+12) {
	     turn_SL			turn_R;
	} else {
	     turn_SR; }
	n=0;    }
	Wait(STEP); }
	short_break; //交差点と判断した場合次の動作を行う
	turn_SR;Wait(nMAX*STEP*2);
	cross;
	n=0;
	break;
	}
 }

 sub trace_L() // 線の左側をライントレースするサブルーチン(交差点判断あり)
 {
	int n = 0;
 while(true) {
	while(n < nMAX) { //交差点判断
	if(SENSOR_1 < CENTER-12) {
	    turn_SR;
	n++; } 
 else {
	if(SENSOR_1 < CENTER-6) {
	    turn_R;
 } else if(SENSOR_1 < CENTER+6) {
	    go_F;
 } else if(SENSOR_1 < CENTER+12) {
	    turn_L;
	} else {
	    turn_SL;  }
	n=0;  }
 Wait(STEP); }
 short_break;
 turn_SL;Wait(nMAX*STEP); //交差点と判断した場合に回転する。
	cross;
		n=0;
		break;
	}
  }

///////////////////////////////////////////////////////////////////right//////////////////////////////////////////////////////////////////
 
 sub left_n() //線の左をライントレースするサブルーチン
 {
	if (SENSOR_1<BLACK_01) {
		turn_right;
	}
	else if (SENSOR_1<BLACK_02) {
		right;
	}
	else if (SENSOR_1<WHITE_01) {
		go_forward;
	}
	else if (SENSOR_1<WHITE_02) {
		left;
	}
	else {
		turn_left;
	}
	Wait(STEP);
 }
///////////////////////////////////////////////////////////////////main/////////////////////////////////////////////////////////////////

 task main()
 {
	SetSensorLight(S1);
	SetSensorLight(S2);
	long timess  = 0;
	/////////////////////////////start///////////////////////////////////

	trace_L(); //ライントレース
	Wait(1000);
	go_b; //後退
	Wait(950);
	turn_SL; //回転して球の方向を向く
	Wait(800);
	PlaySound(SOUND_CLICK);//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ブザー1
	go_F; //
	Wait(550);
	go_F;
	catch; //前進後ボールを掴む
	while(SENSOR_1 >  CENTER+8 )// 線の濃さが53を超えるまで
	{
		Wait(STEP);
	}
	PlaySound(SOUND_CLICK);//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ブザー2
	Off(OUT_AC);
	/////////////////////////////ボールキャッチ後///////////////////////////////
	go_F;
	Wait(90);
	turn_SR; //回転する
	Wait(750);
	PlaySound(SOUND_CLICK);//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ブザー3
	////////////////////////////////////////////////////////////////////////////////
	
	//RotateMotor(OUT_C,70,1040);
	//go_F;
	//Wait(150);
	
	Wait(1000);
	
	//
	//Wait(100);
	trace_R(); //線の右側をライントレース
	turn_SR; //曲がる事により線の左側へ移動する
	Wait(700);
	
	
	
	
	
	trace_L();//左側トレース
	Wait(1000);
	PlaySound(SOUND_CLICK);
	PlaySound(SOUND_CLICK);
	
	//////////////////////////////二回目の交差点終了////////////////////////////////
	
	//trace_L();
	
	
	三回目の交差点認識(ちなみにここはボールを初めて投げる地点)


&ref(2013a/Member/free/Mission2/22.png,621×477);


-今回は球を斜めには打たずに、直角に回転して直線上にロボットを置いて、上図の赤線のようにパスをしあう。



	go_b;
	Wait(800);
	
	
	Off(OUT_AC);
	Wait(100);
	RotateMotor(OUT_A,-70,410); //90度回転してもう一体の方向を向く
	throw;
	RotateMotor(OUT_A,70,470); //もう一度90度回転してもとの向きに戻る
	go_F;
	Wait(200);
	///////////////////////////////////一回目の発射/////////////////////////////////(向き直っている)
	//turn_SR;
	//Wait(500);
	timess  =  CurrentTick();
	while(CurrentTick() - timess < 4000) { //4秒まで下の動作を行う
		 left_n();線の左をライントレース
	}
	Off(OUT_AC); //4秒経ったら一度モーターを止める。
	Wait(2000);
	RotateMotor(OUT_A,-70,440); //再び90度回転
	Off(OUT_AC);
	Wait(10000); //この10秒の待機は相手が投げ終わるのを待つ10秒
	catch;
	catch;
	RotateMotor(OUT_A,70,440);
	//
	go_F;再び前進して投げる位置まで移動
	Wait(1700);
	timess  =  CurrentTick();
	Off(OUT_AC);
	RotateMotor(OUT_A,-70,460); //90度回転してから投げる
	Wait(2000);
	throw;
	//RotateMotor(OUT_C,70,410);
	


*ルート2のプログラム [#lecfc261]


-ルート2では複数人でプログラムを作り、合わせたためにサブルーチンでプログラムが違うが命令内容が同じであるものが発生してしまった。(例:線の左をトレースするサブルーチンetc)

 #define BLACK_01 27
 #define BLACK_02 35
 #define WHITE_01 50
 #define WHITE_02 58
 #define SPEED 38
 #define SPEED_H 50
 #define SPEED_L 30
 #define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_C,speedL);
 #define go_forward OnRL(SPEED,SPEED);
 #define turn_right OnRev(OUT_C,SPEED);OnFwd(OUT_A,SPEED);
 #define turn_left OnFwd(OUT_C,SPEED);OnRev(OUT_A,SPEED);
 #define right Off(OUT_C);OnFwd(OUT_A,SPEED);
 #define left OnFwd(OUT_C,SPEED);Off(OUT_A);
 #define go_forward OnRL(SPEED,SPEED);前進
 #define turn_right OnRev(OUT_C,SPEED);OnFwd(OUT_A,SPEED);急右折
 #define turn_left OnFwd(OUT_C,SPEED);OnRev(OUT_A,SPEED);急左折
 #define right Off(OUT_C);OnFwd(OUT_A,SPEED);右折
 #define left OnFwd(OUT_C,SPEED);Off(OUT_A);左折
 #define STEP 1
 #define MOVE_TIME 8000
 #define shoot OnRev(OUT_B,95);Wait(700);
 #define shoot OnRev(OUT_B,95);Wait(700);ボールを打つ

 #define go_b OnFwd(OUT_A,-50);OnFwd(OUT_C,-50);
 #define go_F OnFwd(OUT_AC,SPEED_H);
 #define turn_R Off(OUT_A); OnFwd(OUT_C,SPEED_L);
 #define turn_L Off(OUT_C); OnFwd(OUT_A,SPEED_L);
 #define turn_SL OnRev(OUT_C,SPEED_L); OnFwd(OUT_A,SPEED_L);
 #define turn_SR OnRev(OUT_A,SPEED_L); OnFwd(OUT_C,SPEED_L);
 #define catch OnFwd(OUT_B,33);Wait(600);Off(OUT_B);
 #define go_b OnFwd(OUT_A,-50);OnFwd(OUT_C,-50);後退
 #define go_F OnFwd(OUT_AC,SPEED_H);前進
 #define turn_R Off(OUT_A); OnFwd(OUT_C,SPEED_L);右折
 #define turn_L Off(OUT_C); OnFwd(OUT_A,SPEED_L);左折
 #define turn_SL OnRev(OUT_C,SPEED_L); OnFwd(OUT_A,SPEED_L);急左折
 #define turn_SR OnRev(OUT_A,SPEED_L); OnFwd(OUT_C,SPEED_L);急右折
 #define catch OnFwd(OUT_B,33);Wait(600);Off(OUT_B);ボールをとる
 #define nMAX 200
 #define CENTER 45
 #define CENTER 45;線の中心の濃さ
 #define short_break Off(OUT_AC);Wait(400);
 #define cross OnFwd(OUT_C,SPEED_L);OnFwd(OUT_A,SPEED_L);Wait(CROSS_TIME+200);short_break;
 #define cross OnFwd(OUT_C,SPEED_L);OnFwd(OUT_A,SPEED_L);Wait(CROSS_TIME+200);short_break;交差点を渡る
 #define CROSS_TIME 400

 #define white1 39
 #define white2 45
 #define black1 55
 #define black2 63
 #define turn_left1 OnFwd(OUT_C,40);Off(OUT_A)
 #define turn_left2 OnFwd(OUT_C,40);OnRev(OUT_A,30)
 #define turn_right1 OnFwd(OUT_A,40);Off(OUT_C)
 #define turn_right2 OnFwd(OUT_A,40);OnRev(OUT_C,20)
 #define turn_left1 OnFwd(OUT_C,40);Off(OUT_A)左折
 #define turn_left2 OnFwd(OUT_C,40);OnRev(OUT_A,30)急左折
 #define turn_right1 OnFwd(OUT_A,40);Off(OUT_C)右折
 #define turn_right2 OnFwd(OUT_A,40);OnRev(OUT_C,20)急右折

 #define CCC 14000
 #define cross_line OnFwd(OUT_A,SPEED_L);OnFwd(OUT_C,SPEED_L);Wait (CROSS_TIME);short_break;
 #define go_R OnFwd(OUT_A,SPEED_H);OnFwd(OUT_C,SPEED_L+10);
 #define mMAX 5


 sub trace_L() //線の左側のトレース(交差点判断あり)するサブルーチン
 {
    int n;
    while(true) {
      while(n < nMAX) {
        if(SENSOR_1 < CENTER-12) 
                 {turn_SR;n++;}
        else {
          if(SENSOR_1 < CENTER-6) 
                 {turn_R;}
          else if(SENSOR_1 < CENTER+6) 
                 {go_forward;}
          else if(SENSOR_1 < CENTER+12) 
                 {turn_L;}
          else 
                 {turn_SL;}
          n=0;
        }
        Wait(STEP);
      }
    short_break;
    turn_SL;Wait(nMAX*STEP);
    cross;
    n=0;
    break;
    }
 }


 sub trace_L_n() //線の左側をトレースするサブルーチン
 {
    if (SENSOR_1<BLACK_01) 
                  {turn_left;}
      else {
        if (SENSOR_1<BLACK_02) 
                  {left;}
        else if (SENSOR_1<WHITE_01) 
                  {go_forward;}
        else if (SENSOR_1<WHITE_02) 
                  {right;}
        else 
                  {turn_right;}
          }
        Wait(STEP); 
 }

 sub right_n() //線の右側をライントレースするサブルーチン
 {	
	if (SENSOR_1<BLACK_01) 
                     {turn_left;}
	else if (SENSOR_1<BLACK_02) 
                     {left;}
	else if (SENSOR_1<WHITE_01) 
                     {go_forward;}
	else if (SENSOR_1<WHITE_02) 
                     {right;}
	else 
                  {turn_right;}
          Wait(STEP);
 }
 

 sub trace_L_m() //線の左をトレースするサブルーチン
 {
      if (SENSOR_1 < white1) {turn_left2;}
      else if (SENSOR_1 < white2) {turn_left1;}
      else if (SENSOR_1 < black1) {go_forward;}
      else if (SENSOR_1 < black2) {turn_right1;}
      else {turn_right2;}
      if (SENSOR_1 < white1) 
                       {turn_left2;}
      else if (SENSOR_1 < white2) 
                        {turn_left1;}
      else if (SENSOR_1 < black1) 
                       {go_forward;}
      else if (SENSOR_1 < black2) 
                       {turn_right1;}
      else 
                       {turn_right2;}
      Wait(STEP);
 }


 sub trace_L_a() //線の左をトレースするサブルーチン
 {
    int n;
    if(SENSOR_1 < BLACK_01){turn_left;n++;} 
    if(SENSOR_1 < BLACK_01)
                      {turn_left;n++;} 
      else {
        if(SENSOR_1 < BLACK_02) {left;n++;} 
        else if(SENSOR_1 < WHITE_01) {go_forward;}
        else if(SENSOR_1 < WHITE_02) {right;}
        else {turn_right;}
        if(SENSOR_1 < BLACK_02) 
                       {left;n++;} 
        else if(SENSOR_1 < WHITE_01) 
                      {go_forward;}
        else if(SENSOR_1 < WHITE_02) 
                       {right;}
        else 
                       {turn_right;}
        n=0;
      }
    Wait(STEP);
 }


 sub trace_R_n() //線の右側をライントレース(交差点判断あり)するサブルーチン
 {
    int n;
    if (SENSOR_1<BLACK_01) {turn_right;n++;}
    if (SENSOR_1<BLACK_01) 
                      {turn_right;n++;}
      else {
        if (SENSOR_1<BLACK_02) {right;n++;}
        else if (SENSOR_1<WHITE_01) {go_forward;}
        else if (SENSOR_1<WHITE_02) {left;}
        else {turn_left;}
        if (SENSOR_1<BLACK_02) 
                      {right;n++;}
        else if (SENSOR_1<WHITE_01) 
                      {go_forward;}
        else if (SENSOR_1<WHITE_02) 
                       {left;}
        else 
                       {turn_left;}
        n=0;
          }
        Wait(STEP); 
 }




 task main()
 {
    SetSensorLight(S1);
    long timess  = 0;
    int nOnline=0;
    int n=0;


 ///////1回目のキャッチまで//////

    Wait(40000);
    Wait(40000);相手がボールを拾って投げ出す直前まで待機
    long t3 = CurrentTick();
    while(CurrentTick()-t3 < 2000) {trace_R_n();}
    while(CurrentTick()-t3 < 2000);2秒経過するまで線の右側をトレース 
    {trace_R_n();}
    Off(OUT_ABC);
    Wait(1000);
    RotateMotor(OUT_C,70,430);
    RotateMotor(OUT_C,70,430);90度回転して相手の方を向く
    Off(OUT_AC);
    Wait(10000)
    OnFwd(OUT_B,33);
    Wait(10000);相手が投げてボールがアーム内に入るまで待機
    OnFwd(OUT_B,33);モーターの逆回転によりボールを挟む
    Wait(600);
    Off(OUT_B);
    Wait(2000);
    RotateMotor(OUT_A,-70,430);Off(OUT_ABC);Wait(500);
    RotateMotor(OUT_A,-70,430);Off(OUT_ABC);Wait(500);再び90度回転
    go_R;Wait(800);
    Off(OUT_ABC);Wait(500);

 ///////1回目のパスまで////////

    PlaySound(SOUND_CLICK);
    long t2 = CurrentTick();
    while(CurrentTick()-t2 <= 1700){right_n();}
    while(CurrentTick()-t2 <= 1700)1.7秒経過するまで線の右側をトレース
    {right_n();}
    PlaySound(SOUND_CLICK);
    Off(OUT_ABC);
    Wait(1000);
    RotateMotor(OUT_A,70,430);Off(OUT_ABC);Wait(1000);
    RotateMotor(OUT_A,70,430);Off(OUT_ABC);Wait(1000);90度回転して相手に球を投げる
    shoot;

 /////////2回目のキャッチまで////////

    PlaySound(SOUND_CLICK);
    Off(OUT_ABC);
    long t1 = CurrentTick();
    RotateMotor(OUT_A,-70,430);Off(OUT_ABC);Wait(500);
    while (CurrentTick()-t1 <= 4800) {trace_L_n();}
    RotateMotor(OUT_A,-70,430);90度回転してもとの向きに戻る
    Off(OUT_ABC);Wait(500);
    while (CurrentTick()-t1 <= 4800) 4.8秒経つまで線の左側をトレース
    {trace_L_n();}
    PlaySound(SOUND_CLICK);
    Off(OUT_ABC);Wait(1000);
    RotateMotor(OUT_A,70,430);Off(OUT_ABC);Wait(10000);
    OnFwd(OUT_B,33);Wait(700);Off(OUT_ABC);Wait(1000);
    RotateMotor(OUT_A,-70,430);
    RotateMotor(OUT_A,70,430);90度回転
    Off(OUT_ABC);Wait(10000);10秒待って相手が投げ終わるまで待つ。
    OnFwd(OUT_B,33);Wait(700);ボールをキャッチする
    Off(OUT_ABC);Wait(1000);
    RotateMotor(OUT_A,-70,430);90度回転する

 ////////シュートまで///////

    PlaySound(SOUND_CLICK);
    Off(OUT_ABC);
    Wait(1000);    
    long t0 = CurrentTick();
    while (CurrentTick()-t0 <= MOVE_TIME) {trace_L_n();}
    while (CurrentTick()-t0 <= MOVE_TIME) 8秒間線の左側をトレース
    {trace_L_n();}
    PlaySound(SOUND_CLICK);
    Off(OUT_ABC);
    Wait(1000);
    shoot;
    shoot;シュートする
    Off(OUT_ABC);
    Wait(1000);
    PlaySound(SOUND_CLICK);

 //////復路のキャッチまで/////
*感想 [#g6bd26a5]

    trace_L();
    Off(OUT_ABC);
    Wait(1000);
    go_b;
    Wait(950);
    turn_SL;
    Wait(600);
    PlaySound(SOUND_CLICK);
    go_F;
    Wait(1600);
    catch;
    Off(OUT_ABC);
    Wait(1500);
    turn_left;
    Wait(1200);
    PlaySound(SOUND_CLICK);
    Off(OUT_ABC);
    Wait(1000);
    trace_L();
    Off(OUT_ABC);
}
-今回の課題は二つのルートがあるため、二つのプログラミングが必要となりややこしかった。

-通信の機能が使えなかったため、タイマーでタイミングを合わさなければならず、電池の消費などに大きく左右されてしまい難しい事も多かった。

-ロボットは少しづつ改良していって、最終的な形となり軽量かつ正確にボールをとれるようなロボットにする事が出来た。

-ルート2のプログラムを何人かで分けてやったためすらすた進んで良かった。だが、最終的には二人に任せる形になってしまったので、もう少しみんなで分担をすればよかった。

-本番直前まで1回のパスすらままならなかったが、本番前から急に調子がよくなりパスもつながり2位という結果で終わって嬉しかった。

-最初は色々と難しい事が多かったが、最後のロボコンではすごい盛り上がりでとても良い授業であった。

-
-
-
-
-


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