[[2017a/Member]]
#contents
*課題3と担当 [#r967ec7c]
**課題3 [#l471b155]
ロボットを2台使い、[[課題2:http://yakushi.shinshu-u.ac.jp/robotics/?2017a%2FMission2]]
で使ったコースを用いてコース上の様々な位置に置かれた缶を指定された位置に入れ、得点を競う。このとき、缶を積み上げると得点が高くなる。詳しくは[[課題3:http://yakushi.shinshu-u.ac.jp/robotics/?2017a%2FMission3]]を参照。
**担当した箇所 [#h06a53a2]
班のメンバーはRyoma、Kawachan、rayonne、kkの4人である。この班はロボット2台を合体させずに、缶を積み上げるロボットと缶を運ぶロボットを作った。Ryoma、Kawachanが積み上げるロボットを、rayonne、私が運ぶロボットを担当した。よって、このページでは、缶を運ぶロボットについて説明する。缶を積み上げるロボットについては、[[Ryoma:http://yakushi.shinshu-u.ac.jp/robotics/?2017a%2FMember%2FRyoma%2FMission3]]、[[Kawachan:http://yakushi.shinshu-u.ac.jp/robotics/?cmd=edit&page=2017a%2FMember%2FKawachan%2FMission3&refer=2017a%2FMember]]を参照。
#ref(./積み上げロボット.JPG,50%,積み上げロボット);
積み上げロボット
#ref(./持ち運びロボット.png,50%,運搬ロボット);
運搬ロボット
*ロボット [#k57b7f1c]
#ref(./持ち運びロボット.png,50%,運搬ロボット);
&br;
#ref(./持ち運びロボット 正面.JPG,50%,運搬ロボット正面);
ライントレースをして缶を取りに行くロボットである。課題2で作ったロボット(詳しくは[[kk:http://yakushi.shinshu-u.ac.jp/robotics/?2017a%2FMember%2Fkk%2FMission2]])を基本に、缶をいれるアームを取り付けた。缶を1つ取るごとに地点Tに運ぶので、アームは缶1つ分の大きさになっている。とてもシンプルな構造である。
*プログラム [#m616e83c]
**全体的な説明 [#u4c673a4]
運ぶ缶はE、F、EF間のカーブの3つのみである。他の缶は時間が足りず、着手できなかった。また、Tの缶は積み上げロボットが動き出すときに押しのけられて排除される。
&br;基本的には黒線をトレースして缶を運ぶが、途中でトレースではうまく缶をアームに入れられない箇所や、Tに缶を置くときなどは、トレースをせずに黒線から外れて動くこともある。詳しくはルートの項目で説明する。
**ルート [#me834eb6]
運搬ロボットの役目は缶をTまで運ぶことである。缶をTに運んでから積み上げロボットに合図を送ると、あとは積み上げロボットが缶を回収し、積み上げる。
缶をTに運ぶルートは、A-Eの缶を取る-Tに置く-Fの缶を取る-Tに置く-EF間の缶を取る-Tに置く-しばらく缶から離れる-3段に積み上げられた缶をゴールの中に入れる-缶から離れる、である。細かくわけて別々に詳しく説明する。下図の赤線はトレースして動く箇所、緑はトレースしないで動く箇所である。コースの画像は[[課題3:http://yakushi.shinshu-u.ac.jp/robotics/?2017a%2FMission3]]のものを使っている。
***A-Eの缶を取る-Tに置く[#e8fab088]
#ref(./start-t.JPG,50%,A-E-T);
A-E-P-S-R-Tの目の前 と動く。Rまでは黒線をトレースして、Rからは秒数を指定し回転、直進する。これは、缶をTに置くためには、アーム部分の大きさを考えて機体は交差点の手前で止まらないといけないが、私の作ったプログラムでは直進の途中でトレースをやめることができなかったからである。なので、Tに缶を置くときはいつもトレースではなく普通に直進する。また、Tに缶を置いたら積み上げロボットに合図を出し、積み上げロボットは動き出す。
***T-Fの缶を取る-Tに置く [#h81eaa77]
#ref(./f-t.JPG,50%,T-F-T);
缶を置いた後、一度バックしてRを越えたあたりまで行く。その後機体は大きく時計回りをして円弧SRを光センサーで見つけ出す。そこからトレースでS-Pと動いたら、Pでしばらく待機し、積み上げロボットが最初に運んだ缶をつかみコースから離れるための時間をかせぐ。ある程度待機したら、Fの方向を向き、直進してFの缶を取る。その後、再び時計回りをして円弧QRを見つけ、トレースし、Rへ行く。Rからは一つ目の缶と同じ要領でTに缶を置く。
&br;PからFに直線で向かうのは、P-Q-FとトレースしていくとQからFの方向を向くときにアームが缶にあたり、缶を弾き飛ばしてしまうからである。
***T-EF間の缶を取る-Tに置く [#l46bbe24]
#ref(./ef-t.JPG,50%,T-EF-T);
同じようにバック、時計回りで円弧SRを見つける。そこからS-P-E-EF間で缶を取る-F-Q-P-S-Rとトレースし続ける。ただし、Pで一度止まって積み上げロボットが仕事をする時間を稼ぐ。そして、Rまで来たらまた同じ要領で缶をTまで運ぶ。
&br;EF間の缶は黒線の右側をトレースしていくと自動的にアームに収まる。
&br;また、Qに着いた後にQ-Rと向かわずにQ-P-S-Rと遠回りするのは、F-Qは線の右側をトレースしていて、線の右側をトレースしていると交差点を認識するときに機体が少し右に曲がってしまうので、交差点を左に曲がるプログラムを作るよりも、そのまま右に曲がるほうが簡単だったからである。
***T-一度離れる-ゴールに缶を押し込む [#kf3efc98]
#ref(./end.JPG,50%,end);
3つ目の缶をTに運んだあと、積み上げロボットが作業する間は運搬ロボットはTから離れていないといけない。また、積みあがった缶がゴールの円よりR側になって、ゴールにきちんと入っていないことがある。よって、同じ様にバック、時計回りで円弧PSを見つけ、S-Pとトレースして待機し積み上げロボットが缶を積み上げるのを待つ。待機し終わったらP-Q-R-Tとトレースし、R-T間で積みあがった缶を取る(大抵の場合はきちんとアームにはいる)。このとき、左側をトレースしているので、Tで交差点と判断して停止するとき、少し左に曲がってから停止する。この動作で缶をゴールにいれる。最後にバックして缶から離れて終了する。
**プログラム [#j635eab0]
時間が足りず、最後に調整や変更した箇所のプログラムが整理されていない。サブルーチンを使えば簡単にできるところを何度も書いていたりして見にくくなってしまっている。
&br;
&br;まず、定義、変数を書く。
#define CONN 1 //積み上げロボットとの接続番号
int a; //トレースして交差点判断に使う
long t; //時間を測るために使う
次にサブルーチンを書く。
&br;�,�ちんと動いているかを確認するために音を鳴らす。
sub sound_up() //SOUND_UPを鳴らす。
{
PlaySound(SOUND_UP);
}
��黒線の右側、左側をトレースする。基本の交差点の判別方法は[[課題2:http://yakushi.shinshu-u.ac.jp/robotics/?2017a%2FMember%2Fkk%2FMission2]]のものと一緒であるが、課題2のプログラムが出来の悪いものだったので、今回はサブルーチンの書き方を変更している。引数x秒以内ならトレースは終了しないが、x秒を越えてから機体が急角度で曲がると機体は停止するようになっている。
sub migi_susumu(int x) //黒線の右側をトレースする。xは出発する交差点の曲がり始めや誤認しやすいカーブを超える大体の秒数を入れる。
{
t=CurrentTick();
while(CurrentTick()-t<x){
a=0;
while(a<=3){
if(SENSOR_1>=55){ //左
OnFwd(OUT_A,30);
OnRev(OUT_C,30);
}else if(SENSOR_1>
OnFwd(OUT_A,30);
Off(OUT_C);
}else if(SENSOR_1>=45){
OnFwd(OUT_C,30);
Off(OUT_A);
}else{ //右
OnFwd(OUT_C,30);
OnRev(OUT_A,30);
a=a+1;
}
}
}
sound_up();
}
sub hidari_susumu(int y) //黒線の左側をトレースする。yは上のxと同じ。
{
t=CurrentTick();
while(CurrentTick()-t<y){
a=0;
while(a<=3){
if(SENSOR_1>=55){ //右
OnFwd(OUT_C,30);
OnRev(OUT_A,30);
}else if(SENSOR_1>=50){
OnFwd(OUT_C,30);
Off(OUT_A);
}else if(SENSOR_1>=45){
OnFwd(OUT_A,30);
Off(OUT_C);
}else{ //左
OnFwd(OUT_A,30);
OnRev(OUT_C,30);
a=a+1;
}
}
}
sound_up();
}
�5‖里聾鮑硬世鯒Ъ韻靴道澆泙襪箸�、少し曲がってから停止するため、交差点を直進したいときは機体の角度を調整、行きたい線上に持っていく。
sub chousei() //黒線の右側をトレースしていたときに使う
{
OnFwd(OUT_A,35); //前を向く
OnRev(OUT_C,35);
Wait(600);
OnFwd(OUT_AC,30); //交差点を越える
Wait(400);
}
sub chousei_2() //黒線の左側をトレースしていたときに使う。やっていることはchousei()と同じ
{
OnFwd(OUT_C,30);
OnRev(OUT_A,30);
Wait(750);
OnFwd(OUT_AC,30);
Wait(500);
}
��S(Q)側からRに来た機体をTの前で停止させる。
sub s_t() //S側からRに来た機体をTの前で停止させる。
{
OnFwd(OUT_C,20); //Tを向く
OnFwd(OUT_A,10);
Wait(600);
OnFwd(OUT_AC,30);
Wait(950);
Off(OUT_AC);
Wait(400);
sound_up();
}
sub q_t() //Q側からRに来た機体をTの前で停止させる。
{
OnRev(OUT_A,15); //Tを向く
OnFwd(OUT_C,40);
Wait(230);
OnFwd(OUT_AC,30);
Wait(600);
sound_up();
}
��Tに缶を置いた後、後退して旋回、円弧SRを見つけ出し、Sまで進む。
sub hukki_s()
{
OnRev(OUT_AC,40);
Wait(950);
OnFwd(OUT_C,35); //この間に直線RTを越え、光センサーが反応しないようにする
OnRev(OUT_A,10);
Wait(1000);
while(SENSOR_1>=50){ //光センサーによって、黒線(円弧SR)がくるまで旋回し続ける。
OnFwd(OUT_C,30);
OnRev(OUT_A,10);
}
Off(OUT_AC);
hidari_susumu(1000); //Sまでトレースする
sound_up();
}
�γ賄�Fの缶を取った後、旋回して円弧QRを見つけ出し、地点Rまで進む。
sub hukki_r()
{
OnFwd(OUT_C,30); //この間に直線EFを越え、光センサーが反応しないようにする
OnRev(OUT_A,10);
Wait(3000);
while(SENSOR_1>=50){ //光センサーによって、黒線(円弧QR)がくるまで旋回し続ける。
OnFwd(OUT_C,30);
OnRev(OUT_A,10);
}
Off(OUT_AC);
hidari_susumu(1500); //Rまでトレースする
sound_up();
}
task main()を書く
task main()
{
SetSensorLight(S1);
OnFwd(OUT_AC,30); //Aから出るため少し直進する
Wait(600);
migi_susumu(1500); //地点E、缶を取る
migi_susumu(1500); //地点P
migi_susumu(1500); //地点S
chousei();
migi_susumu(2000); //地点R
s_t(); //地点Tに缶を置く
RemoteStartProgram(CONN,"taiki.rxe"); //積み上げロボットに合図を送る。この部分をサブルーチンにしておくと便利だった。
hukki_s(); //地点S
chousei_2();
hidari_susumu(2000); //地点P
Off(OUT_AC); //ブレをなくすためにモーターの回転を止める、またしばらく待機する
Wait(20000);
OnFwd(OUT_C,30); //地点Fの方向へ向き、まっすぐ進む
OnRev(OUT_A,30);
Wait(900);
OnFwd(OUT_AC,30);
Wait(1900);
sound_up(); //Fの缶を取った合図
hukki_r(); //地点R
q_t(); //地点Tに缶を置く
OnRev(OUT_A,10);
RemoteStartProgram(CONN,"tumu.rxe"); //積み上げロボットに合図を送るに合図を送る
hukki_s(); //地点S
chousei_2();
hidari_susumu(2000); //地点P
OnFwd(OUT_AC,30); //機体を黒線の左側から右側に変える
Wait(600);
Off(OUT_AC); //待機
Wait(15000);
migi_susumu(1500); //地点E
migi_susumu(28000); //地点Q
migi_susumu(1500); //地点P
chousei();
migi_susumu(2000); //地点S
chousei();
migi_susumu(2000); //地点R
s_t(); //地点Tに缶を置く
OnFwd(OUT_A,30); //積み上げロボットは缶を積む位置が缶を置いた位置よりも前になる。あまりに前に進んでしまうと、ゴールから外れた位置に缶を積み上げてしまうので、少しだけ缶をTよりも前進させる。
OnFwd(OUT_C,35);
Wait(500);
RemoteStartProgram(CONN,"tumu2.rxe"); //積み上げロボットに合図を送る
OnRev(OUT_AC,30); //Tよりも前進した分、後退する
Wait(500);
hukki_s(); //地点S
chousei_2();
hidari_susumu(2000); //地点P
chousei_2();
hidari_susumu(2000); //地点Q
chousei_2();
Off(OUT_AC); //待機
Wait(15000);
hidari_susumu(2000); //地点R
hidari_susumu(1500); //地点T
Off(OUT_AC);
OnRev(OUT_AC,30); //缶から離れる
Wait(1500);
}
*ロボコン結果と総評 [#n4eb9d8d]
ロボコンでは、機体、プログラムともにうまく動き、予定していた行動はすべてとることができた。よって、合計で18点を獲得でき、見事優勝した。こんなにうまくプログラムが動くことが練習ではなかったので、正直びっくりしている。また、本番の朝に電池を変えたことによってうまく動かなくなったりと大変だった。
ロボコンでは、機体、プログラムともにうまく動き、予定していた行動はすべてとることができた。よって、合計で18点を獲得でき、見事優勝した。こんなにうまくプログラムが動くことが練習ではなかったので、正直びっくりしている。しかし、本番の朝に電池を変えたことによってうまく動かなくなったりと大変だった。
&br;今回の課題では、最初は2人ずつに分かれて作業していたので、個々の機体はしっかり動いても、うまく連携させることが難しかった(ロボット同士がぶつかるなど)。分かれて作業するにしても、定期的に連携させていれば、本番直前にプログラムを変更したりしなくてもスムーズに動かせたかもしれない。