#author("2021-07-29T20:58:34+09:00","","") #author("2021-09-09T19:23:46+09:00","d7","d7") 目次 #contents //image 640*480 or 320*240 * 課題 [#oe9f48e8] 課題説明ページ:[[2017b/Mission2]] 自分は第2コースを選択。 * 「EV3 Tracer」設計について [#vfc61a69] 使用機:LEGO MINDSTORMS EV3 **設計思想 [#u4ca1747] 今回のロボットは、思い通りに走って曲がるのは大前提であり、紙コップを移動させる機構が必要とされていた。~ 残念ながら今回は紙を動かすことはできない。~ 基本はEV3のデフォルト設計で良いが、ライントレースに最適なカラーセンサの取り付け、紙コップを掴む機構の取り付けが求められた。~ 前回ほど設計に自由度はなく、奇抜なデザインをする余裕も必要もない。~ よって本機は高い安定性を重視し設計を行った。 **EV3 Tracer-1 [#q74e5be2] //アームv1写真、説明 #ref(./reTracer1.jpg,100%,Tracer1) EV3デフォルトを基に、カラーセンサ、アームの取り付けを行った。~ カラーセンサの固定位置は入念なライントレース試験を行い決定。~ また、カラーセンサの精度を少しでも高めるため、ブルドーザーの如くコース整地用ブレードを取り付けた。~ 事故が起こった際もセンサーを保護するバンパーとして活躍するかもしれない。~ コップを掴むアームは前回の[[X軸制御機構>2017b/Member/ibu/Mission1#b22f294e]]を流用。~ この機構は前回成功を収めて信頼性も高いため、そのまま採用した。~ 右に固定して伸ばしたビームと、駆動する左のビームでコップを挟み込む。~ 左右に広く腕を広げられるため、多少誤差があってもコップを掴むことが可能。~ 前回のコードを流用する狙いもある。 ***問題点 [#xd02d781] -アームによって全幅が大きくなった結果、コース走行時に掴む前のコップを弾いてしまい、うまくコップを掴めない。~ -ミリ単位で調整を行える元X軸制御機構の能力が無用の長物と化している。 **EV3 Tracer-2 [#qf3ef8dd] //アームv2写真、説明 #ref(./reTracer2.jpg,100%,Tracer2) コップを掴むアームの機構は、掴む・離すのオンオフ制御だけできれば良かったと気づいた。~ 無駄に大きい前のアームは廃止し、縦置きモータにビームを直結した単純な構造に変えた。~ 結果、全幅も気にならない程度になり、掴む前にコップに当たって弾くことも無くなった。~ こちらも左右に広く腕を開き、多少の誤差を気にせず掴むことができる。~ * プログラム [#v89b7a00] **Tracer_ver.1.7.3 [#ibdb1e7a] 今回の課題のプログラムの最終形態。~ ここでは関数群を記述している。 #!/usr/bin/env python3 import ev3dev.ev3 as ev3 import time mr = ev3.LargeMotor('outC') assert mr.connected, "Connect right large motor to port C" ml = ev3.LargeMotor('outA') assert ml.connected, "Connect left large motor to port A" arm = ev3.MediumMotor('outB') assert arm.connected, "Connect arm medium motor to port B" cs = ev3.ColorSensor() assert cs.connected, "Connect a color sensor to any sensor port" cs.mode = 'COL-REFLECT' angle = 17/9 #モータのposition_spに与えて角度に変換するための定数 target_val = 50 #トレース時のカラーセンサの目標値 std_speed = 40 #トレーサーの標準スピード kp = std_speed*0.04 #線の境界へ戻る強さ cm = 20.05 #移動をcmに変換するための定数 intersection_time = 0.23 #交差点検知時間 angle_stabilization_time = 0.3 #走行する境界を変更する際の移動時間 def line_following(dev_which_edge): #ライントレース用 if dev_which_edge == 'left_edge': #後述のrun_until_intersectionに組み込む p = (cs.value()-target_val)*kp elif dev_which_edge == 'right_edge': p = (target_val-cs.value())*kp else: print('invalid edge') if p > 0: mr.duty_cycle_sp = std_speed-p ml.duty_cycle_sp = std_speed elif p <= 0: mr.duty_cycle_sp = std_speed ml.duty_cycle_sp = std_speed+p def run_until_intersection(_which_edge): #交差点を検知するまでライントレースを行う global which_edge #引数に"left_edge"か"right_edge"で左右どちらをトレースするか与えて使用 which_edge = _which_edge start_time = time.time() for motor in mr, ml: motor.run_direct() while True: line_following(_which_edge) if 10 < cs.value() < 100: start_time = time.time() if time.time()-start_time > intersection_time: ev3.Sound.beep() while abs(cs.value()-target_val) > 10: line_following(_which_edge) for motor in mr, ml: motor.stop(stop_action='brake') break def change_following_edge(): #トレースする境界を変更する際に交差点で使用 for motor in mr, ml: motor.run_direct() start_time = time.time() if which_edge == 'right_edge': while time.time()-start_time < angle_stabilization_time: line_following('right_edge') for motor in mr, ml: motor.stop(stop_action='brake') circle(90) move(2) circle(-90) elif which_edge == 'left_edge': while time.time()-start_time < angle_stabilization_time: line_following('left_edge') for motor in mr, ml: motor.stop(stop_action='brake') circle(-90) move(2) circle(90) def move(distance): #前進、後退 for motor in mr, ml: motor.run_to_rel_pos(position_sp=distance*cm, speed_sp=std_speed*5, stop_action='brake') for motor in mr, ml: motor.wait_while('running') def circle(r): #超信地旋回 時計回りが正 if r < 0: signs = [-1, 1] elif r >= 0: signs = [1, -1] for motor, sign in zip([mr, ml], signs): motor.run_to_rel_pos(position_sp=sign*abs(r)*angle, speed_sp=std_speed*5, stop_action='brake') for motor in mr, ml: motor.wait_while('running') def intersection_go_straight(): #交差点直進 if which_edge == 'left_edge': circle(-60) move(3) for motor in mr, ml: motor.run_direct() while abs(cs.value()-target_val) > 10: line_following('left_edge') elif which_edge == 'right_edge': circle(60) move(3) for motor in mr, ml: motor.run_direct() while abs(cs.value()-target_val) > 10: line_following('right_edge') for motor in mr, ml: motor.stop(stop_action='brake') def intersection_turn_right(): #交差点右折 if which_edge == 'left_edge': circle(-155) move(2) def intersection_turn_left(): #交差点左折 if which_edge == 'right_edge': circle(155) move(2) def catch(): #コップキャッチ arm.reset() #pos_positive: to inside, pos_negative: to outside arm.run_to_abs_pos(position_sp=-80, speed_sp=60, stop_action="brake") arm.wait_while("running") move(10) arm.run_to_abs_pos(position_sp=0, speed_sp=60, stop_action="brake") arm.wait_while("running") move(-10) def release(): #コップリリース arm.run_to_abs_pos(position_sp=-80, speed_sp=60, stop_action="brake") arm.wait_while("running") move(5) move(-10) arm.run_to_abs_pos(position_sp=0, speed_sp=60, stop_action="brake") arm.wait_while("running") move(5) **TracerGyro [#y0536ff9] カラーセンサを使った交差点検知に一時期挫折し、ジャイロセンサを使って検知を試みたもの。~ 結局カラーセンサのほうがうまく検知できたため使われることはなくなった。 def dev_run(): #ライントレース、後述のrun_while_not_inersectionに組み込む #run on left edge of a line p = (cs.value()-target_val)*kp if p > 0: bgs = gs.value() #白を検知したら角度をリセット mr.duty_cycle_sp = std_speed-p ml.duty_cycle_sp = std_speed elif p <= 0: mr.duty_cycle_sp = std_speed ml.duty_cycle_sp = std_speed+p def run_while_not_intersection(): #交差点検知までライントレース for motor in motors: motor.run_direct() bgs = gs.value() while True: dev_run() if gs.value()-bgs <= -83: #83度以上の回転を検知したら交差点 # play intersection sound print('debug\tintersection gs.value()-bgs', gs.value()-bgs) (Tracerと共通の部分は省略し、交差点検知の部分だけ記述。) 今見直すと、変数bgsをグローバル変数の宣言をしていなかった。 そのため白を検知した時点で正しく値をリセットできていなかったのかもしれない。 **第2コース走行プログラム [#d706c24f] 上記のTraccer_ver1.7.3をインポートして動作する。 #!/usr/bin/env python3 from tracer_v173 import * #Dをスタート #C直進 run_until_intersection("left_edge") intersection_go_straight() run_until_intersection("left_edge") #B左折 intersection_turn_left() run_until_intersection("left_edge") #P一時停止、左折 time.sleep(1) intersection_turn_left() run_until_intersection("left_edge") #Q直進 intersection_go_straight() run_until_intersection("left_edge") #R左折 intersection_turn_left() run_until_intersection("left_edge") #E左折 intersection_turn_left() # avoid misdetection of sharp turn as intersection for motor in mr, ml: motor.run_direct() start_time = time.time() while time.time()-start_time < 12: line_following('left_edge') for motor in mr, ml: motor.stop(stop_action='brake') run_until_intersection('left_edge') #F左折 intersection_turn_left() run_until_intersection("left_edge") #S一時停止、直進 # intersection_go_straight() #Yコップキャッチ circle(-120) catch() circle(50) move(6) run_until_intersection("left_edge") #S一時停止、直進 intersection_go_straight() run_until_intersection("left_edge") #Q一時停止、左折 intersection_turn_left() run_until_intersection("left_edge") #R直進,コップリリース intersection_go_straight() circle(-90) release() circle(90) move(1) run_until_intersection("left_edge") #P左折 intersection_turn_left() run_until_intersection("left_edge") #B一時停止、左折 time.sleep(1) intersection_turn_left() run_until_intersection("left_edge") #Aゴール *結果 [#w175f204] ライントレースは9割ほど成功するまでに洗練されてきたが、コップキャッチ周辺でミスが起こることがまだ多い。次回のロボコンに向けて、より高い精度を目指したい。 &br; 来客数カウンター &color(white,black){&counter;}; &br; 意見や感想などあればどうぞ。 - 35bmur <a href="http://ilnkeduznncm.com/">ilnkeduznncm</a>, [url=http://mixeirpsbxbm.com/]mixeirpsbxbm[/url], [link=http://pphyhotnmssr.com/]pphyhotnmssr[/link], http://jvzxnghmdpcy.com/ -- [[mzgcnmlxgi]] &new{2021-07-29 (木) 20:58:34}; #comment