線上をたどりボールを空き缶に当てる。
基本的な部分は説明書に載っているロボットを流用した。ボールを転がす部分とカラーセンサーと超音波センサーを取り付けた。
#!/usr/bin/env python3 from ev3dev.ev3 import * import time
mL=LargeMotor('outA') #左タイヤの設定 mR=LargeMotor('outB') #右タイヤの設定 mT=MediumMotor('outC') #ボールを転がす腕を動かすモーターの設定 cs=ColorSensor('in1') #カラーセンサーのインスタンスを作成 us=UltrasonicSensor('in2') #超音波センサーのインスタンスを作成
以下の代入はタイヤの速度を決める変数の代入。同じような関数がたくさんあったので外から変えられるように先に定義した。
w=100 v=60 u=-50
タイヤを動かすための関数。直線に動く関数を一つと左右に動く関数を合計六つ作った
def run(): global w mL.run_forever(speed_sp=w, stop_action='brake') mR.run_forever(speed_sp=w, stop_action='brake')
def turn_right(): global w mL.run_forever(speed_sp=w, stop_action='brake') mR.run_forever(speed_sp=0, stop_action='brake')
def turn_left(): global w mL.run_forever(speed_sp=0, stop_action='brake') mR.run_forever(speed_sp=w, stop_action='brake')
def curve_right(): global w global v mL.run_forever(speed_sp=w, stop_action='brake') mR.run_forever(speed_sp=v, stop_action='brake')
def curve_left(): global w global v mL.run_forever(speed_sp=v, stop_action='brake') mR.run_forever(speed_sp=w, stop_action='brake')
def round_right(): global w global u mL.run_forever(speed_sp=w, stop_action='brake') mR.run_forever(speed_sp=u, stop_action='brake')
def round_left(): global w global u mL.run_forever(speed_sp=u, stop_action='brake') mR.run_forever(speed_sp=w, stop_action='brake')
ライントレースをするための関数。右側をトレースするものと、左側をトレースするものの二つが必要だったので二個あるが内容はほぼ同じ。 まず調整をしやすくするため変数を外から定義した。
a=7 b=10 c=15 d=30
aからdまではカラーセンサーの値。
s=1 h=3
def line_trace_right(num=1): time0=time.time() time1=time.time()-h cnt=0 while cnt<num: if cs.value()<=a: round_right() elif a<=cs.value()<=b: curve_right() elif b<=cs.value()<=c: run() time0=time.time() elif c<cs.value()<=d: curve_left() time0=time.time() else: round_left() time0=time.time() if time.time()-time0>=s and time.time()-time1>h: cnt=cnt+1 time1=time.time() time0=time.time() print(cnt) mL.reset() mR.reset()
def line_trace_left(num=1): time0=time.time() time1=time.time()-h cnt=0 while cnt<num: if cs.value()<=a: round_left() elif a<=cs.value()<=b: curve_left() elif b<=cs.value()<=c: run() time0=time.time() elif c<=cs.value()<=d: curve_right() time0=time.time() else: round_right() time0=time.time() if time.time()-time0>=s and time.time()-time1>h: cnt=cnt+1 time1=time.time() time0=time.time() print(cnt) mL.reset() mR.reset()
カラーセンサーの値から現在の状況を五段階に評価し、できるだけ正確に線の上をたどれるようにした。 交差点につくとcntの数値が1増えるようにした。引数に通過して欲しい交差点の数を代入出来るように関数を工夫した。何も代入しない場合1が代入されるようにした。 また、交差点を認識してからすぐの間は交差点を検知しないように工夫した。
その他の関数
交差点を認識したとき車体は少し交差点を行き過ぎているので姿勢を立て直す関数。右側トレースをしていたときと左側トレースをしていたときの二通り必要だった。
def stand_right(): mL.run_to_rel_pos(position_sp=-90, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=30, speed_sp=100, stop_action='brake') time.sleep(1)
def stand_left(): mL.run_to_rel_pos(position_sp=30, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=-90, speed_sp=100, stop_action='brake') time.sleep(1)
少しだけ前へ進む関数。認識して欲しくない交差点を無視するために作った。右側トレースをしていたときと左側トレースをしていたときの二通り必要だった。
def straight_right(): stand_right() mL.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') time.sleep(1)
def straight_left(): stand_left() mL.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') time.sleep(1)
ボールを投げるための関数。腕を倒すだけである。
def throw(): mT.run_to_rel_pos(position_sp=60, speed_sp=100, stop_action='brake') time.sleep(1)
以下の三つは空き缶を探しボールをぶつけるための関数。
回る
def Round(): mL.run_to_rel_pos(position_sp=680, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=-680, speed_sp=100, stop_action='brake')
探す
def search(): global x global y distance=2550 time0=time1=time.time() while time.time()-time0<13: if us.value()<distance: distance=us.value() time1=time.time() print(us.value()) x=680/13(time1-time0) y=time1-time0
当てる
def hit(): mL.run_to_rel_pos(position_sp=x, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=-x, speed_sp=100, stop_action='brake') time.sleep(y) throw() mL.run_to_rel_pos(position_sp=680-x, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=x-680, speed_sp=100, stop_action='brake') time.sleep(13-y)
line_trace_right(2) stand_right() time.sleep(4) line_trace_left(2) straight_left() line_trace_left() straight_left() Round() search() hit() line_trace_left(2) time.sleep(4) line_trace_left(5) stand_left() time.sleep(4) line_trace_right(2) stand_right() mL.run_to_rel_pos(position_sp=360, speed_sp=100, stop_action='brake') mR.run_to_rel_pos(position_sp=360, speed_sp=100, stop_action='brake')
テスト運用ではうまくいくときと行かないときの半々だった。問題は二つあり、急カーブに置ける交差点判定が安定しないのと、ボールを投げたときにうまくカンに当たらず、少し左にそれた事である。本番でも改善しきれず、ライントレースはきちんと出来たが、ボールをうまく当てる事は出来なかった。
ライントレースが思いの他難しかった。カラーセンサーから読み取る値をきちんと設定しないと、正常に動作しないためそこの設定に骨を折った。ライントレースのカラーセンサーの値が間違えているのか、はたまたタイヤのスピードがおかしいのか考えながら何度も試行を重ねた。 また、ライントレースの関数を便利にしようと、関数を工夫したがwhile文がものすごく複雑になってしまいたくさんの時間を要してしまった。今見返してもどこがどうなっているのか考えると頭がこんがらがる。 お題は単純なモノだと思っていたが、機械のセンサーやモーターを扱う事の難しさや、while文の構造の複雑さに頭を悩ました。