フィールドは課題2で使用した紙を使用する。2種類の空き缶(Aタイプ,Bタイプ)をそれぞれ3個づつ用意し、円XにABA、円YにBABとなるように3段づつ積み上げ、それぞれの円にAAA、BBBとなるように運搬する(ただし、円の中に入っていれば良い)。そして、スピードと運搬の技術点の合計得点を競う。
緑色の丸で囲った部分は超音波センサーである。
また本体は主に3つのパーツで出来ている。
1.ラバーパーツが付いていて、2の青い丸で囲まれた部分に挟まれる缶が滑らないようにする
2&3.缶を運ぶために挟む部分を二つに分けてある
モーターを二つ使い、旋回を可能にした。また、エレベーター部分を取り付けると、重心がかなり前になってしまったため、前の方にボールを付け安定するようにした。
1,エレベーター部分を動かすモーター
2.左側は右側とは逆に回るようにはぐるまで繋がっている
3.アーム部分を上下させるエレベーター部分
ここでは缶の大まかな動き方を説明する。
1.円Y内のABAと積まれている缶を上の方にAの缶を二つ集め、下の方にBの缶を置く
2.Aの缶を二つ持ちながら、円Xに移動する
3.円Xも円Y同様に缶をそろぞれ分けながら床に置き、円Xに持ってきたAの缶二つと仕分けたAの缶を積み上げる
4.円Yに円Xで仕分けたBの缶二つを持って行き、円Yで積み上げる
#!/usr/bin/env python3 from ev3dev.ev3 import * #EV3を扱うモジュールをインポート from time import sleep #timeモジュールからsleep関数をインポート
us1 = UltrasonicSensor('in1') #1端子側の超音波センサーをus1とおく us2 = UltrasonicSensor('in3') #3端子側の超音波センサーをus2とおく mL = LargeMotor('outA') #A端子側の移動用モーターをmLとおく mR = LargeMotor('outB') #B端子側の移動用モーターをmRとおく mA = MediumMotor('outC') #C端子側のアーム開閉用モーターをmAとおく mLif = LargeMotor('outD') #D端子側の無限軌道制御用モーターをmLifとおく
以下は各位置での缶をアームでつかんでの積み降ろしをするために,アームを昇降するときに用いるmLifの回転角度の値をおいたものである.
lif2 = 250 #ある缶から一個上の缶までアームが上昇するためのmLifの回転角度値 lif3 = 495 #ある缶から二個上の缶までアームが上昇するためのmLifの回転角度値 dow3 = -520 #ある缶から二個下の缶までアームが降下するためのmLifの回転角度値 dow2 = -280 #ある缶から一個下の缶までアームが降下するためのmLifの回転角度値
def motor_init(): #各モーターをリセットする mL.reset() mR.reset() mLif.reset() def turn(t): #右回りを正とし,指定角度 t だけ移動用モータが回転,車体が旋回する mL.run_to_rel_pos(position_sp=t,speed_sp=60,stop_action='brake') mR.run_to_rel_pos(position_sp=-t,speed_sp=60,stop_action='brake') sleep(3) def run_for_back_pos(t): #指定角度 t だけ移動用モーターが回転,車体が前進または後退する motor_init() mL.run_to_rel_pos(position_sp=t,speed_sp=60,stop_action='hold') mR.run_to_rel_pos(position_sp=t,speed_sp=60,stop_action='hold') sleep(1) def run_adjust(t): #上述定義を用いて,前進または後退の調整 run_for_back_pos(t)
def arm_open(): #アームを開く mA.reset() mA.run_to_rel_pos(position_sp=-20,speed_sp=20,stop_action='hold') sleep(2) def arm_close(): #アームを閉じる mA.reset() mA.run_to_rel_pos(position_sp=50,speed_sp=50,stop_action='hold') sleep(2) def arm_adjust(t): #アーム開閉時に調整のために用いる(mAの回転角度をtとおく) mA.reset() mA.run_to_rel_pos(position_sp=t,speed_sp=50,stop_action='hold') sleep(1)
後の缶を降ろす作業の際に,アームのキャッチングの位置によっては最下点に下がっても缶が接地しない場合があり,リリース時で缶を落とさなければならず、試行の最中に何度も倒れてしまったことから、アームを開く時のモーターの速さはできるだけ小さくし、ラバーパーツの摩擦を利用し倒れないようにしなければならない.
def lift_can2(): #アームが,ある缶から一個上の缶まで上昇する motor_init() mLif.run_to_rel_pos(position_sp=lif2,speed_sp=80,stop_action='hold') sleep(3) def lift_can3(): #ある缶から二個上の缶まで上昇する motor_init() mLif.run_to_rel_pos(position_sp=lif3,speed_sp=80,stop_action='hold') sleep(6) def down_can2(): #ある缶から一個下の缶まで降下する motor_init() mLif.run_to_rel_pos(position_sp=dow2,speed_sp=75,stop_action='hold') sleep(5) def down_can3(): #ある缶から二個下の缶目で降下する motor_init() mLif.run_to_rel_pos(position_sp=dow3,speed_sp=75,stop_action='hold') sleep(6)
def lift_adjust(t): #上述に定義した値以外で昇降を調整(mLifの回転角度を t とおく) motor_init() mLif.run_to_rel_pos(position_sp=t,speed_sp=60,stop_action='hold') sleep(3)
def can_approach(): #缶の積み降ろしの前に,缶を見つけ,缶と適切な距離を取ってつかむ motor_init() while us1.value() > 70: #缶との距離が一定値超の時,前進すして缶に接近 mL.run_forever(speed_sp=80) mR.run_forever(speed_sp=80) run_for_back_pos(80) #一定の距離まで近づいたら,そこから缶に適切な距離まで近づく sleep(2) def turn_can_search(le,s): #前方にある缶を探して旋回 motor_init() while us1.value() > le: mL.run_forever(speed_sp=50*s) mR.run_forever(speed_sp=-50*s) turn(20*s) #検知した後,正面を向くよう修正
sleep(2) 今回は超音波センサーを用い、その検知可能範囲の長さを le (mm)とし,s = ±1 を代入して右回りか左回りかを調節した。その後、関数turn()を用いることによって正面を向くように調節した。
def start(): #スターティングポイントよりB地点に向かい,右へ方向転換 motor_init() run_for_back_pos(600) #↓で旋回して缶の正面になるよう,適当な位置まで後退 sleep(8) turn(165) #缶の正面を向くよう旋回 sleep(2) turn(20) #旋回して缶を見つける準備に入る turn_can_search(250,-1)#左回りに旋回して缶を探す turn(-5) #方向修正
def lift_down_can3_can2(): #三段目の缶と二段目の缶をアームでつかんで降ろす motor_init() lift_can3() //三段目の缶まで移動 arm_close() //アームを閉じる lift_adjust(45) //移動の際に下の缶を引っ掛けないように缶を少し持ち上げる run_adjust(-100) //後退 sleep(2) turn(-110) //左へ旋回 down_can3() //缶をとりあえず降ろす lift_adjust(-40) //最下点まで降ろすよう調整 arm_open() //アームを開いて缶をリリース run_for_back_pos(250) //左斜め前方まで押して移動 sleep(3.5) lift_can3() //移動の際に缶を引っ掛けないよう予め上げておく lift_adjust(45) run_for_back_pos(-250) //積まれた缶の前まで下がる sleep(3.5) turn(110) //缶の正面へ旋回 arm_adjust(-10) //アームを少し開く(確実に缶がキャッチできるように) down_can2() //二段目の缶までアームを降ろす run_adjust(113) //缶の手前まで接近 sleep(2.5) arm_close() //アームを閉じて缶をキャッチ lift_adjust(45) //缶を少し持ち上げる run_for_back_pos(-90) //少し後退 ←この時二段目の缶はサークルから外れるように turn(110) //右へ旋回 down_can2() //缶を降ろす arm_open() //アームを開いて缶をリリース lift_can2() //アームを上げとく(↓collect_can1_can3()へ)
試行中に何度も缶をキャッチする際に超音波センサーが反応しなくなってしまうときがあった。これは超音波センサーと缶との距離が近すぎるために、反応しなくなってしまったのではないかと考え、下がるプログラムを加えることで距離を確保し、実際に反応しない問題は解消された。
def collect_can1_can3(): //三段目と左斜め前方に移した一段目(二つの同種の缶)をまとめる motor_init() turn(-115) //二段目を降ろしてアームを上げた後,三段目の正面を向く down_can2() //二段目にあったアームを三段目まで降ろす run_adjust(110) //三段目の缶がアームの中に入るよう前進 sleep(1.5) arm_close() #7up / CClemon //アームを閉じて缶をキャッチ run_for_back_pos(-320) //後退 ←旋回しても,アームに缶が当たらないような位置に sleep(6) lift_can3() //缶をキャッチしたまま上げて,超音波センサーの視界を確保 turn_can_search(300,-1) //最初に移した缶を探し,左回りに旋回 down_can3() //缶を最下点まで降ろす arm_open() //アームを開いて缶をリリース arm_adjust(-10) //二つの缶が入るようにアームをある程度開いておく run_for_back_pos(500) //アームの中に二つの缶が入るまで適当な距離を前進 sleep(6) arm_adjust(20) //アームを閉じて缶をまとめる(緩めに閉じるので離脱可能)
以下は,二つの同種の缶をキャッチした状態から,手前側の固定された缶を上げて固定されずに残った缶に積むためのプログラムである.
def pile_can(): lift_can3() #手前側のキャッチして固定された缶を上げる run_for_back_pos(130) #残された缶に,積み降ろしに適当な距離まで接近 sleep(3) lift_adjust(40) #上げる過程で傾いた缶を慣性力で傾きを修正する(ほぼ無意味) lift_adjust(-180) #缶を積む arm_open() #アームを開いて積まれた缶をリリース
以下は,Y地点での缶の積み降ろしが終わった後,X地点の積み降ろしの準備に入るためのプログラムである.
def can_approach2(): motor_init() run_for_back_pos(-15) #C地点辺りで二つの缶を降ろした後,離脱準備に入る lift_can2() #周辺の缶を後の動作でアームで引っ掛けないよう,上げた状態に lift_adjust(65) #もう少し上げておく(これが後々に利いてくる...予定) sleep(2) run_for_back_pos(-275) #B地点辺りまで後退 sleep(6) turn(100) #旋回してX地点の方向に合わせる run_for_back_pos(730) #X地点の缶を目指してテキトーな距離まで移動 sleep(11.5) turn(-80) #旋回して,缶を見つける準備に入る turn_can_search(300,1) #右回りに旋回しながら缶を探す turn(20) #適当な位置に正面を戻す arm_adjust(-5) #缶を少し開いておく run_for_back_pos(100) #ある程度の距離まで缶に接近 sleep(3) down_can2() #アームを下げておく(lift_down_can3_can2()に入る準備) (↑ここで利いてくる.一つのルーチンでstart()の状態と同じに)
以下はX地点での缶の積み降ろしと分別を終えた状態から,二つの缶をキャッチしたままY地点へ向かい,二段に積み上げてサークル内に入れるためのプログラムである.
def toward_circleY(): motor_init() arm_close() #アームをしっかり閉じる arm_adjust(11) turn(-360) #Y地点へ向かうため後方へ方向転換 sleep(5) turn(25) #少し旋回 turn(-25) #戻る pile_can() #二つの缶を二段に積み上げる down_can2() #積み上げてアームを開いた後,一段目までアームを下げる lift_adjust(-70) #最下点まで下げておく sleep(1) run_for_back_pos(20) #缶を確実につかむため接近 arm_close() #アームを閉じて缶をキャッチ lift_adjust(20) #缶を少し浮かせ,後の移動で引きずって缶が傾かないようにする run_for_back_pos(380) #サークル付近にある最初に降ろした缶に,ある程度接近 ※※3↓ sleep(7) arm_adjust(5) #缶をしっかりつかむ lift_adjust(340) #缶をキャッチしたまま上げて,正面の超音波センサーの視界を確保 sleep(6) #↓右回りに旋回し,左回りの検知の準備に入る mL.run_to_rel_pos(position_sp=45,speed_sp=40,stop_action='brake') mR.run_to_rel_pos(position_sp=-45,speed_sp=40,stop_action='brake') sleep(4) turn_can_search(300,-1)#左回りに旋回して缶を検知する lift_adjust(-410) #缶を地面まで降ろす sleep(7) arm_open() #アームを開き缶をリリース(can7up_catchへ) ※※3↑(ここまで)
以下は,二つの缶の二段積みを終えて,移動し、二つの缶をキャッチするためのログラムである
def can7up_catch(): motor_init() lift_can3() #移動中,缶に引っ掛けないよう,適当な高さにアームを上げておく lift_adjust(70) run_for_back_pos(-250) #後退 sleep(4) turn(130) #旋回 sleep(1.5) while us2.value() > 160: #側面にある超音波センサーが,二段積みの缶を探して旋回 mL.run_forever(speed_sp=60) mR.run_forever(speed_sp=-60) turn(40) #外周のラインに対してほぼ垂直になるように方向修正 run_for_back_pos(200) #車体が外周ラインに乗るまで前進 sleep(6) turn(-170) #ラインに平行になるよう旋回(C地点辺りに移した缶のキャッチへ) sleep(2) arm_adjust(-15) #二つの缶が確実にアームの中に入るよう,アームを開いておく sleep(1) down_can3() #アームを最下点まで下げておく lift_adjust(-25) while us1.value() > 70: #缶との距離が一定値超のとき,前進して缶に接近 mL.run_forever(speed_sp=60) mR.run_forever(speed_sp=60) run_for_back_pos(100) #缶との距離が一定値に達したら,適当な距離まで接近 arm_close() #アームを閉じて缶をキャッチ arm_open() #アームを開く(toward_circleX()へ)
以下は二つの缶をキャッチした状態より二段に缶を積む上げてX地点へ向かい,サークル付近にある最初に降ろした缶とを合わせて三段に積み上げてサークル内に入れるためのプログラムである。
def toward_circleX(): motor_init() arm_close() #アームを閉じる pile_can() #缶を二段に積み上げる(最後はアームを開く) down_can2() #最下点まで下げておく lift_adjust(-110) sleep(1) run_for_back_pos(20) #下の缶を確実にキャッチできるよう接近 arm_close() #アームを閉じて缶をキャッチ arm_adjust(8) #缶をしっかりキャッチ lift_adjust(20) #缶を少し浮かせ,後の移動で引きずって缶が傾かないようにする run_for_back_pos(-110)#↓で旋回に入ったとき積んだ缶に引っ掛けない距離まで後退 mL.run_to_rel_pos(position_sp=-300,speed_sp=40,stop_action='brake') mR.run_to_rel_pos(position_sp=300,speed_sp=40,stop_action='brake') sleep(8) #↑X地点のほうへ旋回 arm_adjust(8) #ここまでの過程でアームが緩む時があるので缶をしっかりキャッチ lift_adjust(320) #缶を上げて,正面の超音波センサーの視界を確保 sleep(5) turn_can_search(500,1)#右回りに旋回して,缶を探す turn(20) #方向修正 lift_adjust(-320) #缶を降ろす sleep(6) run_for_back_pos(220) #X地点の側の缶にある程度近づく sleep(7) turn_can_search(300,-1)#左回りに旋回して,缶を探す(↑でlift()を入れ忘れてしまった) turn(-15) #方向修正 while us1.value() > 80: #缶との距離が一定値超の時,前進すして缶に接近 mL.run_forever(speed_sp=70) mR.run_forever(speed_sp=70) pile_can() #缶を積み,三段に積み上げる(最後,アームは開いた状態) down_can2() #最下点まで下げておく lift_adjust(-85) sleep(1) arm_close() #三段に積まれた缶をキャッチ mL.run_to_rel_pos(position_sp=-110,speed_sp=30,stop_action='brake') mR.run_to_rel_pos(position_sp=110,speed_sp=30,stop_action='brake') sleep(5) #↑三段に積まれた缶をサークルに入るよう,キャッチしたまま旋回 arm_open() #アームを開いて三段に積まれた缶をリリース
start() //A地点から前進しB地点で旋回。Y地点の缶の方向を向く can_approach() //接近する lift_can3_can2() //Y地点の缶を緑は左、黄色は右に積み下ろす。(左右は機体からみた缶のタワーに対してである) collect_can1_can3() //緑の缶を2本整列させる can_approach2() //X地点に向かう can_approach() //X地点の缶に近づく lift_down_can3_can2() //黄色は左、緑は右に缶を積み下ろす collect_can1_can3() //黄色の缶を整列させる toward_circleY() //Y地点に黄色の缶を積み上げる can7up_catch() //緑の缶を掴む toward_circleX() //緑の缶をX地点に運搬し積み上げる
たった一つの関数、たった一つの変数がそれ以降のプログラムに響き、また失敗に繋がってくるとてもシビアなものだと感じた。それが分かっているからこそ、直前まで懸命に努力をし、なんとか成功に近づけようとしていただけに残念だった。left()、このたった6文字で結果が変わるかもしれない。恐ろしい世界だが、それでもあえて前向きな考えをするならばそのたった6文字で失敗が成功に変わるかも知れない。(もちろんそこに至るまでの時間と労力はかかるが。)僕たちがこの授業で習ったのはプログラミングという世界のほんの一部かも知れないが、それでも難しかったし、楽しかった。この世界はきついことは当たり前だが、その裏にやはり面白さが隠れていると思う。これからはコンピューターの中で様々な処理がされていく時代。自分もこの授業をきっかけとして、これで終わりでなくプログラミングの勉強を続けていきたいと思う。