~目次
#contents
*課題目的 [#ud38a814]
~今回の課題の目的は課題2で使用した紙(下の図)を使用し、ピンポン玉と紙コップを別々に回収して所定の場所に運ぶ。ただし、マジェンタの円に逆さまにした紙コップを置き、その中にピンポン玉を2つ
つ入れておく。また、黄色い円に紙コップを通常の向きに置き、障害物とする。課題の基本得点の計算方法やルールは[[課題3(ロボコン):http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMission3]]のところに見てください。
#ref(2017b/Member/tono/Mission3/課題3.png,center,85%,コース説明)
*ロボットについて [#n2f8ba4d]
#ref(2017b/Member/tono/Mission3/ロボット全体.png,center,75%,ロボット全体)
今回では2台のロボット(MasterとSlave)を作った。Masterの方はA地点からスタートし、左側の紙コップを取る目的とする。また、Slaveの方はD地点からスタートし、右側の紙コップを取る目的とする。詳しくはプログラムのところに説明する。2台のロボットは同じ構造になっているので1台だけの構造を説明する。ロボットの構造では上の図のように2つの部分(車体の部分とアームの部分)によって説明していく。
**ロボットの車体 [#hd831bef]
#ref(2017b/Member/tono/Mission3/ロボット車体.png,center,75%,ロボット車体)
上の図のようにロボットの車体の部分は課題2のように作った。詳しくは[[課題2(tono):http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Ftono%2FMission2]]のところに見てください。まず、2つモータを左側と右側に付けてタイヤ―を回す。また、LineTraceを正確に動くため光センサーをつける場所はできるだけ床に近いである。ケーブル線を邪魔にならないように車体の中にしっかり絞っていた。
**ロボットのアーム [#a28d1edc]
ロボットのアームでは今回の課題の一番重要なものである。ロボット全体のところのように1つのモータだけを使って紙コップを掴む動作や上げる動作をする。そのことは先生の指導と[[2016a/課題3(ngtrz):http://yakushi.shinshu-u.ac.jp/robotics/?2016a%2FMember%2Fngtrz%2FMission3]]のものを参考にしてロボットのアームの部分を作った。また、紙コップとピンポン玉を探し取りにいくまでの動作をできるようにアームの下で超音波センサーを付けた。
***紙コップを掴む構造・仕組み [#r76f95da]
#ref(2017b/Member/tono/Mission3/ロボットのアーム.png,center,50%,ロボットのアーム)
紙コップを掴む構造をわかりやすく説明できるため、上の図のように番号の順番に沿って説明していく。ただし、前後・左右の方向については図の右下に従う。
-1から2
~モータが前の方向に回ると隣の黒い歯車も同様にまわる。そのため、歯車灰色の歯車が右の方向に回る。
-2から3
~灰色の歯車が右の方向に回ると歯車の真ん中の穴にあるウォームギアも右の方向に回転する。
-3から4
~ウォームギアが右の方向に回転すると両隣の灰色の歯車が回転する。(左側の歯車は左へ、右側の歯車は右へ)
-4から5
#ref(2017b/Member/tono/Mission3/ロボットアームの裏.png,center,50%,ロボットアームの裏)
~この仕組みは長い黒い棒の部品を使って下の歯車に動きを伝える。上の図のように下の歯車は上の歯車に動きを使って紙コップを掴む
***紙コップを持ち上げる構造・仕組み [#i6d163b1]
#ref(2017b/Member/tono/Mission3/上げる操作.png,center,50%,上げる動作)
紙コップを掴んでから紙コップを持ち上げることを行う。上の左側の図のようにアームが完全に紙コップを掴むとモータの隣の黒い歯車(No.1)しか回らない。(No.2からNo.5の部品は回らないこと)そのため、上の右側の図のように紙コップが上げられるようになった。ただし、モータの回力が重力より大きくなければならない、そうしないと紙コップが落としてしまうからである。だから、プログラムのときこのことも考える必要がある。
***ピンポン玉を運ぶ動作 [#x45690d0]
#ref(2017b/Member/tono/Mission3/ピンポン玉運ぶ.png,center,75%,ピンポン玉運ぶ動作)
ロボットのピンポン玉を運ぶ動作は最初に部品No.1とNo.2を垂直にした。その結果、ピンポン玉を運ぶことはできたがピンポン玉を目的に入れることはできなかった。だから、部品No.1とNo.2を上の図のように斜めをするとピンポン玉を目的に入れることはできるようになった。また、紙コップの高さが割り箸の高さより高いからと途中でピンポン玉が円の外に出さない。

***超音波センサー [#a01bfd1d]
#ref(2017b/Member/tono/Mission3/超音波センサ.png,center,65%,超音波センサ)
超音波センサーは縦をつけた方がいいといわれた。しかし、今回の課題では私たちが超音波センサーを最後に付けた残ったスペースのせいでよこになってしまった。上の図のように改善前のときかなり後ろのところに付けたからセンサーがうまく働かなかった。そのため、改善後のとき付けるところをちょっと前にすると改善前よりセンサーがうまく働いた。
***スタンド [#gca239fd]
#ref(2017b/Member/tono/Mission3/スクリーンショット 2018-02-13 10.29.21.png,center,100%,スタンド)
私たちのロボットの構造がかなり大きいのでせいでスタート線に越えてしまった。それはルール違反だから、上の図のようにスタンドをつける。このスタンドが動きときに邪魔になることはなかった。
*プログラムについて [#h561943c]
#ref(2017b/Member/tono/Mission3/コース説明.png,center,65%,コース説明)
 上の図のように2つのロボット(LeftRobotとRightRobot)をコースの中で移動する。
-最初にLeftRobotをLine Traceプログラムで移動しながら左側の紙コップを取る。そのとき、紙コップを探して、紙コップの手前までに進むプログラムを使う。RightRobotもLeftRobotと同じように行う。
-次、RightRobotとLeftRobotはX点でピンポン玉を置くSubを使ってピンポン玉を置く。
-そのあと、図のように青いところで紙コップを重ねる。ロボットを2つ連携して通信する。
-最後に重ねられた紙コップをYで置く。そのときは1つのロボットで紙コップ置くプログラムを使って行う。
**Line Traceプログラム [#s1153149]
今回の課題ではまだ課題2のコースを使っている。課題2の結果を見るとriko
のプログラムがグループの中で一番優秀のでrikoの課題2のプログラムを利用した。Sub関数などはrikoのLineTraceと全く同じものを扱っていたから[[課題2(riko):http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Friko%2FMission2#t3e7a27b]]または[[課題3(riko):http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Friko%2FMission3#j25e3fbb]]のところを見てください。
**紙コップを探す・手前までに進むプログラム [#j4a82658]
先生が授業で配ったプリントと授業の参考資料の37ページを参考してプログラムを書いたが、void
の代わりにsubを使った。

 #define SLOW 30		// 速度を遅くして30にする。
 const float diameter=5.45;	// タイヤの直径(cm)
 const float tread=11.3;	// タイヤのトレッド幅(cm)
 const float pi=3.1415;		// 円周率
 int d;				// 整数dとおく
 sub fwdDist(float d)		// 距離d cm 前進
 {
    long angle=d/(diameter*pi)*360.0;		// 必要なタイヤの回転角
    RotateMotorEx(OUT_AB,SLOW,angle,0,true,true);
 }
 sub turnAng(long ang)		// 距離ang度の時間回り旋回
 {
    long angle=tread/diameter*ang;	// 必要なタイヤの回転角
    RotateMotorEx(OUT_AB,SLOW,angle,100,true,true);
 }
 int searchDirection(long ang) //現在の方向を中心にang度の範囲で探し、障害物までの距離を返す。
 {
    long tacho_min;		// もっとも近い距離を実現するタイヤの回転数
    int d_min=300;		// もっとも近い距離の仮の最小値(十分大きくとっておく)
    long angle=(tread/diameter)*ang; 	// 旋回角度からタイヤの回転の計算
    turnAng(ang/2);			// 指定された角度の半径の半分を旋回
    ResetTachoCount(OUT_AB);	// 角度計算をリセット
    OnFwdSync(OUT_AB,SLOW,-100);		// 反時計回りに旋回
    while(MotorTachoCount(OUT_A)<=angle){	
         if(SensorUS(S3)<d_min){		// 現在の距離が仮の最小値より小さい場合
         d_min=SensorUS(S3);		// 仮の最小値の更新
         tacho_min=MotorTachoCount(OUT_A); // この時のタイヤの回転数を記録
     }
 }
    OnFwdSyncEx(OUT_AB,SLOW,100,RESET_NONE);
    until(MotorTachoCount(OUT_A)<=tacho_min||SensorUS(S3)<=d_min);
    Wait(14);			// 微調整
    Off(OUT_AB);
    Wait(500);			// 0.5秒に休止
    return d_min;
 }

**ピンポン玉を拾うプログラム [#r311dfc8]
ピンポン玉がなかにある紙コップを取るプログラムは以下のようなものである:
 sub catch_cop(long ang1)
 {   
    ResetTachoCount(OUT_C);		// モータCの回転角をリセットする
    RotateMotor(OUT_C,-SLOW,ang1);	// モータCをSLOW%のスピードでang1度反転
 }

**紙コップを離すプログラム [#w1ab322e]
紙コップを離すプログラムは以下のようなものである:
 sub release_cop(long ang2)
 {
    ResetTachoCount(OUT_C); 		// モータCの回転角をリセットする
    RotateMotor(OUT_C,SLOW,ang2);	// モータCをSLOW%のスピードでang1度前転
 }
**紙コップを持ち上げるときのプログラム [#m4dd7592]
紙コップを持ち上げるときのプログラムは以下のようなものである
 sub keep_cop()
 {
    ResetTachoCount(OUT_C);		// モータCの回転角をリセットする
    RotateMotor(OUT_C,-SLOW,ang3);	// モータCをSLOW%のスピードでang3度反転
    OnFwd(OUT_C,-20);			// モータCを後ろに20%のスピードをする
 }
**紙コップを重ねるプログラム [#l576aa49]
#ref(2017b/Member/tono/Mission3/紙コップを重ねる.png,center,75%,紙コップを重ねる)
紙コップを重ねるプログラムをわかりやすく説明できるため、上の図のように番号の順番に沿って説明していく。
-1から2
~Master側が紙コップを持って、Slave側はMaster側から離れる。次、超音波センサーを邪魔にならないようにSlave側一回アームを閉める。また、Master側も超音波センサーの邪魔にならないようにアームを持ち上げる。
-2から3
~Slave側が紙コップを掴む。Master側はアームを持ち上げる状態でSlave側に近づく。
-3から4
~Master側は紙コップをSlave側にかぶせる。Slave側はアームを開き、紙コップを離す。
-4から5
~Slave側が離れる。最後にMasterがアームを広げ、紙コップを離すと紙コップを重なることができる。
***LeftRobot(Slave側) [#kf797236]
LeftRobot(Slave側)のプログラムは以下のようなものである。ただし、番号順番については[[紙コップを重ねる順番:http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2017b%2FMember%2Ftono%2FMission3&openfile=%BB%E6%A5%B3%A5%C3%A5%D7%A4%F2%BD%C5%A4%CD%A4%EB.png]]のところに見てください。
LeftRobot(Slave側)のプログラムは以下のようなものである。ただし、番号順番については[[紙コップを重ねる順番:http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2017b%2FMember%2Ftono%2FMission3&openfile=%BB%E6%A5%B3%A5%C3%A5%D7%A4%F2%BD%C5%A4%CD%A4%EB.png]]のところに見てください。また、counterのところはarsoが担当したので詳しくは[[arsoのコップ関連プログラム:http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Farso%2FMission3#mbb4a56f]]のところに見てください。
 #define SIGNALON 11			// モータ回転のためのメッセージ
 #define SIGNALON2 12			// モータ停止のためのメッセージ
 sub tagforleft()
 {
    int msg,counter;			// 受け取った値を格納する変数
    ResetTachoCount(OUT_ABC);		//タイヤとアームの回転をリセットする
    RotateMotor(OUT_C,SLOW,1080);     // アームをSLOWスピードで1080度前転
    RotateMotorEx(OUT_AB,-SLOW,360,0,true,true);  //タイヤのスピードを同期させ360度後転
    RotateMotor(OUT_C,-SLOW,1080);  // アームをSLOWスピードで1080度後転
    while(counter==0){                ////カウンターが0の間繰り返す(番号2の状態)
         ReceiveRemoteNumber(MAILBOX1,true,msg);
         if(msg==SIGNALON) {
           ResetTachoCount(OUT_ABC);
           RotateMotor(OUT_C,SLOW,1080);
           RotateMotorEx(OUT_AB,SLOW,120,0,true,true);
           RotateMotor(OUT_C,-SLOW,1080);
           counter++;                //(番号3の状態)
      }
 }counter=0;                          //(番号4の状態)
 while(counter==0){
    ReceiveRemoteNumber(MAILBOX1,true,msg);
    if(msg==SIGNALON2) {
    ResetTachoCount(OUT_ABC);
    RotateMotor(OUT_C,SLOW,360);
    RotateMotorEx(OUT_AB,SLOW,40,0,true,true);        //(番号5の状態)
    counter++;
    }
 }counter=0;
 ResetTachoCount(OUT_ABC);
 RotateMotor(OUT_C,SLOW,720);                        //(番号6の状態)
 RotateMotorEx(OUT_AB,-SLOW,120,0,true,true);
 }

***RightRobot(Master側) [#c35c2452]
RightRobot(Master側)のプログラムは以下のようなものである。ただし、番号順番については[[紙コップを重ねる順番:http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2017b%2FMember%2Ftono%2FMission3&openfile=%BB%E6%A5%B3%A5%C3%A5%D7%A4%F2%BD%C5%A4%CD%A4%EB.png]]のところに見てください。
 #define SIGNALON1 11			// モータ回転のためのメッセージ
 #define SIGNALON2 12			// モータ停止のためのメッセージ
 sub tagforright()
 {
    keep_cop();		// 番号2の状態
    d=searchDirection(15);	// Slave側のロボットを探す
    if(d>5.0){		// 距離が5cmより遠いとき
        SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);  // Slave側のMAILBOX1にモータ回転を送る
        Wait(5000);		//5秒停止
        fwdDist(d-8.0);		// 近づいてd-8.0cm手前停止(番号3の状態)
        ResetTachoCount(OUT_ABC);	//タイヤとアームの回転をリセットする
        RotateMotorEx(OUT_AB,-SLOW,40,0,true,true);  //タイヤのスピードを同期させ40度前転
        RotateMotor(OUT_C,SLOW,50);  //アームをSLOWスピードで50度前転(番号4の状態)
        SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);  // Slave側のMAILBOX1にモータ停止を送る
        Wait(5000); 	//5秒停止
        RotateMotor(OUT_C,SLOW,100);	// アームをSLOWスピードで100度前転
        ResetTachoCount(OUT_ABC);	 // タイヤとアームの回転をリセットする
        RotateMotor(OUT_C,SLOW,720);  //アームをSLOWスピードで720度前転
        RotateMotorEx(OUT_AB,-SLOW,120,0,true,true); //タイヤのスピードを同期させ120度
                                                       前転(番号5の状態)
    }
 }


**全体プログラム [#v9f2365d]
***LeftRobot [#ndb04038]
LeftRobot の全体プログラムは以下のようなものである。ただし、移動順番については[[コース移動説明:http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2017b%2FMember%2Ftono%2FMission3&openfile=%A5%B3%A1%BC%A5%B9%C0%E2%CC%C0.png]]のところに見てください。

 task main()
 {
    SetSensorLight(S2);		// 光センサーの起動
    SetSensorLowspeed(S3);	// 超音波センサーセンサーの起動
    Start_Set();			// Start Lineの移動
    R_line(300,150);		// Line Trace (番号1の移動)
    d=searchDirection(15);		// 紙コップを探した後、
        if(d>5.0){			// 距離が5cmより遠いとき
        catch_cop(700);			// ここから紙コップを取る(番号2)
        OnFwd(OUT_AB,SLOW);		// ここからはロボットをX地点まで移動する動作
        Wait(1400); 			
        Off(OUT_AB); 			
        catch_cop(300);		
        OnFwd(OUT_AB,-SLOW);		
        Wait(100); 			
        Off(OUT_AB); 		// ここまではロボットをX地点の近くまで移動する動作
    }
    ResetTachoCount(OUT_A);	
    RotateMotor(OUT_A,SLOW,10);  
    OnFwd(OUT_AB,SLOW);		
    Wait(600); 			
    Off(OUT_AB); 			// ピンポン玉をX地点に入れる(番号3)
    catch_cop(40); 			// 紙コップを取ってX地点の外に出る
    OnFwd(OUT_C,-SLOW);     // ここからはロボットを紙コップを重ねるところまで移動する動作
    Wait(1000); 			
    Off(OUT_C); 			
    OnFwd(OUT_AB,-SLOW); 	
    Wait(1000);
    Off(OUT_AB);
    White_to_Black(33,35,15);
    Black_to_White(48,35,15);
    White_to_Black(33,40,25);
    Black_to_White(48,-30,0);
    White_to_Black(33,-30,0);
    Black_to_White(50,0,-30);
    White_to_Black(33,35,30);
    Black_to_White(48,35,30);	// ここまではロボットを紙コップを重ねるところまで移動する動作
    release_cop(50);		// 1回目の紙コップを重ねる動作を行う	
    tagforleft();		// 同上
    keep_cop();			// 同上
    tagforleft();		// 2回目の紙コップを重ねる動作を行う
    OnFwd(OUT_AB,-SLOW);
    Wait(1000);
    Off(OUT_AB);		// LeftRobotの仕事終了
 }

***RightRobot [#ifca1b94]
RightRobot の全体プログラムは以下のようなものである。ただし、移動順番については[[コース移動説明:http://yakushi.shinshu-u.ac.jp/robotics/?plugin=attach&refer=2017b%2FMember%2Ftono%2FMission3&openfile=%A5%B3%A1%BC%A5%B9%C0%E2%CC%C0.png]]のところに見てください。

 task main()
 {
    SetSensorLight(S2);		// 光センサーの起動
    SetSensorLowspeed(S3);	// 超音波センサーセンサーの起動
    reverse_Start_Set(); 		// Start Lineの移動(ロボットの後ろからスタート)
    L_line(1300,110);		// Line Trace (番号1の移動)
    OnFwd(OUT_AB,-SLOW);		// ここから番号2の移動
    Wait(500);
    Off(OUT_AB);			// ここまで番号2の移動
    White_to_Black(43,20,25);		// Line Trace (番号3の移動)
    White_to_Black(33,20,25);		// 同上
    ResetTachoCount(OUT_A);
    RotateMotor(OUT_A,-SLOW,150);
    d=searchDirection(15);		// 紙コップを探した後、
    if(d>5.0){			// 距離が5cmより遠いとき
        catch_cop(600);			// ここで紙コップを取る(番号4)
        OnFwd(OUT_AB,SLOW);		// ここからはロボットをX地点まで移動する動作
        Wait(1000);
        Off(OUT_AB);
        catch_cop(500);
        OnFwd(OUT_AB,-SLOW);
        Wait(400);
        Off(OUT_AB);		// ここまではロボットをX地点の近くまで移動する動作
    }
    ResetTachoCount(OUT_B);
    RotateMotor(OUT_B,-SLOW,110);
    release_ball();		// ピンポン玉を目的に入れる(番号5)
    ResetTachoCount(OUT_A);
    RotateMotor(OUT_A,-SLOW,130);
    tagforright();		// 1回目の紙コップを重ねる動作を行う	
    OnFwd(OUT_AB,-SLOW);		// ここからは番号6の移動
    Wait(1000);
    Off(OUT_AB);
    White_to_Black(48,35,25);
    L_line(300,130);
    Black_to_White(48,0,-30);
    White_to_Black(33,0,-30);	// ここまでは番号6の移動
    d=searchDirection(15);		// 紙コップを探した後、
    if(d>5.0){			// 近づいて5cm手前
        catch_cop(600);			// ここで紙コップを取る(番号6)
        OnFwd(OUT_AB,SLOW);		// ここからはロボットをX地点まで移動する動作
        Wait(1000);
        Off(OUT_AB);
        catch_cop(500);
        OnFwd(OUT_AB,-SLOW);
        Wait(400);
        Off(OUT_AB);		// ここまではロボットをX地点の近くまで移動する動作
    }
    White_to_Black(33,-30,-30);	 // ここからは番号7の移動
    L_line(150,130);
    Black_to_White(48,30,30);	// ここまでは番号7の移動
    release_ball();			// ピンポン玉を目的に入れる(番号7)
    ResetTachoCount(OUT_A);
    RotateMotor(OUT_A,-SLOW,130);
    tagforright();	// 2回目の紙コップを重ねる動作を行う(すべての紙コップ持っている)
    ResetTachoCount(OUT_C);
    RotateMotor(OUT_C,-SLOW,1100);
    White_to_Black(33,-30,-30); 	// ここからはロボットをY地点まで移動する動作
    Black_to_White(48,-30,-30);
    White_to_Black(33,-30,-30);	 
    OnFwd(OUT_AB,SLOW);		// ここまではロボットをY地点まで移動する動作
    Wait(300);
    Off(OUT_AB);			
    ResetTachoCount(OUT_C);
    RotateMotor(OUT_C,SLOW,1200);	 // Y地点で紙コップを入れる動作
 }

*まとめ [#sf289f75]
発表のとき、1回目LeftRobotが1個ピンポン玉をX地点に入れたので2点を取った。2回目はRightRobotが2個ピンポン玉をX地点に入れたが、地点の障害物のを動かしたから減点されて4点であった。
また、技術点としては平均8.8点となり、全体合計は12.8点。順位は9チーム中6位という結果になった。詳しくは[[ロボコン結果:http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMission3#n03a88c3]]のところに見てください。

*考察・感想 [#k329c3e6]
-超音波センサーではロボットの説明で述べた通り、横方向にした。その結果、超音波センサーが読み取れないときもあった。今回の課題では超音波センサー結構大事なところであり、失敗した原因と考えられる。
-各プログラムは起動できたが最後にプログラムを合わせてコースに移動すると失敗確率が多かった。一つ一つのプログラムを作ってからロボットをコースに移動させたよかったと思う。

-発表のときもあったが、機体が長くなってしまったことで障害物にぶつかってしまった。

~最後に、この授業を取ってプログラム入門を触ることができた。プログラムの一ヶ所間違いたら起動できないことや人間はどうやってロボットを動かせるなどがわかった。わたしは今物理コースの学生からきっとロボティクスゼミでやったことを使う機会があると思う。
*参考文献 [#y3dcb0c0]
~松本成司(2013)「自律型ロボットを作ろう!(2013年度版)」(マインドストームを使ったロボット製作の体験教室資料), [online] http://yakushi.shinshu-u.ac.jp/robotics-jr/robotics-jr-2013.pdf(参照2018-2-12).

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS