**目次 [#s0b0810b]
#contents
**前置き [#d14fe986]
-''メンバー''
--''yno8''…電気電子工学科 プログラミングとロボット製作担当。このページの編集者。前期の選択科目をすべてゼミにしていたことに数週間前に気付く。マミー(清涼飲料水の名前である)の新作が出たら必ず買うようにしている。
--''kawa43''…機械システム工学科 プログラミング担当。彼いなくしてプログラムは作り上げれなかった。BlueTooth通信の受信という難しい部分を担ってくれた。ただUSBケーブルを持ってき忘れがち。
--''chise''…看護学科 プログラミング担当。本番に居合わせられなかったのは残念であった。受信側のプログラムの骨格を作ってもらった。
--''penenoryta''…機械システム工学科 ロボット製作担当。アーム部分、動力部分の修正および、ガトリング砲とピストン機構の完成に協力。アームと動力部分は正直一人ではどうしようもなっかたので本当に感謝している。本番に居合わせられなかったことは至極残念である。
--''d.ichi''…機会・ロボット工学系 ロボット製作担当。動力部分の修正、ロボ本体の安定性の向に協力。歯車に「遊び」を作るという発想は彼が元であり、これを利用し球の発射速度を上げることに成功した。
-''注意したこと''
--ロボットの安定化、軽量化(重いパーツをなるべき下に配置し、ブレーキ時のブレを軽減)
--電池残量に左右されないプログラミング(具体的にはタイマーを未使用、かつRotateMotorの多用、かつもしもの時に備えてロボの速さは一か所変えればすべて変わるようにプログラミング)
--動作の安定化(untilを使って、ちょくちょく黒線まで戻らせている)

**課題2の説明 [#cfbf6862]
&ref(robocon2013a.png);~
-''概要''
--基本得点80点+技術点20点の計100点で課題2(ロボコンもしくはMission2ともいう)を評価
--基本得点は自分たち以外のグループ以外の一グループが採点
--技術得点は自分たち以外の全グループが採点し、その平均で決める
--大雑把に書くと、6回ボールをパスして2回缶に当てれば良い
-''基本ルール''
--競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
--書き足した直線部からスタートする。
--図の上部からスタートしたロボットAがピンポン玉を取りにいく
--直線部までピンポン玉を持ってくる (1)
--直線部に入ってからロボットBへパスを送る (2)
--ロボットBは直線部でパスを受け取る
--ロボットBは直線部でパスを送る (3)
--ロボットAは直線部でパスを受けとる
--ロボットAは直線部でパスを送る (4)
--ロボットBは直線部でパスを受け取る
--ロボットBがゴールの空き缶の近くまでピンポン玉を運んで空き缶に当てる (5) (ただし黒い線で囲まれた空き缶の領域には入ってはいけない)
--ロボットBはシュートをした後もう一つのピンポン玉を取りにいく
--以後は、これまでのAとBの役割を反対にして、パスを繰り返し、最終的にはロボットAがもう一つのゴールにシュートする。
--開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
--競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
--途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
-''基本得点(80点)''
--ボールをつかむ ・・・ 5点
--(2)のパスが通る ・・・ 5点
--(3)のパスが通る ・・・ 10点
--(4)のパスが通る ・・・ 5点
--(5)でシュートをする ・・・ 5点
--シュートが空き缶に当たる ・・・ 10点
--反対方向も同じ
-''技術得点(20点)''
--ピンポン玉を取りにいくまでの動作 (3点)
--ピンポン玉を運ぶ動作(2点)
--ピンポン玉をパスする動作(3点)
--ピンポン玉を受ける動作(3点)
--2台以上のロボットの連携の良さ(3点)
--自立型のロボットとしての形や動作の美しさ、斬新さ(3点)
--その他 (3点)

**ロボット [#c09087d8]
-''概要''~
&ref(img_1.jpg);~
二台とも同じデザインのロボットで勝負することとなった。緑のブロックがついている方が通信の時メッセージを送る側(通称マスター)、赤いブロックがついている方がメッセージを受け取る側(通称スレーブ)となっている。製作時間は大体6時間ほどである。
&ref(img_2);~
&ref(img_2.jpg);~
設計の都合上、いちいち裏返さないとプログラムを実行することが出来ずそこら辺は苦労した。
-''特徴''
--''四輪''
---課題1ではモーターとコンピューター本体を上に配置しすぎたせいでブレが生じ、プログラミング通り動かず本当に悔しくてしかたなかった。そこで今回は安定化を図るため四輪の試作品を製作。もともと、説明書に載っていたサンプルは使い勝手が悪いうえに、オリジナリティーがなくなんだか面白くなかったので自分だけの車体を作りたかったという気持ちもあった(むしろ七割方はこれが原因)。見た目が面白いしタイヤとタイヤが離れているから操作しやすそうだなと思い、四輪で製作することを決め、改良を重ねて今の形となった。~
&ref(img_3.jpg);~
&ref(img_4.jpg);~
パーツの個数の関係から四輪にするためにタイヤを簡単化する必要があった。説明書のタイヤを改良したものを二つ用意した。黄色いパーツが10個必要でもともと10個しかなかったので丁度良かった。~
&ref(img_6.jpg);~
--''アーム''~
---''概要''~
&ref(img_9.jpg);~
↑モーターからの動力を歯車を4つ用いることでアームに伝えている。このアームを回転させることでピンポン玉を取り、打つときには逆回転をさせている。
---''受け取るとき''~
&ref(ball_catch.gif);~
↑ピンポン玉を取るときはアームを正回転させている。ロボットを進ませながら球を取ることによって95%を超える捕獲率を手に入れた。また赤外線センサーにピンポン玉を押し付けることでピンポン玉を出ないようにしている。
---''打つとき''~
&ref(ball_utu.gif);~
↑アームを逆回転させることでボールを打っている。打つところが少し出っ張っているため、強く打つとボールが空中に浮く。これを利用して紙面の凸凹による弾道変化を軽減している。
-''苦労したところ''
--''赤外線センサー''~
&ref(img_7.jpg);~
&ref(img_10.jpg);~
一番時間がかかった部分である。ここのパーツだけで3時間かかってしまっている。アームを一回転させるために赤外線センサーをアームとぶつからないように設置しなければならなかった。これが案外難しくずいぶん悩んでこの機構が完成した。
--''歯車部分''
---骨格は40分で製作完了。そのせいで1時間の改善作業が二度行われた。改善において重視するのは軽量化と安定化である。最初はがちがちになり重くなりすぎたが何度も無駄を省いて今の形に至った。
**プログラム [#h7f1574a]
 #define zone1 37 //黒線の中央の値
 #define zone2 45 //黒線の中央よりやや外側よりの値
 #define zone3 60 //黒線と白紙部分の境目の値
 #define zone4 65 //白紙部分の値
 #define SPEED 45 //ロボットの進む速さ
 #define LOWSPEED SPEED*0.625 //「SPEED」の0.625倍の速さ
 #define mae OnFwd(OUT_BC,SPEED*0.8); //「SPEED」の0.8倍の速さで前進
 #define STEP 1 //一回の判定でロボが進む時間(この場合だと0.001秒間に一回処理している)
 #define nMAX 100 //STEP秒間に赤外線センサーの値が37以下をnMAX回出したら交差点と判断する
 #define SIGNAL1 11 //「打った」と宣言する信号
 #define SIGNAL2 12 //「打て」と宣言する信号
 #define CONN 1 //通信の時に設定するスレーブの番号(1〜3まで選べる)

 int p=0; //センサーが黒線の上にあるとき、pを使ってカウントし、pがnMAXの値を超えたらそこは交差点(今回は0.001秒間に一回カウント)
 int n=0; //
 int m=0; //交差点を通過した個数を数えるときにmを使う
 int msg=0; //相手に送るメッセージ


    sub migigawa(int x) //交差点をx回通過するまで右側をライントレースし続ける
        {
          while(m < x) {
            while(p < nMAX && m<x) {
                if (SENSOR_4 < zone1) {
                OnFwd(OUT_B,SPEED);OnRev(OUT_C,LOWSPEED); //小回りな右折
                p++;
          } else {
              if (SENSOR_4 < zone2) {
                OnFwd(OUT_B,SPEED);Off(OUT_C); //普通の右折
            } else if (SENSOR_4 < zone3) {
                mae;
            } else if (SENSOR_4 < zone4) {
                OnFwd(OUT_C,SPEED);Off(OUT_B); // 普通の左折
            } else {
                OnFwd(OUT_C,SPEED);OnRev(OUT_B,LOWSPEED); //小回りな左折
               }
                p=0;
               }
                Wait(STEP);
               }
                OnFwd(OUT_C,SPEED);OnRev(OUT_B,LOWSPEED); //小回りな左折
                Wait(nMAX*STEP);
                OnFwd(OUT_BC,SPEED);Wait(300);
                p=0;
                m++;
               }
                m=0;
 }
↑「赤外線センサーの値がzone1(37)以下ならば小回りに右折し、zone1(37)〜zone2(45)ならばちょっぴり大回りに右折する。zone2〜zone3なら前進しzone3〜zone4ならちょっぴり大回りに左折。zone4〜zone5なら小回りに左折する」。つまるところ黒線の右側に沿ってライントレースするプログラムであり、この動作をmigigawa(x)のみで表現させている。xには整数が入り、x回交差点を通過したらこの動作をやめるようにプログラミングしてある。

    sub hidarigawa(int x) //交差点をx回通過するまでライントレースし続ける
      {
        while(m < x) {
            while(p < nMAX && m<x) {
                if (SENSOR_4 < zone1) {
                OnFwd(OUT_C,SPEED);Off(OUT_B); // 普通の左折
                p++;
          } else {
              if (SENSOR_4 < zone2) {
                OnFwd(OUT_C,SPEED);OnRev(OUT_B,LOWSPEED); //小回りな左折
            } else if (SENSOR_4 < zone3) {
                mae;
            } else if (SENSOR_4 < zone4) {
                OnFwd(OUT_B,SPEED);Off(OUT_C); //普通の右折
            } else {
                OnFwd(OUT_B,SPEED);OnRev(OUT_C,LOWSPEED); //小回りな右折
               }
                p=0;
               }
                Wait(STEP);
               }
                OnFwd(OUT_B,SPEED);OnRev(OUT_C,LOWSPEED);
                Wait(nMAX*STEP);
                OnFwd(OUT_BC,SPEED);Wait(300);
                p=0;
                m++;
               }
                m=0;
 }
↑こちらは黒線の左側をライントレースするプログラムをhidrigawa(x);のみで実行させるために定義している。プログラムが複雑にならないようにするための措置である。



 task main ()
 {
    SetSensorLight(S4); //四番ポートに赤外線センサーを設置
    Wait(2000); //ロボットを置く時間
    //''一回目の缶当てスタート!''
    migigawa(2); //交差点を二回カウントするまでライントレース
    Off(OUT_BC);Wait(1000); //休憩
    RotateMotor(OUT_C,-SPEED,200);RotateMotor(OUT_B,SPEED,120);Off(OUT_BC); //角度調整
    mae;OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //アームで球を捕獲
    mae;until(SENSOR_4 < 50);Off(OUT_BC); //黒線まで直進
    OnRev(OUT_BC,SPEED);Wait(500);OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50); //後ろの黒線までバック
    OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);Wait(500); //旋回
    OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);until(SENSOR_4 < 50); //ライントレース出来る体制に戻る
    hidarigawa(1); //左側をライントレースしながら交差点を一回カウント
    Off(OUT_BC);Wait(1000);RotateMotor(OUT_BC,-SPEED,430);Wait(1000); //打つ地点までバック
    RotateMotor(OUT_B,-SPEED,300);RotateMotor(OUT_C,SPEED,100);Off(OUT_BC); //角度調整
    Wait(1000);SendRemoteNumber(CONN,MAILBOX1,SIGNAL1); //信号を送る
    OnFwd(OUT_BC,SPEED);RotateMotor(OUT_A,100,400);Off(OUT_ABC); //打つ
    RotateMotor(OUT_BC,-SPEED,200); //打った状態からライントレースできる体制に戻る
    OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);RotateMotor(OUT_BC,SPEED,50); //打った状態からライントレースできる体制に戻る
    OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);until(SENSOR_4 < 50); //打った状態からライントレースできる体制に戻る
    Off(OUT_BC);Wait(5000); //五秒待つ
    hidarigawa(1); //左側ライントレース交差点を一回カウント
    RotateMotor(OUT_BC,SPEED,100);Off(OUT_BC); //受け取る場所まで移動
    RotateMotor(OUT_BC,-SPEED,10);RotateMotor(OUT_C,SPEED,550);Off(OUT_BC); //90°旋回
    SendRemoteNumber(CONN,MAILBOX2,SIGNAL2); // 相手に「打て」とメッセージを送る
    Wait(500); //相手が打ってから球が来るまで待つ時間
    OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //球を受け取る
    OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);Off(OUT_BC);RotateMotor(OUT_BC,SPEED,80);
    OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED);until(SENSOR_4 < 50); //ライントレース出来る体制に戻る
    Off(OUT_BC);Wait(7000); //七秒待つ
    hidarigawa(1); //左側、交差点を一回カウント
    RotateMotor(OUT_BC,SPEED,50);Off(OUT_BC); //打つ地点まで移動
    RotateMotor(OUT_B,-SPEED,400);Off(OUT_B);RotateMotor(OUT_C,-SPEED,20); //角度調整
    SendRemoteNumber(CONN,MAILBOX3,SIGNAL1); //「打つ」と送る
    OnFwd(OUT_BC,SPEED);RotateMotor(OUT_A,100,400);Off(OUT_ABC); //打つ
    RotateMotor(OUT_BC,-SPEED,50);Off(OUT_BC); //打った時のズレを修正
    //一回目の缶当て終了!

    //二回目の缶当てスタート
    RotateMotor(OUT_C,-SPEED,50);
    Wait(65000); //相手が準備できるまで待機
    SendRemoteNumber(CONN,MAILBOX4,SIGNAL2); //「打て」と相手に送る    
    Wait(1500);OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //球を受け取る
    RotateMotor(OUT_C,SPEED,50);Wait(5000); //相手が準備できるまで待つ
    RotateMotor(OUT_BC,-SPEED,200);
    RotateMotor(OUT_C,-SPEED,180);RotateMotor(OUT_B,-SPEED,380); //打つ準備をする
    RotateMotor(OUT_BC,SPEED,300);RotateMotor(OUT_B,SPEED,80); //打つ準備をする
    RotateMotor(OUT_BC,-SPEED,100);
    SendRemoteNumber(CONN,MAILBOX5,SIGNAL1); //「打つぞ」と相手に送る
    Wait(500);OnFwd(OUT_BC,SPEED);RotateMotor(OUT_A,80,400);Off(OUT_ABC); //打つ
    Wait(1500);OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);Off(OUT_BC);//打ってから黒線まで戻る
    RotateMotor(OUT_BC,SPEED,50);
    OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED); //ライントレース出来る体制に戻る
    until(SENSOR_4 < 50);Off(OUT_BC); //ライントレースできる体制に戻る
    migigawa(1); //目の前のT字路をカウント
    RotateMotor(OUT_BC,SPEED,350);RotateMotor(OUT_B,SPEED,400); //受け取る位置まで移動
    RotateMotor(OUT_C,-SPEED,180);Off(OUT_BC);RotateMotor(OUT_C,-SPEED,100); //受け取り角度調整
    SendRemoteNumber(CONN,MAILBOX6,SIGNAL2); //「打て」と送る
    Wait(1500); //球が来るのを待つ
    OnRev(OUT_A,20);Wait(1500);Off(OUT_A); //球を受け取る
    Wait(1000);OnRev(OUT_BC,SPEED);until(SENSOR_4 < 50);Off(OUT_BC); //ライントレース出来る体制に戻る
    RotateMotor(OUT_BC,SPEED,50); //ライントレースできる体制に戻る!
    OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED);until(SENSOR_4 < 50);Off(OUT_BC); //ライントレースd(ry
    migigawa(1);
    Off(OUT_BC);
    RotateMotor(OUT_B,-SPEED,420);
    RotateMotor(OUT_A,100,400); //缶に当てる
    //二回目の缶当て終了!
    }
 }
-''球を打つとき''
--モーターを回しただけだと威力が弱いので、前へ進みながら打たせている。威力が低いと紙の凸凹で玉の弾道が変化してしまう。
-''RotateMotorについて''
--Rotatemotor(OUT_A,80,50);と打つと、「Aに接続されているモーターを80%の力で50°回転」を実行する
--回す角度でモーターの動きを決められるので、電池に左右されることがない
--RotateMotor(OUT_BC,80,50);のように同じ方向へ同時に動かすことはできるが、RotateMotor(OUT_B,80,50);rotateMor(OUt_C,80,50);と書いても同時に二つのモーターが動くわけではなく、接続がBのモーターを80%の力で50°回した後にCのモーターを80%,50°回すだけである
--課題2をクリアするために絶対必要なコマンドであった
-''BlueTooth通信について''
--注意点
---通信には電池残量の左側に書いてあるロボットの名前(ほとんどはNXTのはず…)を使うのだが、ほとんどのロボットの名前が「NXT」なので間違って隣のグループのロボットと通信してしまうかもしれない。なので初めて通信するときは他のロボットがいない所でやりましょう。
--やり方
+++Bluetoothを選択した後、My connections(握手してる画像)を選んで、その中のデータを全部消してください(両方とも)
+++メッセージを送るロボット(通称マスター)がSerchを選んで何秒間か探させます
+++Serchし終わると相手のロボットの名前(電池残量の左に書いてある、多分ほとんどの人は「NXT」のはず…)が出てくるのでそれを選ぶ
+++BlueToothのマークとその右に「>」←こんなマークが出てくると思うのでそれを選択(たしかConnectって書いてあるはず)
+++1〜3の番号が出てくると思うので1を選ぶ(2でも3でもいいけどめんどくさいんで1で)
+++1234やらabcdやら出てくるので「1234」と打つ(この過程がない場合もあるかも…)
+++connectしたら左上の「>」が「◇」になるのでそしたら成功
+++以後は、一回電源を落とすたびに接続しなおさなければならないが、My connectionsに接続履歴が残っているのでそこから選びなおせばいい
+++もしうまくいかなかったら先生に聞く、もしくはググる

**反省 [#k139bc56]
-授業は毎回楽しかったが、期末試験前の課外活動はさすがに辛かった。試したい機構や面白いピンポン玉の取り方などやりたいことはまだあるが、メンバーのおかげでよい結果を手に入れることが出来たので悔いはない。プログラミングについては独学でC言語を学んでいたのだが、今回の授業でより理解することが出来るようになった。独学といっても「こんにちは」を表示させるくらいしかまだできていないが…。最後に、授業時間を延ばしに延ばしてくれた松本先生、判定を甘くしてくれたグループ番号6の審判、そして私以外の4班のメンバーに感謝の意を表したい。
**意見 [#r8e90b9c]
-ロボット同士の通信のやり方を詳しく資料に記述してほしい
-RotateMotorのコマンドはほぼ必須なので、詳しく資料に記述してほしい
-ジュースでもいいから景品が欲しかった
-ジュースでもいいから景品が欲しかった(マミーの新作なら尚良し)



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