目次 #contents *課題 [#p8ffa7cc] 今回の課題はライントレース 下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成する。 **コース [#z0c37601] 黒線の幅は20mmでなるべく均等な濃さにすること。なお図の中の寸法の単位はcmで、黒線についてはその真ん中からの距離である。 &ref(2018b/Member/Yoshi/Mission2/robot01.png,100%,完成); **ミッション [#g0e53a91] 次のいずれかのコースで黒い線に沿って動き、途中でボールをゴール付近に立てた350mlの空き缶(黄色で表示)に当てるロボットを製作せよ。 (相棒と違うコースを選ぶこと) ***第1コース [#b648384f] &ref(2018b/Member/Yoshi/Mission2/ロボティクス.jpg,100%,完成); 1.ロボットを長方形X内におき、Aをスタート~ 2.Bを右折~ 3.Kで一時停止して左折~ 4.Jを直進~ 5.Iを直進~ 6.Hを左折~ 7.Gで一時停止して左折~ 8.Eで一時停止して右折~ 9.Lを経て正方形Y内に入って停止 (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧KJIH上にある時にQ地点の空き缶に当てる ***第2コース [#u59f67a4] &ref(2018b/Member/Yoshi/Mission2/ロボティクス2.jpg,100%,完成); 1.ロボットを正方形X内におき、Lをスタート~ 2.Eを一時停止して直進~ 3.Iを一時停止して左折~ 4.Hを直進~ 5.Kを直進~ 6.Jを左折~ 7.Cを一時停止して右折~ 8.Eを一時停止して直進~ 9.Gを一時停止して直進~ 10.長方形X内に入って停止~ (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧IHKJ上にある時にQ地点の空き缶に当てる ***注意 [#vab219ae] ・一時停止の指示がある交差点と丁字路、およびボールを投げる時以外は停止しないこと。~ ・一つの交差点(or T字路 or 直角カーブ)から次の交差点(or T字路 or 直角カーブ)までの移動を一つの関数で定義すること。~ ・前の交差点からの時間や距離を微調整して交差点を判断するのではなく、通常のカーブと交差点の違いを光センサの値から判断すること。~ *ロボットの説明 [#k484be43] ロボットは以下の写真のようなものにした。かなりごつくなってしまった(笑) 今回、長めのコードが壊れていたため、通常のロボットと前後を逆にすることで短めのコードで装置につなげるようにした。その時、関数を定義する際に左と右が逆転することに注意した。 &ref(2018b/Member/Yoshi/Mission2/001.JPG,100%,完成); **カラーセンサについて [#v9dfb4a4] &ref(2018b/Member/Yoshi/Mission2/003.JPG,100%,完成); カラーセンサは地面とかなり近い位置で置くようにした遠い位置に置くと白と黒の見分けがつかなくなってしまうからだ。また、滑らかにライントレースを行うために真ん中に置いた。 **超音波センサについて [#a3b6ab17] &ref(2018b/Member/Yoshi/Mission2/ロボティクス3.jpg,100%,完成); 超音波センサーはかなり前のほうに置いた。タッチセンサによって場所がなかったのと、前のほうにすることで、最短距離を正確に求められるようにするためだ。また、超音波センサーの値によって、空き缶の向く方向が決まるので、中央に置く必要があった。 **アームについて [#q32f2751] &ref(2018b/Member/Yoshi/Mission2/004.JPG,100%,完成); アームは上のほうに置いて、位置エネルギーを利用して、ボールを転がすようにした。ボールが移動中に落ちないように、ストッパーを付けた。 *ライントレースについて [#pb91d749] *プログラムの説明 [#bc99ed95] **プログラムの導入 [#g55cbe87] #!/usr/bin/env python3 from ev3dev.ev3 import * import time ml=LargeMotor('outA') #装置Aのモーターをmlと置く mr=LargeMotor('outB') #装置Bのモーターをmrと置く mm=MediumMotor('outC') #装置Cのモーターをmmと置く cs=ColorSensor('in1') #in1のカラーセンサーをcsと置く us=UltrasonicSensor('in2') #in2のカラーセンサーをusと置く w=100 #wに100を代入 v=60 #vに60を代入 u=-50 #uに-50を代入 **定義の導入 [#a6d7d641] def run(): #直進するプログラム global w #定義外にあるwを定義内に持ってくる 以下globalは同じ意味を待つ ml.run_forever(speed_sp=w, stop_action='brake') mr.run_forever(speed_sp=w, stop_action='brake') def turn_right(): #右に回転するプログラム global w ml.run_forever(speed_sp=w, stop_action='brake') mr.run_forever(speed_sp=0, stop_action='brake') def turn_left(): #左に回転するプログラム global w ml.run_forever(speed_sp=0, stop_action='brake') mr.run_forever(speed_sp=w, stop_action='brake') def curve_right(): #右にカーブするプログラム turnと比べて曲がり方が小さい global w global v ml.run_forever(speed_sp=w, stop_action='brake') mr.run_forever(speed_sp=v, stop_action='brake') def curve_left(): #左にカーブするプログラム turnと比べて曲がり方が小さい global w global w global v ml.run_forever(speed_sp=v, stop_action='brake') mr.run_forever(speed_sp=w, stop_action='brake') def round_right(): #右に曲がるプログラム turnやcurveよりも曲がり方が大きい global w global u ml.run_forever(speed_sp=w, stop_action='brake') mr.run_forever(speed_sp=u, stop_action='brake') def round_left(): #左に曲がるプログラム turnやcurveよりも曲がり方が大きい global w global u ml.run_forever(speed_sp=u, stop_action='brake') mr.run_forever(speed_sp=w, stop_action='brake') def stand_right(): #交差点に来た際に一度右に曲がったのを元に戻し前を向かせるプログラム ml.run_to_rel_pos(position_sp=-90, speed_sp=100, stop_action='brake') mr.run_to_rel_pos(position_sp=30, speed_sp=100, stop_action='brake') time.sleep(1) def stand_left(): #交差点に来た際に一度左に曲がったのを元に戻し前を向かせるプログラム ml.run_to_rel_pos(position_sp=30, speed_sp=100, stop_action='brake') mr.run_to_rel_pos(position_sp=-90, speed_sp=100, stop_action='brake') time.sleep(1) def straight_right(): #右側トレースをしていて交差点に来た際に直進するプログラム stand_right() ml.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') mr.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') time.sleep(1) def straight_left(): #左側トレースをしていて交差点に来た際に直進するプログラム stand_left() ml.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') mr.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') time.sleep(1) def throw(): #球を投げるプログラム mm.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') time.sleep(1) mm.reset() def round(): #その場で一回転するプログラム ml.run_to_rel_pos(position_sp=680, speed_sp=50, stop_action='brake') mr.run_to_rel_pos(position_sp=-680, speed_sp=50, stop_action='brake') def search(): #空き缶を探すプログラム global x global y distance=2550 #空き缶との最短距離を探すのでus.value()の最高値2550を代入しておく time0=time1=time.time() #time0と1に時間を代入 while time.time()-time0<13: #time0から13秒間経たないなら実行する if us.value()<distance: #もしus.value()がdistanceの数字より小さいなら実行する distance=us.value() #disatnceにus.value()を代入する time1=time.time() #代入した時間をtime1とする print(us.value()) #いつus.value()を入れたかわかるようにプリントする x=680/13*(time1-time0) #1周を約13秒で約680度回転するので680/13で1秒当たりに進む角度を計算しそれに先ほどの時間差をかけることで何度戻せばよいか計算する y=time1-time0 #yに時間差を代入 def hit(): #空き缶に球を充てるプログラム ml.run_to_rel_pos(position_sp=x, speed_sp=50, stop_action='brake') #空き缶分回転する mr.run_to_rel_pos(position_sp=-x, speed_sp=50, stop_action='brake') #空き缶分回転する time.sleep(y) ml.run_to_rel_pos(position_sp=-60, speed_sp=50, stop_action='brake') #目視で回転する秒数や角度を決めたのですこしずれてしまう。 そこで微調整する time.sleep(1) throw() #球を投げる ml.run_to_rel_pos(position_sp=60, speed_sp=50, stop_action='brake') #微調整した分の角度を戻す time.sleep(1) ml.run_to_rel_pos(position_sp=680-x, speed_sp=50, stop_action='brake') #空き缶分回転した角度を戻す mr.run_to_rel_pos(position_sp=x-680, speed_sp=50, stop_action='brake') #空き缶分回転した角度を戻す time.sleep(13-y) a=8 b=13 c=18 d=30 s=1 h=3 def line_trace_right(num=1): #右側ライントレースを定義 time0=time.time() time1=time.time()-h #3秒間はカウントしないようにする 詳しくは下で cnt=0 while cnt<num: if cs.value()<=a: round_right() elif a<=cs.value()<=b: curve_right() elif b<=cs.value()<=c: run() time0=time.time() elif c<cs.value()<=d: curve_left() time0=time.time() else: round_left() time0=time.time() if time.time()-time0>=s and time.time()-time1>h: cnt=cnt+1 time1=time.time() time0=time.time() print(cnt) #数えた回数を確認するためにいれた。 mL.reset() mR.reset() ここで今回の課題で最も作るのに苦労した、この関数について説明する。この関数は、ライントレースする際に何回交差点を検知するかでどこまで進むかを決めることができるものである。しかし、実際やってみると、このやり方では毎回交差点を検知する回数が異なってしまった。なので、上のプログラムのように一度交差点を検知したら3秒間は検知しないようにした。そうすることで交差点では1回、半円では2回カウントするようなプログラムを作り、ライントレースをうまくすることができるようになった。 def line_trace_left(num=1): #左側ライントレースを定義する time0=time.time() time1=time.time()-h cnt=0 while cnt<num: if cs.value()<=a: round_left() elif a<=cs.value()<=b: curve_left() elif b<=cs.value()<=c: run() time0=time.time() elif c<=cs.value()<=d: curve_right() time0=time.time() else: round_right() time0=time.time() if time.time()-time0>=s and time.time()-time1>h: cnt=cnt+1 time1=time.time() time0=time.time() print(cnt) ml.reset() mr.reset() **第2コースのプログラム [#e3be338b] 今回、自分は第2コースの担当だったので、そのプログラムを示す。 line_trace_left(1) straight_left() time.sleep(2) line_trace_left(1) time.sleep(2) line_trace_left(1) straight_left() round() search() hit() line_trace_left(1) straight_left() line_trace_left(2) stand_left() time.sleep(2) line_trace_right(4) straight_right() time.sleep(2) line_trace_right(1) stand_right() ml.run_to_rel_pos(position_sp=360, speed_sp=100, stop_action='brake') mr.run_to_rel_pos(position_sp=360, speed_sp=100, stop_action='brake') *感想 [#m836d589] 今回の課題では、どのようにすれば交差点を検知できたり、空き缶を感知し最短距離を求めることができるのかという問題の答えを見つけることが難しかった。また、前回の課題に比べてもやることが多く時間もかかり大変だった。次回の課題は、ロボコンなので、いままでの授業の経験を生かして、しっかりと課題が達成できるようにしたい。