[[2018b/Member]] *課題 [#k8a07480] 今回の課題はライントレース 下の図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成する。 **コース [#l7051c32] 線の幅は20�个任覆襪戮�均等な濃さにすること。なお図の中の寸法の単位は�僂如�黒線についてはその真ん中からの距離である #ref(robot01.png,,100%) **ミッション [#x5e5b1a6] 次のいずれかのコースで黒い線に沿って動き途中でボールをゴール付近に立てた350mlの空き缶(黄色で表示)に当てるロボットを作成せよ。(相方と違うコースを選ぶこと) ***第一コース [#id485b8b] 1.ロボットを長方形X内におき、Aをスタート 2.Bを右折 3.Kで一時停止して左折 4.Jを直進 5.Iを直進 6.Hを左折 7.Gで一時停止して左折 8.Eで一時停止して右折 9.Lを経て正方形Y内に入って停止 (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧KJIH上にある時にQ地点の空き缶に当てる ***第二コース [#vfb1846f] 1.ロボットを正方形X内におき、Lをスタート 2.Eを一時停止して直進 3.Iを一時停止して左折 4.Hを直進 5.Kを直進 6.Jを左折 7.Cを一時停止して右折 8.Eを一時停止して直進 9.Gを一時停止して直進 10.長方形X内に入って停止 (一時停止の指定がある場所は、1秒間停止すること) ボールはロボットが弧IHKJ上にある時にQ地点の空き缶に当てる ***注意 [#ud98b516] ・一時停止の指示がある交差点と丁字路、およびボールを投げる時以外は停止しないこと。 ・一つの交差点(or T字路 or 直角カーブ)から次の交差点(or T字路 or 直角カーブ)までの移動を一つの関数で定義すること。 ・前の交差点からの時間や距離を微調整して交差点を判断するのではなく、通常のカーブと交差点の違いを光センサの値から判断すること。 *ロボットの説明 [#r6dde026] #ref(IMG_0795-min.jpg,,10%) これがロボットの全体図でなるべくシンプルな形にした カラーセンサーと超音波センサーをほぼ中心に取り付け、ライントレースが左右対称にやりやすいように、また空き缶の位置をより正確に調べられるようにした。 そしてボールはモーターを回転させて蹴り出す形で発射させるようにした。 *プログラム [#kb69f6c7] **はじめに [#de08090e] それぞれのセンサーとモーターを以下のように定義する #!/usr/bin/env python3 from ev3dev.ev3 import * import time from time import sleep mR=LargeMotor('outC') mL=LargeMotor('outB') mM=MediumMotor('outD') cs=ColorSensor('in3') us=UltrasonicSensor('in1') 右タイヤのモーターをmR、左タイヤのモーターをmL、発射機構のモーターをmMとして定義した **ライントレースのプログラム [#a0e8098f] def traceR(): t0=time.time() while time.time()-t0<0.35: if cs.value()<35: #カラーセンサーの値が35未満の時大きく右に回る turnR2() if 35<=cs.value()<40: #カラーセンサーの値が35以上40未満の時小さく右に回る turnR1() t0=time.time() if 40<=cs.value()<=50: #カラーセンサーの値が40以上50以上の時まっすぐ進む run() t0=time.time() if 50<cs.value()<=60: #カラーセンサーの値が50より大きく60未満の時左に小さく回る turnL1() t0=time.time() if cs.value()>60: #カラーセンサーの値が60より大きいとき左に大きく回る turnL2() t0=time.time() mR.stop() mL.stop() def traceL(): t0=time.time() while time.time()-t0<0.25: if cs.value()<35: #カラーセンサーの値が35未満の時左に大きく回る turnL2() if 35<=cs.value()<40: #カラーセンサーの値が35以上40未満の時左に小さく回る turnL1() t0=time.time() if 40<=cs.value()<=50: #カラーセンサーの値が40以上50以下の時まっすぐ進む run() t0=time.time() if 50<cs.value()<=60: #カラーセンサーの値が50より大きく60以下の時右に小さく回る turnR1() t0=time.time() if cs.value()>60: #カラーセンサーの値が60より大きいとき右に大きくまわる turnR2() t0=time.time() それぞれtraceRは右側traceLは左側をトレースするようになっている、こうすることで左側の交差点また右側の交差点それぞれを発見しやすくした、交差点の認識方法は0.35秒以上黒いところを通った時に交差点として止まるようにした 以下はこれらのtrace関数の中身の関数である def turnR1(): #右に小さく回る mL.run_forever(speed_sp=100,stop_action='brake') mR.stop() def turnL1(): #左に小さく回る mR.run_forever(speed_sp=100,stop_action='brake') mL.stop() def run(): #まっすぐ進む mR.run_forever(speed_sp=100,stop_action='brake') mL.run_forever(speed_sp=100,stop_action='brake') def turnR2(): #右に大きく回る mL.run_forever(speed_sp=100,stop_action='brake') mR.run_forever(speed_sp=-70,stop_action='brake') def turnL2(): #左に大きく回る mR.run_forever(speed_sp=100,stop_action='brake') mL.run_forever(speed_sp=-70,stop_action='brake') 次に小さい半径でライントレースをする時に交差点と誤認識することがあったので以下の一定時間トレースをする関数を作った def traceLa(t): t1=time.time() while time.time()-t1<t: if cs.value()<35: turnL2() if 35<=cs.value()<40: turnL1() if 40<=cs.value()<=50: run() if 50<cs.value()<=60: turnR1() if cs.value()>60: turnR2() mR.stop() mL.stop() def traceRa(t): t0=time.time() while time.time()-t0<t: if cs.value()<35: turnR2() if 35<=cs.value()<40: turnR1() if 40<=cs.value()<=50: run() if 50<cs.value()<=60: turnL1() if cs.value()>60: turnL2() mR.stop() mL.stop() 次に交差点を発見した後にその交差点を通過するためのプログラムを書く def turnR3(t): #t秒その場で右に回転する mL.run_timed(time_sp=t,speed_sp=100,stop_action='brake') mR.run_timed(time_sp=t,speed_sp=-100,stop_action='brake') sleep(t/1000) mR.stop() mL.stop() def turnL3(t): #t秒その場で左に回転する mR.run_timed(time_sp=t,speed_sp=100,stop_action='brake') mL.run_timed(time_sp=t,speed_sp=-100,stop_action='brake') sleep(t/1000) mR.stop() mL.stop() def runT(t): #t秒まっすぐ進む mR.run_timed(time_sp=t, speed_sp=100, stop_action='brake') mL.run_timed(time_sp=t, speed_sp=100, stop_action='brake') sleep(t/1000) mR.stop() mL.stop() 交差点を発見した後turnR3またはturnL3で向きを戻した後runTでまっすぐ進んで交差点を越えるようにした **缶を発見し発射するプログラム [#h44f0951] まずは缶を発見するプログラムについて def search(): d_min=5000 #仮の最小値を作る t1=time.time() while time.time()-t1 < 15: #15秒間回り続ける turnR() if us.value()<d_min: d_min=us.value() #もし仮の最小値より超音波センサーの値が小さかったら新しい最小値を記録する t2=time.time() #最小値を記録した時の時間を記録する mM.reset() mR.stop() mL.stop() t3=time.time() sleep(1) mR.run_timed(time_sp=1000*(t3-t2), speed_sp=50, stop_action='brake') mL.run_timed(time_sp=1000*(t3-t2), speed_sp=-50, stop_action='brake') sleep(t3-t2+2) #回転し終わった時間から最後に最小値を記録した時間に逆回転する fire() #ボールを発射する sleep(1) ボールを発射するプログラム関数は以下である def fire(): mM.run_to_abs_pos(position_sp=150,speed_sp=500,stop_action='coast') #mMを回転させてボールを発射する **まとめ [#m73c9511] def LtoE(): traceL() sleep(1) turnR3(230) runT(500) def EtoI(): traceL() sleep(1) turnL3(600) def ItoH(): traceLa(2) traceL() turnR3(230) runT(700) def HtoJ(): traceLa(4) turnR3(600) traceRa(4) turnL3(600) traceLa(2) traceL() turnL3(600) def JtoC(): traceLa(2) traceL() sleep(1) turnR3(1500) def CtoE(): traceRa(30) traceR() turnL3(300) runT(500) def EtoG(): traceRa(30) traceR() turnL3(300) runT(500) def GtoGole(): traceR() turnL3(300) runT(4000) #最後の交差点を発見した後一定の値進んでゴールに収まる それぞれの関数名はどの地点からどの地点へと移動するときに使うプログラムを示してある。 LtoE() EtoI() ItoH() search() HtoJ() JtoC() CtoE() EtoG() GtoGole() 以上がロボットを動かすプログラムである *感想 [#x9ec2d09] 成功率としては50%くらいで発表会では失敗をしてしまった。 原因としては交差点を発見する制度が高くなく認識しなかったり誤認識を起こしてしまったからだと考えられる