#author("2019-12-25T17:38:11+09:00","roboticsND","roboticsND")
#author("2019-12-25T17:39:07+09:00","roboticsND","roboticsND")
[[2019b/Member]]

* 目次 [#c05d6d27]
#contents

* 課題の説明 [#h39e48d7]
#ref(./コース.png, 868*563, コース)
 A地点を出発し、次のいずれかの経路を黒い線にそって動くロボットを作成する。

1,A地点から出発

2,B

3,C (直進)

4,D (一時停止の後、直進)

5,E, F 通過

6,G (一時停止の後、左折)

7,H (一時停止の後、左折)

8,I (ボール or キューボイドをつかんでUターン)

9,H (直進)

10,J (一時停止)

11,A地点に入る(ゴール)

ここで一つ勘違いをしてしまい、C地点で直進せず一時停止をしてしまった。ご容赦願いたい。

* ロボットの説明 [#nbead2b0]

** ロボットの全体像 [#h4b1ea1c]
 2輪駆動でCuboidをキャッチするためのアームをつけた単純な構造となっている。本能の赴くままにロボットを組み立てた結果、長くなってしまった。しかし、その分アームにゆとりができたためCuboidに対して多少ずれてもきれいにキャッチすることができる。使ったモーダーはタイヤを動かす用のLargeMotor2つとアーム用のMidiumMotor1つを使っている。センサーはタッチセンサー、光センサー、超音波センサを使っている。
#ref(./ロボ全体像.JPG, 640*480, ロボット全体像)

** センサーについて [#k56ceab4]
 タッチセンサーは以降紹介するプログラムから抜けるために使っている。光センサーと超音波センサーはそれぞれ前方の下につけた。ただ、光センサーについては下に寄せすぎて紙の凹凸によって誤作動を起こしてしまうことがあり、紙を押さえなければいけなくなってしまった。
#ref(./センサー.JPG, 640*480, センサー)

* プログラムの説明 [#j73660e4]

** 使うもののimportと置き換え [#f081040f]

 #!/usr/bin/env python3
 
 from ev3dev2.sensor.lego import ColorSensor, TouchSensor, UltrasonicSensor
 from ev3dev2.motor import MoveTank, OUTPUT_A, OUTPUT_C
 from ev3dev2.motor import MediumMotor, OUTPUT_D
 from time import sleep
 import time
 
 mo = MoveTank(OUTPUT_A, OUTPUT_C)
 mmo = MediumMotor(OUTPUT_D)
 ts = TouchSensor()
 cs = ColorSensor()
 us = UltrasonicSensor()
 必要なセンサーとモーターをインポートし、わかりやすいものに置き換えた。

** 関数の定義 [#i9a5f145]

*** ライントレースの関数 [#w5037ba0]
 def migifollow_line(maxtime):#ラインの右側をトレースするための関数
     str = time.time()#この関数を始めた時の時間を記憶する
     end = time.time()#この関数が開始してからどれくらいの時間がたったかを出すための時間を記憶する
     stw = time.time()#白いところにいる時間を記憶する
     stb = time.time()#黒いところにいる時間を記憶する
     n = 0#交差点判断をしたときに下記のループを抜け出すための変数を定義する
     while not ts.is_pressed and n < 1:
         if cs.value() < 15:
             mo.on(5, -5)
             stb = time.time()#黒にいる時間を更新する
         elif 14 < cs.value() < 45:
             mo.on(10, 0)
             stb = time.time()
         elif 44 < cs.value() < 56:
             mo.on(10, 10)
             stw = time.time()#白にいる時間を更新する
         elif 55 < cs.value() < 85:
             mo.on(0, 10)
             stw = time.time()
         else:
             mo.on(-5, 5)
             stw = time.time()
         if end - str > maxtime:#設定したmaxtimeより関数の起動時間が長くなった場合に交差点を審査するようにする
             if stb - stw > 0.7:#交差点を判断し、次の動きにつなげるのにちょうどいい時間を設定した
                 mo.on(0, 0)
                 sleep(2)
                 n = 1#nを更新することでループから抜け出す
         end = time.time()#関数の起動時間を更新する
         sleep(0.1)
     mo.off()
 
 def hidarifollow_line(maxtime):#上記のmigifollow_lineのモーターの回転方向を逆にしたもの
     str = time.time()
     end = time.time()
     stw = time.time()
     stb = time.time()
     n = 0
     while not ts.is_pressed and n < 1:
         if cs.value() < 15:
             mo.on(-5, 5)
             stb = time.time()
         elif 14 < cs.value() < 45:
             mo.on(0, 10)
             stb = time.time()
         elif 44 < cs.value() < 56:
             mo.on(10, 10)
             stw = time.time()
         elif 55 < cs.value() < 85:
             mo.on(10, 0)
             stw = time.time()
         else:
             mo.on(5, -5)
             stw = time.time()
         if end - str > maxtime:
             if stb - stw > 0.7:
                 mo.on(0, 0)
                 sleep(2)
                 n = 1
         end = time.time()
         sleep(0.1)
     mo.off()
 はじめは3つに分けて黒白判断をしていたのだが、直角の曲がり角や急なカーブに対応することができなかったため結局5つに分けて黒白判断をすることにした。真っ黒、真っ白の時にそれぞれのモーターを逆回転させることで上手にライントレースをすることができた。maxtimeを設定することでどんな道でも交差点判断を誤らないようにした。

*** Cuboidをキャッチする関数 [#ff86ef9d]
 def migifetch_cuboid():#Cuboidをキャッチするための関数
     n = 0#Cuboidをキャッチしたらループを抜け出すための変数を定義する
     while n < 1:
         if cs.value() < 45:#上記したライントレースの簡易版
             mo.on(5, 0)
         elif 44 < cs.value() < 56:
             mo.on(5, 5)
         else:
             mo.on(0, 5)
         if us.distance_centimeters < 10:#超音波センサーとCuboidとの距離が10cmより短いとき下記の処理をする
             mo.on_for_rotations(-5, -5, 0.2)#ロボットが長いため、少し下がる必要がある
             sleep(1)
             mmo.on_for_degrees(4, -60)#Cuboidをキャッチする
             sleep(2)
             mo.on_for_rotations(15, -15, 0.8)#逆の方向を向く
             n = n + 1#nを更新し、ループから抜ける
         sleep(0.1)
     mo.off()
 今回は右側をトレースしてCuboidをキャッチする方が都合がよかったため、右側をトレースする関数を定義した。

*** 交差点判断後の行動を定義した関数 [#zd603513]
 def turn_right():#右折するときの関数
     mo.on_for_rotations(15, -15, 0.25)
     mo.on_for_rotations(15, 15, 0.20)
 
 def turn_left():#左折するときの関数
     mo.on_for_rotations(-15, 15, 0.25)
     mo.on_for_rotations(15, 15, 0.20)
 
 def noturn():#直進するときの関数
     mo.on_for_rotations(15, 15, 0.20)

 交差点判断後ライントレースの関数のループから抜け出すようになっているので、そこに上記の関数をつけることで任意の動きをすることができる。

** 実行するプログラム [#a26c7a80]
 if __name__ == '__main__':#おまじない
     migifollow_line(12)#Cで一度一時停止する
     noturn()#直進する
     migifollow_line(10)#カーブを曲がり、Dで一時停止する
     noturn()#直進する
     migifollow_line(20)#直角を2度曲がり、Gで一時停止する
     turn_left()#左折する
     migifollow_line(3)#ライントレースし、Hで一時停止する
     turn_left()#左折する
     migifetch_cunoid()#右側をトレースしCuboidをキャッチした後、反転する
     hidarifollow_line(35)#左側をトレースしてゴールで一時停止する
     mo.on_for_rotations(5, 5, 1)#少し前に進む

* まとめ [#x5ffca6a]
 スピードは遅いものの、ミッションをクリアすることはできた。

** 反省点 [#ke31ab06]
 今回はロボット面の反省が多い。もう少しコンパクトにしてスピードを上げてもブレが起こらないようにしたかった。また、光センサーをもう少し上に設置すれば紙の凹凸に大きく左右されることはなかっただろう。プログラムについてはコースに合わせて引数を調整したり、順番を変えれば大体動いてくれると思うのでそこそこのできになっていると思う。次回の課題ではロボットの小型化を実現したい。
 今回はロボット面の反省が多い。もう少しコンパクトにしてスピードを上げてもブレが起こらないようにしたかった。また、光センサーをもう少し上に設置すれば紙の凹凸によって黒白判定が大きく左右されることはなかっただろう。プログラムについてはコースに合わせて引数を調整したり、順番を変えれば大体動いてくれると思うのでそこそこのできになっていると思う。次回の課題ではロボットの小型化を実現したい。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS