#contents 今回は紙コップとピンポン玉を運び既定の位置に置くロボットをつくり、ロボコンとして競い合った ルールはhttp://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMission3 **ロボット [#r8de61a3] *第一段階 [#sffe76aa] 課題をこなすためのロボットとして、二台同時に走らせ効率的に紙コップを回収することにした。 そのため各班に与えられた六つのモータを二つに分け三つで作らなければならない。そこで授業で先生から教えてもらった歯車を使いつかみと持ち上げをモータ一つで賄う方法をためした。 #ref(./daiitidankaia-mu.jpg,80%) #ref(./daiitidankaia-mu (2).jpg,80%) 画像のように歯車を使うことで片方を開閉させ持ち上げることには成功した。しかしながら歯車同士をかみ合わせるための機構(下の画像の左部分)がややこしくかつ重くなってしまったため機体に取り付けたとこ ろ誤差が大きくうまく作動しなかった *第二段階 [#l7c1467e] 第一段階でうまくいかなかったので一台にまとめることにした単純にコップをつかむ部分と持ち上げる部分で二つのモータを使うことで機体を簡素化した。 #ref(./dai2dankaia-mu.jpg,80%) 画像のようにつかむ部分をモータにして、モータのついていないほうは紙コップが奥に行き過ぎることを防ぐために突起をつけた #ref(./daiitidankaidodai.jpg,80%) 車体部分も超音波センサーを縦につけることで誤差を軽減させた。 #ref(./dainidankai.jpg,80%) しかしながらいざつけてみると画像のようにアームのモータが重く持ち上げたままにすることができなかった。 *第三段階 [#wb9b1524] 第二段階でアームをつかむ部分にモータをつけると重くなることが分かったので第一段階の歯車を改良した。 #ref(./daisandankaikitai-5.jpg,80%) 画像のように軸に方向を変換できる歯車をつけることで軸が回るとアームが開閉するようにして、アーム同士が合わさり固定されると軸のみが回り上下するようになっている。(画像左がアームをつけた状態・右がアームのない状態) #ref(./daisandankaidodai.jpg,80%) 車体はキットの説明書に載っているものを改良し、センサを取り付けることで安定した走りにすることができた。画像では超音波センサがないが超音波センサはアームに取り付けていた。 #ref(./daisandankaikitai-4.jpg,80%) アームと車体をつなげたものアームの先端にゴムの部品をつけることで滑りにくくしている #ref(./daisandankaikitai-3.jpg,80%) #ref(./daisanndankaikitai-2.jpg,80%) アームが開いた状態と持ち上がった状態。これでうまくいくかのように思われたがアームと共にセンサも持ち上がったため、紙コップを持ったまま次のコップが探せず、さらにアームと紙コップの接点が二点だったため紙コップが回転した *第四段階 [#w6f33c7e] 基礎となる部分が第三段階でできたので問題点を改良しそれを二台つくった #ref(./daisandannkaikitai.jpg,80%) 画像のようにアームのつかむ部分に棒を刺しそこにゴムをつけることで紙コップとの接点を増やし超音波センサをアームの下につけた。 *プログラミング [#i19ac945] 今回プログラミングはチームメイトが行ってくれたので詳しくはhttp://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Fibu%2FMission3を **概略 [#m9cc5ee5] #ref(./2017b-mission3.png,80%) 今回は機体を二台に分け赤ラインを一号車、緑ラインを二号車が担当することで効率的にコップを回収しかつどちらかが失敗をしてもある程度ポイントを稼げるようにした **プログラミング [#fa6f63e6] ここではプログラムの概略だけ説明する。今回ライントレース・アームの動作・コップのサーチこの三つを関数化した import ev3dev.ev3 as ev3 import time defnite constants, instance, function 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' us = ev3.UltrasonicSensor() assert us.connected, "Connect a color sensor to any sensor port" us.mode = 'US-DIST-CM' position_sp_to_angle = 1.55 target_val = 50 std_speed = 22 kp = std_speed*0.04 position_sp_to_cm = 20.05 intersection_time = 0.23/1.8 angle_stabilization_time = 0.3*1.8 def run_until_intersection(edge): 'If it find intersection,it will beep.' global global_edge global_edge = edge start_time = time.time() for motor in mr, ml: motor.run_direct() while time.time()-start_time <= intersection_time: line_following(edge) if 10 < cs.value() < 100: start_time = time.time() ev3.Sound.beep() while abs(cs.value()-target_val) > 10: line_following(edge) for motor in mr, ml: motor.stop(stop_action='brake') def line_following(edge): 'It is used by other function' if edge == 'left_edge': p = (cs.value()-target_val)*kp elif edge == 'right_edge': p = (target_val-cs.value())*kp else: print('invailed 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 change_following_edge(): 'It is used,when you wanna change following edge' line_adjust_by_time(global_edge) if global_edge == 'right_edge': circle(90) move(2) circle(-90) elif global_edge == 'left_edge': circle(-90) move(2) circle(90) def move(distance): 'The argument means cm distance.You can use negative and positive argument' for motor in mr, ml: motor.run_to_rel_pos(position_sp=distance*position_sp_to_cm, speed_sp=std_speed*5, stop_action='brake') for motor in mr, ml: motor.wait_while('running') def circle(rotation_angle): 'Counterclockwise is positive,like math' if rotation_angle < 0: signs = [-1, 1] elif rotation_angle >= 0: signs = [1, -1] for motor, sign in zip([mr, ml], signs): motor.run_to_rel_pos(position_sp=sign*abs(rotation_angle)*position_sp_to_angle, speed_sp=std_speed*5, stop_action='brake') for motor in mr, ml: motor.wait_while('running') def intersection_go_straight(): 'It is used,when it find a intersection' if global_edge == 'left_edge': circle(-70*1.2) elif global_edge == 'right_edge': circle(70*1.2) for motor in mr, ml: motor.run_direct() while abs(cs.value()-target_val) > 10: line_following(global_edge) for motor in mr, ml: motor.stop(stop_action='brake') def intersection_turn_right(): 'It is used,when it find a intersection' if global_edge == 'left_edge': circle(-145) move(2) def intersection_turn_left(): 'It is used,when it find a intersection' if global_edge == 'right_edge': circle(145) move(2) def init_arm(): 'pos_positive: to inside, pos_negative: to outside' arm.reset() # del stop_action='hold' input('Press Enter to initialize closed arm position') arm.reset() def arm_open(): 'You must run init_arm() beforehand' arm.run_to_abs_pos(position_sp=200, speed_sp=std_speed*5, stop_action="hold") arm.wait_while("running") def cup_catch(): 'You must run init_arm() beforehand' mr.run_forever(speed_sp=std_speed*5) ml.run_forever(speed_sp=std_speed*5) while us.value() > 50: pass for motor in mr, ml: motor.stop(stop_action='brake') move(5) arm.run_to_abs_pos(position_sp=0, speed_sp=std_speed*5, stop_action="hold") arm.wait_while("running") move(-5) def cup_a_little_lift(): 'You must run init_arm() beforehand' arm.run_to_abs_pos(position_sp=-42, speed_sp=std_speed*5, stop_action="hold") arm.wait_while("running") def cup_lift(): 'You must run init_arm() beforehand' arm.run_to_abs_pos(position_sp=-230, speed_sp=std_speed*5, stop_action="hold") arm.wait_while("running") def search_min_d(search_time=4.5, i=1): 'if i=1 hantokeimawari,i=-1tokeimawari' 'serch minimum distance and face the angle' if i == 1: sign = [1, -1] elif i == -1: sign = [-1, 1] min_d = 500 start_time = time.time() mr.run_forever(speed_sp=sign[0]*std_speed*5) ml.run_forever(speed_sp=sign[1]*std_speed*5) while time.time()-start_time < search_time: if min_d > us.value(): min_d = us.value() for motor in mr, ml: motor.stop(stop_action='brake') start_time = time.time() mr.run_forever(speed_sp=sign[1]*std_speed*5) ml.run_forever(speed_sp=sign[0]*std_speed*5) while time.time()-start_time < search_time: if us.value() <= min_d: for motor in mr, ml: motor.stop(stop_action='brake') return for motor in mr, ml: motor.stop(stop_action='brake') search_min_d(search_time) def line_adjust_by_edge(edge): 'it is used for avoid misditect as intersection' for motor in mr, ml: motor.run_direct() while abs(cs.value()-target_val) > 10: line_following(edge) for motor in mr, ml: motor.stop(stop_action='brake') def line_adjust_by_time(edge, stab_time=angle_stabilization_time): 'it is used for make it parallel to the line' for motor in mr, ml: motor.run_direct() start_time = time.time() while time.time()-start_time < stab_time: line_following(edge) for motor in mr, ml: motor.stop(stop_action='brake') def run_until_line(): 'finding line,stops.' for motor in mr, ml: motor.run_forever(speed_sp=std_speed*5) while abs(cs.value()-target_val) > 10: pass for motor in mr, ml: motor.stop(stop_action='brake') 一号車はライントレース、コップをつかむ、xに行く、コップを持ち上げピンポン玉を落とす、yに行き紙コップを置くという動作をするようにした def arm_set(): a = input('w, s') while a in {'w', 's'}: if a == 'w': arm.run_timed(time_sp=0.1*1000, speed_sp=200, stop_action='brake') arm.wait_while('running') elif a == 's': arm.run_timed(time_sp=0.1*1000, speed_sp=-200, stop_action='brake') arm.wait_while('running') a = input('w, s') ''' def mqtt_send(x): #値を送信 position = x #位置情報をアルファベットで送信 client.publish("position", position) # "position"というトピックでブローカに送る print("send_position_"+x) ''' def main(): #client.connect("10.60.2.156",1883, 60) # ブローカに接続、(60秒以上接続がないと切断) line_adjust_by_time('left_edge', 1.3) run_until_intersection('left_edge') intersection_turn_left() change_following_edge() run_until_intersection('right_edge') intersection_turn_right() line_adjust_by_time('right_edge', 1) run_until_intersection('right_edge') circle(145) # intersection,change direction arm_open() move(-4) search_min_d(1) cup_catch() circle(-105) move(1) line_adjust_by_time('left_edge', 1) circle(-20) run_until_intersection('left_edge') cup_a_little_lift() move(4) circle(35) move(5) cup_a_little_lift() move(10) cup_lift() circle(-30) move(-5) search_min_d(1, -1) cup_catch() arm_open() cup_a_little_lift() circle(60) cup_lift() circle(-140) arm_open() move(-4) circle(-90) #mqtt_send(1) move(50) #client.disconnect() # 切断 if __name__ == '__main__': arm_set() init_arm() main() 二号車は画像下の紙コップをとる、xに行く、ピンポン玉を落とす、画像上の紙コップをとる、xに行く、ピンポン玉を落とす、yに行く、紙コップを置くという動作をするようにした rom def_green_v016 import * def arm_set(): a = input('w, s') while a in {'w', 's'}: if a == 'w': arm.run_timed(time_sp=0.25*1000, speed_sp=200, stop_action='brake') arm.wait_while('running') elif a == 's': arm.run_timed(time_sp=0.25*1000, speed_sp=-200, stop_action='brake') arm.wait_while('running') a = input('w, s') def main() run_until_line() move(4) line_adjust_by_edge('right_edge') run_until_intersection('right_edge') circle(33) arm_open() search_min_d(0.8) cup_catch() circle(-160) line_adjust_by_edge('left_edge') run_until_intersection('left_edge') intersection_turn_left() line_adjust_by_time('left_edge', 1.3) cup_a_little_lift() move(5) cup_lift() move(-50) line_adjust_by_time('left_edge', 5) run_until_intersection('left_edge') move(15) circle(35*1.2) line_adjust_by_edge('left_edge') line_adjust_by_time('left_edge', 3) run_until_intersection('left_edge') intersection_turn_left() run_until_intersection('left_edge') circle(-27) arm_open() if __name__ == '__main__': arm_set() init_arm() main() 二号車は画像下の紙コップをとる、xに行く、ピンポン玉を落とす、画像上の紙コップをとる、xに行く、ピンポン玉を落とす、yに行く、紙コップを置くという動作をするようにした *結果 [#vcf79bb0] 今回自分たちのチームは基本点8技術点10.7で総合2位だった。しかしながらうまくいかなかった部分が多々あり悔しい結果であった。改善点としてはセンサでの誤差をアームでカバーするために可動域を広くするというのが見つかった。これで最後の課題となったがまだまだ自分たちは未熟であるためこれからもしっかりと学んでいきたい