フィールドは課題2で使用した紙を使用する.
2種類の空き缶(Aタイプ,Bタイプ)をそれぞれ3個づつ用意し,円XにABA,円YにBABとなるように3段づつ積み上げる.その缶を分別し、それぞれの円に運搬し積み上げるミッション。 今回は黄色の缶と緑の缶を使用し、X地点に黄色 緑 黄色、Y地点に緑 黄色 緑と積んだ。
ロボットに求められる機能は缶を積み上げ、積み下ろす機能と缶を運搬する能力である
1.超音波センサー 2.ボール
作成したロボットは主に3つのパーツで成り立つ
1.缶を掴む際滑り止めとなるゴムのパーツ
2.この前方のアーム事態につかむ能力はないが、缶を押して運搬するためのもの
3.モーターで2つのギアをかいてんさせ、それぞれに取り付けたアームを開閉させる
二つのタイヤで全身や旋回を行う
全体を組み立てるとリフトが重く、前方に重心が偏ってしまったため機体前方にボールをつけてバランスを取っている
モーターでキャタピラを巻き取り、アームを持ち上げる
1.この部位は、ギアを使うことでもう一列のリフトにも回転を伝え、一つのモーターで二列のリフトを動かしている。二列にすることで上下運動の揺れを抑えられた
2.このモーターで巻き上げる
キャタピラ内部のギアを回転させ、巻き取る。
缶の移動の際に振動が大きく缶を落とすことがあった。そこで、キャタピラを棒で(↑3.)つっつぱらせて張力を高めて対策した。
超音波センサーで感知した缶を整列させる
アームでつかみ、手前の缶を持ち上げる。その後機体を前進させ、缶を積む
積み下ろしの際はセンサーで缶と適性な距離に接近し、二段目以上の缶をつかむ。機体を後退させ、リフトを下ろし、ゆっくりとアームを開いてこけないように地面に落とす
今回缶との距離を測るため、または缶の位置を感知するために超音波センサーを使用した。
機体の前方と側面に1つずつ設置した。
缶の位置を探す際に、一定距離以内に缶があると感知するまで一定距離旋回、その後逆方向に旋回を繰り返して缶を探した。
超音波センサーは缶との接近の精度を高くすることができた
以下は定義までの導入である
#!/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 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 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 turn_can_search(le,s): //前方の缶を探す motor_init() while us1.value() > le: //缶との距離がle以上の時 mL.run_forever(speed_sp=50*s) //缶を探して、左右に旋回する。sに+または-を代入して方向を決める mR.run_forever(speed_sp=-50*s) turn(20*s) //缶との距離がle以下の時,正面を向くよう修正
近距離での精度は非常に高かったが、距離が開くと誤差などが生じることが多かった。それにより生じる誤差の調整などに苦労した
def start(): motor_init() run_for_back_pos(600) //適当な位置まで前進 sleep(8) turn(165) //缶の正面を向くよう旋回 sleep(2) turn(20) turn_can_search(250,-1)//左回りに旋回して缶を探す turn(-5) //向きを調整
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 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 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()
def collect_can1_can3(): //三段目と左斜め前方に移した一段目(二つの同種の缶)をまとめる motor_init() turn(-115) //二段目を降ろしてアームを上げた後,三段目の正面を向く down_can2() //二段目にあったアームを三段目まで降ろす run_adjust(110) //三段目の缶がアームの中に入るよう前進 sleep(1.5) arm_close() //アームを閉じて缶をキャッチ 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()
def can_approach2(): //Y地点での缶の積み降ろしが終わった後,X地点の積み降ろしの準備に入る 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() //アームを下げておく
以下はX地点での缶の積み降ろしと分別を終えた状態から,緑の缶を2本キャッチしたまま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) //サークル付近にある最初に降ろした缶に,ある程度接近 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へ)
以下はY地点の黄色の缶をキャッチするためのプログラムである.
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()へ)
以下は、Y地点の緑の缶をX地点に運搬し、3段に積み上げて円の中に入れるプログラムである
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) //Y地点の側の缶にある程度近づく sleep(7) turn_can_search(300,-1)//左回りに旋回して,缶を探す 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地点に運搬し積み上げる
授業の中でロボコンを体験出来て貴重な経験になったと思う。 事前のテストではかなりうまくいっており、3段積むことも可能であったが本番のスコアは奮わなかった。機体の構築などに時間を取られたため、調整の時間が少なくなってしまったことが原因として考えられる。特に今回は超音波センサーやアーム、リフトなどの各種数値の調整する点が非常に多かったため、調整に時間がかかってしまった。 その分機体構築においては、求められる機能を達成できるロボットの構造についてのアイデア を出し合い(キャタピラを使ってリフトを作成する、リフトを2列にするなど)かなり満足のいく構築ができたと思う。プログラムについても試行錯誤の中で完成度が上がっていった。こんなことを言っても負け惜しみになるが調整時間さえもう少しあれば1位も夢ではなかったのではないかと悔しく思う。 この授業の中で機械などを思うように動かす難しさ、チームで課題に取り組む姿勢の重要性について深く実感できた。一人では達成できなかっただろう課題もあり、思うように動かずプログラムに苛立つこともあったがそれらも含めて本当によい学習の機会であったと思う。