#contents *課題の内容 [#u9b90b8a] #ref(2018b/Member/prague/Mission3/2018b-mission3.png,100%,経路1); フィールドの説明 フィールドは課題2で使用した紙を使用する。 〇350ml缶(中が入っていても空でよい)は逆さまにして使い、ロボットのスタート直後にサイコロを〇振って出た目の番号の位置に置く。 〇その番号の次の番号のところにもダミーの缶を置くことができる。ただし6の目が出た場合は6の〇位置と25cm以上離れていない場所ならどこに置いてもよいものとする。距離は缶と缶のもっとも近い部分で測る。 空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。 赤と青のボールは、図のように所定の場所に置いておく。その際、キットに含まれない小さな輪ゴムを使用するものとする。 **ルール [#y3f0fc85] 基本ルール 競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。 図のX地点または(および)Y地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。 赤いボールを図のピンクのいずれかに置いた缶に、青いボールを図の水色のいずれかに置いた缶に、それぞれ乗せる。 開始の合図から5秒以内にスタートボタンを押す作業を完了すること。 競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。 途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 基本得点の計算方法 ボールを一つ乗せればそれぞれ10点、二つとも乗せればボーナス点としてさらに10点。 ダミーの缶を設置した上で、正しい缶に乗せれば、それぞれさらに6点加点する。 ボールを目的の缶に当てることができれば、それぞれ4点。 ボールを同じ領域内の間違った缶に乗せた場合は、それぞれ6点。 ボールを同じ領域内の間違った缶に当てた場合は、それぞれ2点。 ボールを違う領域内の缶に乗せた場合は、それぞれ2点。 ボールを違う領域内の缶に当てた場合は、0点。 目的の缶をもとの位置(直径7cmの円)から少し出してしまった場合は1点減点、半分以上出してしまった場合は2点または取得した得点の半分のいずれか少ないほうを減点、その缶を完全にだしてしまったときは点数を半分にする。 ダミーの缶がもとの位置から移動しても減点はしない。 技術点の計算方法 以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。 得点の目安: ボール探し取りにいくまでの動作 (3点) ボール掴む動作 (3点) ボールを運ぶ動作 (2点) ボールを缶に置く動作 (2点) 2台のNXT、EV3の連携の良さ(2点) 自立型のロボットとしての形や動作の美しさ、斬新さ(2点) その他 (3点) *ロボット [#a4e79040] **ロボットの全体図 [#m5f1452e] #ref(2018b/Member/prague/Mission3/s_mae.jpg,100%,経路1); #ref(2018b/Member/prague/Mission3/s_usiro.jpg,100%,経路1); #ref(2018b/Member/prague/Mission3/s_yoko.jpg,100%,ボールの動き); **ロボットを作る過程 [#u63bad55] 今回の課題を進めるうえでまず作ろうとしたのはベルトコンベアを使ってフォークリフトのようにボールを上げるものだった。 #ref(2018b/Member/prague/Mission3/s_folk.jpg,100%,経路1); しかしこの機構は大きくかさばったり重くてロボットのバランスが悪くなってしまったりと様々な問題が起こったのでこの機構は使わなかった。 そのあとに考えたのがコンベアを使ってボールをすくい上げ、それを転がして間の中に入れるというものである。 この見た目からもわかるように超音波センサがある方を前とするとボールを放つ機構が車体の前方に、ボールを持ち上げるコンベアが車体の後方にあるので車体にかかる重心のバランスが良いという利点がある。よってこの方法ならうまくいきそうだと考え、今回のロボットの制作に取り掛かった。 **車体 [#ae8477a6] 車体については全体図からもわかるように説明書でみられるような比較的スタンダードな形のものにしてある。 今回はボールを取るときと、前に進むとききっちりと180度車体の向きを変える必要があるためジャイロセンサーを使用した。 #ref(2018b/Member/prague/Mission3/jailo.jpg,100%,ジャイロセンサー); ↑ジャイロセンサー これを使うと車体を回転させたときの角度を測れるようになりセンサーが正確なら毎回同じだけ回転してくれる 工夫した点としては、車体の前頭部に付けた2つの角を作ったことである。この役割は缶とロボットが少し左右にずれてしまったときこの角の部分にあてることで、減点しない程度に缶を動かしロボットとの距離を修正するというものである。 #ref(2018b/Member/prague/Mission3/s_tuno.jpg,100%,経路1); ボールを投げるとき...↓ #ref(2018b/Member/prague/Mission3/s_cancan.jpg,100%,経路1); このようになる。 **ボールを扱う機構 [#ze37cd98] #ref(2018b/Member/prague/Mission3/s_korokoro.1.jpg,100%,ボールの動き); ↑図のようにボールが上がっていき転がって缶の上に置かれる この機構を使う上でまず気を付けなければならないのはどのようにボールを上げるかということである。解決法としてはコンベアにかきづめのようなものを付け、車体とコンベアでボールを挟んで持ち上げることにした。コンベアと壁で挟まれているうちはボールを持ったまま保管でき、放つときにはボールを車体の上まで上げれば自然に転がっていく。 #ref(2018b/Member/prague/Mission3/s_belt.jpg,100%,経路1); 図の黄色く囲まれた場所がかきづめの役割を果たす。 またかきづめは二つ付けてあるので1度に赤いボール、青いボールどちらも保持することができる。 これで一回球を置いてからもう一つの球を取りに行く手間を省くことができる。 #ref(2018b/Member/prague/Mission3/s_bear.jpg,120%,ボールを乗せる); コンベアの図 2つかきづめがある #ref(2018b/Member/prague/Mission3/s_double.jpg,100%,ボールを乗せる); ↑ボールが二つのる。コンベアを途中で止めれば、どちらか片方だけのボールを放出することも可能 また後ろにコンベアを付けることで超音波センサーがボールを持つ機構の動きにとらわれずいつでも缶の位置を把握できるようになった。 続いてボールを転がす機構について説明する。基本的には滑り台のようにボールを転がした。この際ただ転がすだけだとボールの勢いが強く缶を大きくはみ出し落ちてしまうので、勢いを相殺するための壁のようなものを取り付けた。 あまり硬い防護壁のようなものを作ってしまうと、ロボットが缶に近づいたときに壁に当たって缶が動いてしまったり、ロボットと缶の距離が少しでも離れると缶の上に落ちてくれなくなるので割と簡単な力で動くように作った。そうすることで缶のような重いものに当たっいても間違えて動かしてしまうことはなく、ボールのような軽いものに対しては効果を発揮してくれる。 #ref(2018b/Member/prague/Mission3/s_can.jpg,100%,ボールの動き); *プログラミング [#vec07fde] #!/usr/bin/env python3 from ev3dev.ev3 import * import time ml=LargeMotor('outA') * mr=LargeMotor('outD') ma=LargeMotor('outB') cs=ColorSensor('in3') us=UltrasonicSensor('in4') gs=GyroSensor('in1') def stop(): #ロボットを停止させる ml.stop() mr.stop() def linetrace_rin(): #線の左側のライントレース c1=cs.value() while c1>13: c1=cs.value() x=(abs(c1-10)/70)*100 if x>100: x=100 l=(x/100)*210-30 r=150-l ml.run_forever(speed_sp=l,stop_action='brake') mr.run_forever(speed_sp=r,stop_action='brake') stop() def linetrace_lin(): #線の右側のライントレース c1=cs.value() while c1>13: c1=cs.value() x=abs((c1-10)/70)*100 if x>100: x=100 r=(x/100)*210-30 l=150-r ml.run_forever(speed_sp=l,stop_action='brake') mr.run_forever(speed_sp=r,stop_action='brake') stop() def linetrace_ltime(j): #ある程度時間がたってから実行するプログラム c1=cs.value() t1=time.time() t2=time.time() while t2-t1<j: c1=cs.value() t2=time.time() x=abs((c1-10)/70)*100 if x>100: x=100 r=(x/100)*210-30 l=150-r ml.run_forever(speed_sp=l,stop_action='brake') mr.run_forever(speed_sp=r,stop_action='brake') stop() def linetrace_lout(): c1=cs.value() while c1<40: c1=cs.value() x=(abs(c1-10)/70)*100 if x>100: x=100 r=(x/100)*120-40 l=40-r ml.run_forever(speed_sp=l,stop_action='brake') mr.run_forever(speed_sp=r,stop_action='brake') stop() 今回の課題のライントレースでは定義を4つ利用した。 def runtime(l,r): #ロボットの動きを左右で別に動かす ml.run_timed(time_sp=l*1000,speed_sp=70,stop_action='brake') mr.run_timed(time_sp=r*1000,speed_sp=70,stop_action='brake') time.sleep((l+r)/2) def angle(l,r,t): #ロボットを回転させるプログラム ml.run_to_rel_pos(position_sp=l,speed_sp=115,stop_action='hold') mr.run_to_rel_pos(position_sp=r,speed_sp=115,stop_action='hold') time.sleep(t) def kaiten_r(s,t): #ジャイロセンサーのとる値を使って右回転させる g1=gs.value() g2=gs.value() while g2-g1<s: ml.run_forever(speed_sp=t,stop_action='hold') mr.run_forever(speed_sp=-t,stop_action='hold') g2=gs.value() stop() def kaiten_l(s,t): #ジャイロセンサーのとる値を使って左回転させる g1=gs.value() g2=gs.value() while g1-g2<s: ml.run_forever(speed_sp=-t,stop_action='hold') mr.run_forever(speed_sp=t,stop_action='hold') g2=gs.value() stop() def g(): #g1の値をプリントする g1=gs.value() while g1<10000: g1=gs.value() print(g1) def roll(s): # ma.run_to_rel_pos(position_sp=s,speed_sp=80,stop_action='hold') time.sleep(3) def discover_l(s,t): 缶を探すプログラミング u1=us.value() g1=gs.value() g2=gs.value() while g1-g2<s: u2=us.value() ml.run_forever(speed_sp=-70,stop_action='hold') mr.run_forever(speed_sp=70,stop_action='hold') g2=gs.value() if u2<u1: u1=u2 g3=gs.value() ml.run_forever(speed_sp=70,stop_action='hold') mr.run_forever(speed_sp=-70,stop_action='hold') g4=gs.value() g5=gs.value() if u1<=t: while g5-g4<g3-g2-6: mr.run_forever(speed_sp=-70,stop_action='hold') ml.run_forever(speed_sp=70,stop_action='hold') g5=gs.value() stop() u3=us.value() t1=time.time() while u3<2550: ml.run_forever(speed_sp=100,stop_action='hold') mr.run_forever(speed_sp=100,stop_action='hold') u3=us.value() t2=time.time() stop() roll(220) ml.run_timed(speed_sp=-100,time_sp=(t2-t1)*1000,stop_action='hold') mr.run_timed(speed_sp=-100,time_sp=(t2-t1)*1000,stop_action='hold') time.sleep(t2-t1) g6=gs.value() g7=gs.value() while g7-g6<=g1-g3-6: mr.run_forever(speed_sp=-70,stop_action='hold') ml.run_forever(speed_sp=70,stop_action='hold') g7=gs.value() stop() else: while g5-g4<90: mr.run_forever(speed_sp=-70,stop_action='hold') ml.run_forever(speed_sp=70,stop_action='hold') g5=gs.value() stop() def discover_r(s,t): u1=us.value() g1=gs.value() g2=gs.value() while g2-g1<s: u2=us.value() ml.run_forever(speed_sp=70,stop_action='hold') mr.run_forever(speed_sp=-70,stop_action='hold') g2=gs.value() if u2<u1: u1=u2 g3=gs.value() ml.run_forever(speed_sp=-70,stop_action='hold') mr.run_forever(speed_sp=70,stop_action='hold') g4=gs.value() g5=gs.value() if u1<=t: while g4-g5<g2-g3-6: mr.run_forever(speed_sp=70,stop_action='hold') ml.run_forever(speed_sp=-70,stop_action='hold') g5=gs.value() stop() u3=us.value() t1=time.time() while u3<2550: ml.run_forever(speed_sp=100,stop_action='hold') mr.run_forever(speed_sp=100,stop_action='hold') u3=us.value() t2=time.time() stop() roll(220) ml.run_timed(speed_sp=-100,time_sp=(t2-t1)*1000,stop_action='hold') mr.run_timed(speed_sp=-100,time_sp=(t2-t1)*1000,stop_action='hold') time.sleep(t2-t1) g6=gs.value() g7=gs.value() while g6-g7<=g3-g1-6: mr.run_forever(speed_sp=70,stop_action='hold') ml.run_forever(speed_sp=-70,stop_action='hold') g7=gs.value() stop() else: while g4-g5<90: mr.run_forever(speed_sp=70,stop_action='hold') ml.run_forever(speed_sp=-70,stop_action='hold') g5=gs.value() def Redball(): #スタートから赤いボールを取るまでの指令の定義 angle(250,250,3) kaiten_r(180,110) roll(220) kaiten_r(195,110) linetrace_lin() def Blueball(): #スタートから青いボールを取るまでの指令の定義 angle(-20,160,2) linetrace_lin() angle(-35,-35,1.5) kaiten_r(175,110) roll(220) def move(): kaiten_r(190,110) angle(-50,-50,1) linetrace_lin() linetrace_lout() linetrace_lin() linetrace_lout() linetrace_lin() def BlueZone(): linetrace_rin() linetrace_rout() linetrace_rin() angle(0,70,1) linetrace_rin() angle(70,0,1) linetrace_rin() def discover2(): kaiten_l(60,100) discover_r(90,500) def start(): #今回の課題でさせる命令の定義 r=int(input("insert numbera")) Redball() Blueball() move() if r<=2: kaiten_l(90,110) discover_l(90,250) kaiten_l(95,100) if r==3: angle(-40,180,2) linetrace_lin() discover_r(60,250) angle(-150,-150,2) kaiten_l(195,110) linetrace_rin() angle(230,-40,2) if r==4: angle(-40,180,2) linetrace_lin() discover_l(60,250) kaiten_l(195,110) linetrace_rin() angle(230,-40,2) if 5<=r: angle(-40,180,2) linetrace_lin() linetrace_lout() linetrace_ltime(3) discover_l(60,190) angle(-130,-130,3) kaiten_l(180,110) linetrace_rin() linetrace_rout() linetrace_rin() angle(230,-40,2) BlueZone() discover2() def vv(): u1=gs.value() while u1>0: u1=gs.value() print(u1) time.sleep(1) start() #実際に動作をさせるプログラム *反省 [#v014e287] 今回はテスト期間に制作をしたのでほとんど時間が取れなかった。そのため完成にこぎ付けるかどうか不安要素は大きかったが時間に余裕をもって完成させることができた。 最後の調整の段階では失敗することはほとんどなかったが、本番は一個目のボールを缶に乗せた後にライントレースにたどり着けずそのまま失敗してしまった。 おそらく失敗の原因は、2つ配られていたジャイロセンサーの感度があまりよくなく、動作させるたびに少しずれてしまったことであった。もしもう一度作る機会があるとするならば、今度はジャイロセンサーの値が少しずれても、ある程度ロボットの構造や動きで修正できるものにしたい。 *閲覧回数 [#f0e6620b] 総計:&counter(total); 今日:&counter(today); 昨日:&counter(yesterday);