#contents *課題2の内容 [#fb0bb097] 今回の課題はライントレースで決められた場所を走らせ、その途中で空き缶を認知し缶に向かってボールを投げさせるロボットを作成するというものであった。コースは2つあり、その内容や経路は経路は以下に表す通りである。 第1コース #ref(2018b/Member/prague/Mission2/robo street1.png,100%,経路1); ロボットを長方形X内におき、Aをスタート 1,Bを右折 2,Kで一時停止して左折 3,Jを直進 4,Iを直進 5,Hを左折 6,Gで一時停止して左折 7,Eで一時停止して右折 8,Lを経て正方形Y内に入って停止 (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧KJIH上にある時にQ地点の空き缶に当てる。 第2コース #ref(2018b/Member/prague/Mission2/robo street2.png,100%,経路2); ロボットを正方形Y内におき、Lをスタート 1,Eを一時停止して直進 2,Iを一時停止して左折 3,Hを直進 4,Kを直進 5,Jを左折 6,Cを一時停止して右折 7,Eを一時停止して直進 8,Gを一時停止して直進 長方形X内に入って停止 (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧IHKJ上にある時にP地点の空き缶に当てる。 *機体について [#ga36b92c] **機体の全体図[#n28e5578] #ref(2018b/Member/prague/Mission2/robobo.png,10%,機体の全体像) #ref(2018b/Member/prague/Mission2/robo zentaizu .png,10%,機体の全体像〜後ろから〜) **機体の特徴 [#fb1be886] ***車体部分 [#z82b9af6] 今回はライントレースということで色を読み取って機体を黒線に合わせながら進んでいくこと、さらに缶の位置を検知してボールを投げることが課題に挙げられているため超音波センサーとカラーセンサーをロボットに組み込まなければならない。ここでいうセンサはそれぞれ以下のようなものである。 今回の課題ではカラーセンサーが読み取る値が非常に重要になってくる。それを考慮し私たちの機体はなるべく前輪とカラーセンサーの位置が近くなるようにした。こうすることでカラーセンサーが把握する色と前輪の色が近くなり、黒線に沿って動いてくれるようになる。 今回大きな課題となったのは配線である。モーターが3つ、センサも3つずつあったので工夫してつなげないと長さが足りなくなったり絡まって車輪に巻き込んだりということが起こる恐れがあった。私たちはセンサの入力が数字、モータの出力がアルファベットの ***放出部分 [#z5a87b02] このロボットではボールを転がす形で投げるような設計にした。動きは下図の表すとおりである。 ここの部分は車体より上に作る必要があったのだが、ある程度頑丈に作っておかないと車体を動かしている途中で #ref(2018b/Member/prague/Mission2/throwing.png,10%,投げる前) *プログラミング [#t681e04a] #!/usr/bin/env python3 from ev3dev.ev3 import * from time import sleep mL = LargeMotor('outA') #左タイヤの出力の定義 mR = LargeMotor('outB') #右タイヤの出力の定義 mi = MediumMotor('outD') #放出部分の出力の定義 s1 = TouchSensor('in3') #タッチセンサの出力の定義 s2 = ColorSensor('in4') #カラーセンサの出力の定義 U1 = UltrasonicSensor('in2') #超音波センサの出力の定義 def laf(t): #left and forwardの略 mL.run_timed(time_sp=30,speed_sp=120+20*t,stop_action='brake') mR.run_timed(time_sp=30,speed_sp=120-20*t,stop_action='brake') def raf(t): #right and forwardの略 mL.run_timed(time_sp=30,speed_sp=120-20*t,stop_action='brake') mR.run_timed(time_sp=30,speed_sp=120+20*t,stop_action='brake') def tl(t): #turn leftの略 mL.run_timed(time_sp=20,speed_sp=-150*t,stop_action='brake') mR.run_timed(time_sp=20,speed_sp=150*t,stop_action='brake') def tr(t): #turn lightの略 mL.run_timed(time_sp=20,speed_sp=100*t,stop_action='brake') mR.run_timed(time_sp=20,speed_sp=-100*t,stop_action='brake') def fd(): mL.run_timed(time_sp=20,speed_sp=150,stop_action='brake') mR.run_timed(time_sp=20,speed_sp=150,stop_action='brake') def roll(t,s): mL.run_to_rel_pos(position_sp=t,speed_sp=150,stop_action='brake') mR.run_to_rel_pos(position_sp=s,speed_sp=150,stop_action='brake') 基本的なロボットの動かし方は以下のとおりである。 #ref(2018b/Member/prague/Mission2/sikumi.png,100%,トレースの仕組み); 以下はボールを投げる際に利用した定義である。 def throwing(s,t): #ボールを投げる際につかわれる定義 mi.run_timed(time_sp=s,speed_sp=t,stop_action='brake') def turn(s,t): mL.run_timed(time_sp=s,speed_sp=t,stop_action='brake') mR.run_timed(time_sp=s,speed_sp=-t,stop_action='brake') ここからは実際にロボットを動かすプログラミングである。 roll(150,150) #前にロボットを動かす sleep(3) #3秒止まる w=0 #変数wの定義 b=0 #変数bの定義 i=0 #変数iの定義 while s1.value() == 0: #タッチセンサーが押されていないときに命令を実行させる。 t0 = time.time() if i == 0: #i=0の時の数える時間 s=0.2 elif i == 3: #i=3の時の数える時間 s=1.0 elif i == 6: #i=6の時の数える時間 s=3 elif i == 7: #i=7の時の数える時間 s=1.1 elif i == 8: #i=8の時の数える時間 s=6.5 elif i == 9: #i=9の時の数える時間 s=0.7 else: #その他での数える時間 s=0.8 while i <= 9: if time.time()-t0 <= 7*s: b=0 if 65 < s2.value(): #道から大きく外れたときの命令 tl(-1) w=w+1 b=0 if 55 < s2.value() <= 65: #道から少し外れたときの命令 laf(1) w=w+1 b=0 if 50 < s2.value() <= 55: #黒と白のちょうど境界線を走るときの命令 fd() w=0 b=0 if 40 < s2.value() <= 50: #道の中に少しだけ入り込んだときに実行する命令 raf(1) b=b+0.6 if s2.value() <= 40: #道に深く入り込んだ時の命令 tr(-1) b=b+1 #変数bに1を足す w=0 #変数wを0に戻す elif b>33: #交差点を認識した時の命令 i=i+1 #iに1を足す print(i) #コマンドプロンプトにiの値を表示させる break #命令を終わらせる if i == 1: #iが1の時の命令 sleep(2) #2秒休み roll(30,-30) sleep(1) #1秒休み roll(50,50) sleep(2) #2秒休み if i == 3: #iが3の時の命令 roll(200,0) sleep(2) #2秒休み I=0 while s1.value()==0: #ここから缶を見つけてボールを投げる命令が始まる。 u = 100000 t0=time.time() print(I) turn(12000,70) while time.time()-t0<= 12: #命令を実行する際の条件 if u >=U1.value(): u = U1.value() t1 = time.time() print(u) else: continue sleep(0.5) #0.5秒休み t2=time.time() #t2の定義 sleep(1) #1秒休み print(t1) print(t2) t3=t2-t1 print(t3) turn(t3*(1040+10*i),-70) sleep(t3*1.2) #t3の1.2倍だけ秒休み if u+20>U1.value(): throwing(1000,50) sleep(3) #3秒休み throwing(1000,-50) break elif I == 3: throwing(1000,50) sleep(3) #3秒休み throwing(1000,-50) break else: I=I+2 sleep(2) #2秒休み roll(-30,-30) sleep(3) #3秒休み if i == 4: #iが4の時の命令 roll(200,0) sleep(2) #2秒休み if i == 6: #iが6の時の命令 roll(-10,-10) sleep(2) #2秒休み roll(420,-20) sleep(6) #6秒休み if 8 <= i <= 9: #iが8,9の時の命令 roll(30,-30) sleep(1) #1秒休み roll(70,70) sleep(2) #2秒休み if i == 10: #iが10の時の命令 roll(50,-50) sleep(1) #1秒休み roll(250,250) break #実行を終了させる ルート2では左沿いでのみトレースを行ったので、 ここで変数w,b,iというものが存在しているが、これは順に白の検知数、黒の検知数、交差点の検知数を表すものであり、白と黒をを認識した数を数えさせることで今ロボットが動いている場所が交差点であるのかということや、今いる交差点は何回目のものであるのかを数えてそれにより実行する命令を変えさせるために用意した。 またsという変数は時間を表す。このsは交差点を認知した瞬間から計られ、この時間の範囲内はbの値が常に0となり普通の道を間違えて交差点だと検知しないように設定されている。 *考察と反省 [#m4a19783] 今回ライントレースをやってみて、一番難しいと感じたところは交差点を認識する部分だった。この交差点を認識する条件が厳しいと認識せずに進んでいってしまうし、逆に条件が易しすぎると交差点でない普通の直線やカーブを認識してしまったのでそこの調整は結構長い時間をかけてやったと思う。 反省点としてまず挙げられるのは、ロボットの進ませ方である。発表の際にほかのグループと比べ右や左にそれたり、途中で止まりながら動いたりとぎこちない動きになってしまった。もっと条件分岐やrun_foreverを多くつけてまっすぐ動くところを増やしていけばよかったと思う。