#author("2020-01-10T04:52:13+09:00","traffic","traffic") #author("2020-02-13T17:43:59+09:00","traffic","traffic") [[2019b/Member]] *課題2 [#sfb8799b] #contents **概要 [#f6ab6b45] #ref(2019b/Mission2/2019b-mission2.png,70%,概要) A地点を出発し、黒い線にそって動くロボットを作成する。また、I地点のキューボイドを掴んでA地点に戻ってくる。 今回は2人目のコースを走った。 A地点から出発 J H (直進) I (ボール or キューボイドをつかんでUターン) H (右折) G (一時停止の後、直進) D (右折) E, F 通過 G (一時停止の後、直進) C (一時停止の後、左折) B (一時停止) A地点に入る(ゴール) **ロボットの説明 [#ae57c3e2] #ref(2019b/Member/traffic/Mission2/20191220_182450.jpg,60%,外観) キューボイドを掴むアームは課題1のペンを上げ下げする機構のモーターを前に出した形になった。 ~アームの下にカラーセンサとキューボイドを認識する超音波センサがある。 #ref(2019b/Member/traffic/Mission2/20191220_182455.jpg,60%,外観) カラーセンサはタイヤから少し離れた位置になった。 **プログラムの説明 [#c13c0e56] #ref(2019b/Member/traffic/Mission2/setumei.png,50%,説明) ライントレースの方法は、ラインの右側を走りセンサの値が一定値以下になったら右に、一定値以上になったら左に曲がるシンプルなものにした。 #ref(2019b/Member/traffic/Mission2/kousaten.png,50%,交差点) 交差点では、カラーセンサが黒だと判断して右に曲がったとき、まだ黒だった場合、それを交差点として認識するものにした。黒の時間を計測して交差点を認識する機構も考えたが、うまくプログラムをかけそうになかったので、この形になった。 ***前進 [#vaf86143] from ev3dev2.motor import MoveTank, OUTPUT_B, OUTPUT_C, from ev3dev2.sensor.lego import ColorSensor motor = MoveTank(OUTPUT_B,OUTPUT_C) cs = ColorSensor() cs.mode = 'COL-REFLECT' def forward(v_max,v_min,left,right): while (cs.value() <= v_max and cs.value() >= v_min): motor.on(left,right) カラーセンサの値がv_min(黒)以上v_max(白)以下の間は直進し続けるという関数。 カラーセンサの値がv_min(黒)以上v_max(白)以下の間は左右のタイヤをleft,rightの速度で直進し続けるという関数。 ***右左折 [#j81929dc] (略) def turn(): if cs.value() > 78: motor.on_for_degrees(-12,6,13) if cs.value() < 14: motor.on_for_degrees(6,-12,13) カラーセンサの値が大きくなったら左折し小さくなったら右折する。 カラーセンサの値が大きくなったら(78以上)左折し小さくなったら(14以下)右折する。 ***交差点 [#vdbb7248] (略) from time import sleep def crossroad(): if cs.value() < 12: motor.on_for_degrees(6,-12,13) if cs.value() < 10: motor.on_for_degrees(-12,6,18) sleep(1) motor.on_for_degrees(10,10,35) global counter counter += 1 上で説明したように、右に曲がってもまだ黒だった場合はそれを交差点として認識する関数。グローバル変数のcounterは後に使用する。 上で説明したように、カラーセンサの値が12以下で右に曲がっても、まだ黒だった場合(10以下)はそれを交差点として認識する関数。グローバル変数のcounterは後に使用する。 ***曲がり角 [#w1b880be] (略) def right_90_turn(): if cs.value() < 12: motor.on_for_degrees(6,-12,13) if cs.value() < 10: sleep(1) motor.on_for_degrees(12,9,35) global counter counter += 1 交差点の関数だけではH,G地点には対応できないので、右に90度曲がる関数も制作した。 交差点の関数で交差点だと認識した後戻っていたところをなくし、無理矢理曲がり白いところに突っ込む形になっている。また、交差点か曲がり角かの使い分けはcounterの値で行うことにした。 ***キューボイド [#uf59b23c] (一部略) from ev3dev2.motor import MoveTank, Motor, OUTPUT_B, OUTPUT_C, OUTPUT_D motor = MoveTank(OUTPUT_B,OUTPUT_C) arm_motor = Motor(OUTPUT_D) def fetch_cuboid(): arm_motor.on_for_degrees(-30,50) sleep(0.5) motor.on_for_degrees(20,20,150) motor.on_for_degrees(30,-30,(240/360)*685) motor.on_for_degrees(-10,-10,100) motor.on_for_degrees(-20,20,(120/360)*685) キューボイドを掴んでUターンする関数。Uターンするときにラインの右側に復帰する必要があるため、煩雑な手順を踏んでいる。ここはもっと簡単にできたはずだと反省している。 キューボイドを掴んでUターンする関数。~ 小モーター(アーム)を下げた後、0.5秒止まり、一度直進した後、左タイヤ30、右-30の速度で240度右に旋回して少し下がり、左-20、右20の速度で120度左に曲がり軌道を修正している。~ Uターンするときにラインの右側に復帰する必要があるため、煩雑な手順を踏んでいる。ここはもっと簡単にできたはずだと反省している。 ***全体のプログラム [#if9d7494] from ev3dev2.motor import MoveTank, Motor, OUTPUT_B, OUTPUT_C, OUTPUT_D from ev3dev2.sensor.lego import ColorSensor, UltrasonicSensor from time import sleep motor = MoveTank(OUTPUT_B,OUTPUT_C) arm_motor = Motor(OUTPUT_D) cs = ColorSensor() us = UltrasonicSensor() cs.mode = 'COL-REFLECT' (関数の定義) #上記の関数の定義 def forward(v_max,v_min,left,right): while (cs.value() <= v_max and cs.value() >= v_min): motor.on(left,right) def turn(): if cs.value() > 78: motor.on_for_degrees(-12,6,13) if cs.value() < 14: motor.on_for_degrees(6,-12,13) def crossroad(): if cs.value() < 12: motor.on_for_degrees(6,-12,13) if cs.value() < 10: motor.on_for_degrees(-12,6,18) sleep(1) motor.on_for_degrees(10,10,35) global counter counter += 1 def right_90_turn(): if cs.value() < 12: motor.on_for_degrees(6,-12,13) if cs.value() < 10: sleep(1) motor.on_for_degrees(12,9,35) global counter counter += 1 def fetch_cuboid(): arm_motor.on_for_degrees(-30,50) sleep(0.5) motor.on_for_degrees(20,20,150) motor.on_for_degrees(30,-30,(240/360)*685) motor.on_for_degrees(-10,-10,100) motor.on_for_degrees(-20,20,(120/360)*685) #ここから動作させるためのプログラム #超音波センサでキューボイドを見つけるまでの間、forward関数とturn関数を繰り返す while (us.distance_centimeters > 10): forward(78,14,12,12) turn() #見つけたらwhile文を抜け、キューボイドを掴む fetch_cuboid() #二人目のルートではここまで交差点(曲がり角)が存在しないので、ここから交差点を判断する関数を組み込む #最初の二回の交差点(曲がり角)のHとGは右に曲がるものなので、右に曲がる関数を2回動かしたら次の交差点を直進するプログラムに進む counter = 0 while (counter < 2): forward(78,12,15,15) right_90_turn() turn() #CとB地点を判断する counter = 0 while (counter < 2): forward(78,12,15,15) crossroad() turn() motor.off 2人目のコースではキューボイドを掴むまで曲がり角や交差点がないため、キューボイドに近づくまではライントレースをするだけになっている。キューボイドを掴んだ後、曲がり角や交差点を通過するたびにcounterが1増え2回(H,G地点とD,B地点、B地点も交差点と同じ挙動をするようになっている)になるとループを抜けるようにした。 **結果と反省 [#se91123d] 結果としては、精度があまりよくなく、何度もコース外に出てしまったり、交差点ではないところで交差点判定をしてしまいcounterがずれてしまったりと失敗が多かった。キューボイドを認識して掴むことは精度がよかったが、反転してコースに戻る時にコースから外れてしまい挙動がおかしくなってしまうこともあった。全体的に数値の調整が甘かったと感じている。~ 最初は黒になっている時間で交差点を判断するプログラムを組もうと考えたが、うまくいかずこの単純な機構になった。次の課題で一緒に作業をするE4の班の機構がよく考えられていたものであっただけにもったいないことをしたと思った。