目次 #contents *コース [#l2ad74e9] 自分はコース1を担当した。赤線はロボットの軌道を表していて、軌道を貫いている棒は停止位置を表している(停止時間1秒)。青の円は球を発射する位置。 #ref(2018b/Member/Kisuke/Mission2/map.jpg,30%); *ロボット [#db61e790] #ref(2018b/Member/Kisuke/Mission2/robot.jpg,20%) 車体の前方に光センサーと超音波センサーをを取り付けている。 車体上部にミディアムモーターを取り付け画像のように機能する。 #ref(2018b/Member/Kisuke/Mission2/mediummotor.jpg,20%) *プログラム [#p695aa19] **ライントレース(基本編) [#m7cd746a] 今回の課題の根幹となる部分のプログラム c1=cs.value() x=(abs(c1-10)/70)*100 #だいたい10<c1<80といった範囲だったので、0<x<100になるようにした。絶対値がついているのはc1<10の時でも負の値にならないように。 if x>100: x=100 #最大値が100を超えないようにする。 l=(x/100)*210-30 #1 r=150-l #2 ml.run_forever(speed_sp=l,stop_action='brake') #lの速さで進む。 mr.run_forever(speed_sp=r,stop_action='brake') #rの速さで進む。 #1 左タイヤの速度を設定する部分。x=0(黒い時)でl=-30,x=100(白い時)でl=180となり-30<l<180の速さで走る。 #2 右タイヤの速度を設定する部分。x=0(黒い時)でr=180,x=100(白い時)でr=-30となり-30<r<180の速さで走る。 こうすることで、直線も曲線も滑らかに移動できた。 ***このプログラムに至った経緯 [#k33a7966] はじめは下のプログラムのようにカラーセンサーの値の増加量を読み取らせてラインを判別していた。 t1=time.time() s1=cs.value() sleep(0.1) t2=time.time() s2=cs.value() x=(s2-s1)/(t2-t1) #カラーセンサーの0.1秒間の増加量 if x>0: a=200 b=200-x forward(a,b) #増加量の大きさの分だけ速さが減少して進む if x=0: a=200 b=200 forward(a,b) if x<0: a=200+x b=200 forward(a,b) しかし増加量を取ると、少しの明るさの違いで大きく移動してしまうし、かといって増加量の秒間を増やすとラインをはみ出してしまうため、sleep関数をプログラムに入れてはダメだと分かった。 **ライントレース(応用編) [#se998bb6] 基本編でのプログラムは線の左側にいるときにしか使えない上に、丁字路や急カーブを曲がり切れないので、条件別に4つに分類した。 定義名のl,rの違いは線の右に居るか左に居るかで、in,outの違いは交差点を認識するか境界線を認識するか 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_rout(): #左側にいて、境界線を認識すると終わる c1=cs.value() while c1<40: c1=cs.value() x=(abs(c1-10)/70)*100 if x>100: x=100 l=(x/100)*120-40 r=40-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_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() lout,routのスピードの値の範囲は-40<l<80 -40<r<80となっており最小値がより低くなっている このように分類することで、直線や緩やかなカーブの時でもある程度のスピードを保ちつつ、急カーブでは減速して曲がり切れるようになる。文字では分かりにくいので画像を載せておく。 丁字路 linetrace_lin() linetrace_lout() linetrace_lin() #ref(2018b/Member/Kisuke/Mission2/curve1.jpg,20%) 急カーブ linetrace_rin() linetrace_rout() linetrace_rin() #ref(2018b/Member/Kisuke/Mission2/curve2.jpg,20%) 画像の緑の丸あたりで関数が切り替わっている。 ※lが右側に居て、rが左側に居るというのは誤植ではない。白い紙の上にロボットを置いたとき、どの方向に回転するかでl,rを決めている。 #ref(2018b/Member/Kisuke/Mission2/lr.jpg,10%) ***このプログラムに至った経緯 [#h7b9c24e] 最初はGからEにかけてのコースを次のようなプログラムで走らせようと思った。 i=0 while i<300: #iが300になった時点で終了 c1=cs.value() if c1<13: #カラーセンサーが黒を認識したときにiのカウントが1増える i=i+1 else: i=i #カラーセンサーが灰色や白を認識したときはカウントは増えない x=(abs(c1-10)/70)*100 if x>100: x=100 l=(x/100)*60-20 #カーブを曲がり切れるようにさっきよりは速度が控えめ r=20-l ml.run_forever(speed_sp=l*5,stop_action='brake') #最初はここでlの値の大きさを調整していた。 mr.run_forever(speed_sp=r*5,stop_action='brake') stop() これはループするうちに急カーブなどで黒を認識した数だけカウントを蓄積し、交差点の黒を認識するとき止まれるようにしている。この場合は黒線上でwhileが300回ループしたときに止まる。 しかしこのプログラムだとEV3のバッテリー量に左右されやすく、成功するかしないかは日によって違ったため安定性に欠けた。しかも丁字路や急カーブも曲がれる速度に設定してあるため、直線や緩やかなカーブも遅かった。なので条件ごとに分けた。 **ボール射出のプログラム [#vb134d9e] def shoot(): #ボールを放つプログラム mm.run_to_rel_pos(position_sp=-60,speed_sp=150,stop_action='hold') #上の画像のようにモーターを回転させることでスロープを作る time.sleep(3) mm.run_to_rel_pos(position_sp=60,speed_sp=150,stop_action='hold') #元の位置に戻す time.sleep(3) def discover(): t0=time.time() #回転し始めで時間の計測を始める u1=us.value() #超音波センサーの値をwhile関数でで使うため定義しておく ml.run_to_rel_pos(position_sp=-700,speed_sp=150,stop_action='hold') mr.run_to_rel_pos(position_sp=700,speed_sp=150,stop_action='hold') #360度回転 t2=time.time() #whileの条件で使うため、あらかじめ定義しておく while t2-t0<4.7: #一回転するまでループする(4.7秒) u2=us.value() #u2としてもう一つの値を定義しておく。 if u2<u1: u1=u2 #n回目の観測距離(u2)がn-1回目の(u1)より小さい場合、u1の値を更新する t1=time.time() #更新した時の時間を計測 t2=time.time() #whileでかかる時間をt2-t0として計測 time.sleep(1) ml.run_timed(time_sp=(t1-t0)*1000,speed_sp=-150,stop_action='hold') #t1-t0が回転し始めてから一番近い物体を捉えるまでの時間を表しているので、その分回転をする mr.run_timed(time_sp=(t1-t0)*1000,speed_sp=150,stop_action='hold') time.sleep(t1-t0) #回っている時間にプログラムが進まないようにしている time.sleep(1) shoot() #上の関数を起動 ml.run_timed(time_sp=(t1-t0)*1000,speed_sp=150,stop_action='hold') #回った分だけ戻る。 mr.run_timed(time_sp=(t1-t0)*1000,speed_sp=-150,stop_action='hold') time.sleep(t1-t0) **プログラム全体 [#rbe345ee] #!/usr/bin/env python3 from ev3dev.ev3 import * import time #time.time()とtime.sleep()を使う ml=LargeMotor('outA') mr=LargeMotor('outD') mm=MediumMotor('outC') cs=ColorSensor('in4') ts=TouchSensor('in1') us=UltrasonicSensor('in2') ロボットに情報を打ち込むところ。 def motor_init(): #モーターの値を初期化 mr.reset() ml.reset() 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_rout(): c1=cs.value() while c1<40: c1=cs.value() x=(abs(c1-10)/70)*100 if x>100: x=100 l=(x/100)*120-40 r=40-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_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() def shoot(): mm.run_to_rel_pos(position_sp=-60,speed_sp=150,stop_action='hold') time.sleep(3) mm.run_to_rel_pos(position_sp=60,speed_sp=150,stop_action='hold') time.sleep(3) def discover(): t0=time.time() u1=us.value() ml.run_to_rel_pos(position_sp=-700,speed_sp=150,stop_action='hold') mr.run_to_rel_pos(position_sp=700,speed_sp=150,stop_action='hold') t2=time.time() while t2-t0<4.7: u2=us.value() if u2<u1: u1=u2 t1=time.time() t2=time.time() time.sleep(1) ml.run_timed(time_sp=(t1-t0)*1000,speed_sp=-150,stop_action='hold') mr.run_timed(time_sp=(t1-t0)*1000,speed_sp=150,stop_action='hold') time.sleep(t1-t0) time.sleep(1) shoot() ml.run_timed(time_sp=(t1-t0)*1000,speed_sp=150,stop_action='hold') mr.run_timed(time_sp=(t1-t0)*1000,speed_sp=-150,stop_action='hold') time.sleep(t1-t0) 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): #指定した数値の角度だけ進む 主に向きを変える用 ml.run_to_rel_pos(position_sp=l,speed_sp=70,stop_action='hold') mr.run_to_rel_pos(position_sp=r,speed_sp=70,stop_action='hold') 実際に進むために必要なプログラム。 def AtoB(): AからBに行くプログラム runtime(2,2) #Pの枠を越えるために少し進ませる linetrace_lin() print("AtoB") #ちゃんと関数が終了したか確かめる def BtoK(): linetrace_lout() linetrace_lin() print("BtoK") time.sleep(1) #停止地点で1秒止まる def KtoJ(): angle(-120,120) #交差点を跨ぐために向きを変える time.sleep(2.5) #上の動作中に次のプログラムへ進まないようにする linetrace_rin() print("KtoJ") def JtoI(): angle(150,20) #交差点を跨ぐために向きを変える time.sleep(2) linetrace_rin() print("JtoI") def ItoH(): angle(100,20) time.sleep(2) linetrace_rin() print("ItoH") def HtoG(): linetrace_rout() linetrace_rin() time.sleep(1) print("HtoG") def GtoE(): angle(0,180) time.sleep(2) linetrace_lin() linetrace_lout() linetrace_lin() time.sleep(1) print("GtoE") def EtoL(): linetrace_lout() linetrace_lin() print("EtoL") def Goal(): runtime(5,5) #Qに入るために少し進む def start(): #全てをまとめた AtoB() BtoK() KtoJ() JtoI() discover() ItoH() HtoG() GtoE() EtoL() Goal() start() #起動 ***動画 [#l58af828] https://youtu.be/-_e3MriktZk 総計:&counter(total);