2019b/Member

課題2

ライントレースで二人目のミッションを達成する

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 (一時停止)

ロボットの説明 ハード面

このロボットはEV3で作成されています。最新型での説明をします。

12841_2.jpg

カラーセンサ

まず、図1を見てください。カラーセンサの高さを、近すぎず遠すぎない位置に設定し、値の取得がし易いようにしました。そしてできるだけタイヤの近くに設置し、コンパクトにしました。

図1

12839_2.jpg

超音波センサとカコイ

次に、図2を見てください。超音波センサを地面に対して垂直に、地面に向かせて取り付けてあります。これによりキューボイドが真下に来た時にしか反応しないようにしています。もし地面に対して平行に取り付けると、反応して欲しくない時に反応してしまう恐れがあったので、そのリスクを避けました。

そして、キューボイドを掴む仕組みはモータでカコイを上げ下げすることでキューボイドを捕らえるようにしました。このモータは超音波センサと連動させています。それはプログラム面で解説します。

図2

12846_2.jpg

ロボットの説明 プログラム面

ロボットの強み

このロボットの最大の強みは汎用性の高さです。

メインとなるプログラムは同じ班のメンバーと全く同じで、走らせたいコースによって読み込ませるテキストファイルを変えることでどんなコースにも対応できます。なぜこのようなことができるかというと、このロボットは黒い線の左右どちらかをライントレースするかを選択でき、道の分岐があることを判断すると、そこの分岐にいくつ道があるかを探索するという機能を持っており、分岐判断後にどの道の左右のどちらかのライントレースをするか選べるという仕組みがあるからです。この探索機能は線が直角に交わっているところと急なカーブで反応し、そこに差し掛かると探索を始めるようになっています。なので分岐を判断したい時は黒い線の分岐判断できる側のライントレースする必要があります。そこだけはあらかじめ考えておく必要があります。これにより理論上どのコースでもテキストファイルを読み込むだけで走らせることができます。

キューボイドを捕らえる

そして、ロボットがキューボイドを捕らえる仕組みも工夫しました。超音波センサが真下にきたキューボイドを認識すると、カコイが下りるという関数が呼び出され、キューボイドを捕らえるようにしています。これにより精度が高くキューボイドを捕らえることができます。

Uターン

二人目のミッションはUターンをしなければいけないのでUターンも工夫しました。Uターンはただ180度回転させるのではなく、90度までは回転し、そこからは黒い線を認識できるまで回転するという仕組みを採用しました。この仕組みにより綺麗にUターンできるようになってます。

実際のプログラム 全体

  • メインプログラム
       #!/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

実際のプログラム 説明

  • はじめのほうに書いてあることを読んでください。
   #!/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で:で区切ってある場合「どういう値をとるか:変数などが何を表しているか」というふうに書かれてる
       基本的には""""""の説明は空行で区切られている(""""""の説明はその説明が書いてある行から次の空行までについての説明である)

   """

定数

   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)

   cs.mode ="COL-REFLECT"
   us.mode ="US-DIST-CM"


   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()
   a1_is=-0.2
       値           :基本的には0以下で-1より大きく、intersection()実行時にtankを分岐点から
                     遠ざかる方向に外側に向くように回転させるときにどのくらい大きく回転さ
                     せるかを決める値
       使ってる場所 :intersection()
   a2_is=1
       値           :基本的には0より大きく、intersection()実行時にtankが道を探すため分岐点
                     周辺を回るときにどのくらい大きく回るかを決める値
       使ってる場所 :intersection()

変数

読み込みはmain()に含まれているが、ここではmain()と書いた場合はmain()関数のうち読むこむ部分を除いたものとする。
fetch_cuboid()と書いたときはfetch_cuboid3()も含むとする。
使っている場所に書いてるものは関数実行時に引数として渡している関数も含む。

main_break_bool

   main_break_bool
       とりうる値     :True,False
       どんな値か     :main()でファイルを読み込みそこでエラーやファイルの書き方に間違いが
                       あったときTrueとなり、main()の動かす部分を行わずにプログラムを終了
                       する。
       使っている場所 :読み込み,main()

index_list_is

   index_list_is
       とりうる値     :0,1,2,...
       どんな値か     :最初は0でありintersection()が行われるたびに1増え、intersection()実
                       行時、list_intersection[index_list_is]を使う。
       使っている場所 :intersection(),main()

after_fl

   after_fl
       とりうる値     :"after_fl","fc","is","ts_break"
       どんな値か     :follow_line()実行時に交差点に差し掛かったりcuboidが見つかるなどによ
                       りfollow()を終了するが、そのあと何をするかを表す値
                       "fc"      :fetch_cuboid()を実行する
                       "is"      :intersection()を実行する
                       "ts_break":タッチセンサーが押されたときにこの値になり、main()を終わ
                                  らせる
                       "after_fl":初期化のときに使い、follow_line()実行時に代入はされず、
                                  特に意味のある値ではない。
       使っている場所 :intersection(),読み込み

fc_ab

   fc_ab
       とりうる値     :"a","b"
       どんな値か     :最初は"b"でありfetch_cuboid()が実行されると"a"になる値で、
                       fetch_cuboid()が複数回実行されるのを防ぐために使われている。
       使っている場所 :fetch_cuboid(),follow_line(),main()

number

   number
       とりうる値     :1,2,3
       どんな値か     :プログラム実行開始時に入力する値でlist_isの何番のファイルを読み込む
                       か、その他の読み込むファイルの何行目を使うかを決める値
       使っている場所 :main(),読み込み

list_intersection

   list_intersection
       とる値の例     :[[2,l],[2,l],[1,l],[1,l],[1,r],[1,l],"end"]
       どんな値か     :何回目の分岐(分岐と判断される場所)でどのような道をとるかを決める値
                       でファイルlist_isから読み込む("end"はファイルには書かないもので自動
                       で追加される)
                       [数字n,文字a]:進行方向に合わせて時計回りか反時計回りで近いほうから
                                     n番目の道でa=rなら右、a=lなら左の境界をとる。
                       "end"        :ゴールに着いたこと表す値
       使っている場所 :intersection(),main(),読み込み

sign

   sign
       とりうる値     :-1,1
       どんな値か     :follow_line()実行時右と左のどっちの境界をとっているかを表す値で、
                       右の時1、左の時-1をとる。
       使っている場所 :intersection(),follow_line(),main(),読み込み

sign_fc

   sign_fc
       とりうる値     :-1,1
       どんな値か     :(),fetch_cuboid3()の実行後に右と左のどちらの境界をとる
                       かを表す値で、右の時1、左の時-1をとる。ファイルu_turn_rlから読み込
                       む。
       使っている場所 :fetch_cuboid(),main(),読み込み

関数

intersection()

   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()

   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()

   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()

   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()

#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()

読み込み

こちらはテキストファイルではありません。main()の中の読み込みに使われる部分です。

#list_is、#sign0、#u_turn_rlでは与えられたnumberに応じて読み込みたいテキストファイルを読み込む

   #read

list_is

与えられた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

       #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

       #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("")

読み込むファイル

次のようなファイルプログラム実行前に用意する必要がある。

list_is(list_is3)

list_isは自分がライントレースする道が何人目の課題かによってlist_isの直後にその数字を 付け加えたものをファイル名として保存する。今回は3人目の課題について書くのでファイル名はlist_is3とする。

2,r
1,l
2,r
1,r
2,r
1,l
2,l
1,r

sign0

r
r
r

u_turn_rl

l
r
r

もともと目指していたロボット

僕らの班ではもともと別の機構を採用したロボットを目指していました。下の写真のようなロボットです。製作するにあたり、ロボット完成発表の日に間に合わず製作を一時断念しました。

12872_2.jpg

もともと僕たちが作ろうとしていたロボットはモータでカラーセンサを振動させて、カラーセンサを二つ使用していると仮定して黒い線の両側どちらもライントレースできる仕組みを持ったロボットでした。このロボットの強みは黒い線の左右関係なくライントレースし分岐を判断できるところです。しかしモータとカラーセンサの連動、モータをカラーセンサの振動に使っている分キューボイドを捕らえる仕組みはどうするかなど様々な問題を解決するにあたり、大量の時間を要してしまいました。そして、授業で毎週課題がだされており、その課題をこなすための予備用に一般的なライントレースをするロボットも同時並行で作っていたので、ロボットを製作する時間が単純に2倍、それ以上にかかってしまいました、しかしそれでも時間が足りず、このロボットの完成には至りませんでした。ですが結果的にはもともと作っていたロボットと予備用のロボットを組み合わせることで今の最新型のロボットになりました。最新型のロボットは目指していたロボットの長所を引き継いでおり、分岐探索機能と超音波センサを地面方向へ向かせるアイデアはこのロボットから来ています。

一応、図3が振動させる仕組みです。モータに歯車をかみ合わせ、カラーセンサを乗せている台が二つの棒を軸に平行に振動するようになっています。

図3

12871_2.jpg

反省点

  • 発表までに自分たちの目指していた機構を実現できなく、もう少し上手く開発をして行けば良かった。
  • 班員に任せっきりになってしまう部分があった。班員に感謝。
  • ライントレースする紙を本番までに書いて来なかった。他の班の紙を使わせてもらった。しかし、使わせてもらった紙は、ライントレースの線の太さが不均一だったので本番でしっかり力を発揮できなかった、これは書いて来なかった僕たちの班の責任だ。
  • ロボットの性能でもっと移動スピードをあげたかった。変数調整するテスト回数が少なかったのが原因。

さいごに

この課題2は大変楽しかった。プログラミングではpythonの知識も増えて、できることが増えて、自分のできる幅が広がった。

課題1ではたった一つの命令だけでやっていたので成長を感じる。一緒に開発した仲間が良かった。


添付ファイル: file2019b-mission2.png 21件 [詳細] file12871_2.jpg 21件 [詳細] file12872_2.jpg 17件 [詳細] file12846_2.jpg 17件 [詳細] file12841_2.jpg 14件 [詳細] file12839_2.jpg 13件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-01-24 (金) 22:50:22