今回は黒の線をライントレースするロボットを作りました
↑ロボットの全容 今回は紙コップをつかむためにコップの両側から挟み込むよう形にした。モーター三つ使い、二つはタイヤのモーターとして、もう一つはコップを掴むアームを回すために使用した。センサーはカラーセンサーだけを使い、RGBの値を読み取って30より大きいか小さいかで白か黒かを判断した。また、カラーセンサーがタイヤから離れてしまうと、後々誤差が大きくなってしまうため、なるべくタイヤから近い位置に取り付けるようにした。
今回は上記もコースを下記のようなルートでライントレースをした
1.Aをスタート 2.Bを直進 3.Cで一時停止の後、直進 4.Dで一時停止の後、Xの空き缶をキャッチしてD地点に戻る 5.DからEに向かい、Eを直進 6.Fを左折 7.Gで一時停止の後、左折 8.Hで一時停止の後、右折 9.Iで一時停止の後、右折 10.Lを直進 11.Kを直進 12.Jで一時停止の後、空き缶をYに置きてJに戻りBに向かう 13.Bで一時停止の後、左折 14.Aで停止
今回は黒の線に対して左側をジグザグに指定した時間動き、その後白か黒の継続時間によって停止するようにしたものと右側を同様に動く二つの主となるプログラムを作った。 これによって、前半は前者のプログラムを、後半は後者のプログラムを使うことで他のプログラムを関数なしの大雑把なプログラムで解決することが出来た。 試行錯誤を繰り返している最中にどうしても継続時間がカーブで長くなってしまい、止まってしまった。そこで、ある時間まではひたすらコースを逸れずに同じ色の領域にいても線の境界に無理矢理にでも戻るようにした。 線の境界が左側のプログラム(tが境界に居続ける時間、sがt秒以降、s秒以上同じ色の領域にいると止まる。)
def sharpstop_line(t,s): t0 = time.time() t1 = time.time() while t0 - t1 < t: t0 = time.time() if cs.value() <=30: while cs.value() <=30: ml.run_forever(speed_sp= -25) mr.run_forever(speed_sp= 100) elif cs.value() >30: while cs.value() >30: ml.run_forever(speed_sp= 100) mr.run_forever(speed_sp= -25) ml.stop() mr.stop() s0 = time.time() s1 = time.time() while s0 - s1 < s: s1 = time.time() if cs.value() <=30: while cs.value() <=30: ml.run_forever(speed_sp= 100) mr.run_forever(speed_sp= -25) s0=time.time() elif cs.value() >30: while cs.value() >30: ml.run_forever(speed_sp= -25) mr.run_forever(speed_sp= 100) s0=time.time() ml.reset() mr.reset() sleep(1)
線の境界が右側のプログラム(tが境界に居続ける時間、sがt秒以降、s秒以上同じ色の領域にいると止まる。)
def rev_sharpstop_line(t,s): t0 = time.time() t1 = time.time() while t0 - t1 < t: t0 = time.time() if cs.value() <=30: while cs.value() <=30: ml.run_forever(speed_sp= 100) mr.run_forever(speed_sp= -25) elif cs.value() >30: while cs.value() >30: ml.run_forever(speed_sp= -25) mr.run_forever(speed_sp= 100) ml.stop() mr.stop() s0 = time.time() s1 = time.time() while s0 - s1 < s: s1 = time.time() if cs.value() <=30: while cs.value() <=30: ml.run_forever(speed_sp= -25) mr.run_forever(speed_sp= 100) s0=time.time() elif cs.value() >30: while cs.value() >30: ml.run_forever(speed_sp= 100) mr.run_forever(speed_sp= -25) s0=time.time() ml.reset() mr.reset() sleep(1)
def right():#右折 ml.run_timed(time_sp = 500,speed_sp =100,stop_action ='brake') mr.run_timed(time_sp = 500,speed_sp =-100,stop_action ='brake') sleep(1)
def left():#左折 ml.run_timed(time_sp = 500,speed_sp =-100,stop_action ='brake') mr.run_timed(time_sp = 500,speed_sp =100,stop_action ='brake') sleep(1)
def forward():#直進 ml.run_timed(time_sp = 500,speed_sp =100,stop_action ='brake') mr.run_timed(time_sp = 500,speed_sp =100,stop_action ='brake') sleep(1)
def cop_catch():#コップを掴む ml.stop() mr.stop() ma.reset() ma.run_timed(time_sp=2000,speed_sp=-100,stop_action='hold') sleep(3)
def cop_throw():#コップを放す ml.stop() mr.stop() ma.reset() ma.run_timed(time_sp=2000,speed_sp=100,stop_action='brake') sleep(3)
sharpstop_line(0,0.7)#1の動作 sleep(1) right() right()
sharpstop_line(34,0.6)#2.3の動作
cop_catch()#4の動作
left()#5の動作 left() sharpstop_line(2.5,0.7)
right()#6の動作 sharpstop_line(9,0.7)
left()#7の動作 sharpstop_line(1.5,0.65) sleep(1)
left()#8の動作 sharpstop_line(38,0) sleep(1) right() right() rev_sharpstop_line(2,0.75) sleep(1)
rev_sharpstop_line(3,0.75)#9の動作 sleep(1) right()
rev_sharpstop_line(2,0.75)#10の動作 left() left()
rev_sharpstop_line(2,0.75)#11の動作 left() left()
rev_sharpstop_line(2,0.75)#12の動作 sleep(1) left() left() left() left() left() left() cop_throw()
left()#13.14の動作 left() left() left() left() left() rev_sharpstop_line(4,0.75) sleep(1) left() left() left() forward() rev_sharpstop_line(3,0.75)
あえてright()、left()、forward()の車体の動く大きさを大きくしてある。また、領域内にいて良い時間も長くしてある。そのため、コースの途中で間違って止まることが格段に減ったが、その分車体がコースと90°くらいに曲がってしまうが、right()、left()の値が大きく設定され、かつ次のsharpstopでは白の領域にさえ入ってしまえば、いくらでも修正してくれるので少ないプログラムで済んだ。
前回に比べ、かなり簡潔なプログラムが出来たと思う。その分sharpstopのプログラムに行き着くまでが長くなってしまい、かなり時間がぎりぎりになってしまった。成功率は最後にはほぼ100%にまで持って行けたのでそこは良かった。