#author("2020-01-10T16:32:06+09:00","bearch","bearch") [[2019b/Member]] #contents *課題2 [#ge4abbdc] **ライントレースで二人目のミッションを達成する [#l881fc8d] #ref(2019b-mission2.png) -二人目のミッション ~1.A地点から出発 ~2.J ~3.H (直進) ~4.I (ボール or キューボイドをつかんでUターン) ~5.H (右折) ~6.G (一時停止の後、直進) ~7.D (右折) ~8.E, F 通過 ~9.G (一時停止の後、直進) ~10.C (一時停止の後、左折) ~11.B (一時停止) *ロボットの説明 ハード面 [#rfe86f5b] このロボットはEV3で作成されています。最新型での説明をします。 #ref(12841_2.jpg) **カラーセンサ [#g20383c1] まず、図1を見てください。カラーセンサの高さを、近すぎず遠すぎない位置に設定し、値の取得がし易いようにしました。そしてできるだけタイヤの近くに設置し、コンパクトにしました。 ~図1 #ref(12839_2.jpg) **超音波センサとカコイ [#v7139fc0] 次に、図2を見てください。超音波センサを地面に対して垂直に、地面に向かせて取り付けてあります。これによりキューボイドが真下に来た時にしか反応しないようにしています。もし地面に対して平行に取り付けると、反応して欲しくない時に反応してしまう恐れがあったので、そのリスクを避けました。 ~そして、キューボイドを掴む仕組みはモータでカコイを上げ下げすることでキューボイドを捕らえるようにしました。このモータは超音波センサと連動させています。それはプログラム面で解説します。 ~図2 #ref(12846_2.jpg) *ロボットの説明 プログラム面 [#w59e7b42] **ロボットの強み [#u5f6eae8] このロボットの最大の強みは汎用性の高さです。 ~メインとなるプログラムは同じ班のメンバーと全く同じで、走らせたいコースによって読み込ませるテキストファイルを変えることでどんなコースにも対応できます。なぜこのようなことができるかというと、このロボットは黒い線の左右どちらかをライントレースするかを選択でき、道の分岐があることを判断すると、そこの分岐にいくつ道があるかを探索するという機能を持っており、分岐判断後にどの道の左右のどちらかのライントレースをするか選べるという仕組みがあるからです。この探索機能は線が直角に交わっているところと急なカーブで反応し、そこに差し掛かると探索を始めるようになっています。なので分岐を判断したい時は黒い線の分岐判断できる側のライントレースする必要があります。そこだけはあらかじめ考えておく必要があります。これにより理論上どのコースでもテキストファイルを読み込むだけで走らせることができます。 **キューボイドを捕らえる [#w417cc11] ~そして、ロボットがキューボイドを捕らえる仕組みも工夫しました。超音波センサが真下にきたキューボイドを認識すると、カコイが下りるという関数が呼び出され、キューボイドを捕らえるようにしています。これにより精度が高くキューボイドを捕らえることができます。 **Uターン [#m4b5fc9f] ~二人目のミッションはUターンをしなければいけないのでUターンも工夫しました。Uターンはただ180度回転させるのではなく、90度までは回転し、そこからは黒い線を認識できるまで回転するという仕組みを採用しました。この仕組みにより綺麗にUターンできるようになってます。 *実際のプログラム 全体 [#x747b325] -メインプログラム #!/usr/bin/env python3 from ev3dev2.motor import Motor,OUTPUT_A,MoveTank,LargeMotor,OUTPUT_B,OUTPUT_C from ev3dev2.sensor.lego import ColorSensor,TouchSensor,UltrasonicSensor from time import sleep m_r = LargeMotor(OUTPUT_C) m_l = LargeMotor(OUTPUT_B) tank = MoveTank(OUTPUT_B,OUTPUT_C) cs = ColorSensor() ts =TouchSensor() us = UltrasonicSensor() fc_m = Motor(OUTPUT_A) threshold = 45 v_s = 12.5 v_c = 5.0 k_s = 0.25 k_c = 2.25 cs_val_black = 15 cs_th_d_max = 20 csd_s_max = 3 v_is = 5 v_fc = 5 v_fc_m = 5 cs.mode ="COL-REFLECT" us.mode ="US-DIST-CM" a1_is=-0.2 a2_is=1 def intersection (sign,index_list_is,list_intersection): print(list_intersection[index_list_is]) n_w = int(list_intersection[index_list_is][0]) if list_intersection[index_list_is][1]=="r": sign_is = 1 elif list_intersection[index_list_is][1]=="l": sign_is = -1 tank.on((a1_is+sign)*v_is,(a1_is-sign)*v_is) print("check1") while True: if cs.value()>threshold: break tank.on((a2_is-sign)*v_is,(a2_is+sign)*v_is) for i in range(n_w): while True: if cs.value()<=cs_val_black: break while True: if cs.value()>threshold: break if sign_is*sign==1: tank.on(sign_is*v_is,-sign_is*v_is) while True: if cs.value()<=cs_val_black: break while True: if cs.value()>threshold: break tank.on(0,0) return sign_is def fetch_cuboid(sign_fc): fc_m.reset() fc_m.on_to_position(v_fc_m,-90) tank.on_for_degrees(v_fc,-v_fc,180) while cs.value()>cs_val_black: tank.on(v_fc,-v_fc) while cs.value()<threshold: tank.on(sign_fc*v_fc,-sign_fc*v_fc) tank.on(0,0) def fetch_cuboid3(sign_fc): fc_m.reset() fc_m.on_to_position(v_fc_m,-90) tank.on_for_degrees(v_fc,v_fc,600) tank.on_for_degrees(v_fc,-v_fc,180) while cs.value()>cs_val_black: tank.on(v_fc,-v_fc) tank.on(0,0) fc_m.on_to_position(v_fc_m,0) tank.on_for_degrees(-v_fc,-v_fc,60) tank.on_for_degrees(v_fc,-v_fc,180) while cs.value()>cs_val_black: tank.on(v_fc,-v_fc) while cs.value()<threshold: tank.on(sign_fc*v_fc,-sign_fc*v_fc) tank.on(0,0) def follow_line(sign_fl,fc_ab): while True: cs_d = max(min(cs.value(),threshold+cs_th_d_max),threshold-cs_th_d_max)-threshold if -csd_s_max < cs_d < csd_s_max: v_fl=v_s k_fl=v_fl*k_s/cs_th_d_max else: v_fl=v_c k_fl=v_fl*k_c/cs_th_d_max v_r_fl = v_fl+sign_fl*k_fl*cs_d v_l_fl = v_fl-sign_fl*k_fl*cs_d if fc_ab == "b" and us.value()<110: after_fl_fl = "fc" break if cs.value()<cs_val_black: after_fl_fl = "is" break if ts.is_pressed: after_fl_fl = "ts_break" break tank.on(v_l_fl,v_r_fl) tank.off() return after_fl_fl def main(): main_break_bool=False index_list_is = 0 after_fl="after_fl" fc_ab = "b" #input while True: print("start:num") try: number = int(input("number(1~3):")) if 0<number<4: break except: pass print("number:",number) print("") #read #list_is print("start:list_is") list_intersection=[] file_name = "list_is" + str(number) try: with open(file_name, "r") as f: list_intersection_raw = f.readlines() for i in list_intersection_raw: list_intersection.append(i.strip().split(",")) for n,i in enumerate(list_intersection): list_intersection[n][0] = i[0].strip() list_intersection[n][1] = i[1].strip() if not ((i[0].strip() in {"1","2","3"}) and (i[1].strip() in {"r","l"}) and len(i)==2): print("file content error") raise Exception list_intersection.append("end") print("raw list:",list_intersection_raw) print("list:",list_intersection) print("") except: print("file is_list error") main_break_bool=True #list_sign0 print("start:list_sign0") try: with open("sign0", "r") as f: list_sign0_raw = f.readlines() if list_sign0_raw[number-1].strip()=="r": sign = 1 elif list_sign0_raw[number-1].strip()=="l": sign = -1 else: print("file content error") raise Exception except: print("file sign0 error") main_break_bool=True print("sign0:",sign) print("") #u_turn_rl print("start:u_turn_rl") try: with open("u_turn_rl", "r") as f: list_ut_raw = f.readlines() if list_ut_raw[number-1].strip()=="r": sign_fc = 1 elif list_ut_raw[number-1].strip()=="l": sign_fc = -1 else: print("file content error") raise Exception except: print("file u_turn_rl error") main_break_bool=True print("sign_fc:",sign_fc) print("") #move if not main_break_bool: while cs.value()>cs_val_black: tank.on(10,10) tank.on(0,0) while True: after_fl = follow_line(sign,fc_ab) #follow_line if after_fl == "fc" and fc_ab=="b": #fetch cuboid print("fetch cuboid") if number<3: fetch_cuboid(sign_fc) else: fetch_cuboid3(sign_fc) sign = sign_fc fc_ab = "a" elif after_fl == "is": #intersection if list_intersection[index_list_is]=="end": tank.on_for_degrees(v_fc,v_fc,270) print("list:end") break else: print("intersection") sign = intersection(sign,index_list_is,list_intersection) print("index:",index_list_is) index_list_is += 1 elif after_fl == "ts_break": #touch sensor break print("touch break") break else: print("after_fl error") after_fl="after_fl" else: print("main break") print("end") tank.on(0,0) if __name__ == "__main__": main() -テキストファイル u_turn_rl l r r -テキストファイル sign0 r r r -テキストファイル list_is2 2,r 1,l 2,l 1,r 2,r 1,l 2,l 1,l *実際のプログラム 説明 [#r223136f] -はじめのほうに書いてあることを読んでください。 #!/usr/bin/env python3 from ev3dev2.motor import Motor,OUTPUT_A,MoveTank,LargeMotor,OUTPUT_B,OUTPUT_C from ev3dev2.sensor.lego import ColorSensor,TouchSensor,UltrasonicSensor from time import sleep """ 動作について ラインの内側の境界をとりながら曲がる道は分岐点として判断され、intersection()が実行されるのでそれに合わせてlist_isを作る プログラムを開始したとき白い場所にいる場合ラインの中まで進んでから(ラインの中から開始した場合はその状態から)、sign0に書いてある値に合わせてlist_isの一行目を使いintersection()を実行する list_is(n),sign0,u_turn_rlについて list_is(n) :何回目の分岐でなにをするかを書く sign0 :プログラムを実行してから最初にラインまで走るとき(ライン上でプログラムを実行した場合はその状態のとき)右と左のうちどちらの境界をとっているということにするかを書く u_turn_rl :fetch_cuboid()またはfetch_cuboid3()の実行後に右と左のうちどっちの境界をとるかを書く このプログラムのコメントについて #のコメントは大雑把にみるための簡単なメモ """"""のコメントは説明 このプログラムのコメントの説明等について 関数の定義での引数に関する説明では「引数の名前=引数がどういう値をとるか:引数が何を表しているか」という形で書き、引数が複数ある場合は;で区切ってある 変数の代入やreturnで:で区切ってある場合「どういう値をとるか:変数などが何を表しているか」というふうに書かれてる 基本的には""""""の説明は空行で区切られている(""""""の説明はその説明が書いてある行から次の空行までについての説明である) """ **定数 [#s1b51dfa] m_r = LargeMotor(OUTPUT_C) m_l = LargeMotor(OUTPUT_B) tank = MoveTank(OUTPUT_B,OUTPUT_C) cs = ColorSensor() ts =TouchSensor() us = UltrasonicSensor() fc_m = Motor(OUTPUT_A) threshold = 45 """境界として使う場所でのcsの値"""#intersection(),fetch_cuboid(),fetch_cuboid3(),follow_line() v_s = 12.5 """まっすぐ進むときのtankの速さ"""#follow_line() v_c = 5.0 """曲がるときのtankの速さ"""#follow_line() k_s = 0.25 """まっすぐ進むときのtankの曲がりやすさ"""#follow_line() k_c = 2.25 """曲がるときのtankの曲がりやすさ"""#follow_line() cs_val_black = 15 """黒いと判断させたい場所でのcsの値の中での最大値"""#intersection(),fetch_cuboid(),fetch_cuboid3(),follow_line() cs_th_d_max = 20 """csの値を使うときその値を-cs_th_d_max<=csの値<=cs_th_d_maxの範囲で制限するために使う値"""#follow_line() csd_s_max = 3 """-csd_s_max<threshold-csの値<csd_s_maxのときまっすぐ進んでると判断させるために使う値"""#follow_line() v_is = 5 """intersection()実行時のtankの速さ"""#intersection() v_fc = 5 """fetch_cuboid()またはfetch_cuboid3()実行時のtankの速さ"""#fetch_cuboid(),fetch_cuboid3() v_fc_m = 5 """fetch_cuboid()またはfetch_cuboid3()実行時のfc_mの速さ"""#fetch_cuboid(),fetch_cuboid3() cs.mode ="COL-REFLECT" us.mode ="US-DIST-CM" a1_is=-0.2 """基本的には0以下で-1より大きい:intersection()実行時にtankを分岐点から遠ざかる方向に外側に向くように回転させるときにどのくらい大きく回転させるか"""#intersection() a2_is=1 """基本的には0より大きい:intersection()実行時にtankが道を探すため分岐点周辺を回るときにどのくらい大きく回るか"""#intersection() **変数 [#f356ca28] main_break_bool= True,False (とりうる値) index_list_is = 1,2,3,... (とりうる値) after_fl= "after_fl","fc","is","ts_break" (とりうる値) fc_ab = "a","b" (とりうる値) number = 1,2,3 (とりうる値) list_intersection = [[2,l],[2,l],[1,l],[1,l],[1,r],[1,l],"end"] (例) sign = -1,1 (とりうる値) sign_fc = -1,1 (とりうる値) **関数 [#s5d875de] ***intersection() [#de5621fa] def intersection (sign,index_list_is,list_intersection): """sign=1か-1:intersection()実行前にとってる境界が右か左か;index_list_is=整数:何回目の分岐か;list_intersection=二次元リスト:何回目の分岐でなにをするか""" print(list_intersection[index_list_is]) """道の番号とその道でとる境界の右左の表示""" n_w = int(list_intersection[index_list_is][0]) """道の番号""" if list_intersection[index_list_is][1]=="r": """とる境界の右左に合わせてsign_isの値を1か-1に決める""" sign_is = 1 elif list_intersection[index_list_is][1]=="l": sign_is = -1 tank.on((a1_is+sign)*v_is,(a1_is-sign)*v_is) """tankを分岐点から遠ざかる方向に外側に向くように回転させる""" print("check1") while True: if cs.value()>threshold: break tank.on((a2_is-sign)*v_is,(a2_is+sign)*v_is) """分岐点周辺を回って指定された道まで行く""" for i in range(n_w): while True: if cs.value()<=cs_val_black: break while True: if cs.value()>threshold: break if sign_is*sign==1: """指定された道の右か左の境界のうち指定された境界のほうにtankが行くように調整してそこで止める""" tank.on(sign_is*v_is,-sign_is*v_is) while True: if cs.value()<=cs_val_black: break while True: if cs.value()>threshold: break tank.on(0,0) return sign_is """1か-1:intersectiont()実行後にとる境界が右か左か""" ***fetch_cuboid() [#n7dab819] def fetch_cuboid(sign_fc): """sign_fc=1か-1:fetch_cuboid()が終わった後でとる境界が右か左か""" fc_m.reset() """fc_mの角度をリセットする""" fc_m.on_to_position(v_fc_m,-90) """cuboidを捕まえる""" tank.on_for_degrees(v_fc,-v_fc,180) """tankの向きをおよそ90度回転させる""" while cs.value()>cs_val_black: """tank.on_for_degrees(v_fc,-v_fc,180)と同じ向きで黒いラインまで回転する""" tank.on(v_fc,-v_fc) while cs.value()<threshold: """黒いラインの中からsign_fcに合わせて右か左の境界まで移動して止める""" tank.on(sign_fc*v_fc,-sign_fc*v_fc) tank.on(0,0) ***fetch_cuboid3() [#be2b1a85] def fetch_cuboid3(sign_fc): """sign_fc=1か-1:fetch_cuboid3()が終わった後でとる境界が右か左か""" fc_m.reset() """fc_mの角度をリセットする""" fc_m.on_to_position(v_fc_m,-90) """cuboidを捕まえる""" tank.on_for_degrees(v_fc,v_fc,600) """tankを前に進める""" tank.on_for_degrees(v_fc,-v_fc,180) """tankの向きをおよそ90度回転させる""" while cs.value()>cs_val_black: """tank.on_for_degrees(v_fc,-v_fc,180)と同じ向きで黒いラインまで回転して止める""" tank.on(v_fc,-v_fc) tank.on(0,0) fc_m.on_to_position(v_fc_m,0) """cuboidを放す""" tank.on_for_degrees(-v_fc,-v_fc,60) """tankを少し後ろに下げる""" tank.on_for_degrees(v_fc,-v_fc,180) """tankの向きをおよそ90度回転させる""" while cs.value()>cs_val_black: """tank.on_for_degrees(v_fc,-v_fc,180)と同じ向きで黒いラインまで回転する""" tank.on(v_fc,-v_fc) while cs.value()<threshold: """黒いラインの中からsign_fcに合わせて右か左の境界まで移動して止める""" tank.on(sign_fc*v_fc,-sign_fc*v_fc) tank.on(0,0) ***follow_line() [#cec601d2] def follow_line(sign_fl,fc_ab): """sign_fl=1か-1:follow_line()する境界が右か左か;fc_ab=aかb:fetch_cuboid()またはfetch_cuboid3()がすでに実行されたか""" while True: cs_d = max(min(cs.value(),threshold+cs_th_d_max),threshold-cs_th_d_max)-threshold """csでとった値と境界での値の差をある範囲で制限したもの""" if -csd_s_max < cs_d < csd_s_max: """tankの速さを決める(まっすぐ進むときと曲がるときで変えてある)""" v_fl=v_s k_fl=v_fl*k_s/cs_th_d_max else: v_fl=v_c k_fl=v_fl*k_c/cs_th_d_max v_r_fl = v_fl+sign_fl*k_fl*cs_d """右のタイヤと左のタイヤの速さをそれぞれ決める""" v_l_fl = v_fl-sign_fl*k_fl*cs_d if fc_ab == "b" and us.value()<110: """ある条件を満たすときfollow_line()を止めて、その条件に応じてそのあと行動が決まるので、その行動に対応してる文字列をafter_fl_flに代入する""" after_fl_fl = "fc" break if cs.value()<cs_val_black: after_fl_fl = "is" break if ts.is_pressed: after_fl_fl = "ts_break" break tank.on(v_l_fl,v_r_fl) """v_l_flとv_r_flを使ってtankを動かす""" tank.off() return after_fl_fl """fcかisかts_break:follow_line()実行後になにをするか""" ***main() [#vdea6671] #inputでは何番目の人のミッションを行うか選べる ~1番目→"1"を入力 ~2番目→"2"を入力 ~3番目→"3"を入力 ~というようにする。変数numberに1〜3の値が入力され、【読み込み】の#list_is、#sign0、#u_turn_rlに変数numberが渡される。 ~【読み込み】で何をしているかは【読み込み】で説明しています。 def main(): main_break_bool=False """ファイル読み込みでエラーが起きたときTrueになり、そうでないときFalseをとるboolean型の変数""" index_list_is = 0 """何番目の分岐点か""" after_fl="after_fl" """:follow_line()が止まってから何をするかを保存しておく変数""" fc_ab = "b" """aかb:fetch_cuboid()またはfetch_cuboid3()がすでに実行されたか(a:すでに実行された,b:まだ実行されてない)""" #input while True: """1か2か3を入力し、それをnumberに代入する""" print("start:num") try: number = int(input("number(1~3):")) if 0<number<4: break except: pass print("number:",number) print("") -------------------------------------------------------------------------------------- 読み込み -------------------------------------------------------------------------------------- #move if not main_break_bool: """ファイル読み込みでエラー等がなければこの中身を実行する""" while cs.value()>cs_val_black: """ラインに着くまでまっすぐ進む""" tank.on(10,10) tank.on(0,0) while True: """このwhileの中がメインのプログラム""" after_fl = follow_line(sign,fc_ab) """follow_line()を実行"""#follow_line if after_fl == "fc" and fc_ab=="b": """usによってキューボイドがあると判断されプログラムを始めてからまだfetch_cuboid()またはfetch_cuboid3()が一度も実行されてなければnumberに応じてそれらのうちいずれかを実行する"""#fetch cuboid print("fetch cuboid") if number<3: fetch_cuboid(sign_fc) else: fetch_cuboid3(sign_fc) sign = sign_fc fc_ab = "a" elif after_fl == "is": """list_intersection[index_list_is]がendならばtankを少し進めてから止めてメインのプログラムを止め,そうでなければlist_intersection[index_list_is]に合わせてintersection()を実行する"""#intersection if list_intersection[index_list_is]=="end": tank.on_for_degrees(v_fc,v_fc,270) print("list:end") break else: print("intersection") sign = intersection(sign,index_list_is,list_intersection) print("index:",index_list_is) index_list_is += 1 elif after_fl == "ts_break": """tsが押されたら止める"""#touch sensor break print("touch break") break else: """after_flに正しい値が入力されていることの確認用(正しい値が代入されてなければこれの中身を実行する)""" print("after_fl error") after_fl="after_fl" else: print("main break") print("end") tank.on(0,0) if __name__ == "__main__": main() **読み込み [#t5b8e99c] こちらはテキストファイルではありません。main()の中の読み込みに使われる部分です。 ~#list_is、#sign0、#u_turn_rlでは与えられたnumberに応じて読み込みたいテキストファイルを読み込む #read ***list_is [#i4f2528e] 与えられたnumberに応じて読み込みたいテキストファイルを読み込みます。 ~(例)number = 2 →list_is2 を読み込む ~ぼくは2番目のミッションなのでlist_is2を読み込みました。 ~そして、読み込んだテキストファイルからlist_intersectionという二次元リストを作ります。これは【関数】のintersection()で使います。 #list_is print("start:list_is") """list_is(n)という名前のファイルを読み込みlist_intersectionという名前の二次元リストでまとめる。(n)はプログラム実行時に入力する数字とする""" list_intersection=[] file_name = "list_is" + str(number) try: with open(file_name, "r") as f: list_intersection_raw = f.readlines() for i in list_intersection_raw: list_intersection.append(i.strip().split(",")) for n,i in enumerate(list_intersection): list_intersection[n][0] = i[0].strip() list_intersection[n][1] = i[1].strip() if not ((i[0].strip() in {"1","2","3"}) and (i[1].strip() in {"r","l"}) and len(i)==2): print("file content error") raise Exception list_intersection.append("end") print("raw list:",list_intersection_raw) print("list:",list_intersection) print("") except: print("file is_list error") main_break_bool=True ***sign0 [#w7280591] #list_sign0 print("start:list_sign0") """sign0という名前のファイルを読み込みnumber行目の値に応じてsignに1か-1を代入する""" try: with open("sign0", "r") as f: list_sign0_raw = f.readlines() if list_sign0_raw[number-1].strip()=="r": sign = 1 elif list_sign0_raw[number-1].strip()=="l": sign = -1 else: print("file content error") raise Exception except: print("file sign0 error") main_break_bool=True print("sign0:",sign) print("") ***u_turn_rl [#rddc2e62] #u_turn_rl print("start:u_turn_rl") """u_turn_rlという名前のファイルを読み込み(n)行目の値に応じてsign_fcに1か-1を代入する。(n)はプログラム実行時に入力する数字とする""" try: with open("u_turn_rl", "r") as f: list_ut_raw = f.readlines() if list_ut_raw[number-1].strip()=="r": sign_fc = 1 elif list_ut_raw[number-1].strip()=="l": sign_fc = -1 else: print("file content error") raise Exception except: print("file u_turn_rl error") main_break_bool=True print("sign_fc:",sign_fc) print("") *もともと目指していたロボット [#dac968c8] 僕らの班ではもともと別の機構を採用したロボットを目指していました。下の写真のようなロボットです。製作するにあたり、ロボット完成発表の日に間に合わず製作を一時断念しました。 #ref(12872_2.jpg) もともと僕たちが作ろうとしていたロボットはモータでカラーセンサを振動させて、カラーセンサを二つ使用していると仮定して黒い線の両側どちらもライントレースできる仕組みを持ったロボットでした。このロボットの強みは黒い線の左右関係なくライントレースし分岐を判断できるところです。しかしモータとカラーセンサの連動、モータをカラーセンサの振動に使っている分キューボイドを捕らえる仕組みはどうするかなど様々な問題を解決するにあたり、大量の時間を要してしまいました。そして、授業で毎週課題がだされており、その課題をこなすための予備用に一般的なライントレースをするロボットも同時並行で作っていたので、ロボットを製作する時間が単純に2倍、それ以上にかかってしまいました、しかしそれでも時間が足りず、このロボットの完成には至りませんでした。ですが結果的にはもともと作っていたロボットと予備用のロボットを組み合わせることで今の最新型のロボットになりました。最新型のロボットは目指していたロボットの長所を引き継いでおり、分岐探索機能と超音波センサを地面方向へ向かせるアイデアはこのロボットから来ています。 ~一応、図3が振動させる仕組みです。モータに歯車をかみ合わせ、カラーセンサを乗せている台が二つの棒を軸に平行に振動するようになっています。 ~図3 #ref(12871_2.jpg) *反省点 [#i642ea52] -発表までに自分たちの目指していた機構を実現できなく、もう少し上手く開発をして行けば良かった。 -班員に任せっきりになってしまう部分があった。班員に感謝。 -ライントレースする紙を本番までに書いて来なかった。他の班の紙を使わせてもらった。しかし、使わせてもらった紙は、ライントレースの線の太さが不均一だったので本番でしっかり力を発揮できなかった、これは書いて来なかった僕たちの班の責任だ。 -ロボットの性能でもっと移動スピードをあげたかった。変数調整するテスト回数が少なかったのが原因。 *さいごに [#b9a23a3b] この課題2は大変楽しかった。プログラミングではpythonの知識も増えて、できることが増えて、自分のできる幅が広がった。 ~課題1ではたった一つの命令だけでやっていたので成長を感じる。一緒に開発した仲間が良かった。