目次
#contents
*課題3について [#s2efe45a]
青と赤のボールを運搬して、それぞれ所定の350ml缶の上に乗せる。
#ref(2018b-mission3.png)
**フィールドの説明 [#s03f3ddd]
フィールドは課題2で使用した紙を使用する。
350ml缶(中が入っていても空でよい)は逆さまにして使い、ロボットのスタート直後にサイコロを振って出た目の番号の位置に置く。
その番号の次の番号のところにもダミーの缶を置くことができる。ただし6の目が出た場合は6の位置と25cm以上離れていない場所ならどこに置いてもよいものとする。距離は缶と缶のもっとも近い部分で測る。
空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。
赤と青のボールは、図のように所定の場所に置いておく。その際、キットに含まれない小さな輪ゴムを使用するものとする。
**基本ルール [#re19d184]
競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
図のX地点または(および)Y地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。
赤いボールを図のピンクのいずれかに置いた缶に、青いボールを図の水色のいずれかに置いた缶に、それぞれ乗せる。
開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
*方針 [#x6029586]
#ref(loute.png)
この画像のルートでやっていく。
��Xからスタートして赤のボールを拾う。→�■鼎泙嚢圓�缶を探査。赤のボールを置く。→��Iでボールを拾い、Kで探査しボールを置く。
*ロボット [#r3c7af6e]
#ref(s_IMAG0782.jpg)
まずは全体図。EV3が二つ付いているがこれは通信を行っているわけではなく機体が倒れないように錘として載せているだけである。車輪は二つ左右についていて、アームの方向に進む機体だ。
#ref(s_IMAG0778.jpg)
超音波センサがアームの下についていて、それに垂直にする形でカラーセンサがついている。
*プログラム [#m0ed8e0b]
**定義[#y81c0bce]
まずはそれぞれのモータやセンサの定義について
mL=LargeMotor('outA') #進行方向に対して左側のモータ
mR=LargeMotor('outD') #進行方向に対して右側のモータ
mA=MediumMotor('outC') #アーム部分のモータ
mC=MediumMotor('outB') #ハンド部分のモータ
csR=ColorSensor('in1') #ライントレース用のカラーセンサ
#csL=ColorSensor('in2') #使わなかったもう一つのライントレース用のカラーセンサ。詳しくは後述。
us=UltrasonicSensor('in3') #超音波センサ
それぞれの役割については対応するプログラムで詳しく説明する。
**ライントレース [#v76f2770]
はじめは以下のライントレースのプログラム使おうとした。
def linetrace():
t0=time.time()
while time.time()-t0<0.35 #t0とtime,timeの差が0.35秒より小さいときに繰り返す
if csR.value()=>50: # 右側のカラーセンサの値が50以上で実行
mR.run_forever(speed_sp=150,stop_action='brake')
t0=time.time()
if csL.value()=>50: # 左側のカラーセンサの値が50以上で実行
mL.run_forever(speed_sp=150,stop_action='brake')
t0=time.time
if csR.value()<50: # 右側のカラーセンサの値が50より小さいとき実行
mL.run_forever(speed_sp=150,stop_action='brake')
if csL.value()<50: # 左側のカラーセンサの値が50より小さいとき実行
mR.run_forever(speed_sp=150,stop_action='brake')
mR.stop()
mL.stop()
黒の線を挟むように二つのカラーセンサを用いてライントレースの精度を上げようとした。しかしこれは動かなかった。
理由としてはif文の条件分岐がよくできていない、並列処理のような構造になってるということが挙げられる。それの改善案が以下のプログラムである。
def linetrace():
t0=time.time()
while time.time()-t0<0.35
if csR.value()=>50:
mR.run_forever(speed_sp=150,stop_action='brake')
t0=time.time()
elif csL.value()=>50:
mL.run_forever(speed_sp=150,stop_action='brake')
t0=time.time
elif csR.value()<50:
mL.run_forever(speed_sp=150,stop_action='brake')
elif csL.value()<50:
mR.run_forever(speed_sp=150,stop_action='brake')
mR.stop()
mL.stop()
2〜4番目のif文をelifにすることによって条件式の処理の順番を整理した。
def turnR1():
mL.run_forever(speed_sp=100,stop_action='brake')
mR.stop()
def turnL1():
mR.run_forever(speed_sp=100,stop_action='brake')
mL.stop()
def run1():
mR.run_forever(speed_sp=100,stop_action='brake')
mL.run_forever(speed_sp=100,stop_action='brake')
def turnR2():
mL.run_forever(speed_sp=100,stop_action='brake')
mR.run_forever(speed_sp=-70,stop_action='brake')
def turnL2():
mR.run_forever(speed_sp=100,stop_action='brake')
mL.run_forever(speed_sp=-70,stop_action='brake')
def traceR():
t0=time.time()
while time.time()-t0<0.35:
if cs.value()<35: #カラーセンサの値が35より小さいときその場で右に回る
turnR2()
if 35<=cs.value()<40: #カラーセンサの値が35以上で40より小さいとき前に進みながら右にカーブする
turnR1()
t0=time.time()
if 40<=cs.value()<=50: #カラーセンサの値が40以上で50以下のとき真っすぐ走る
run()
t0=time.time()
if 50<cs.value()<=60: #カラーセンサの値が50より大きくて60以下のとき前に進みながら左にカーブする
turnL1()
t0=time.time()
if cs.value()>60: #カラーセンサの値が60より大きいときその場で左に回る
turnL2()
t0=time.time()
mR.stop() #黒を一定の時間以上認識したらwhile構文から抜け出し、停止する
mL.stop()
しかし結局本番では上記の課題2でのライントレースのプログラムを流用した。
**それ以外のマクロ [#qae6a57b]
def run2(): #前にゆっくり進む
mL.run_forever(speed_sp=50, stop_action='brake')
mR.run_forever(speed_sp=50, stop_action='brake')
def forword_bit(): #前に少し進む
mL.run_to_rel_pos(position_sp=20, speed_sp=500, stop_action='brake')
mR.run_to_rel_pos(position_sp=200, speed_sp=500, stop_action='brake')
def forward(): #前に一定距離進む
mL.run_to_rel_pos(position_sp=360, speed_sp=500, stop_action='brake')
mR.run_to_rel_pos(position_sp=360, speed_sp=500, stop_action='brake')
def catchup():
while us.value()>=50: #ボールに近づく
run2()
mR.stop()
mL.stop()
mC.reset()
mC.run_to_abs_pos(position_sp=60 ,speed_sp=20, stop_action='brake') #ハンドを開く
time.sleep(3)
mA.run_to_abs_pos(position_sp=100, speed_sp=30, stop_action='brake') #腕を下げる
time.sleep(4)
mC.run_to_abs_pos(position_sp=0, speed_sp=20, stop_action='brake') #ハンドを閉じてボールをつかむ
time.sleep(6)
mA.run_to_abs_pos(position_sp=0, speed_sp=100, stop_action='hold') #腕を上げる
time.sleep(3)
def puton_red():
time4=time.time()
while us.value>=40: #赤の缶に近づく
run2()
time_kan=time.time()
mC.run_to_rel_abs(position_sp=30, speed_sp=20, stop_action='brake') #ボールを離す
time.sleep(1)
timenow=time.time()
while time.time()-timenow<=time_kan-time4: #缶に近づいた分の距離戻る
mL.run_forever(speed_sp=-50, stop_action='brake')
mR.run_forever(speed_sp=-50, stop_action='brake')
def puton_blue():
while us.value>=40: #青の缶に近づく
run()
mC.run_to_rel_abs(position_sp=30, speed_sp=20, stop_action='brake') #ボールを離す
def direct_one():
time1=time.time()
while time.time()-time1<=20:
mL.run_forever(speed_sp=-50, stop_action='brake')
mR.run_forever(speed_sp=50, stop_action='brake')
今回は赤の�,隆未魎霆爐亡未涼戯困鬚垢襪里任修諒�向を向くのが上のプログラム。
def Round_red(): #赤の缶の周りを回転する
time1=time.time()
while time.time()-time1<=fuga:
mL.run_forever(speed_sp=50, stop_action='brake')
mR.run_forever(speed_sp=-50, stop_action='brake')
def direct_redkan(): #正しい赤の缶を見分けるためにその周りを回転する
time1=time()
while time.time()-time1<=fuga-(think_red()-time_start):
mL.run_forever(speed_sp=-50, stop_action='brake')
mR.run_forever(speed_sp=50, stop_action='brake')
def direct_I(): #I地点を向く
time1=time.time()
while time.time()-time1<=think_red()-time_start+いくらか:
mL.run_forever(speed_sp=-50, stop_action='brake')
mR.run_forever(speed_sp=50, stop_action='brake')
def direct_B(): #B地点を向く
time1=time.time()
while time.time()-time1<=20:
mL.run_forever(speed_sp=-50, stop_action='brake')
mR.run_forever(speed_sp=50, stop_action='brake')
def Round_blue(): #青の缶の周りを回転する
time1=time.time()
while time.time()-time1<=fuga2:
mL.run_forever(speed_sp=50, stop_action='brake')
mR.run_forever(speed_sp=-50, stop_action='brake')
def direct_bluekan(): #正しい青の缶を見分けるためにその周りを回転する
time1=time()
while time.time()-time1<=fuga2-(think_blue()-time_start):
mL.run_forever(speed_sp=-50, stop_action='brake')
mR.run_forever(speed_sp=50, stop_action='brake')
time_start=0
time_a=0
time_b=0
def search(fuga,hoge): #fugaはこのマクロを動かす時間 hogeは最短距離にある缶を探すための適当な距離の値
global time_start
global time_a
global time_b #globalを用いて他のマクロからtime_bをとってくる 上二つも同様
a=1250 #適当な大きい距離を代入する
b=1250 #同上
time0=time_start=time.time()
while us.value()>=hoge: #超音波センサの値がhoge以上なら何もしない
continue
while time.time()-time0<=fuga: #fuga以下の時間実行
if us.value()<=hoge: #超音波センサの値がhoge以下ならば実行
if us.value()<=a: #超音波センサの値がa以下ならば実行7
a=us.value() #aに超音波センサの値を代入して更新する
time_a=time.time() #time_aにその時の時間を代入
else: #hogeより超音波センサの値が大きいときループを抜ける
break
while time.time()-time0<=fuga and us.value()>=hoge: #fuga以下の時間かつ超音波センサの値がhoge以上ならば何もしない
continue
while time.time()-time0<=fuga: #fuga以下の時間実行
if us.value()<=hoge: #超音波センサの値がhoge以上のとき実行
if us.value()<=b: #超音波センサの値がb以下のとき実行
b=us.value() #bに超音波センサの値を代入して更新する
time_b=time.time() #time_bにその時の時間を代入
else: #hogeより超音波センサの値が大きいときループを抜ける
break
def think_red():
if a<b:
return time_a
else:
return time_b
上のプログラムはaとbの値の大小関係を比べて、それによって戻り値を変える。
これによって正しい赤の缶を見分ける際につかう時間の値を決める。
def think_blue(): #青の正しい缶を決める関数を定義
if a<150 and b<150: #1の缶だと決定
return time_b #time_bを戻りとして返す
if a<150 and 150<=b<300: #2の缶だと決定
return time_a #time_aを戻り値として返す
if 150<=a<300 and 150<=b<300: #3の缶だと決定
return time_a #time_aを戻り値として返す
if a<300 and b=1250: #4の缶どと決定
return time_a #time_aを戻り値として返す
if a>=300 and b=1250: #5の缶だと決定
return time_b #time_bを戻り値として返す
if 450<b<550: #6の缶だと決定
return time_b #time_bを戻り値として返す
上のプログラムはセンサで測ったaとbの値を二つ参照して正しい缶を決定するプログラムである。また決定した後にそこに行くまでの時間でtime_aとtime_bのどちらを採用するかも、このときに決定する。
*問題点 [#c66f4207]
ロボットの抱えている問題としてアームの重さがある。アームが重すぎてアームを下げた後にまた上げることができなかったのだ。これを解決するためにモータのスピードをもっと遅くする、ギア比の調節をする必要があった。
さらに全体的な問題として試行を行えなかったというのがある。そのせいで種々の問題を発見できなかった。
*感想 [#h68f052b]
テスト直後ということは言い訳にできないが、準備をまったくすることができなかった。本番でも最初のボールをつかむことさえできずにとても悔しい結果に終わった。この悔しい経験は来年以降の様々な授業で糧にしていきたいと思う。