目次

#contents

*課題2  ~ライントレース~ [#ia867925]
-B地点をスタートしてQ付近の3/4円周上でピンポン玉をつかみ、そのピンポン玉をC地点においたゴールへシュートする
-なるべく速く正確に動くロボットになるように工夫して、交差点では1秒間停止すること
-可能であればC,Dのゴールエリアライン上からシュートする
#br
今回の課題において大きなポイントはライントレースのコースを黒のビニルテープで作成したことによりプログラム作成の速度が格段と向上した点である。ビニルテープで作成するとコースの色のムラを無くすことができ、コース作成にかかる時間を大幅に短縮できるため、次にこの課題に取り組む人は是非試してもらいたいと思う。
#br
**ライントレースのアプローチ [#ec206763]
+黒いライン上をジグザグに移動する
+黒いラインと模造紙の白色の境目をジグザグに移動する(今回使用した方法)
+PID制御 等
 
***解説 [#o08f2bad]
いずれの方法もカラーセンサによってラインを検知している
+&size(20){黒いライン上をジグザグに移動する};
#br
#ref(./1lt.jpg,80%)
#br
メリット:ラインを見失わない&br;デメリット:交差点を検知できない可能性が高く、移動に時間がかかる
#br
+&size(20){黒いラインと模造紙の白色の境目をジグザグに移動する};
#br
#ref(./2.jpg,80%)
#br
メリット:移動が早い、交差点を検知しやすい&br;デメリット:交差点を誤検知することがある
#br
+&size(20){PID制御};
#br
#ref(./3.jpg,80%)
#br
メリット:直進、カーブでの動きがスムーズになる&br;デメリット:急なカーブが多いコースには不向きであり、調整が難しい

PID制御とは“比例と積分と微分を使った制御”のことであり、P制御では現在の状況に対して操作量を決定する(カーブをどのぐらい曲がるのかを操作する)、I制御では過去の状況に対して操作量を決定する(カーブが終わり際に発生するP制御の誤差を修正する)、D制御は未来の状況を予測して操作量を決定する(カーブに差し掛かかった際にロボットが曲がり始めるようにする)今回はこの制御を断念したため、使用していない。よって詳しい説明は割愛する。
#ref(./pid.jpg,80%)

*ロボット本体の解説 [#i92926bf]
今回ロボット本体の設計を行ったのはbeingさんであり、前回の課題から流用しているパーツも多いため、比較的すぐに完成した
#ref(./catch1.JPG,80%)
#br
**駆動機構 [#l696d499]
#ref(./bottom.JPG,around,80%)
EV3 Lモーター ×2 (税込4,644円/個)
-特徴:重いものをゆっくり 動かすのが得意
-このモーターでロボットの直進、回転を行う
#br
キャスター
#clear
#br
**ライン検知機構 [#ed578a88]
#ref(./cs.JPG,around,80%)
EV3カラーセンサー
-カラーモード(7種類の色(色なしを加えると8種類)を計測)、反射光の強さモード(光の反射量を計測)&br;
(今回は反射光の強さモードを使用する)
#clear
**ボール検知機構 [#q782cc83]
#ref(./us.JPG,around,80%)
EV3超音波センサー
-3cmから250cmまでを計測でき、5cmを計測すると(ボールを検知すると)アームを動かす
#clear
**ボール保持機構(アーム) [#f2e91cec]
#ref(./arm.JPG,around,80%)
EV3 Mモーター ×1(税込3,780円)
-特徴:軽いものを素早く 動かすのが得意
-今回はアームの上げ下げが行えるようになっている
#clear
#br
#ref(./catch_1.JPG,around,80%)
ボール発射ガイド
-ボールの射出の精度を上げるために取り付けてある
#clear
#br
*プログラムの解説 [#j545b986]
 #!/usr/bin/env python3           # python3でプログラムを作成する
 from ev3dev.ev3 import *
 import ev3dev.ev3 as ev3
 import time
 
 arm = ev3.MediumMotor('outA')     #ボールを保持するアームをMidiumMotorで制御する
 mr = ev3.LargeMotor('outB')           #mr : 右駆動輪
 ml = ev3.LargeMotor('outC')           #ml : 左駆動輪
 
 us = ev3.UltrasonicSensor('in1')     #us : 超音波センサ
 gy = ev3.GyroSensor('in2')             #gy : ジャイロセンサ(今回は使用しない)
 cs = ev3.ColorSensor('in3')            #カラーセンサ(反射光の強さモード)5~80の値が返ってくる
 
 x = 0                                                #x : 交差点のカウントに用いる
 lfr = 200                                          #lfr :右駆動輪の出力値 (line follow right)
 lfl = 80                                            #lfl : 左駆動輪の出力値 (line follow left)
 

 ###ライントレース###
 
 def line_follow():
     while cs.value() >= 50:          #カラーセンサが白を検知した時、右に曲がる
         mr.run_forever(speed_sp=lfr)
         ml.run_forever(speed_sp=-lfl)
         t0 = time.time()
     while cs.value() < 50:         #カラーセンサが黒を検知した時、左に曲がる
         mr.run_forever(speed_sp=-lfl)
         ml.run_forever(speed_sp=lfr)

#ref(./line_trace.jpg,80%)

 ###交差点について(何も指定しない場合、交差点を右折する)###
 #ライントレース時にカラーセンサが黒色を認識している時間が一定以上になった時に交差点と判断する
#ref(./intersection.jpg,80%)

                #交差点を直進
 def go_straight():                                           #交差点と認識するとロボットを目的の進行方向に向け、直進する。
     mr.run_forever(speed_sp=lfl)                    #このあと直進時の交差点の誤検知を防ぐ措置をとる(後述)
     ml.run_forever(speed_sp=-lfr)
     time.sleep(1.2)
     mr.run_forever(speed_sp=200)
     ml.run_forever(speed_sp=210)
     time.sleep(0.5)
     if cs.value() >= 50:          #white
        while cs.value() >= 50:
           mr.run_forever(speed_sp=lfr)
           ml.run_forever(speed_sp=-lfl)
           t0 = time.time()
     else:         #black
         mr.run_forever(speed_sp=-lfl)
         ml.run_forever(speed_sp=lfr)
     t0 = time.time
 
   
                   #交差点を左折
 def turn_left():
     mr.run_forever(speed_sp=lfl)
     ml.run_forever(speed_sp=-lfr)
     time.sleep(elapsed_time)
     mr.run_forever(speed_sp=lfr)
     ml.run_forever(speed_sp=-lfl)
     time.sleep(elapsed_time)
  
 

 ###ボールに対する動作###
  
 def ball_catch():                                       #アームを上げる
     arm.run_forever(speed_sp=-60)
     time.sleep(2)
     arm.stop()
  
 def shoot():
  
             #ゴールを狙う
     mr.run_forever(speed_sp=lfl)
     ml.run_forever(speed_sp=-lfr)
     time.sleep(1.4)
     mr.stop()
     ml.stop()
     time.sleep(1)
  
             #助走をするためゴールとの距離を少し開ける
     mr.run_forever(speed_sp=-100)
     ml.run_forever(speed_sp=-100)
     time.sleep(0.6)
  
             #ボールを設置する
     arm.run_forever(speed_sp=60)
     time.sleep(1)
     mr.stop()
     ml.stop()
     time.sleep(1)
     arm.stop()
     mr.run_forever(speed_sp=-100)
     ml.run_forever(speed_sp=-100)
     time.sleep(1)
     arm.run_forever(speed_sp=-60)
     time.sleep(2)
     arm.stop()
  
              #助走する
     mr.run_forever(speed_sp=300)
     ml.run_forever(speed_sp=300)
     time.sleep(1)
     mr.stop()
     ml.stop()
 
               #射出する
     arm.run_forever(speed_sp=300)
     time.sleep(0.6)
     arm.stop()
#br
shoot()の動作
#ref(./shoot.gif,80%)
 
 ###今回の流れ#############################################
 # B -> R(go_straight) -> P(turn_R) -> Q(go_straight) -> ball_catch
 # -> Q(go_straight) -> R(turn_R) -> P(go_straight) -> S(turn_R) -> shoot
 #######################################################
  
 Sound.play('start.wav')                  #音声ファイルを再生
 time.sleep(1)
 
 mr.run_forever(speed_sp=220)
 ml.run_forever(speed_sp=220)
 time.sleep(1)
 
 ###直進時の交差点の誤検知を防ぐ措置### 
 if cs.value() >= 50:          #カラーセンサが白を検知した時、右に曲がる
    while cs.value() >= 50:           #カラーセンサが黒を検知するまで続ける
        mr.run_forever(speed_sp=lfr)
        ml.run_forever(speed_sp=-lfl)
        t0 = time.time()
 
 else:                                 #カラーセンサが黒を検知した時、左に曲がる
     mr.run_forever(speed_sp=-lfl)
     ml.run_forever(speed_sp=lfr)
     t0 = time.time()           #これによって交差点と認識させないようにしている
 
 #########################
&size(20){直進時の交差点の誤検知を防ぐ措置を取らない場合};
#ref(./start.jpg,80%)


 while True:
     t0 = time.time()
     line_follow()
     elapsed_time = time.time() - t0      #elapsed_time:カラーセンサが黒を検知している間の経過時間
 
 ######交差点の判定######
     if elapsed_time > 1.18:                 #elapsed_timeが1、18秒以上のとき現在位置を交差点と認識する
         x += 1                                       #交差点の数を数える
         mr.stop()
         ml.stop()
 
         Sound.play('kousatendesu.wav')        #音声ファイルを再生する
         time.sleep(1.2)
  
 ########交差点での動作################
        if x == 1 or x == 3 or x == 4 or x == 6:          #交差点R,Q,Q(2回目),P(2回目)では直進する
             go_straight() 
 
             if x == 3:                              #交差点Qを通過した時、超音波センサを起動しボールをさがす
                 while True:
       ###超音波センサの誤検知を防ぐ措置###
                     us1 = us.value()     #稀に一瞬ボール以外のものを検知することもあるため3回計測し、その平均値によって判断している
                     us2 = us.value()
                     us3 = us.value()
       ###############################
 
                     line_follow()
                     if (us1 + us2 + us3)/3 < 85:    #ボールを検知した時、停止してボールを掴む
                         break
 
                 mr.stop()
                 ml.stop()
                 ball_catch()
 
         elif x == 8:           #ゴールにたどり着いた時、ゴールにボールをシュートする
             time.sleep(1)
             Sound.play('neraimasu.wav')   #音声ファイルを再生する
 
             shoot()                                    #ボールをシュートする
 
             Sound.play('unicorn.wav')       #音声ファイルを再生する
             break                                     #動作を終了する

**うまくいかなかった時の対処法 [#scc0244f]
***交差点での誤検知 [#x7266592]
#ref(./notinter.jpg,80%)
対処法
#br
+ロボットが交差点と判断する時間を調整する
+駆動輪間を狭くする(回転面半径を小さくする=細かく振動しながらライントレースする)

***急カーブでの誤検知 [#lf09dc14]
#ref(./wrong.jpg,80%)
対処法
#br
+ロボットが交差点と判断する時間を調整する
+駆動輪間を狭くする(回転面半径を小さくする=細かく振動しながらライントレースする)
+毎回誤検知する場合、この場所も交差点とみなす(交差点のカウントを調整する)

*まとめ [#ubed82b6]
今回の課題ではライトセンサ2個とPID制御によるライントレースを計画していたが、ライトセンサが1個しかなかったため計画を変更した。また、余裕を持ってプログラムを作成することができたため成功率を非常に高めることができた。交差点の判断にはモーターの角度制御を用いたかったが、作成時にはうまく動作しなかったため時間を計ることによって行った。次の課題では、角度制御やジャイロセンサなど、ev3の性能を活用していきたいと思う


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS