目次
#contents
*課題3 [#e40a6e93]
**ボール運搬ロボット [#gc2da996]
青と赤のボールを運搬して、それぞれ所定の350ml缶の上に乗せる。
**コース [#p43f2f90]
#ref(2018b/Member/riho/Mission3/2018b-mission3.jpg,80%,コースの通る道順)

私のグループでは、上の図のように
+Xからスタート
+Gで赤いボールを取る
+Fを通過しEを直進
+Dで缶を探しボールを置く
+ボールを置いたらDに戻る
+Eを右折
+Iを直進して青いボールを取る
+缶を探しボールを置く

という経路でロボットを動かすことにした。

*ロボットの説明 [#n6d09df4]
**ロボットの全体像 [#t9ba1293]
今回のミッションではNXTの本体が2つ使えたので、NXTの本体を1つずつ使って2つのロボットを作るか、2つのNXTを通信して1つのロボットを作るか選択できた。2つのロボットを作ると、移動・ボールの掴み・ボールの持ち上げに4つのモータが必要になり、数が足りなかった。先生に3つのモータでも動かせるロボットの組み立て方を教えてもらったが、1つのロボットを作った方が簡単だという結論に至り、私たちのグループでは2つのNXTを通信して1つのロボットを作ることに決めた。
また、2つのNXTを横に並べることと、後ろのタイヤ(駆動輪)を2つつけることでタイヤ1つにかかる重さを分散させて、急カーブなど曲がりやすくしたところを工夫した。

#ref(2018b/Member/riho/Mission3/IMG_1122.jpg,50%,ロボットの全体写真)

**アーム [#m163f6d4]
-アームの持ち上げ

1つのモータはアームの持ち上げに使った。

#ref(2018b/Member/riho/Mission3/IMG_1128.jpg,50%,横から見たロボットの写真)

これはモータを回すことで、写真のように�‐�さな歯車が回り、��大きな歯車が回ることでアームが持ち上げられる。アームが持ち上げた状態で缶に近づくので、持ち上げる時の高さも意識した。

-アームの開け閉め

#ref(2018b/Member/riho/Mission3/IMG_1120.jpg,70%,ロボットのアーム部分)

モータを回すと、上の写真のように�々�い小さな歯車が回り、��黒い小さな歯車に垂直に設置されている灰色の歯車が回ることでアームの開け閉めが行われる。

#ref(2018b/Member/riho/Mission3/IMG_1129.jpg,70%,ボールの取り方の説明図)

上の図はボールを掴む仕組みを床と平行方向の目線で見た時の図である。灰色を黒の部品でできているものがアームで赤がボールである。ボールはすくうようなイメージで、ボールを掴む際、黒い部品は底、灰色の部品は壁になるように作った。

**センサ [#v0b2c9c8]

#ref(2018b/Member/riho/Mission3/IMG_1119.jpg,50%,センサの写真)

-光センサ

課題2の時と同様に、光センサの値を見ながら白色と黒色の値がはっきり変わるように床と適度な間隔をあけた。
-超音波センサ

今回のボールの持ち上げ方は上記で述べたようにアームを上げ下げするようにした。超音波センサを使うときはアームを持ち上げている状態の時なので、NXTの本体の上につけるとアームが邪魔になって超音波センサが正しく作動しない。そのため、超音波センサは写真のように下に取り付けた。


*通信 [#y0c074d2]
**通信の仕組み [#nf5c9192]
2体あるNXTの1つを親機、1つを子機とする。親機が主体となってプログラミングを実行し、通信することで子機に命令ができる。親機が子機に命令することで、子機の中に入っているプログラムを実行することができる。簡単に考えると、やることが多すぎて親機だけではまかなえない分を子機が手伝うというイメージである。2つはBluetoothで繋げる。

今回はアームの開け閉め時、アームの上げ下げ時に通信を使用した。詳しいプログラムの説明は下にある。



*プログラムの説明 [#o85242e9]
**ライントレース [#yf494112]
課題2と同じである。「真っ白」「白と境界線の間」「境界線」「黒と境界線の間」「真っ黒」の5つの段階で分け、光センサで測定すると以下の結果になった。

#ref(2018b/Member/riho/Mission3/IMG_1131.jpg,60%,光センサで測定した結果)

光センサで測定すると「真っ白」は58以上、「白と境界線の間」は53以上57以下、「境界線」は44以上52以下、「黒と境界線の間」は34以上43以下、「真っ黒」は33以下であることがわかった。

線の左側を進むので、「真っ白」の時は右旋回、「白と境界線の間」の時は右折、「境界線」の時は直進、「黒と白の境界線」の時は左折、「真っ黒」の時は左旋回をするプログラムにする。それにより、線の左側を沿って進むことができる。

#ref(2018b/Member/riho/Mission3/IMG_1130.jpg,60%,光センサで測定した値によっての進み方)

そのプログラムは以下のとおりである。

まず、以下のプログラムを定義しておく。
 #define turn_l1 OnFwd(OUT_B,33);OnRev(OUT_C,33);  //左旋回
 #define turn_r1 OnFwd(OUT_C,33);OnRev(OUT_B,33);  //右旋回
 #define turn_l0 OnFwd(OUT_B,30);Off(OUT_C);  //左折
 #define turn_r0 Off(OUT_B);OnFwd(OUT_C,30);  //右折
 #define go_s OnFwd(OUT_BC,30); //直進

左旋回と右旋回の時だけモータのパワーを33にした。それはロボットの総重量が重いため、急なカーブを曲がるときにモータが止まってしまったので、その2つだけパワーを少し大きくした。



 SetSensorLight(S1); //1番に繋がっている光センサを使う
 if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら
     turn_r1;   //右旋回                        
 }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
     turn_r0; //右折
 }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
     go_s;   //直進                                                  
 }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
     turn_l0; //左折                                         
 }else{ //もし光センサが33以下の値を測定したら
     turn_l1; //左旋回
 }

これを応用して交差点を見つけたら終わるプログラムを作る。上記のような線をジグザグしながら動くプログラムの場合、交差点では以下の図のように光センサは「真っ黒」を長い時間測定し続ける。

#ref(2018b/Member/riho/Mission3/IMG_1133.jpg,60%,交差点を認識する仕組み)

図の赤い矢印は全て同じ長さである。直線上にある矢印は、白から黒、黒から白の部分を走っているが、交差点に入っている矢印だけ、矢印全体が黒い部分を走っている。これより、ロボットが交差点に入った時だけ光センサはずっと「真っ黒」を測定し続ける。

これを利用して以下のような交差点に入ると終わるプログラムを作る。

 void tuuzyou()
 {
     SetSensorLight(S1);  //1番に繋がっている光センサを使う
     long t0;              //long型のt0を定義                                                   
     t0=CurrentTick();   //現在の時間を記録
     while(CurrentTick()-t0<90){   //現在の時間とt0の差が0.09秒以下の時、以下のプログラムを繰り返す
         if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら
             turn_r1;   //右旋回    
             t0=CurrentTick(); //t0を更新する                   
         }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
             turn_r0; //右折
             t0=CurrentTick(); //t0を更新する
         }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
             go_s;   //直進       
             t0=CurrentTick(); //t0を更新する                                           
         }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
             turn_l0; //左折   
             t0=CurrentTick(); //t0を更新する                                      
         }else{ //もし光センサが33以下の値を測定したら
             turn_l1; //左旋回
             }
     }
 }

これは、「真っ黒」以外が測定されるたびにt5を更新すると現在の時間とt5の差が0.09秒にならず、while文のプログラムを繰り返し続ける。しかし交差点に入ると、「真っ黒」が測定されて、t5は更新されないため、現在の時間とt5の差が0.09秒以上になるのでwhile文の繰り返しが終わり、プログラムが終わる。

これを基本としてライントレースのプログラムを作る。

***G-F間の止まらないプログラム [#ie76575f]
GとFの間にある急カーブやFの直角だと交差点と同じように「真っ黒」を一定時間測定して止まってしまう。今回は止まる必要がないので、DからFの直角まで通る時間をあらかじめ測定しておいて、その時間は基本形のライントレース(「真っ黒」を一定時間測定してもライントレースを続けるということ)を行うプログラムを作った。それが以下のプログラムである。
 void special()
 {
     SetSensorLight(S1);   //1番に繋がっている光センサを使う                                                       
     long t1;                  //long型のt1を定義する                                                     
     t1=CurrentTick() //現在の時間を記録
     while(CurrentTick()-t1<23500){ //現在の時間とt1の差が23,5秒以下の時、以下のプログラムを繰り返す  
         if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら
             turn_r1;   //右旋回                        
         }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
             turn_r0; //右折
         }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
             go_s;   //直進                                                  
         }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
             turn_l0; //左折                                         
         }else{ //もし光センサが33以下の値を測定したら
             turn_l1; //左旋回
             }
     }                                              
 }

***Eの交差点を直進するプログラム [#rdfb6961]
Eの交差点を直進するには、まず交差点を認識してライントレースするプログラムを終わらせて直進するプログラムを行えばいいので、「task main」中に交差点を認識したら終わる「tuuzyou」のプログラムの次に一定時間直進する「massugu」というプログラムを置けばよい。「massugu」のプログラムは以下のとおりである。

 void massugu()
 {                                                                             
     turn_r1;    //右旋回
     Wait(150); //右旋回を0.15秒実行
     go_s; //直進
     Wait(1200);    //直進を1.2秒実行
 }

交差点を見つけてロボットが「tuuzyou」のプログラムを終えると、ロボットの機体が少し左に曲がってプログラムが終わるため「turn_r1(右旋回)」によって右に機体を戻さないとラインから外れてしまうので、「turn_r1(右旋回)」はロボットの機体をライン上に戻すための微調整である。

***Dの直角を認識するプログラム [#rf4c2994]
Dの位置でボールを探そうとしていたので、Dの直角で止まらなければならない。このためにはDの直角を認識したら終わるプログラムが必要である。しかし、「tuuzyou」のプログラムは「真っ黒」の時間が長いときに終わるプログラムなので、左に曲がる直角でなければ終わらない。

#ref(2018b/Member/riho/Mission3/IMG_1135.jpg,60%,直角Dの認識の仕組み)

ということは、「真っ白」を認識したら終わるプログラムを作ればよいということだ。「tuuzyou」のプログラムを応用して以下のようなプログラムを作った。

 void sirotuuzyou()
 {
     SetSensorLight(S1); //1番に繋がっている光センサを使う
     long t2;         //long型のt2を定義                                                          
     t2=CurrentTick();  //現在の時間を記録
     while(CurrentTick()-t2<90){ //現在の時間とt2の差が0.9秒以下の時に以下のプログラムを繰り返す
         if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら 
             turn_r1;   //右旋回                        
         }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
             turn_r0; //右折
             t2=CurrentTick(); //t2を更新する
         }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
             go_s;   //直進   
             t2=CurrentTick(); //t2を更新する                                               
         }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
             turn_l0; //左折                
             t2=CurrentTick(); //t2を更新する                         
         }else{ //もし光センサが33以下の値を測定したら
             turn_l1; //左旋回
             t2=CurrentTick(); //t2を更新する
         }
     }   
 }

***D-E間の線の右側を沿って進み、Eの直角でも止まらないプログラム [#rf8a636d]

まずは、今までとは違い、線の右側を沿って進むプログラムを考える。

#ref(2018b/Member/riho/Mission3/IMG_1132.jpg,60%,右側通行の進み方)

線の左側に沿って進むプログラムは、光センサが測定する値が白ければ白いほど右に向かって進み、黒ければ黒いほど左に向かって進んでいた。しかし、線の右側を進むプログラムはその逆で、光センサが測定する値が白ければ白いほど左に向かって進み、黒ければ黒いほど右に向かって進めば、線の右側をライントレースするプログラムができる。そのプログラムは以下のとおりである。
 
 SetSensorLight(S1); //1番に繋がっている光センサを使う
 if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら
     turn_l1; //左旋回
 }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
     turn_l0; //左折
 }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
     go_s;   //直進                                                   
 }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
     turn_r0; //右折                                         
 }else{ //もし光センサが33以下の値を測定したら
     turn_r1;   //右旋回   
 }

これを応用してD-E間を通る時間をあらかじめ測定してその時間内は交差点や直角があってもプログラムを続ける以下のようなプログラムを作った。

 void gyakuspe()
 {
     SetSensorLight(S1); //1番に繋がっている光センサを使う
     long t6;    //long型のt6を定義                                                          
     t6=CurrentTick();      //現在の時間を記録                                        
     while(CurrentTick()-t6<6000){   //現在の時間とt6の差が6秒以内の時、以下のプロフラムを続ける
         if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら
         turn_l1; //左旋回
     }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
         turn_l0; //左折
     }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
         go_s;   //直進                                                   
     }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
         turn_r0; //右折                                         
     }else{ //もし光センサが33以下の値を測定したら
         turn_r1;   //右旋回   
         }
     }
 }

***Iの交差点で直進するプログラム [#uba7966a]
Iの交差点で直進するには線の右側に沿って進み、交差点を認識するプログラムが必要である。上記の線の右側に沿って進むプログラムを応用して、以下のプログラムを作った。

 void gyakutuuzyou()                                                     
 {
     SetSensorLight(S1); //1番に繋がっている光センサを使う
     long t5;        //long型のt5を定義する                                                                   
     t5=CurrentTick();  //現在の時間を記録
     while(CurrentTick()-t5<90){   //現在の時間とt5の差が0.09秒以内の時以下のプログラムが繰り返す
         if(SENSOR_1>58){  //もし光センサが58以上の値を測定したら
             turn_l1; //左旋回
             t5=CurrentTick();  //t5を更新する
         }else if(SENSOR_1>53){  //もし光センサが53以上57以下の値を測定したら
             turn_l0; //左折
             t5=CurrentTick();  //t5を更新する
         }else if(SENSOR_1>44){ //もし光センサが44以上52以下の値を測定したら
             go_s;   //直進       
             t5=CurrentTick();  //t5を更新する                                            
         }else if(SENSOR_1>34){ //もし光センサが34以上43以下の値を測定したら
             turn_r0; //右折         
             t5=CurrentTick();  //t5を更新する                                
         }else{ //もし光センサが33以下の値を測定したら
             turn_r1;   //右旋回   
         }
     }
 }

線の左側に沿って進むプログラムと同様に、交差点があると、光センサは「真っ黒」を長く測定する。

#ref(2018b/Member/riho/Mission3/IMG_1134.jpg,60%,右側で交差点の認知の仕組み)

これを用いる。「真っ黒」以外が測定されるたびにt5を更新すると現在の時間とt5の差が0.09秒にならず、while文のプログラムを繰り返し続ける。しかし交差点に入ると、「真っ黒」が測定されて、t5は更新されないため、現在の時間とt5の差が0.09秒以上になるのでwhile文の繰り返しが終わり、プログラムが終わる。

交差点を認知して直進するには、「task main」中に今のプログラムをおいて、次に直進するプログラム(go_s)を置けばよい。


**ボールを掴むプログラム [#a457f9b0]
ボーつを掴む時は通信を使った。

 #define CONN 1 //子機の接続番号
を定義し、

まずは親機のプログラム
 void tukamu()
 {
     RemoteStartProgram(CONN,"CATCH.rxe");   //ボール取る...��
     Wait(9000);                                     //ボール取る時間...��
 }

�,六匍,砲△蕕�じめ入れておいた「CATCH.nxc」というプログラムを実行しろと命令している。子機で実行するプログラムは「CATCH.nxc」なのに親機に書いたプログラムは「CTACH.rxe」なのは、NXT上にあるプログラムの名前はコンパイル後の test2.rxe となるからである。

�△呂△蕕�じめ子機で「CATCH.nxc」を実行する時間を測定しておいて、その時間は親機は待つということである。


次に子機のプログラムは
 #define UP OnFwd(OUT_B,20);Wait(4750);Off(OUT_BC);   //腕上げ
 #define DOWN OnRev(OUT_B,20);Wait(2600);Off(OUT_BC);  //腕下げ
 #define CATCH OnRev(OUT_C,15);Wait(725);Off(OUT_BC);  //手掴み
を定義して
 task main()
 {
 DOWN //アームを下げる
 CATCH //元々腕は開いていてアームの腕を閉じてボールを掴む
 UP //アームを持ち上げる
 }



**缶を探して缶に置くプログラム [#ve422815]
***ロボットからの距離が最小の物体を探す [#q2645e2c]
コンテストではダミーの缶も置けたが、私たちのグループはダミーの缶を置かず、ボールを置かなければいけない缶を必ずロボットとの距離を1番近い物体にした。これにより、缶を探すプログラムは超音波センサを使って、ロボットとの距離が最小の物体の方向を向くプログラムを使う。それは以下のとおりである。

まず
 #define speed 70
 #define speed_s 50
 const float diameter=5.54;  //タイヤの直径(cm)                                              
 const float track=10.35; //タイヤのトレッド幅(cm)
 const float pi=3.1415; //円周率
と定義し、

 void fwdDist(float d)
 {
     long angle;                                                         
     angle= d/(diameter*pi)*360.0;
     RotateMotorEx(OUT_BC,speed_s,angle,0,true,true);                      
 }
 
 void turnAng(long ang) //角度ang度の時計回りの旋回をする
 {
     long angle;
     angle=track/diameter*ang;
     RotateMotorEx(OUT_BC,speed_s,angle,100,true,true);
 }                                                                     
 
 int searchDirection(long ang)  //現在の方向を中心にang度の範囲で探す                                      
                                                  //障害物までの距離を返す
 {
     long angle,tacho_min=0,tacho_corr;
     int d_min;
 
     d_min=300; //仮の最小値
 
     angle=(track/diameter)*ang;  //旋回角度からタイヤの回転を計算する                                                
     turnAng(ang/2); //指定された角度の半分を旋回する
     ResetTachoCount(OUT_BC);       //角度計測をリセット                                       
 
     OnFwdSync(OUT_BC,speed_s,-100); //反時計回りに旋回する
     while(MotorTachoCount(OUT_B)<=angle){
         if(SensorUS(S4)<d_min){
             d_min=SensorUS(S4); //仮の最小値を更新する
             tacho_min=MotorTachoCount(OUT_B);
         }
     }                                                                           
     OnFwdSyncEx(OUT_BC,speed_s,100,RESET_NONE);
     until(MotorTachoCount(OUT_B)<=tacho_min||SensorUS(S4)<=d_min);             
 
     Wait(14); //微調整
     Off(OUT_BC);Wait(500);
     return d_min;
 }

上のプログラムは、ロボットが回転することによって、ロボットの周りにある物体との距離を測定し、それをd_minとする。d_minは測定されたら更新されてることで、別の物体がロボットの周りにあったらその物体との距離もd_minとして記録する。

#ref(2018b/Member/riho/Mission3/IMG_1053.jpg,60%,超音波センサで距離の最小値を探す仕組み)

そして、測定が終わったら、測定したd_minの中で1番小さい値を見つけて、d_minが1番小さかった物体の方向へ向く。

***缶の近くに移動する [#h6b052df]

あらかじめ超音波センサを用いて缶にボールを置くのに適している距離を測定して、缶とロボットが13.5cm離れているとボールを乗せることができるということがわかった。その結果を用いて以下のプログラムを作った。

 SetSensorLowspeed(S4); //4番に繋いだ超音波センサを使う
 int d=searchDirection(360); //int型でdを定義し、ロボットを360°回転させて距離を測定してその最小値を探す
 if (d>13.5){                    //もし見つけた最小値の距離が13.5cmより大きかったら
     fwdDist(d-13.5); //缶とロボットの距離が13.5cmになるまで近づく
 }


***缶を置くプログラム [#c82e4c0c]
缶を置くときは通信を使う。
***ボールを置くプログラム [#c82e4c0c]
ボールを置くときは通信を使う。

 #define CONN 1 //子機の接続番号
を定義し、

親機のプログラムは
 RemoteStartProgram(CONN,"lost.rxe");   //ボール置く...��
 Wait(2000);   //親機の待ち時間...��

ボールを掴むプログラムと同様である。�,六匍,法�lost.nxc」というプログラムを実行しろと命令している。子機で実行するプログラムは「CATCH.nxc」なのに親機に書いたプログラムは「CTACH.rxe」なのは、NXT上にあるプログラムの名前はコンパイル後の test2.rxe となるからである。

�△呂△蕕�じめ子機が「lost.nxc」のプログラムを実行する時間を測っておいて、親機はその時間待っているということである。

次に子機のプログラムは
 #define LOST OnFwd(OUT_C,15);Wait(685);Off(OUT_C);  //手離す
を定義して、

 task main(){      //ボールを持って腕は上がっている状態から
 LOST   //アームを広げてボールを置く
 }


***缶を探して赤いボールを缶に置いて元いたDに戻るプログラム [#na74e28b]
上記のプログラムを組み合わせて缶を探してボールを置いて元いたDに戻るプログラムを作った。

 void sagasu()
 {
     SetSensorLowspeed(S4); //4番に繋いだ超音波センサを使う
     int d=searchDirection(360); //int型でdを定義し、ロボットを360°回転させて距離を測定してその最小値を探す
     if (d>13.5){                    //もし見つけた最小値の距離が13.5cmより大きかったら
         long t3,t4;  //long型のt3,t4を定義する
         t3=CurrentTick(); //ロボットが缶に近づく前の時間をt3に記録
         fwdDist(d-13.5); //缶とロボットの距離が13.5cmになるまで近づく
         t4=CurrentTick(); //ロボットが缶に近づいた後の時間をt4に記録
         stoop; //親機はボールを置く際に動かないのでモータの動きを一旦止める
         RemoteStartProgram(CONN,"lost.rxe");   //親機が子機に命令してボール置く
         Wait(2000); //子機がボールを置いている時間、親機は待つ
         OnRev(OUT_BC,30); //元の位置(直角D)に戻るためにロボットを後退させる
         Wait(t4-t3);  //t4-t3の時間後退させる...��                                      
     }
 }

�,�t3はロボットが缶に近づく前の時間で、t4はロボットが缶に近づいた後の時間である。これよりt4-t3とは、ロボットが缶に近づくために動いた時間だけ後退させる。これにより、どの位置に缶があっても元の位置に戻ってこられる。

***缶を探して青いボールを缶に置くプログラム [#j7c36667]
上記の缶を探して赤いボールを缶に置いて元いたDに戻るプログラムとほぼ同じだが、青いボールを缶に置いたら終わりなので、ボールを置いた後に元いた位置に戻らなくてもよい。そのプログラムが以下のとおりである。

 void sagasu2()
 {
     SetSensorLowspeed(S4); //4番に繋いだ超音波センサを使う
     int e=searchDirection(100); //int型でeを定義し、ロボットを100°回転させて距離を測定してその最小値を探す...��
     if (e>13.5){                    //もし見つけた最小値の距離が13.5cmより大きかったら
         t3=CurrentTick(); //ロボットが缶に近づく前の時間をt3に記録
         fwdDist(e-13.5); //缶とロボットの距離が13.5cmになるまで近づく
         stoop; //親機はボールを置く際に動かないのでモータの動きを一旦止める
         RemoteStartProgram(CONN,"lost.rxe");   //親機が子機に命令してボール置く
         Wait(2000); //子機がボールを置いている時間、親機は待つ        
     stoop; //これでミッションが終わりなのでモータを止める                        
     }
 }

�,�
 int d=searchDirection(360);
にすると、缶の位置はサイコロで決まるので、赤いボールを乗せる缶の方が青いボールを乗せる缶よりロボットとの距離が近くなる可能性もあったので測定する範囲を絞った。

*メインプログラム [#nbc9d5f3]

 task main()
 {
     go_s;       //Xから赤いボールの方向に直進                                                     
     Wait(1000); //1秒間直進
     stoop; //ボールを掴むためロボットの動きを一旦止める
     tukamu(); //赤いボールを掴んで持ち上げる
     go_s; //交差点Dを直進
     Wait(2000); //2秒間直進
     special(); //D-F間の急カーブとFの直角があっても止まらなでライントレース
     tuuzyou(); //F-E間ライントレースをしてEの交差点を認識する
     massugu();    //Eの交差点は直進                                          
     sirotuuzyou(); //Dの直角で終わるプログラム
     sagasu(); //缶を探して、缶に近づいて、赤いボールを缶に置いて元の位置(直角D)に戻る
     gyakuspe(); //D-E間の走行でEの直角があっても終わらないプログラム
     gyakutuuzyou(); //E-I間の走行で、Iの交差点で終わるプログラム
     go_s; //直進して青いボールを撮れる距離まで移動する
     Wait(700); //0.7秒間直進
     stoop; //ボールを掴むためロボットの動きを一旦止める
     tukamu();    //ボールを掴んで持ち上げる                         
     sagasu2(); //缶を探して、缶に近づいて、青いボールを缶に乗せて終了
 }


*まとめ [#y672fdfb]
**反省点 [#mb4d4d15]
-缶一直線にロボットが近づくときと近づかないときがあった

これによってボールが缶に乗るときと乗らないときがあり、本番では乗らなかった。正確な解決方法はわからないが、本番中に「スピードが速い」という声が聞こえた。缶を探すためにロボットを回転させる際に、回転するスピードを遅くすることで距離の測定がより正確になったかもしれない。

また超音波センサは超音波を出して物体によって反射され、跳ね返ってくる時間で距離を測っている。缶の側面が曲線なので、超音波の跳ね返り方が曲がってしまったりするかもしれないと思った。

-赤いボールを置く缶を探すためにロボットが回転した際、ロボット本体の後ろに付いていたコードが缶に当たってしまった

缶の近くで探したほうが正確に測定できると思い直角Dで缶を探すことにしたが、直角Dで缶を探そうとすると思ったよりも缶との距離が近く、コードが当たってしまった。直角Dではなく交差点Eで缶を探すか、後ろのコードをまとめたりするなどの、コードの処理が必要だった。

**感想 [#x6ff1ed4]
今回はミッション3回目でプログラムを作るのも慣れてきたと思ったが、とても苦労した。新しく習った通信もすぐできたのに、なぜ苦労したか。それは微調整である。大まかなプログラムは作れても、乾電池の消費によってパワーを変えたり、少しロボットを組み替えただけで重さのバランスなどが変わり、数字の微調整。また、なんでボールが缶に乗らないのか、なんでボールが缶のある方向に近づかないかなどの解決方法を考えるなど、プログラム上の細かい作業がとても大変だった。最後に先生もおっしゃっていたが、いかに正確ではないかが分かった。

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