目次
#contents
* 課題3のレポートを見る前に [#o928e753]
今回の課題の機体の構想やプログラムの書き方、発想は私の課題2の踏まえた上で作っています。

特にこの機体のライントレースのやり方についての詳しい説明は[[私の課題2のレポート:http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Friko%2FMission2]]に記載されています。そちらを読んだ後であると理解しやすいと思われます。

* 課題3 [#m41fb4d5]
** 内容 [#le8145e6]
課題2で使用した紙を用い、下図のマジェンタの円に逆さまにした紙コップを置き、その中にピンポン玉を2つずつ入れておく。そして、割り箸を使って一辺が14cmの正方形を作り、X地点を中心とした円に接するように置き、その中にピンポン玉を入れていき、最後には紙コップを重ね、Y地点を中心とした円の中に置く。また、下図の黄色い円に紙コップを通常の向きに置き、障害物とする。直径6cmの円の外周をペンまたは鉛筆でマークしておく。

&ref(2017b/Member/riko/Mission3/課題3_フィールドの図.png,400x300,課題3_フィールドの図);

** ルール [#cadfbda7]
詳しいルール説明は[[2017年度後期・課題3:http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMission3]]を参照してください。

** チームメンバー [#xd992990]
N5・N6の合同メンバー。課題1・2・3とすべて下記の私を含めた三人で行いました。他の人達のレポートも分かりやすいと思うので、見てくださると幸いです。

主に私は機体を作る作業をしていたのでプログラムについて詳しく知りたい方は他お二方のレポートを参照ください。

・riko

・[[arso:http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Farso%2FMission3]]

・[[tono:http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Ftono%2FMission3]]


* 今回の機体について [#t5cc74a2]

今回の課題を成功させるために必要な動きとして、

 .侫ールド上を自由に動くために動き
 
 ∋罐灰奪廚鬚弔む動き
 
 D呂鵑聖罐灰奪廚鮖ち上げ、被せる動き

の三点が挙げられる。

,竜々修亡悗靴討浪歛2のものを今回の課題に合わせて少しだけ変えたものを使用することにした。

◆↓の機構は最初の構想ではクワガタのハサミのような形と動きで紙コップを掴む機構とその機構を持ち上げる機構を個々にモーターを使い、,竜々修塙腓錣擦4つのモーターで動かす予定であった。

しかし、1つのモーターで◆↓の動きをこなす機構(以下、「アーム機構」という)があることが松本先生の話から判明し、先生が出した例を応用、過去にこの授業を受けた偉大なる先駆者達のレポートを参考にすることで、アーム機構を作り出すことができた。

これにより、フィールド上に二台のロボットを動かすことが可能となった。
** アーム機構 [#yb3b004f]
上記のアーム機構についてできる限り詳しく説明するが、私の説明力では全てが伝わるか怪しいため、私のレポートで理解できなかった場合は私以外の優秀な人たちのレポートを参考にしてもらいたい。

*** 掴む機構_1 [#g57efdf2]
初めに、紙コップをつかむ機構を作る。

ウォームギアを用いることで紙コップを掴む両腕の部分の動きを同期させる。下図は両腕部分を取り外したものとなる。

&ref(2017b/Member/riko/Mission3/アーム部分_1.PNG,600x350,アーム部分_1);

ウォームギアが回る仕組みとしてまず、,硫色の矢印方向に黒い歯車を回すことで、黒い歯車の中の棒が回り、真ん中の黒い歯車も回る。

次に、真ん中の黒い歯車が回ることで△寮嵜Г量隶方向に白い歯車が回る。

最後に白い歯車の中の棒が回ることでの緑色の矢印方向にウォームギアが回る。

*** 掴む機構_2 [#f7bc3389]
次にウォームギアとそれに隣接する歯車「ウォームホイール」の動き方について

この説明においては私が図を書き、説明するよりは下記のURLに詳しい説明が記載されている。一応、下記のサイトの説明を簡単に説明させてもらうが、理解できない場合は飛ばすか、下記のサイトを読んでもらえるとわかりやすい。

ウォームギアとは、ねじのような形状のウォームと、それにかみあうウォームホイールによって構成されている。ウォームギアの特徴として、直角に交差した回転軸に動力を伝えられることができる。他にはウォームギアがウォームホイールを回すことができるが、ウォームホイールがウォームギアを回すことができないことがあげられる。動力の働き方としては下記のサイトの画像がわかりやすかったため、下図に転載しておく。

&ref(2017b/Member/riko/Mission3/ウォームギアとウォームホイールの動き.jpg,400x300,ウォームギアとウォームホイールの動き(転載));



〇[[「ロボジョイくらぶ」(第二回「平歯車の仕組み」と「かさ歯車とウォームギアウォームギア仕組み」):http://www.robojoy-club.com/challenge/challenge_c10_2_02.php?p=4&loc=cc10_2_02]]


*** 掴む機構_3 [#wa92fa91]

次に実際に組み立てた機構のウォームギアとウォームホイールの動き方について見てみる。下図は一応アーム機構としては完成形ではあるが、今は腕部分だけを見てもらいたい。

&ref(2017b/Member/riko/Mission3/アーム部分_2.PNG,600x350,アーム部分_2);

上図の腕部分が回る仕組みとしてまず、,領仗Г量隶方向にウォームギアを回すことで、二つのウォームホイールが互いに逆方向に回る。その方向としては、△寮弔ぬ隶方向にそれぞれ回る。

それによって、ウォームホイールに固定された腕部分がの灰色の矢印方向にそれぞれ回り腕の中のものを掴む仕組みとなっている。

*** アームを持ち上げる機構_0(謝罪) [#u80404b2]
まず初めに、謝罪をさせてもらいます。本当に申し訳ありません。私の画力では絶対にアームを持ち上げる機構の説明が伝わらないため、例を用いて説明させてもらいます。理解できない場合はウォームギアの時と同様に、私以外の優秀な人のレポートを見て理解してもらうことを祈ります。

あくまで私の意見ですが、機構の理解を得るための近道は実際にその機構を作ることだと思います。写真そっくりでも、簡易版でもいいので作ってみて、納得した後に改造することで新たな理解が得られると思います。

*** アームを持ち上げる機構_1-1 [#qb4fd471]
まず、かさ歯車と呼ばれるものの下図を見てもらいたい。

&ref(2017b/Member/riko/Mission3/かさ歯車による持ち上げる機構の簡略説明_1.PNG,550x300,かさ歯車による持ち上げる機構の簡略説明_1);

上図の青色の矢印はそれぞれの歯車の軸を表していることがわかるだろうか。

次に ↓△了車がそれぞれその場に固定されていたと仮定する。

そう仮定した場合、△了車を緑色の矢印方向に回したとすると、,了車はその場で灰色の矢印方向に回転を得ることができる。

*** アームを持ち上げる機構_1-2 [#ub4da0ea]
次に,了車自体の回転(灰色の矢印の回転)だけ固定された場合を考える。

&ref(2017b/Member/riko/Mission3/かさ歯車による持ち上げる機構の簡略説明_2.PNG,550x300,かさ歯車による持ち上げる機構の簡略説明_2);

先ほどと同様に△了車を緑色の矢印方向に回したとする。

そうした場合、,了車の動きとしてはー体の回転は存在せず、赤色の矢印方向に△了車を軸としてついていくように回転を得る。

*** アームを持ち上げる機構_2-1 [#j48407ed]
以上の二つの仕組みを利用してアームを持ち上げる機構を作っていく。また、上記の二つの条件の違いを作るために今回は負荷値の限界(最大値)を使っていく。下図は上図の歯車の関係の位置を表している。

&ref(2017b/Member/riko/Mission3/アーム機構における置き換え.PNG,400x300,アーム機構における置き換え);

今回の機構の場合、歯車の負荷値が低い方から順番に回る為「アームを持ち上げる機構_1」の条件の場合が先に実行される。つまり、「掴む機構_3」に記載されている図の表の方の機構が動くということになる。

下の図は、「掴む機構_3」に記載されている図の表の方を切り抜いたものである。

&ref(2017b/Member/riko/Mission3/掴む機構_1の図の表.PNG,400x300,掴む機構_1の図の表);


*** アームを持ち上げる機構_2-2 [#bb3f9e19]

次に上図のアームがに動きをし続けると、両アームが互いのアームを押し合い始めることがわかるだろうか。そうなった場合、△了車の動きに対する負荷値の限界(最大値)に達したこととなり、△瞭阿ができなくなることにつながる。そうなると次に負荷値が低いものの歯車が動きを行うこととなる。ここで、「アームを持ち上げる機構_2」の動きをすることになる。注意すべき点として、今回の機構の場合、この動きをするときには既に一度、負荷値の限界(最大値)に達しているため、「アームを持ち上げる機構_1-1」の図の,粒タГ量隶の動きはなくなると考えてよい。

&ref(2017b/Member/riko/Mission3/持ち上げる機構の回転方向.PNG,400x300,持ち上げる機構の回転方向);

上図の青色の矢印は ↓△了車の軸を表している。黄緑色、橙色はそれぞれ、 ↓△了車の回転を表しており、同じ方向に回る。そして、,了車から繋がっている部分、要するにアーム機構全体が、※のついた青矢印を軸に回転する仕組みとなっている。

*** アームを持ち上げる機構_3 [#p4bbdaab]
上記の機構を利用することで、アーム機構が完成する。そして、アーム機構を作成するにあたって、どちらを表(上向き)にするか、紙コップをつかみやすくするためも工夫などを考えながら作成していったものが下の写真となる。また、工夫については後述してあるので、読んでもらうと幸いである。

&ref(2017b/Member/riko/Mission3/アーム部分_3.PNG,550x300,アーム部分_3);

※おおよそ上の写真の通りに制作されたがロボット本体に取り付ける際、アームの位置を上下を逆にしたり他にも細々としたところを改造しているので注意してもらいたい。


** アーム機構_工夫点 [#kdc4a642]
このアーム機構の主な工夫点としては三つ挙げられる。

 〇罐灰奪廚鮗茲蟾む際の工夫(緑色の枠線)
 ∋罐灰奪廚鯆呂犧櫃旅夫(水色の枠線)
 持ち上げた紙コップを下げるための工夫(赤色の枠線)

&ref(2017b/Member/riko/Mission3/アーム機構_工夫部分.PNG,300x400,アーム機構_工夫部分);

それぞれの工夫を下記に説明していく。

*** アーム機構_工夫点 [#u7e20bfc]
アームを閉じる際、紙コップを取らなければならない。紙コップが内側にはいっている場合、きれいに掴むことが実験で分かったので、細いタイヤを両腕につけるようにした。この時の最大の特徴として、タイヤが回ることである。

&ref(2017b/Member/riko/Mission3/紙コップを内側に取り込む工夫.PNG,470x360,紙コップを内側に取り込む工夫);

&ref(2017b/Member/riko/Mission3/紙コップを内側に取り込む手順.PNG,700x220,紙コップを内側に取り込む手順);

上図はアームのタイヤ部分上から見た際の簡略図である。タイヤが黄色の矢印方向に回ることで、紙コップの位置が多少ずれていたとしても中に取り込むことが可能となる。この時のタイヤの回転は自然と起きるものである。

また、細かな点ではあるがタイヤのゴムによって紙コップを掴む際の摩擦係数を高くすることによって掴み上げやすくなっている。


*** アーム機構_工夫点-1 [#g41c004e]
紙コップを掴むとき、紙コップの状態をよりきれいに支える、紙コップの体制を確定させるための工夫である。

まず紙コップをきれいに支える為の工夫として、三点で支えていることである。

&ref(2017b/Member/riko/Mission3/紙コップを掴むための工夫_1.PNG,450x270,紙コップを掴む工夫_1);

上図のように赤色の三点で支えることによって紙コップがぐらつくことなくしっかりと掴むことができる。この仕組みについては特に難しいことではないため特別詳しく説明はしない。

特徴としては、二点より三点の方が安定する。支える三点の位置関係を上から見たときにできるだけきれいな正三角形、二等辺三角形にすることで安定性が増すくらいである。

*** アーム機構_工夫点-2 [#d9aef073]
次に紙コップの体制の話である。普通であるならば、紙コップを地面と平行の体制のまま移動させるのだが、後に記載する「ピンポン玉をどうやって割りばしの中に入れるかという」過程において紙コップを斜めにしたまま安定させる必要が出てきた。その工夫として生まれたのが下図の工夫である。

&ref(2017b/Member/riko/Mission3/紙コップを掴むための工夫_2.PNG,700x250,紙コップを掴む工夫_2);

上図は紙コップを横から見ている図である。簡単に説明すると紙コップと当たる中心の棒の位置をタイヤの支点部分より下に下げた。そうすることで紙コップが斜めの状態を維持できるのである。

取り付け方としてはウォームギアの為の棒を短くし、その下に紙コップを支える為だけの黒棒を取り付けただけである。

※現段階では中心の黒い棒が支えとなっているが機体の完成体では黒い棒ではなくなっている。詳しい説明は後述はする。



*** アーム機構_工夫点 [#m7a0aa22]
今から説明する工夫はアームを締めてから持ち上げるまでは必要のない工夫である。しかし、紙コップを持ち上げた後、下したアームを広げるためには絶対に必要となっている。その工夫されてる部分とは、下図の緑色の枠線に囲まれた部分(以下、「ストッパー」という)となる。

&ref(2017b/Member/riko/Mission3/ストッパー.PNG,400x300,ストッパー);

まず、ストッパーがなかった場合どうなるか。その時の写真がないため、略図として書いたのが下図となる。見てわかる通り、ストッパーがないとアームを広げようとするとウォームギアが回転しながらどんどん前に行ってしまい機構として破綻してしまう。

&ref(2017b/Member/riko/Mission3/ストッパー_説明.PNG,400x440,ストッパー_説明);

&ref(2017b/Member/riko/Mission3/ストッパーなしの場合.PNG,600x400,ストッパーなしの場合);

そのため、ストッパーをつけることでウォームギアの前進を止め、同じ位置で回転させることができるようになる。

** アーム機構_反省 [#nd3118b6]
アーム機構を制作するにあたって、実はこんなに大きなものを作らなくても良かった。さらに言えば、もっとパーツ数を減らし、軽くすることもできると思う。ではなぜ、この形になったかという主な理由は二つある。

一つ目は、紙コップを取る際に色々と工夫して取りやすくしようと思い、それらを無計画に付け足しっていったことである。

二つ目は、ロボット製作期間が短く、アーム機構の理解に時間がかかってしまったことである。終わってから改善してみたい点がでてきたので、時間に余裕があればもっと良いアームや全く違う機構ができたと思う。

上記の理由という名の言い訳を述べさせてもらったが、一言付け加えさせてもらうなら「もう少し時間が欲しかった」というのが正直なところである。

** 機体_β版 [#r0110778]
取り合えず、アーム機構にモーターを取り付け、課題2で作ったようなフィールド上を自由に動くための機体と合体させ、超音波センサーをつける。できたものの全体の写真は下のものとなる。

&ref(2017b/Member/riko/Mission3/機体_β版_全体.JPG,400x300,機体_β版_全体);

機体の上面、側面からの写真、アーム部分の写真となる。

&ref(2017b/Member/riko/Mission3/機体_β版_上面_横.JPG,400x300,機体_β版_上面);
&ref(2017b/Member/riko/Mission3/機体_β版_側面.JPG,400x300,機体_β版_側面);
&ref(2017b/Member/riko/Mission3/機体_β版_アーム_1.JPG,400x300,機体_β版_アーム);

試作品として付けただけなので欠点だらけとなっている。例として挙げるのなら、超音波センサーがもう少し前にないとならない、前のアームが邪魔で超音波センサーがちゃんとした数値を取らない、アームの支えが雑であるとかだ。

因みに、この時は三点で支える発想はなかった。

** 機体_完成版 [#ee53e672]
最終的に完成した機体の全体が下の写真となる。この機体の自体に様々な工夫が施されているがそれは後に記載する。

&ref(2017b/Member/riko/Mission3/機体_完成版_全体.JPG,400x300,機体_完成版_全体);

機体の上面、側面、正面からの写真、アーム部分の写真となる。

&ref(2017b/Member/riko/Mission3/機体_完成版_上方.JPG,400x300,機体_完成版_上方);
&ref(2017b/Member/riko/Mission3/機体_完成版_側面_スタンド_2.JPG,400x300,機体_完成版_側面);
&ref(2017b/Member/riko/Mission3/機体_完成版_正面.JPG,400x300,機体_完成版_正面);
&ref(2017b/Member/riko/Mission3/機体_完成版_アーム.JPG,400x300,機体_完成版_アーム);

基本的な構造はβ版と変わらない。この機体は一つのNXTの箱で完成するように作った為、今回の課題で同じ機体の二台体制でフィールドを走らせることができる。何故、二台体制にしたかというと、一台が失敗したとしてももう一台でポイントを確実に取るためである。その他の理由として完走のタイムを短くさせるというものもあったのだが、もはや最後までうまくいかないということで理由としてはかなり薄いものとなってしまった。

** 機体_完成版_工夫点 [#t4ca023a]
最終的な機体の主な工夫点としては三つ挙げられる。

 .◆璽犁々修梁寮維持の為の工夫とその他(緑色の枠線)
 ▲好拭璽斑賄斉發房まる為の工夫(水色の枠線)
 5‖遼楝里梁寮維持の為の工夫(赤色の枠線)

&ref(2017b/Member/riko/Mission3/機体_完成版_工夫部分.PNG,400x300,機体_完成版_工夫部分);

それぞれの工夫を下記に説明していく。

*** 機体_完成版_工夫点-1 [#z4225233]
アーム機構の仕組み上、持ち上げる際に下図の※と示された部分を軸してアームが回る。そのため何もしないとアームを床を引きずっている状態で移動しなければならない。

&ref(2017b/Member/riko/Mission3/アーム機構の体制維持の為の工夫.PNG,400x300,アーム機構の体制維持の為の工夫.PNG);

工夫した部分は上図の水色の枠線部分となっている。超音波センサーに乗せることで基本のアームの姿勢を地面と平行にしている。この際、超音波センサーの邪魔にならないようにする必要があり、そのため、超音波センサーを前に持ってくることで解決しつつ、前に持ってくることで計測値がより正確となるので一石二鳥となった。(上図ではぎりぎり乗るか乗らないかにみえるが実際には、超音波センサーの邪魔にはなっていない)

*** 機体_完成版_工夫点-2 [#i980bcca]
工夫として特筆すべきというものではないが、機体を作る際に注意した点があったので一応記載しておく。

下図のアーム部分がわかるだろうか、この部分が長すぎる、余計なものをつけるなどのことをしてしまうとアームを持ち上げるときに床と接触し、それ以上アームを持ち上がらなくなる。これに関してはまだまだ改良の余地があると思っている。

&ref(2017b/Member/riko/Mission3/アームの上げ下げの工夫.PNG,650x260,アームの上げ下げの工夫);

*** 機体_完成版_工夫点 [#ad581265]
機体を作り終え、今回の課題のルールを見直すと「床と接着している部分はスタート範囲内になければならない」というルールがあることが発覚した。そして、下図の「ここ」の部分、つまり超音波センサーが床と接着してたのである。

&ref(2017b/Member/riko/Mission3/スタンド_1.PNG,400x300,スタンド_1);

その対策として生まれた工夫が下図のものとなっている。自転車などのスタンドを思い浮かべてもらうと分かりやすいだろう。機体が発進するとスタンド部分が動き、機体が動くのに邪魔にならないようになる。

&ref(2017b/Member/riko/Mission3/スタンド_2.PNG,650x250,スタンド_2);

*** 機体_完成版_工夫点 [#h46ca2de]
ここの工夫はあまりにも無計画で機体を制作してしまったおかげでできてしまった欠点を無くすための補助の工夫となっている。その欠点とは機体の重心がアームを動かすときに不安定にぶれ、シーソーのようになってしまうことである。

そしてその欠点を補う工夫は下図の赤色の枠線で囲まれた補助輪である。補助輪の分、機体のケツが持ち上がることで機体がぶれることを防いでいる。

&ref(2017b/Member/riko/Mission3/補助輪の工夫_1.PNG,400x300,補助輪の工夫_1);

実際に下図の分、機体のケツが持ち上がっている。

&ref(2017b/Member/riko/Mission3/補助輪の工夫_2.PNG,400x300,補助輪の工夫_2);

この工夫部分もまだまだ改良の余地があり、できることならこの補助輪などなかった方が実際は良いだろう。機体作りの計画性、改造の余地を残しておくことが大切だあると身が染みた。

* プログラム [#j25e3fbb]
今回のプログラム制作に私自身はほとんど関与していないため、穴のある説明になってしまうことをご了承願いたい。初めの辺りで記載したが私と同じ班のもののレポートを見ると理解していただけると思われる。

** 課題成功への作戦 [#x9755c4f]
上記に数度記載したと思うが今回の私たちの班の作戦として同じ機体の二台体制で動かしていく作戦だ。理由としては、一台が失敗したとしてももう一台が保険としてポイントを確保してくれるだろうと思ったからだ。

二台を動かすにあたり、スタート位置を二つに分け、作業をする紙コップを分けている。下図は「左」と「右」の機体の作業分担場所である。


&ref(2017b/Member/riko/Mission3/左・右機体の行動範囲.PNG,400x270,左・右機体の行動範囲);

** 紙コップに関するプログラム [#nb2d92f2]
今回の私の仕事の役割分担によって、紙コップに関するプログラムはほとんど触れていない。そのため説明が簡易なものとなることを許してもらいたい。

*** 紙コップを少し持ち上げて割りばし内に入れるプログラム [#w553b69a]
どうやって紙コップの中にピンポン玉を保持したまま割りばしの上を通過するか。そこの仕組みをまず説明させてもらいたい。

&ref(2017b/Member/riko/Mission3/紙コップと割りばし_1.PNG,400x300,紙コップと割りばし_1);

普通に考えると紙コップを持ち上げるだけでピンポン玉が出ていくことは誰でもわかるだろう。だから、ピンポン玉が軽いということを利用して割りばし内にもっていく。

&ref(2017b/Member/riko/Mission3/紙コップと割りばし_2.PNG,400x300,紙コップと割りばし_2);

上図のように紙コップを割りばし以上の高さから、ピンポン玉のおおよそ半分までの高さまで上げることによりピンポン玉が紙コップ内に収まったまま割りばしを通過できる。

動き方としては下図のようになる。

&ref(2017b/Member/riko/Mission3/紙コップの割りばし越え.PNG,400x300,紙コップの割りばし越え);

今回の機体の紙コップの上げ方は斜めに上がるのでそこらのことは考えなければならない。下図のように紙コップが上がるのが理想である。

&ref(2017b/Member/riko/Mission3/紙コップの割りばし越え(斜め).PNG,400x300,紙コップの割りばし越え(斜め));

     d=searchDirection(15);
     if(d>5.0){
         catch_cop(700);
         OnFwd(OUT_AB,SLOW);
         Wait(1400);
         Off(OUT_AB);
         catch_cop(300);
         OnFwd(OUT_AB,-SLOW);
         Wait(100);
         Off(OUT_AB);
     }   

恐らく上記のプログラムが紙コップに近づき、掴んだ紙コップを割りばしの高さ以上ピンポン玉の半分の高さ未満まであげるプログラムとなっている...はずである。

*** 紙コップを重ねるプログラム_1 [#p44d8a6c]
初めの予定では紙コップを重ねる時は機体一台でやるつもりであった。しかし、いざやってみるとほとんどうまく紙コップが重ならなかった。

そのため、紙コップを確実に重ねられるように2台の機体を連携させてやるようにした。
下図は機体の動き方である。前提として左側の機体が子機、右側の機体が親機として考える。



&ref(2017b/Member/riko/Mission3/紙コップ連携_1.JPG,400x300,紙コップ連携_1);

まず、親機(右の機体)が紙コップを持ち、子機(左の機体)が紙コップから離れた状態から始まる。



&ref(2017b/Member/riko/Mission3/紙コップ連携_2.JPG,400x300,紙コップ連携_2);

子機が腕を閉じ、親機の超音波センサーの邪魔にならないようにする。



&ref(2017b/Member/riko/Mission3/紙コップ連携_3.JPG,400x300,紙コップ連携_3);

親機が紙コップを持ち上げ、超音波センサーの邪魔にならないようにし、紙コップの方向に向く。



&ref(2017b/Member/riko/Mission3/紙コップ連携_4.JPG,400x300,紙コップ連携_4);

子機の腕を広げる。



&ref(2017b/Member/riko/Mission3/紙コップ連携_5.JPG,400x300,紙コップ連携_5);

子機が紙コップに近づく。



&ref(2017b/Member/riko/Mission3/紙コップ連携_6.JPG,400x300,紙コップ連携_6);

子機が紙コップを掴み動かないようにする。



&ref(2017b/Member/riko/Mission3/紙コップ連携_7.JPG,400x300,紙コップ連携_7);

親機が子機の持っている紙コップに近づく。



&ref(2017b/Member/riko/Mission3/紙コップ連携_8.JPG,400x300,紙コップ連携_8);

親機の持っている紙コップを子機の持っている紙コップにかぶせる。



&ref(2017b/Member/riko/Mission3/紙コップ連携_9.JPG,400x300,紙コップ連携_9);

子機が親機に近づくことで紙コップに角度が生まれる。



&ref(2017b/Member/riko/Mission3/紙コップ連携_10.JPG,400x300,紙コップ連携_10);

子機が腕を広げ、紙コップを離す。



&ref(2017b/Member/riko/Mission3/紙コップ連携_11.JPG,400x300,紙コップ連携_11);

子機が離れる。



&ref(2017b/Member/riko/Mission3/紙コップ連携_12.JPG,400x300,紙コップ連携_12);

最後に親機がアームを広げ、紙コップを離すことで紙コップが重なる。

*** 紙コップを重ねるプログラム_2 [#ob6d3d88]
上記の動きをするためのプログラムが下記の通りとなる。ここの部分のプログラムは本当にノータッチなので解説ができない。

一つ言えるとしたら、ここのプログラムはBluetoothによる機体同士の通信をしているため、お互いのタイミングがずれる恐れはない。

〇親機(右の機体)

 sub tag()
 {
     keep_cop();
     d=searchDirection(15);
 
     if(d>5.0){
         SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);
         Wait(5000);
         fwdDist(d-8.0);
         ResetTachoCount(OUT_ABC);
         RotateMotorEx(OUT_AB,-SLOW,40,0,true,true);
         RotateMotor(OUT_C,SLOW,50);
 
         SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);
         Wait(5000);
         RotateMotor(OUT_C,SLOW,100);
         ResetTachoCount(OUT_ABC);
         RotateMotor(OUT_C,SLOW,720);
         RotateMotorEx(OUT_AB,-SLOW,120,0,true,true);
     }
 }   

〇子機(左の機体)

 sub tag()
 {
     int msg,counter;
     ResetTachoCount(OUT_ABC);
     RotateMotor(OUT_C,SLOW,1080);
     RotateMotorEx(OUT_AB,-SLOW,360,0,true,true);
     RotateMotor(OUT_C,-SLOW,1080);
 
     while(counter==0){
          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++;
             }
     }
     counter=0;
 
     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);
             counter++;
            }
     }
     counter=0;
     ResetTachoCount(OUT_ABC);
     RotateMotor(OUT_C,SLOW,720);
     RotateMotorEx(OUT_AB,-SLOW,120,0,true,true);
 }



** 左側機体(子機)のプログラム [#o464f4c8]

正直に言わせてもらう。私は同じ班が書いたプログラムを理解できない。なので私が書いた部分の説明はさせてもらおうと思う。これは右側機体も同じことがいえる。

以下は左側機体の全体のプログラムとなっている。

〇私以外が書いたプログラムはコメントとして「※」を書いておきます。なので「※」がついていてわからない箇所がある場合は私の班の人のレポートを読んでください。私が分かる部分はこちらでも()内で簡単に説明はします。

〇私が課題2で使ったプログラムと同じ部分にはコメントとして「☆」を書いておきます。

 #define SO 392                                                        //☆
 #define DO 523                                                        //☆
 #define MI 659                                                        //☆
 #define SO_H 784                                                      //☆
 #define SI 988                                                        //☆
 #define DO_H 1047                                                     //☆
 #define MI_H 1318                                                     //☆
 #define RE 1175                                                       //☆
 #define SO_SH 1568                                                    //☆
 
 #define SIGNALON 11                                                   //※
 #define SIGNALON2 12                                                  //※
 #define SLOW 30                                                       //※
                                                                       //※
 const float diameter=5.45;                                            //※
 const float tread=11.3;                                               //※
 const float pi=3.1415;                                                //※
                                                                       //※
 int d;                                                                //※
                                                                       //※
 sub fwdDist(float d)                                                  //※
 {                                                                     //※
     long angle=d/(diameter*pi)*360.0;                                 //※
     RotateMotorEx(OUT_AB,SLOW,angle,0,true,true);                     //※
 }                                                                     //※
                                                                       //※
 sub turnAng(long ang)                                                 //※
 {                                                                     //※
     long angle=tread/diameter*ang;                                    //※
     RotateMotorEx(OUT_AB,SLOW,angle,100,true,true);                   //※
 }                                                                     //※
                                                                       //※
 int searchDirection(long 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);                                                        //※
     return d_min;                                                     //※
 }                                                                     //※
                                                                       //※
 sub tag()                                                             //※
 {                                                                     //※
     int msg,counter;                                                  //※
     ResetTachoCount(OUT_ABC);                                         //※
     RotateMotor(OUT_C,SLOW,1080);                                     //※
     RotateMotorEx(OUT_AB,-SLOW,360,0,true,true);                      //※
     RotateMotor(OUT_C,-SLOW,1080);                                    //※
                                                                       //※
     while(counter==0){                                                //※
          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++;                                               //※
             }                                                         //※
     }                                                                 //※
     counter=0;                                                        //※
                                                                       //※
     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);                //※
             counter++;                                                //※
            }                                                          //※
     }                                                                 //※
     counter=0;                                                        //※
     ResetTachoCount(OUT_ABC);                                         //※
     RotateMotor(OUT_C,SLOW,720);                                      //※
     RotateMotorEx(OUT_AB,-SLOW,120,0,true,true);                      //※
 }                                                                     //※
 
 sub pose_SE()                                                         //☆
     PlayTone(MI_H,90);Wait(100);                                      //☆
     PlayTone(DO_H,90);Wait(100);                                      //☆
     PlayTone(MI_H,90);Wait(100);                                      //☆
     PlayTone(DO_H,90);Wait(100);                                      //☆
 }                                                                     //☆
 sub one_UP_SE()                                                       //☆
 {                                                                     //☆
     PlayTone(MI,110);Wait(120);                                       //☆
     PlayTone(SO_H,110);Wait(120);                                     //☆
     PlayTone(MI_H,110);Wait(120);                                     //☆
     PlayTone(DO_H,110);Wait(120);                                     //☆
     PlayTone(RE,110);Wait(120);                                       //☆
     PlayTone(SO_SH,110);Wait(120);                                    //☆
 }                                                                     //☆
 sub coin_SE()                                                         //☆
 {                                                                     //☆
     PlayTone(SI,90);Wait(100);                                        //☆
     PlayTone(MI_H,140);Wait(150);                                     //☆
 }                                                                     //☆
 sub Start_SE()                                                        //☆
 {                                                                     //☆
     PlayTone(MI,100);Wait(110);                                       //☆
     PlayTone(MI,100);Wait(250);                                       //☆
     PlayTone(MI,100);Wait(160);                                       //☆
     PlayTone(DO,90);Wait(100);                                        //☆
     PlayTone(MI,90);Wait(230);                                        //☆
     PlayTone(SO_H,90);Wait(420);                                      //☆
     PlayTone(SO,170);Wait(180);                                       //☆
 }                                                                     //☆
 
 
 #define move1 OnFwd(OUT_A,40);OnFwd(OUT_B,-35);                       //☆
 #define move2 OnFwd(OUT_A,30);OnFwd(OUT_B,-20);                       //☆
 #define move3 OnFwd(OUT_A,54);OnFwd(OUT_B,54);                        //☆
 #define move4 OnFwd(OUT_B,30);OnFwd(OUT_A,-20);                       //☆
 #define move5 OnFwd(OUT_B,40);OnFwd(OUT_A,-35);                       //☆
 #define average 45                                                    //☆
 
 
 sub Stop_Motion()                                                     //☆
 {                                                                     //☆
     Wait(300);                                                        //☆
     pose_SE();                                                        //☆
     Wait(1000);                                                       //☆
 }                                                                     //☆
 sub L_Assist_line(int Assist_time)                                    //☆
 {                                                                     //☆
     long ta=CurrentTick();                                            //☆
     while (CurrentTick()-ta<=Assist_time){                            //☆
         if (SENSOR_2<average-11) {                                    //☆
             move1                                                     //☆
         }else if (SENSOR_2<average-7){                                //☆
             move2;                                                    //☆
         } else if (SENSOR_2<average+7){                               //☆
             move3;                                                    //☆
         } else if (SENSOR_2<average+11){                              //☆
             move4;                                                    //☆
         } else {                                                      //☆
             move5;                                                    //☆
         }                                                             //☆
      }                                                                //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub R_Assist_line(int Assist_time)                                    //☆
 {                                                                     //☆
     long tb=CurrentTick();                                            //☆
     while (CurrentTick()-tb<=Assist_time){                            //☆
         if (SENSOR_2<average-11) {                                    //☆
             move5;                                                    //☆
         } else if (SENSOR_2<average-7){                               //☆
             move4;                                                    //☆
         } else if (SENSOR_2<average+7){                               //☆
             move3;                                                    //☆
         } else if (SENSOR_2<average+11){                              //☆
             move2;                                                    //☆
         } else {                                                      //☆
             move1;                                                    //☆
         }                                                             //☆
      }                                                                //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub L_line(int Assist_time,int Stop_time)                             //☆
 {                                                                     //☆
     L_Assist_line(Assist_time);                                       //☆
     long t1=CurrentTick();                                            //☆
     while (CurrentTick()-t1<=Stop_time){                              //☆
         if (SENSOR_2<average-11) {                                    //☆
             move1;                                                    //☆
         } else if (SENSOR_2<average-7){                               //☆
             move2;                                                    //☆
             t1=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+7){                               //☆
             move3;                                                    //☆
             t1=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+11){                              //☆
             move4;                                                    //☆
             t1=CurrentTick();                                         //☆
         } else {                                                      //☆
             move5;                                                    //☆
             t1=CurrentTick();                                         //☆
          }                                                            //☆
      }                                                          //☆
     Off(OUT_AB);                                                      //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub R_line(int Assist_time,int Stop_time)                             //☆
 {                                                                     //☆
     R_Assist_line(Assist_time);                                       //☆
                                                                       //☆
     long t2=CurrentTick();                                            //☆
     while (CurrentTick()-t2<=Stop_time){                              //☆
         if (SENSOR_2<average-11) {                                    //☆
             move5;                                                    //☆
         } else if (SENSOR_2<average-8){                               //☆
             move4;                                                    //☆
             t2=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+6){                               //☆
             move3;                                                    //☆
             t2=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+11){                              //☆
             move2;                                                    //☆
             t2=CurrentTick();                                         //☆
         } else {                                                      //☆
             move1;                                                    //☆
             t2=CurrentTick();                                         //☆
         }                                                             //☆
      }                                                                //☆
     Off(OUT_AB);                                                      //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub White_to_Black(int blight,int A_speed,int B_speed)                //☆
 {                                                                     //☆
     while (SENSOR_2>blight){                                          //☆
         OnFwd(OUT_A,A_speed);                                         //☆
         OnFwd(OUT_B,B_speed);                                         //☆
      }                                                                //☆
     Off(OUT_AB);                                                      //☆
 }                                                                     //☆
 sub Black_to_White(int blight,int A_speed,int B_speed)                //☆
 {                                                                     //☆
     while (SENSOR_2<blight){                                          //☆
         OnFwd(OUT_A,A_speed);                                         //☆
         OnFwd(OUT_B,B_speed);                                         //☆
      }                                                                //☆
     Off(OUT_AB);                                                      //☆
 }                                                                     //☆
 sub Start_Set()                                                       //☆
 {                                                                   //,砲堂鮴
     Start_SE();                                                     //,砲堂鮴
     move3;                                                          //,砲堂鮴
     Wait(600);                                                      //,砲堂鮴
     White_to_Black(48,30,5);                                        //,砲堂鮴
 }                                                                   //,砲堂鮴
 
 
 sub catch_cop(long ang1)                                              //※
 {                                                                     //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,-SLOW,ang1);                                    //※
 }                                                                     //※
                                                                       //※
 sub release_cop(long ang2)                                            //※
 {                                                                     //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,SLOW,ang2);                                     //※
 }                                                                     //※
                                                                       //※
 sub release_ball()                                                    //※
 {                                                                     //※
     ResetTachoCount(OUT_ABC);                                         //※
     OnFwd(OUT_AB,SLOW);                                               //※
     Wait(700);                                                        //※
     Off(OUT_AB);                                                      //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,-SLOW,50);                                      //※
     OnFwd(OUT_C,-20);                                                 //※
     Wait(1000);                                                       //※
     OnFwd(OUT_AB,-SLOW);                                              //※
     Wait(700);                                                        //※
     Off(OUT_AB);                                                      //※
 }                                                                     //※
                                                                       //※
 sub keep_cop()                                                        //※
 {                                                                     //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,-SLOW,50);                                      //※
     OnFwd(OUT_C,-20);                                                 //※
 }                                                                     //※
 
 task main()
 {
     SetSensorLight(S2);                                             //光センサーの起動
     SetSensorLowspeed(S3);                                          //超音波センサーの起動
     Start_Set();                                                    //,砲堂鮴
     R_line(300,150);                                                //,砲堂鮴
 
     d=searchDirection(15);                                            //※
     if(d>5.0){                                                        //※
         catch_cop(700);                                               //※
         OnFwd(OUT_AB,SLOW);                                           //※
         Wait(1400);                                                   //※
         Off(OUT_AB);                                                  //※
         catch_cop(300);                                               //※
         OnFwd(OUT_AB,-SLOW);                                          //※
         Wait(100);                                                    //※
         Off(OUT_AB);                                                  //※
     }                                                                 //※
     ResetTachoCount(OUT_A);                                           //※(モーターAの回転角度をリセット)
     RotateMotor(OUT_A,-SLOW,370);                                     //※(モーターAを370度回転させる。)
     OnFwd(OUT_AB,SLOW);                                               //※
     Wait(600);                                                        //※
     Off(OUT_AB);                                                      //※
     catch_cop(40);                                                    //※
     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);                                                  //※(紙コップをはなす)
     tag();                                                            //※(紙コップを重ねる)
     keep_cop();                                                       //※
     tag();                                                            //※(紙コップを重ねる)
     OnFwd(OUT_AB,-SLOW);                                              //※
     Wait(1000);                                                       //※
     Off(OUT_AB);                                                      //※
 }

前回の私のレポート読んだ方であるなら、フィールドの移動方法が全く一緒なのを理解していただけるだろうか。なのでSEや音が出るタイミングは課題2と同じである。

紙コップ関連には私は触れることができないが、移動については触れさせてもらう。

*** 左側機体のプログラムの解説 [#qdc2677e]
場面としてはスタート地点から紙コップを取るところまでの移動である。

 sub Start_Set()                 //ライントレースを始める為のプログラム
 {
     Start_SE();                 //スタートのSE
     move3;                      //初めのラインの囲いから出る為のプログラム
     Wait(600);
     White_to_Black(48,30,5);    //このプログラムでラインの境界線を確実に探し当てることができる
 }

     Start_Set();
     R_line(300,150);

上記の移動の説明をする。このコースの出発時は黒線で囲まれているため、まずそこを抜け出さなければならない。その後、コースに復帰もしなくてはならないため少し特殊なサブのプログラムが用いられている。

&ref(2017b/Member/riko/Mission3/左側機体のプログラムの解説.PNG,400x300,左側機体のプログラムの解説);


言葉だけでは分かりずらいの図で表す。上はスタート地点から始まっている。黄色の矢印はただの直進を表している。灰色の円は光センサーの位置を表しており、その中の数字はその時の明るさの数値を表している。赤い矢印はプログラムによる移動を表している。

ラインを見つけた後、右側のライントレースを行い交差点認識したところで紙コップをとる動きが始まる。
*** 左側機体のプログラムの解説 [#nf966642]
場面としては紙コップからピンポン玉を取り出した後、紙コップをもう一台と重ねるための連携場所に行くための移動である。

     OnFwd(OUT_AB,-SLOW);
     Wait(1000);
     Off(OUT_AB);

まず上記のプログラムは紙コップを持ち上げた場面からの移動でまっすぐ後ろに下がっているだけである。黄色い矢印は秒数管理における移動を表している。

&ref(2017b/Member/riko/Mission3/左側機体のプログラムの解説_1.PNG,600x200,左側機体のプログラムの解説_1);

     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);

上記のプログラムは、紙コップをもう一台と重ねるための連携場所に行くための移動である。

&ref(2017b/Member/riko/Mission3/左側機体のプログラムの解説_2.PNG,400x300,左側機体のプログラムの解説_2);

青い矢印はバック走行を表している。





















** 右側機体(親機)のプログラム [#w1f74bf0]
以下は右側機体の全体のプログラムとなっている。

〇私以外が書いたプログラムはコメントとして「※」を書いておきます。なので「※」がついていてわからない箇所がある場合は私の班の人のレポートを読んでください。私が分かる部分はこちらでも()内で簡単に説明はします。

〇私が課題2で使ったプログラムと同じ部分にはコメントとして「☆」を書いておきます。

 #define SO 392                                                        //☆
 #define DO 523                                                        //☆
 #define MI 659                                                        //☆
 #define SO_H 784                                                      //☆
 #define SI 988                                                        //☆
 #define DO_H 1047                                                     //☆
 #define MI_H 1318                                                     //☆
 #define RE 1175                                                       //☆
 #define SO_SH 1568                                                    //☆
 sub pose_SE()                                                         //☆
     PlayTone(MI_H,90);Wait(100);                                      //☆
     PlayTone(DO_H,90);Wait(100);                                      //☆
     PlayTone(MI_H,90);Wait(100);                                      //☆
     PlayTone(DO_H,90);Wait(100);                                      //☆
 }                                                                     //☆
 sub one_UP_SE()                                                       //☆
 {                                                                     //☆
     PlayTone(MI,110);Wait(120);                                       //☆
     PlayTone(SO_H,110);Wait(120);                                     //☆
     PlayTone(MI_H,110);Wait(120);                                     //☆
     PlayTone(DO_H,110);Wait(120);                                     //☆
     PlayTone(RE,110);Wait(120);                                       //☆
     PlayTone(SO_SH,110);Wait(120);                                    //☆
 }                                                                     //☆
 sub coin_SE()                                                         //☆
 {                                                                     //☆
     PlayTone(SI,90);Wait(100);                                        //☆
     PlayTone(MI_H,140);Wait(150);                                     //☆
 }                                                                     //☆
 sub Start_SE()                                                        //☆
 {                                                                     //☆
     PlayTone(MI,100);Wait(110);                                       //☆
     PlayTone(MI,100);Wait(250);                                       //☆
     PlayTone(MI,100);Wait(160);                                       //☆
     PlayTone(DO,90);Wait(100);                                        //☆
     PlayTone(MI,90);Wait(230);                                        //☆
     PlayTone(SO_H,90);Wait(420);                                      //☆
     PlayTone(SO,170);Wait(180);                                       //☆
 }                                                                     //☆  
 
 #define FAST 50                                                       //※
 #define SLOW 30                                                       //※
 #define CONN 1                                                        //※
 #define SIGNALON1 11                                                  //※
 #define SIGNALON2 12                                                  //※
                                                                       //※
 const float diameter=5.45;                                            //※
 const float tread=11.3;                                               //※
 const float pi=3.1415;                                                //※
                                                                       //※
 int d;                                                                //※
                                                                       //※
 sub keep_cop()                                                        //※
 {                                                                     //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,-SLOW,50);                                      //※
     OnFwd(OUT_C,-20);                                                 //※
 }                                                                     //※
                                                                       //※
 sub fwdDist(float d)                                                  //※
 {                                                                     //※
     long angle=d/(diameter*pi)*360.0;                                 //※
     RotateMotorEx(OUT_AB,SLOW,angle,0,true,true);                     //※
 }                                                                     //※
                                                                       //※
 sub turnAng(long ang)                                                 //※
 {                                                                     //※
     long angle=tread/diameter*ang;                                    //※
     RotateMotorEx(OUT_AB,SLOW,angle,100,true,true);                   //※
 }                                                                     //※
                                                                       //※
 int searchDirection(long 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);                                                        //※
     return d_min;                                                     //※
 }                                                                     //※
                                                                       //※
 sub tag()                                                             //※
 {                                                                     //※
     keep_cop();                                                       //※
     d=searchDirection(15);                                            //※
                                                                       //※
     if(d>5.0){                                                        //※
         SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);                    //※
         Wait(5000);                                                   //※
         fwdDist(d-8.0);                                               //※
         ResetTachoCount(OUT_ABC);                                     //※
         RotateMotorEx(OUT_AB,-SLOW,40,0,true,true);                   //※
         RotateMotor(OUT_C,SLOW,50);                                   //※
                                                                       //※
         SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);                    //※
         Wait(5000);                                                   //※
         RotateMotor(OUT_C,SLOW,100);                                  //※
         ResetTachoCount(OUT_ABC);                                     //※
         RotateMotor(OUT_C,SLOW,720);                                  //※
         RotateMotorEx(OUT_AB,-SLOW,120,0,true,true);                  //※
     }                                                                 //※
 }                                                                     //※
                                                                       //※
 sub catch_cop(long ang1)                                              //※
 {                                                                     //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,-SLOW,ang1);                                    //※
 }                                                                     //※
                                                                       //※
 sub release_cop(long ang2)                                            //※
 {                                                                     //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,SLOW,ang2);                                     //※
 }                                                                     //※
                                                                       //※
 sub release_ball()                                                    //※
 {                                                                     //※
     ResetTachoCount(OUT_ABC);                                         //※
     OnFwd(OUT_AB,SLOW);                                               //※
     Wait(700);                                                        //※
     Off(OUT_AB);                                                      //※
     ResetTachoCount(OUT_C);                                           //※
     RotateMotor(OUT_C,-SLOW,50);                                      //※
     OnFwd(OUT_C,-20);                                                 //※
     Wait(1000);                                                       //※
     OnFwd(OUT_AB,-SLOW);                                              //※
     Wait(700);                                                        //※
     Off(OUT_AB);                                                      //※
 }                                                                     //※
 
 
 #define move1 OnFwd(OUT_A,40);OnFwd(OUT_B,-35);                       //☆
 #define move2 OnFwd(OUT_A,30);OnFwd(OUT_B,-20);                       //☆
 #define move3 OnFwd(OUT_A,54);OnFwd(OUT_B,54);                        //☆
 #define move4 OnFwd(OUT_B,30);OnFwd(OUT_A,-20);                       //☆
 #define move5 OnFwd(OUT_B,40);OnFwd(OUT_A,-35);                       //☆
 #define average 45                                                    //☆
 
 
 sub Stop_Motion()                                                     //☆
 {                                                                     //☆
     Wait(300);                                                        //☆
     pose_SE();                                                        //☆
     Wait(1000);                                                       //☆
 }                                                                     //☆
 sub L_Assist_line(int Assist_time)                                    //☆
 {                                                                     //☆
     long ta=CurrentTick();                                            //☆
     while (CurrentTick()-ta<=Assist_time){                            //☆
         if (SENSOR_2<average-11) {                                    //☆
             move1                                                     //☆
         }else if (SENSOR_2<average-7){                                //☆
             move2;                                                    //☆
         } else if (SENSOR_2<average+7){                               //☆
             move3;                                                    //☆
         } else if (SENSOR_2<average+11){                              //☆
             move4;                                                    //☆
         } else {                                                      //☆
             move5;                                                    //☆
         }                                                             //☆
      }                                                                //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub R_Assist_line(int Assist_time)                                    //☆
 {                                                                     //☆
     long tb=CurrentTick();                                            //☆
     while (CurrentTick()-tb<=Assist_time){                            //☆
         if (SENSOR_2<average-11) {                                    //☆
             move5;                                                    //☆
         } else if (SENSOR_2<average-7){                               //☆
             move4;                                                    //☆
         } else if (SENSOR_2<average+7){                               //☆
             move3;                                                    //☆
         } else if (SENSOR_2<average+11){                              //☆
             move2;                                                    //☆
         } else {                                                      //☆
             move1;                                                    //☆
         }                                                             //☆
      }                                                                //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub L_line(int Assist_time,int Stop_time)                             //☆
 {                                                                     //☆
     L_Assist_line(Assist_time);                                       //☆
     long t1=CurrentTick();                                            //☆
     while (CurrentTick()-t1<=Stop_time){                              //☆
         if (SENSOR_2<average-11) {                                    //☆
             move1;                                                    //☆
         } else if (SENSOR_2<average-7){                               //☆
             move2;                                                    //☆
             t1=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+7){                               //☆
             move3;                                                    //☆
             t1=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+11){                              //☆
             move4;                                                    //☆
             t1=CurrentTick();                                         //☆
         } else {                                                      //☆
             move5;                                                    //☆
             t1=CurrentTick();                                         //☆
          }                                                            //☆
      }                                                          //☆
     Off(OUT_AB);                                                      //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub R_line(int Assist_time,int Stop_time)                             //☆
 {                                                                     //☆
     R_Assist_line(Assist_time);                                       //☆
                                                                       //☆
     long t2=CurrentTick();                                            //☆
     while (CurrentTick()-t2<=Stop_time){                              //☆
         if (SENSOR_2<average-11) {                                    //☆
             move5;                                                    //☆
         } else if (SENSOR_2<average-8){                               //☆
             move4;                                                    //☆
             t2=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+6){                               //☆
             move3;                                                    //☆
             t2=CurrentTick();                                         //☆
         } else if (SENSOR_2<average+11){                              //☆
             move2;                                                    //☆
             t2=CurrentTick();                                         //☆
         } else {                                                      //☆
             move1;                                                    //☆
             t2=CurrentTick();                                         //☆
         }                                                             //☆
      }                                                                //☆
     Off(OUT_AB);                                                      //☆
     coin_SE();                                                        //☆
 }                                                                     //☆
 sub White_to_Black(int blight,int A_speed,int B_speed)                //☆
 {                                                                     //☆
     while (SENSOR_2>blight){                                          //☆
         OnFwd(OUT_A,A_speed);                                         //☆
         OnFwd(OUT_B,B_speed);                                         //☆
      }                                                                //☆
     Off(OUT_AB);                                                      //☆
 }                                                                     //☆
 sub Black_to_White(int blight,int A_speed,int B_speed)                //☆
 {                                                                     //☆
     while (SENSOR_2<blight){                                          //☆
         OnFwd(OUT_A,A_speed);                                         //☆
         OnFwd(OUT_B,B_speed);                                         //☆
      }                                                                //☆
     Off(OUT_AB);                                                      //☆
 }                                                                     //☆
 
 
 #define reverse_move OnFwd(OUT_A,-54);OnFwd(OUT_B,-50);             //,砲堂鮴
                                                                     //,砲堂鮴
 sub reverse_Start_Set()                                             //,砲堂鮴
 {                                                                   //,砲堂鮴
    reverse_move;                                                    //,砲堂鮴
    Start_SE();                                                      //,砲堂鮴
    Wait(2000);                                                      //,砲堂鮴
    White_to_Black(48,20,35);                                        //,砲堂鮴
 }                                                                   //,砲堂鮴
 
 task main()
 {
     SetSensorLight(S2);                                             //光センサーの起動
     SetSensorLowspeed(S3);                                          //超音波センサーの起動
     reverse_Start_Set();                                            //,砲堂鮴
     L_line(1300,110);                                               //,砲堂鮴
 
     ResetTachoCount(OUT_A);                                           //※(モーターAの回転角度をリセット)
     RotateMotor(OUT_A,-SLOW,150);                                     //※(モーターAを−150度回転)
     d=searchDirection(15);                                            //※
     if(d>5.0){                                                        //※
         catch_cop(600);                                               //※
         OnFwd(OUT_AB,SLOW);                                           //※
         Wait(1000);                                                   //※
         Off(OUT_AB);                                                  //※
         catch_cop(500);                                               //※
         OnFwd(OUT_AB,-SLOW);                                          //※
         Wait(400);                                                    //※
         Off(OUT_AB);                                                  //※
     }                                                                 //※
     ResetTachoCount(OUT_B);                                           //※(モーターBの回転角度をリセット)
     RotateMotor(OUT_B,-SLOW,110);                                     //※(モーターBを−110度回転)
     release_ball();                                                   //※
     RsetTachoCount(OUT_A);                                            //※(モーターAの回転角度をリセット)
     RotateMotor(OUT_A,-SLOW,130);                                     //※(モーターAを−130度回転)
     tag();                                                            //※(紙コップを重ねる)
 
     OnFwd(OUT_AB,-SLOW);                                            //△砲堂鮴
     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);                                       //△砲堂鮴
 
     d=searchDirection(15);                                            //※
     if(d>5.0){                                                        //※
         catch_cop(600);                                               //※
         OnFwd(OUT_AB,SLOW);                                           //※
         Wait(1000);                                                   //※
         Off(OUT_AB);                                                  //※
         catch_cop(500);                                               //※
         OnFwd(OUT_AB,-SLOW);                                          //※
         Wait(400);                                                    //※
         Off(OUT_AB);                                                  //※
     }                                                                 //※
 
     White_to_Black(33,-30,-30);                                     //にて解説
     L_line(150,130);                                                //にて解説
     Black_to_White(48,30,30);                                       //にて解説
     release_ball();                                                 //にて解説
  
     ResetTachoCount(OUT_A);                                           //※(モーターAの回転角度をリセット)
     RotateMotor(OUT_A,-SLOW,130);                                     //※(モーターAを−130度回転)
     tag();                                                            //※(紙コップを重ねる)
     ResetTachoCount(OUT_C);                                           //※(モーターCの回転角度をリセット)
     RotateMotor(OUT_C,-SLOW,1100);                                    //※(モーターCを−1100度回転)
 
     White_to_Black(33,-30,-30);                                     //い砲堂鮴
     Black_to_White(48,-30,-30);                                     //い砲堂鮴
     White_to_Black(33,-30,-30);                                     //い砲堂鮴
     OnFwd(OUT_AB,SLOW);                                             //い砲堂鮴
     Wait(300);                                                      //い砲堂鮴
     Off(OUT_AB);                                                    //い砲堂鮴
     ResetTachoCount(OUT_C);                                         //い砲堂鮴
     RotateMotor(OUT_C,SLOW,1200);                                   //い砲堂鮴
 }


*** 右側機体のプログラムの解説 [#e122a2ce]
場面としてはスタート地点から紙コップを取るところまでの移動である。

 #define reverse_move OnFwd(OUT_A,-54);OnFwd(OUT_B,-50);
 
 sub reverse_Start_Set()
 {
    reverse_move;
    Start_SE();
    Wait(2000);
    White_to_Black(48,20,35);
 }

まず、初めの走行をバックから始める。そのためのプログラムが上記のものとなる。

    reverse_Start_Set();
    L_line(1300,110);

&ref(2017b/Member/riko/Mission3/右側機体のプログラムの解説.PNG,400x300,右側機体のプログラムの解説);

動きとしては後ろに下がり、その後黒線を見つけ、そのまま交差点まで移動する。
*** 右側機体のプログラムの解説 [#q080aeae]
場面としては1個目の紙コップを重ねた後、次の紙コップを見つける動作の手前までの移動である。

    OnFwd(OUT_AB,-SLOW);
    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);

&ref(2017b/Member/riko/Mission3/右側機体のプログラムの解説.PNG,400x300,右側機体のプログラムの解説);

動きとしては秒管理によるバックの後、黒線を探し、ライントレースにて交差点を発見。そこから少しずれることで紙コップの方向を向く。
*** 右側機体のプログラムの解説 [#t295b938]
場面としては2個目の紙コップを捕まえた後、それを割りばし内に移動させるための移動である。

    White_to_Black(33,-30,-30);
    L_line(150,130);
    Black_to_White(48,30,30);
    release_ball();

&ref(2017b/Member/riko/Mission3/右側機体のプログラムの解説.PNG,400x300,右側機体のプログラムの解説);

動きとしてはバックにて黒線を探し、そのままライントレースで交差点を発見。前に少し進んだ後、紙コップを持ち上げることでピンポン玉を割りばし内に出す。
*** 右側機体のプログラムの解説 [#v3c280da]
場面としては紙コップを3つ重ねた後、それを目的地にもっていくための移動である。

    White_to_Black(33,-30,-30);
    Black_to_White(48,-30,-30);
    White_to_Black(33,-30,-30);
    OnFwd(OUT_AB,SLOW);
    Wait(300);
    Off(OUT_AB);
    ResetTachoCount(OUT_C);
    RotateMotor(OUT_C,SLOW,1200);

&ref(2017b/Member/riko/Mission3/右側機体のプログラムの解説.PNG,400x300,右側機体のプログラムの解説);

動きとしては紙コップを重ね終えた場所からバックで確実に目的の黒線まで下がり、その後ゴールに少しだけ近づき紙コップを置く。

* 結果・反省・感想 [#w4d930a0]
** 結果 [#m39f8878]
1回目は、子機が1個ピンポン玉を枠内に入れたが、子機、親機も予期せぬ動作をして失敗し2点だった。2回目は子機が2個ピンポン玉を枠内に入れたが、その後左側スタート地点の障害物のコップを動かし減点。最終的に計4点となった。

技術点としては平均8.8点となり、全体合計は12.8点。順位は9チーム中6位という結果になった。
** 反省 [#y702adce]
今回、ロボットもプログラミングも全体的に作りが甘かったと思われる。

超音波センサーの仕組みは左右どちらかから超音波を発し、反対側で受け取っているものらしく、縦向きにつけると誤検知が減らせるとかんがえられる。

また、超音波センサーの縦横関係なく、工夫して2回の検知で確実に紙コップの位置をとれるようにできたのではないかとも考えられる。

アームの作りや機体全体の作りをもっと柔軟な発想で生み出すことが大切であると痛感した。
** 感想 [#g7ad1f77]
今回、課題3の取り掛かりがテスト終了後でほとんど時間が足りないことが今回の機体やプログラミングの甘さを招いたと思う。トライ&エラーを繰り返しより確実なものを作るのが私の基本的なやり方であったがそれをする時間があまりにも足りず、このような結果となってしまった。

しかし、正直なところそんなことはどうでもよいとも思える。なぜなら、このゼミを通して本当に普通では学べない様々なことを学べることができたからだ。初めはプログラムを打つことすらできず、本当にこのゼミをやり通すことができるのかと不安であったがチーム内、時にはチーム外の人達とも助け合いながらロボットもプログラムも完成させ、やり遂げることができた。終わり良ければ総て良しという言葉の実感を久しぶりに得たような気がする。このゼミに受講することができ、本当に良かったと思えました。今まで本当に、本当にありがとうございました。

* 最後に [#zeb05996]
ここまでいろいろとレポートに書いたが改善したい点やほかの形の機体など、まだまだ試してみたいことが山ほどある。それらもレポートに書きたかったが予定が色々重なり、時間が足りず断念する羽目になった。

そして、もしもこのレポートを読んでいる人がこのゼミを受けているのなら、私のものやほかの人の作品から様々なヒントを得てより良いロボット、プログラムを作ることを願っている。そして、最後まであきらめず頑張ってほしい。

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