今回の課題はライントレースをすることである。
ルート内には複数の交差点があり、交差点を判別すると音を鳴らします。
今回自分がたどるルートは地点B→地点R→右折→地点Q→直進→地点Q→直進→地点P→右折→地点S→右折→地点Cです。
今回使用したロボットはとてもシンプルなロボットに光センサーをつけただけの物になります。
ロボットの中心がラインの中心に重なるように光センサーの設置位置は中心から左に寄せて設置しました。
光センターはラインを判別しやすいように、できる限り地面に近づくように設置しました。
#!/usr/bin/python # -*- coding: utf-8 -*-
import ev3dev.ev3 as ev3
MR = ev3.LargeMotor('outA') #右側のモーターを出力ポートAで制御 ML = ev3.LargeMotor('outB') #左側のモーターを出力ポートBで制御 cs = ev3.ColorSensor('in1') #光センサーのデータを入力ポート1で受信 S = ev3.Sound()
ロボットを停止させるプログラムを st() のみで表せるように設定する。
def st(): MR.stop() #右側のモーターを停止 ML.stop() #左側のモーターを停止
今回ロボットがラインをトレースするために作成したプログラムを説明する。
ロボットには黒のラインの左端の境界部分をトレースするプログラムを入れました。
仕組みは事前に光センサーでライン上の黒い部分・境界線上の部分・白い部分の明るさをはかります。
計測した明るさを用いてロボットは自分の位置を把握し、黒いライン上にいると判断したら進路を少し左に、
白い部分にいると判断したら進路を少し右にとり進行方向を調節します。
また交差点を判別するためにロボットは自分が何秒以上黒いライン上にいるか計測します。
具体的にはロボットは動き始めたら時間の計測を始め、
ロボットは自分が白い部分、もしくは境界線上にいると判断した場合のみ計測時間をリセットし再び計測を再開します。
黒いライン上にいると判断したときのみ計測を継続し、
計測した時間が一定時間を超えると停止するようにプログラムし交差点と判断するように調節する。
ライントレースのプログラムは複雑なため、複数回書くと間違える確率が高くなるため、
line(a) で表すための設定をする。
def line(a): t0 = time.time() #動き始めてからの時間を計測する while time.time() - t0 < a: #計測を始めてからの時間がa以内の時、動き続ける if cs.value() > 30: #センサーが感知した光の明るさが30以上の時 MR.run_forever(duty_cycle_sp=-30) ML.run_forever(duty_cycle_sp=20) #車体を右に回転させる t0 = time.time() 計測をリセットする elif cs.value() >= 10: #光センサーが感知した光の明るさが10以上30以下の時 MR.run_forever(duty_cycle_sp=35) ML.run_forever(duty_cycle_sp=35) #車体を直進させる t0 = time.time() #計測をリセットする else: MR.run_forever(duty_cycle_sp=20) ML.run_forever(duty_cycle_sp=-30)
ロボットが前後左右に動くプログラムを run(r,l,t) で表すための設定する。
def run(r,l,t): MR.run_forever(duty_cycle_sp=r) #右側モーターの出力をrに設定 ML.run_forever(duty_cycle_sp=l) #左側モーターの出力をlに設定 time.sleep(t) #t秒間動き続ける MR.stop() #右側モーターを停止 ML.stop() #左側モーターを停止
ロボットが交差点を右折するためのプログラムを R(b) で表すための設定をする。
def R(b): MR.run_forever(duty_cycle_sp=-30) #右側モーターの出力を-30に設定 ML.run_forever(duty_cycle_sp=20) #左側モーターの出力を20に設定 time.sleep(1) #1秒間動き続ける MR.stop() #右側モーターを停止 ML.stop() #左側モーターを停止 MR.run_forever(duty_cycle_sp=30) #右側モーターの出力を30に設定 ML.run_forever(duty_cycle_sp=30) #左側モーターの出力を30に設定 time.sleep(b) #b秒間動き続ける MR.stop() #右側モーターを停止 ML.stop() #左側モーターを停止
line(0.22) #地点Rまでライントレース S.beep() #交差点を判別しビープ音をならす R(0.75) #右に旋回 line(0.245) #地点Qまでライントレース S.beep() #交差点を判別しビープ音をならす run(-30,20,0.22) run(50,50,0.5) #直進する line(0.22) #地点Qまでライントレース S.beep() #交差点を判別しビープ音を鳴らす run(-30,20,0.22) run(50,50,0.3) #直進する line(0.22) #地点Pまでライントレース S.beep() #交差点を判別しビープ音をならす R(0.75) #右に旋回する line(0.22) #地点Sまでライントレース S.beep() #交差点を判別しビープ音をならす R(0.75) #右に旋回する line(0.22) #地点Cまでライントレース S.beep() #地点Cの枠を認識しビープ音を鳴らす run(-30,20,0.22) run(50,50,0.3) #直進する run(100,100,1) st() #停止
今回ルートをトレースするのにかかった時間は50.05秒です。
はじめプログラム内の定義を行う部分でスペースの空け方を間違えていて気づくのに手間取りました。
今回の課題で一番難しかった部分は交差点を判別し、右に旋回する部分です。
はじめは全く交差点を判別できませんでした。
そこで計測する時間を細かく設定することにより交差点を判別することが可能になりました。
また、急カーブの部分でもロボットが交差点と誤認することが多く、計測し時間をリセットするまでの時間を何回も調節しました。
また右に旋回するときもロボットがラインを判別できず、そのまま迷走を始めてしまったり停止してしまったりしました。