[[2019a/Member]]
#contents
*課題2の説明 [#n0298a67]
**内容 [#ia2d03e5]
下図のようなコースを各チームで作成し、「ミッション」を遂行するためのロボットを作成する。
#ref(2019a/Mission2/2019a-mission2.png,100%,コース)
**ミッション [#h288e325]
A地点から出発 → M → K(直進) → L(ピンポン玉をつかむ) → K(右折) → J(一時停止の後、左折) → I(直進) → H(直進) → G(左折) → F → E → D(一時停止の後、直進) → C(直進) → B(一時停止) → シュート→ A地点に入る(ゴール)
交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止する。
*ロボット [#r9e2a62a]
課題1で使ったロボットを活用。組み立て説明書に書いてあるものにカラーセンサーとボールを拾うためのシャベルのようなものを付けた。
#ref(2019a/Member/reifur/Mission2/kadai2_3.jpg,40%,全体)
*プログラミング [#yad50e7f]
課題の目的がライントレースをすることなので、まずライントレースを使ってゴールまでたどり着くことを第一目標にした。
**ライントレース [#f101b013]
どうやって線をたどるかだが基本的に下図のようにプログラムする。
#ref(2019a/Member/reifur/Mission2/kadai2_1.jpg,40%,ライントレース)
黒い線をたどる時を考える。青はロボット、赤が動く軌跡とする。カラーセンサーを下を向くようにロボットに取り付け、明るさ(白がどれだけ多いか)を計測することで黒線の上にいるのか、いないのかを判断する。そして黒線の上、つまり黒が多いとき左に曲がり、黒線の上にいないときは右に曲がることを連続して行えば黒線の左側を走ることができる。
&br;また、黒線の右側を走りたいときは下図のように曲がる方向を逆にすればいい。
#ref(2019a/Member/reifur/Mission2/kadai2_2.jpg,40%,ライントレース2)
**交差点の判断 [#k4654e14]
先に言うと今回「交差点」は判断してません。「黒がすごい多い場所」と認識させました。そのため交差点でなくとも黒ければロボットは「交差点」と認識してしまうでしょう。おそらく今回のルート以外はまずゴールまでたどり着けません。
&br;今回作ったプログラムの基本はライントレース、それと何回黒い部分を通ったかでできています。そしてその「何回目の黒い部分」かで交差点を判断しています。
*実際に使ったプログラム [#y5478c66]
**モジュールのインポート、インスタンスの作成、引数 [#e1169d77]
#!/usr/bin/env python3
from ev3dev.ev3 import*
from time import sleep
cs = ColorSensor('in2') カラーセンサー
l = LargeMotor('outA') 左のタイヤ
r = LargeMotor('outB') 右のタイヤ
a = Motor('outC') シャベル
cs.mode = 'COL-REFLECT' カラーセンサーのモード
カラーセンサーのモードを明るさを判断するものに変えておく
i = 0
k = 0
p = 0
黒い線を何回越えたかを数える変数。黒い線を数えることで交差点やT字路を認識させ、その回数によって今使っているプログラムから別のプログラムへ移行させた。i,k,pは個人的にわかりやすくするために分けたが役割が同じなので一つにしても構わない。むしろ分けない方がわかりやすかったかもしれない。
黒い線を何回越えたかを数える変数。黒い線を数えることで交差点やT字路を認識させ、その回数によって今使っているプログラムから別のプログラムへ移行させた。i,k,pは個人的に場所で分けた方がわかりやすい気がしたので分けたが役割が同じなので一つにしても構わない。むしろ分けない方がわかりやすかったかもしれない。
**関数 [#f5771746]
今回一回しか使わない動作を関数として作ったりしたため後から読むとすごくわかりにくくなっています。
リセット
def motor_init():
l.reset()
r.reset()
a.reset()
前に進む
def move_forward():
l.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
r.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
sleep(0.1)
前に進む2
def move_forward2():
l.run_timed(time_sp=250, speed_sp=200, stop_action='hold')
r.run_timed(time_sp=250, speed_sp=200, stop_action='hold')
sleep(0.25)
前に進む3
def move_forward3():
l.run_timed(time_sp=300, speed_sp=240, stop_action='hold')
r.run_timed(time_sp=300, speed_sp=60, stop_action='hold')
sleep(0.3)
前に進む4
def move_forward4():
l.run_timed(time_sp=300, speed_sp=200, stop_action='hold')
r.run_timed(time_sp=300, speed_sp=200, stop_action='hold')
sleep(0.3)
左に曲がる、ライントレース用。
def move_left():
r.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
sleep(0.1)
左に曲がる2
def move_left2():
l.run_timed(time_sp=2000, speed_sp=0, stop_action='hold')
r.run_timed(time_sp=2000, speed_sp=90, stop_action='hold')
sleep(2)
左に曲がる3
def move_left3():
l.run_timed(time_sp=2000, speed_sp=20, stop_action='hold')
r.run_timed(time_sp=2000, speed_sp=100, stop_action='hold')
sleep(2)
右に曲がる、ライントレース用。
def move_right():
l.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
sleep(0.1)
右に曲がる2
def move_right2():
r.run_timed(time_sp=2000, speed_sp=-40, stop_action='hold')
l.run_timed(time_sp=2000, speed_sp=100, stop_action='hold')
sleep(2)
右に曲がる3
def move_right3():
l.run_timed(time_sp=100, speed_sp=200, stop_action='hold')
sleep(0.1)
バックする
def move_back():
l.run_timed(time_sp=100, speed_sp=-80, stop_action='hold')
r.run_timed(time_sp=100, speed_sp=-80, stop_action='hold')
sleep(0.1)
バックする2
def move_back2():
l.run_timed(time_sp=100, speed_sp=-120, stop_action='hold')
r.run_timed(time_sp=100, speed_sp=-120, stop_action='hold')
sleep(0.1)
バックする3
def move_back3():
l.run_timed(time_sp=3200, speed_sp=-120, stop_action='hold')
r.run_timed(time_sp=3200, speed_sp=-120, stop_action='hold')
sleep(3.2)
シャベルを上げる
def move_up():
a.run_timed(time_sp=800, speed_sp=-80, stop_action='hold')
sleep(0.8)
シャベルを下げる
def move_down():
a.run_timed(time_sp=800, speed_sp=80, stop_action='hold')
sleep(0.8)
その場で回転、だいたい180度回るようになっている
def move_kaiten():
l.run_timed(time_sp=3000, speed_sp=110, stop_action='hold')
r.run_timed(time_sp=3000, speed_sp=-110, stop_action='hold')
sleep(3)
最後の動作、正直何のための動作なのか私にもわからない。多分気分で作ったもの。
def move_last():
l.run_timed(time_sp=500, speed_sp=50, stop_action='hold')
r.run_timed(time_sp=500, speed_sp=50, stop_action='hold')
sleep(0.5)
l.run_timed(time_sp=3000, speed_sp=100, stop_action='hold')
r.run_timed(time_sp=3000, speed_sp=100, stop_action='hold')
sleep(3)
**MからLまで [#d5d0a39a]
リセット
motor_init()
while i == 0:
state = cs.value()
print (state)
if 80 > state > 65:
move_right()
elif 50 > state > 15:
move_left()
elif 86 >= state >= 80:
move_back()
elif state > 86:
i+=1
move_up()
move_kaiten()
else:
move_forward()
else:
今回のプログラムは常に現在のカラーセンサーの値をstateにおき変え続け、stateの値によって動作を決定する。なお、予想と動作が場合、修正がしやすいようにその時のカラーセンサーの値が確認できるようにprint(state)でしている。
&br;while関数を使いライントレースを行う。
&br;線の左側を通る。また、上に書いたライントレースの方法に加えて白が多すぎるとき後ろに戻るようにしている。こうしないと急なカーブがうまく曲がれなかった。
&br;MからKまではただライントレースしていればいいのだがそのままだとKからJに行ってしまう。のでstateが15以下の時、つまり線KLの上を通る時まっすぐ進むようにしている。何度試した結果からMからLまでstateは86までしかいかないことが分かった。また、Lに着くと前に進み、後ろに戻るという動作を何回か繰り返した後stateが87を超えることが分かった。なのでstate>86となったときiを+1し、ボールを拾い、180度回転するようにした。またこのプログラムはiが0の間だけ続くのでiを+1したことで次のプログラムに行くようにしている。ちなみにここでちゃんとボールを拾えたのは2回だけだった。
**LからKまで [#p8b007b5]
Lで回転する前はロボットは下図のようになっている。
#ref(2019a/Member/reifur/Mission2/kadai2_4.jpg,40%,全体)
赤線がロボットを表しとがっている方が前です。カラーセンサーは前についているのでこのまま180度回転するとカラーセンサーが線の右側にいくのでここから線の右側を走ります。
while i == 1:
state = cs.value()
print (state)
if 80 > state > 65:
move_left()
elif 50 > state > 15:
move_right()
elif 15 >= state:
i+=1
move_forward2()
move_right2()
elif state >= 80:
move_back()
else:
move_forward()
else:
今回はKで曲がるため15以下でiを+1し、少し前に進み、右に曲がるようにする。iを+1する理由は前のプログラムと同じ。前に進み右に曲がるのはこの後線の左側を走るため。ここで運がよかったのか、たまたまカラーセンサーがJの上に来るためKからJのプログラムが不要に。
**KからJまで [#s0932435]
while i == 2:
state = cs.value()
print(state)
if 80 > state > 65:
move_right()
elif 50 > state > 15:
move_left()
elif 15 >= state:
i+=1
sleep(1)
move_left2()
move_forward2()
elif state >= 80:
move_back()
else:
move_forward()
else:
意図せずJの上に来なかったときようの保険になったプログラム。Jで一度止まるためsleep(1)を入れている。またここのプログラムの
move_left2()
move_forward2()
は次のJからGまでの項目で説明する。
**JからHまで [#rf10bbb8]
while i == 3 and 1 >= k:
state = cs.value()
print(state,k)
if 85 > state >= 75:
move_right3()
elif 75 > state > 65:
move_right()
elif 50 > state > 10:
move_left()
elif state >= 85:
move_back()
elif 10 >= state:
k+=1
move_forward3()
else:
move_forward()
else:
まずJで止まったところからの動きを説明する。
#ref(2019a/Member/reifur/Mission2/kadai2_5.jpg,40%,J)
赤線がロボット、とがっている方が前。上図の番号の順に進む。
move_left2()
move_forward2()
のプログラムで図の�△泙任い�。その後JからHのプログラムの
elif state >= 85:
move_back()
によって��まで戻り線の左側を走る。
&br;JからHまでのプログラムは黒線はまっすぐ通るようにし、黒線を2回通ったら終わるようにしている。
**HからGまで [#geaef619]
while k == 2:
state = cs.value()
print(state)
if 80 > state > 65:
move_right()
elif 50 > state > 15:
move_left()
elif state >= 80:
move_back()
elif 15 >= state:
k+=1
move_left3()
else:
move_forward()
else:
Gに着くと
move_left3()
によって下図の赤丸の位置に移動させる。
#ref(2019a/Member/reifur/Mission2/kadai2_6.jpg,40%,G)
**GからDまで [#g1be8645]
while p == 0:
state = cs.value()
print(state)
if state > 65:
move_left()
elif 50 > state > 15:
move_right()
elif 15 >= state:
p+=1
sleep(1)
move_forward4()
else:
move_forward()
else:
上図の赤丸の位置からライントレースの動きで線まで戻り、線の右側を走る。Dの交差点に着くとsleep関数で一度止まり一気に進むことで交差点を超える。
**DからAまで [#u2f59d77]
while p == 1:
state = cs.value()
print(state)
if state > 65:
move_left()
elif 50 > state > 15:
move_right()
elif 15 >= state:
p+=1
sleep(1)
move_down()
move_last()
else:
move_forward()
最後もこれまでと同様にAの黒線を認識したら一度sleep関数で止まり、シャベルを下げ、最後に謎の動きをする。
*反省点と改善点 [#r29e9b96]
2回完璧にミッションをクリアしたので私としては満足のいく結果だった。ただ、ライントレースと言っていいのか微妙な点がかなりあったのとゴールすることを優先したためボールを拾うのがあまりうまくいかなかった。
*プログラム全文 [#sc117290]
最後に読みやすいようにプログラム全文を載せておきます。
#!/usr/bin/env python3
from ev3dev.ev3 import*
from time import sleep
cs = ColorSensor('in2')
l = LargeMotor('outA')
r = LargeMotor('outB')
a = Motor('outC')
cs.mode = 'COL-REFLECT'
i = 0
k = 0
p = 0
def motor_init():
l.reset()
r.reset()
a.reset()
def move_forward():
l.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
r.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
sleep(0.1)
def move_forward2():
l.run_timed(time_sp=250, speed_sp=200, stop_action='hold')
r.run_timed(time_sp=250, speed_sp=200, stop_action='hold')
sleep(0.25)
def move_forward3():
l.run_timed(time_sp=300, speed_sp=240, stop_action='hold')
r.run_timed(time_sp=300, speed_sp=60, stop_action='hold')
sleep(0.3)
def move_forward4():
l.run_timed(time_sp=300, speed_sp=200, stop_action='hold')
r.run_timed(time_sp=300, speed_sp=200, stop_action='hold')
sleep(0.3)
def move_left():
r.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
sleep(0.1)
def move_left2():
l.run_timed(time_sp=2000, speed_sp=0, stop_action='hold')
r.run_timed(time_sp=2000, speed_sp=90, stop_action='hold')
sleep(2)
def move_left3():
l.run_timed(time_sp=2000, speed_sp=20, stop_action='hold')
r.run_timed(time_sp=2000, speed_sp=100, stop_action='hold')
sleep(2)
def move_right():
l.run_timed(time_sp=100, speed_sp=120, stop_action='hold')
sleep(0.1)
def move_right2():
r.run_timed(time_sp=2000, speed_sp=-40, stop_action='hold')
l.run_timed(time_sp=2000, speed_sp=100, stop_action='hold')
sleep(2)
def move_right3():
l.run_timed(time_sp=100, speed_sp=200, stop_action='hold')
sleep(0.1)
def move_back():
l.run_timed(time_sp=100, speed_sp=-80, stop_action='hold')
r.run_timed(time_sp=100, speed_sp=-80, stop_action='hold')
sleep(0.1)
def move_back2():
l.run_timed(time_sp=100, speed_sp=-120, stop_action='hold')
r.run_timed(time_sp=100, speed_sp=-120, stop_action='hold')
sleep(0.1)
def move_back3():
l.run_timed(time_sp=3200, speed_sp=-120, stop_action='hold')
r.run_timed(time_sp=3200, speed_sp=-120, stop_action='hold')
sleep(3.2)
def move_up():
a.run_timed(time_sp=800, speed_sp=-80, stop_action='hold')
sleep(0.8)
def move_down():
a.run_timed(time_sp=800, speed_sp=80, stop_action='hold')
sleep(0.8)
def move_kaiten():
l.run_timed(time_sp=3000, speed_sp=110, stop_action='hold')
r.run_timed(time_sp=3000, speed_sp=-110, stop_action='hold')
sleep(3)
def move_last():
l.run_timed(time_sp=500, speed_sp=50, stop_action='hold')
r.run_timed(time_sp=500, speed_sp=50, stop_action='hold')
sleep(0.5)
l.run_timed(time_sp=3000, speed_sp=100, stop_action='hold')
r.run_timed(time_sp=3000, speed_sp=100, stop_action='hold')
sleep(3)
motor_init()
while i == 0:
state = cs.value()
print (state)
if 80 > state > 65:
move_right()
elif 50 > state > 15:
move_left()
elif 86 >= state >= 80:
move_back()
elif state > 86:
i+=1
move_up()
move_kaiten()
else:
move_forward()
else:
while i == 1:
state = cs.value()
print (state)
if 80 > state > 65:
move_left()
elif 50 > state > 15:
move_right()
elif 15 >= state:
i+=1
move_forward2()
move_right2()
elif state >= 80:
move_back()
else:
move_forward()
else:
while i == 2:
state = cs.value()
print(state)
if 80 > state > 65:
move_right()
elif 50 > state > 15:
move_left()
elif 15 >= state:
i+=1
sleep(1)
move_left2()
move_forward2()
elif state >= 80:
move_back()
else:
move_forward()
else:
while i == 3 and 1 >= k:
state = cs.value()
print(state,k)
if 85 > state >= 75:
move_right3()
elif 75 > state > 65:
move_right()
elif 50 > state > 10:
move_left()
elif state >= 85:
move_back()
elif 10 >= state:
k+=1
move_forward3()
else:
move_forward()
else:
while k == 2:
state = cs.value()
print(state)
if 80 > state > 65:
move_right()
elif 50 > state > 15:
move_left()
elif state >= 80:
move_back()
elif 15 >= state:
k+=1
move_left3()
else:
move_forward()
else:
while p == 0:
state = cs.value()
print(state)
if state > 65:
move_left()
elif 50 > state > 15:
move_right()
elif 15 >= state:
p+=1
sleep(1)
move_forward4()
else:
move_forward()
else:
while p == 1:
state = cs.value()
print(state)
if state > 65:
move_left()
elif 50 > state > 15:
move_right()
elif 15 >= state:
p+=1
sleep(1)
move_down()
move_last()
else:
move_forward()