#author("2020-02-02T23:07:02+09:00","Nakakoo","Nakakoo")
#author("2020-02-02T23:36:00+09:00","Nakakoo","Nakakoo")
目次
#contents

*課題3 [#ode19250]

&size(20){今回の課題は、「&color(blue){青};と&color(red){赤};のボールを運搬して空き缶の上に載せる」というものである。};

**コース [#e075453b]

&size(22){フィールドの説明};

#ref(./2019b-mission3.png,100%,コース画像)

-フィールドは課題2で使用した紙を使用する。
-空き缶は6本用意し、そのうち3本をC、E、Fの交差点に描いた半径4cmの円内に置き、その上にボールを載せておく。
-同様に残りの空き缶をC’、E’、F’地点に置く。
**使用したルート [#zfaf4d39]

#ref(./ルートs.PNG,120%,ルート説明)

+A地点から出発し、ライントレースをしてC地点の缶の直前まで行く。
+ボールをつかんだら缶を避ける。
+再びライントレースをしてE地点の缶の前まで行く。
+ボールをつかんだらバックをし、ライントレースをしてF地点の缶の前まで行く。
+ボールをつかんだらバックをし、ライントレースでC'地点まで行く。
+缶の上にボールを置く。

時間がなかったのでゴールまでのプログラミングは書けなかったが、ボールを一つ缶の上に置くことはできた。

ロボットに時間をかけたせいで、プログラミングが最後まで書けなかったことがとても悔しかった。

**ルール [#n6453cbf]
&size(20){基本ルール};

-競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
-図のA地点または(および)A'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。
-開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
-競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
-途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
-競技終了後、ロボットが、空き缶に触れていてはいけない。

&size(20){基本得点の計算方法};

-ボールを1個運べば8点。3つとも運べば24点。
-競技終了後、ゴールの空き缶が半分以上円からはみ出しまった場合、3点減点。
-競技終了後、ゴールの空き缶が完全に円から出しまった場合、4点減点。
-競技終了後、空き缶にロボットが触れていれば、もとの基本点の3減点。

&size(20){芸術点の計算方法};

以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。
-ボールを探し取りにいくまでの動作 (3点)
-ボールを掴む動作 (3点)
-ボールを運ぶ動作 (2点)
-ボールを容器の中に入れる動作 (2点)
-2台のNXT、EV3の連携の良さ(2点)
-自立型のロボットとしての形や動作の美しさ、斬新さ(2点)
-その他 (3点)

*ロボットについて [#dae290a5]
**ロボット全体像 [#hd135659]

#ref(./IMG_6095s.JPG,60%,全体画像)

課題3ではNXTが2台あり通信することが目的であったので、当初はそれぞれを独立させボールを回収するロボットと

それを缶の上に置くロボットの2つを作ろうと考えていたが、自分の技術的にも時間的にも厳しかったので、一体型のロボットを作ることにした。

下の部分が各種センサーでライントレースと缶の発見を行うマスター側で、上の部分がアームでボールの回収と設置を行うスレーブ側である。

**工夫した点(マスター側) [#af5f74cc]

***後輪 [#eb2208f0]

#ref(./IMG_6104s.jpg,60%,後輪画像)

このロボットを作った当初は後輪がついていたのだが、ゴムの摩擦によって右左折が上手くいかずやむを得ずタイヤを外すことにした。

タイヤのゴムを外してみても解決しなかったので、結果このように少し不細工な見た目になってしまった。

モーターの回転速度を50程度まで上げてみたらタイヤがついていても右左折ができるようになったが、動作が速すぎるために安定しなかったので棒で支えることにした。

***各種センサー [#i7b6d2a2]

#ref(./IMG_6096s.JPG,60%,センサー画像)

光センサーは、課題2での反省を生かして車体との距離を縮めることでカーブを交差点だと認識することを減らした。さらに地面と近すぎず、

遠すぎない位置に設置することで安定した値を取れるようにした。

また、超音波センサーは過去のレポートを参考にして横ではなく縦に設置した。缶は曲面になったいるので、横にするとうまく距離が測れないと考えた。

#ref(./センサー説明s.JPG,120%,センサー説明)

このように片方から出た音波をもう片方で受け取っているので、横に設置すると正確に距離が測れないことがあった。

***レール [#abb13d0f]

今回はボールをすべて回収してから缶の上まで運ぶというロボットなので、ボールをためておく場所が必要であった。

その場所にはブロックで作ったレールを採用した。

#ref(./sレール.JPG,120%,レール)

本物のボールを載せている画像を撮影し忘れたのでこれで代用するが、このように回収したボールがレールの上に集まっていく。

**反省点(マスター側) [#icf4e724]

***センサーの種類 [#k55b48d4]
工夫した点で超音波センサーを盾に設置したと説明したが、それでもやはり正確に距離が測れないことがあった。

このレポートを描いているときに気付いたが、ボールを回収する時に超音波センサーが缶に接触するくらい近くに行かないとうまく回収できなかったので、

センサーをタッチセンサーに変えたほうがプログラムがすっきりするし、上手く缶を認識できたのではないかと思った。

***スレーブ側との接地部分 [#ic149f7d]

#ref(./IMG_6118s.jpg,75%,接地部分画像)

このようにマスター側とスレーブ側が接触しているのはレゴブロックの凸4つ分だけでありとても不安定であった。

スレーブ側の重みで傾き、ボールを回収するときに崩れそうになったこともあるので、縦方向の固定だけでなく横方向にも固定をすべきであった。

***レール [#j40cbc60]

#ref(./レールs.JPG,120%,レール画像)

ボールを載せるレールは、前の部分は固定をしていたが後ろは固定しなかったので、ボールがたまるにつれて外に開いてしまった。

ボールがレールの上から落ちてしまうことはなかったが、前にあるボールの上下の位置が変わってしまい、缶の上に置くときの障害になっていた。

後ろ側のレールを固定し、スムーズにボールを送り出せたらよかったと感じた。

**工夫した点(スレーブ側) [#kb045646]

***歯車 [#ffe5630b]

スレーブ側にはモーターが2つ付いており、1つはボールを回収する機構を動かすため。もう1つは缶が動かないように支えるアームを上下させるためについている。

#ref(./IMG_6314s.jpg,70%,歯車画像)

これはアーム側の歯車であり

#ref(./IMG_6316s.jpg,70%,歯車画像)

こちらはボールをつかむ機構の歯車である。

どちらも歯車の数を調整し、モーターの回る方向と最後の歯車が回る方向が一致するようにした。そのおかげでプログラムを書くときに分かりやすかった。

***アーム [#zc1bb542]

ボールを回収する時、缶が動かないようにアームで缶を固定しておく。画像のように缶を挟んでおく。

#ref(./缶を固定s.JPG,120%,アーム画像)

#ref(./arm.gif,50%,アーム画像)

***ボールを回収する機構 [#l1321a39]

ボールは回転する3本の棒でレールの上にのせる。ボールの下をすくい上げるようにして回収する。

#ref(./回転レールs.JPG,120%,レール画像)

スムーズにボールを回収するために棒の長さを3本とも同じ長さにして、ボールの上から押さえつけずしっかり下からすくい上げられるようにした。

#ref(./ボール回収s.JPG,100%,回収画像)

*プログラミングについて [#r11266a7]
今回作ったロボットはNXTが2台にモーターが4つ、センサーが2つ使われている。マスター側のNXTに2つのセンサーと車体を動かすためのモーターが2つ。

スレーブ側のNXTにはアームとボールを回収する機構を動かすためのモーターが2つ付いている。

**車体(Master) [#m23e89af]

***マクロ [#s4573398]

 #define SPEED 35                                             //モーターの回転速度
 #define STEP 1                                               //一回の判断で進む時間
 #define mae OnFwd(OUT_BC,SPEED);                             //前進する
 #define usiro(t) OnRev(OUT_BC,SPEED);Wait(t);Off(OUT_BC);    //後退する
 #define migi1 OnFwd(OUT_C,SPEED);                            //右折する
 #define migi2 OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED);         //右に旋回
 #define hidari1 OnFwd(OUT_B,SPEED);                          //左折する
 #define hidari2 OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);       //左に旋回
 #define CONN 1                                               //スレーブの番号
 #define SIGNALON 11                                          //SIGNALONは11と定義
 #define SIGNALOFF 12                                         //SIGNALOFFは12と定義

***サブルーチン [#b467d462]

 sub linefollow1()
 {
     SetSensorLight(S3);                //S3に光センサーをつける
     SetSensorLowspeed(S4);             //S4に超音波センサーをつける
     long t0;
     t0=CurrentTick(); 
     while(CurrentTick()-t0<200){       //t0が0.2秒の間繰り返す
         if(SensorUS(S4)<=6){           //6cm以内に近づくと
             Off(OUT_BC);               //モーターが止まる
             PlaySound(SOUND_UP);       //ピロピロという音が鳴る
             break;                     //whileループから抜け出す
         }
         if(SENSOR_3>60){               //値が60以上の時
             migi2;                     //右に旋回
             t0=CurrentTick();          //時間をリセット
         }else if(SENSOR_3>52){         //値が52以上の時
             migi1;                     //右折する
             t0=CurrentTick();          //時間をリセット
         }else if(SENSOR_3>40){         //値が40以上の時
             hidari1;                   //左折する
             t0=CurrentTick();          //時間をリセット
         }else if(SENSOR_3>30){         //値が30以上の時
             hidari2;                   //左に旋回
         }else{                         //そのほかの時  
             mae;                       //前進する
             t0=CurrentTick();          //時間をリセット 
         }                             
          Wait(STEP);                    
         }
     Off(OUT_BC);                       //モーターを止める
     Wait(1000);                        //1秒待つ
 }

これがラインの左をトレースするプログラムである。右のトレースはほぼ同じであり、設定した値が違うだけであるので省略する。

課題2と違うところは超音波センサーをプログラムに取り入れたことだけである。いろいろテストしたところ値を6cm以下にするとうまく缶を認識できなかった。

当初はwhileループを抜け出す条件に超音波センサーの6cm以下という条件を入れていなかったためにループを抜け出せず、ライントレースが上手くいかなかった。

先生には迷惑をかけたがbreakを使ってループから抜け出し、わかりやすいように音を出す方法も教えてもらった。

今回の課題をするまでwhileの意味をよく理解せずに使っていたことがよく分かった。しかし、最後には理解し、breakでルー0プを抜け出したり、

音を出して今何をしているかが分かるようになったのは良い収穫であった。

 sub kaihi()
 {
     OnFwd(OUT_B,SPEED);OnRev(OUT_C,speed);Wait(1600);Off(OUT_BC);   //左に1.6秒曲がる
     OnFwd(OUT_BC,SPEED);Wait(2200);Off(OUT_BC);                     //前に2.2秒進む                 
     OnFwd(OUT_C,SPEED);OnRev(OUT_B,speed);Wait(1200);Off(OUT_BC);   //右に1.2秒曲がる
     OnFwd(OUT_BC,SPEED);Wait(1700);Off(OUT_BC);                     //前に1.7秒進む
     OnFwd(OUT_C,SPEED);OnRev(OUT_B,speed);Wait(1700);Off(OUT_BC);   //右に1.7秒進む
     OnFwd(OUT_BC,SPEED);Wait(2100);Off(OUT_BC);                     //前に2.1秒進む 
 }

これはC'地点の缶を回避するサブルーチンである。タイヤの摩擦によって動作に差が出てしまい3回に1回は避けられないこともあった。

***メイン [#if37e4d3]

task main()
 {
     Wait(1000);                                  //1秒待つ
     PlaySound(SOUND_CLICK);                      //ピッという音を出す
     linefollow1();                               //左側をライントレースし缶の前まで行く
     mae;Wait(350);Off(OUT_BC);                   //缶の前でもう少し前へ行く(タッチセンサーならいらなかったかも) 
     SendRemoteNumber(CONN,MAILBOX1,SIGNALON);    //スレーブに11を送る(C地点の缶) 
     Wait(17000);                                 //17秒待つ(これを無くしたかった)
     usiro(1400);                                 //後退する
     kaihi();                                     //缶を回避
     linefollow1();                               //左側をライントレース
     mae;Wait(700);Off(OUT_BC);                   //D地点の交差点を直進 
     linefollow1();                               //左側をライントレース
     mae;Wait(350);Off(OUT_BC);                   //缶の前まで調節 
     SendRemoteNumber(CONN,MAILBOX1,SIGNALON);    //スレーブに11を送る
     Wait(17000);                                 //17秒待つ
     usiro(1100);                                 //後退する
     migi2;Wait(1600);Off(OUT_BC);                //D地点の交差点を右折
     linefollow1();                               //左側をライントレース
     hidari2;Wait(1600);Off(OUT_BC);              //G地点の交差点を左折
     linefollow1();                               //左側をライントレース
     mae;Wait(350);Off(OUT_BC);                   //缶の前まで調節 
     SendRemoteNumber(CONN,MAILBOX1,SIGNALON);    //スレーブに11を送る 
     Wait(17000);                                 //17秒待つ
     usiro(1100);                                 //後退する
     migi2;Wait(1700);Off(OUT_BC);                //G地点の交差点を右折
     linefollow1();                               //左側をライントレース
     hidari1;Wait(2000);Off(OUT_BC);              //H地点の交差点を左折
     linefollow2();                               //右側をライントレース
     migi1;Wait(2000);Off(OUT_BC);                //H'地点の交差点を右折
     linefollow1();                               //左側をライントレース 
     hidari2;Wait(1600);Off(OUT_BC);              //G'地点の交差点を左折
     linefollow1();                               //左側をライントレース 
     mae;Wait(350);Off(OUT_BC);                   //缶の前まで調節 
     SendRemoteNumber(CONN,MAILBOX1,SIGNALOFF);   //スレーブに11を送る 
     Wait(17000);                                 //17秒待つ
     usiro(1100);                                 //後退する
 }         

これは言い訳になってしまうが引っ越しの関係で時間がとれず、ボールを1つ置くまでのプログラムしか書けなかった。さらにプログラムを別々に

動かしたときにはしっかり動いてくれたが、プログラムを通して動かしたときには摩擦などによる誤差によって最後まで動いてくれなかった。

練習しているときでもプログラムを通して試してみることが大切なんだと気づいた。

さらにこのプログラムには気に入らない点があり、それはスレーブ側が動いている間にマスターがじっと待っている点である。

本当はスレーブが動き終わった後にマスターに信号を返し、それを受け取ってからマスターが再び動き出すプログラムにしたかった。

しかし僕に能力がなかったせいでただ17秒待つだけのプログラムになってしまった。

**アーム(Slave) [#rca3a86e]

***マクロ [#l5292814]

 #define speed 15                                              //モーターの回転速度
 #define SIGNALON 11                                           //SIGNALONを11と定義
 #define SIGNALOFF 12                                          //SIGNALOFFを12を定義
 #define tukamu OnFwd(OUT_B,speed);Wait(7000);Off(OUT_B);      //ボールをつかむ 
 #define hanasu OnRev(OUT_B,speed);Wait(7000);Off(OUT_B);      //ボールをはなす 
 #define arm_up OnFwd(OUT_C,speed);Wait(3800);Off(OUT_C);      //アームを上げる
 #define arm_down OnRev(OUT_C,speed);Wait(3500);Off(OUT_C);    //アームを下げる

***メイン [#db070c22]

 task main()
 {
     int msg;                                      //受け取った値を格納する変数
     while(true){                                  //ロボットのボタンを押すまでループを続ける
         ReceiveRemoteNumber(MAILBOX1,true,msg);   //MAILBOX1に変数を受け取る
         if(msg==SIGNALON){                        //11を受け取った時
             arm_down;                             //アームを下げる
             tukamu;                               //ボールをつかむ
             arm_up;                               //アームを上げる 
         }     
         if(msg==SIGNALOFF)                        //12を受け取った時
             arm_down;                             //アームを下げる
             hanasu;                               //ボールをはなす
             arm_up;                               //アームを上げる
         }    
     }
 }

メインの中にwhile(true)と書いてあるのでずっとこのループを続ける。whileの使い方をしっかり理解していなかったのでこのようなプログラムになってしまった。

*感想と反省 [#tb4a2e8d]

この授業を通して簡単なプログラミングの書き方を学ぶことができた。しかし、ハードがしっかりしていないとソフトがどれだけ素晴らしくても

良い作品にならないことも分かった。時間をもっと作ることができれば最後までプログラムを作ることができたかもしれないという後悔もあった。

さらにすべての課題を通して、ほぼすべて一人で作らなければいけなかったのでもっとチームメイトと協力して作業を進めるべきだったのが反省点である。

しかし、チームメイトにやる気がなく全く作業に参加してくれなかったこともあったので、チームを作る際にはじゃんけんのようにランダムでなく

自分たちで相談してチームを決めることも検討してもらいたいと思った。

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