[[2018a/Member]] *方針 [#t5c57c67] RISにはあるラックとピニオンやEV3にはあるベルトコンベアのような上下運動に強い機構がNXTにはなく、いかにして上下運動を行うかに頭を悩ませた。 当初、クランクアームなどをもちいて上下運動させることも考えたが、動作、強度どちらにしても不安が多く、採用しなかった。 そこで、缶の上下運動は重力に任せ、落ちてくる缶を一つ一つ処理することにした。 大まかな流れとしては以下のようになる +積んである状態の缶を3つとも抱え込むようにキャッチする。 +最下段の缶の色の目標の円のそばまで走行 +最下段の缶を押し出す +落ちてきた2段目以降の缶を缶を押し出す機構の上にのせたまま次の目標地点まで移動 +押し出す機構を引き、2段目を接地させる +2段目を押し出す +落ちてきた3段目の缶を缶を押し出す機構の上にのせたまま次の目標地点まで移動 +3段目を押し出す *ロボット本体 [#l956fe5d] #ref(2018a/Member/Areidaaa/Mission3/image9.jpeg) アームは缶3段分をつかんでも安定する高さと形状とした。またNXT本体は背中合わせに設置することで左右のバランスの安定を図った。本体と各種モータをつなぐケーブルはロボットの動作に支障をきたしたりロボット旋回時にケーブルが缶にあたって動いてしまうことを防ぐため本体にできる限り絡ませた。 アームは3段に積まれた缶を確実につかむことができる形状と高さとした。左右の腕をギアを用いて連動させ、挟むというシンプルなものである。 #ref(2018a/Member/Areidaaa/Mission3/image4.jpeg) 後輪は前回同様先端が丸いパーツを使用した。これにより安定した旋回が行えた。今回は前回と異なりロボット本体がかなり重いので、後輪も2輪設置した。 #ref(2018a/Member/Areidaaa/Mission3/image5.jpg) #ref(2018a/Member/Areidaaa/Mission3/image10.jpeg) アームそのものがそれなりの重さと大きさを持っているうえ、アームの重心が本体から離れていた。そのためアーム取り付け部が自重に耐え切れず、下に垂れ下がるような格好となってしまっていた。そのため -アームが斜めになっているので缶を安定してキャッチしない -モータに負荷がかかって動作が安定しない -不格好 以上のような問題が発生した。そここでアームの可動部分下部にガイド(上図赤丸部)を設置した。 これにより上記の問題を一気に解決することができた。 #ref(2018a/Member/Areidaaa/Mission3/image8.jpeg) アームの下にはアームが缶を確実にとらえられるように缶のガイドを設置した。缶とロボット本体が多少ずれてもこのガイド内に缶が入ればつかむことができる。 #ref(2018a/Member/Areidaaa/Mission3/image7.jpeg) #ref(2018a/Member/Areidaaa/Mission3/image6.jpeg) ↑缶を押し出す部分の稼働状況 押し出す部分も形状を工夫し、缶をまっすぐに押し出せるようにした。 *プログラム [#l19cf8a2] 今回はモータを4つ使用した。NXT1台ではモータを3つしか稼働することができないので、2機のNXTを連動させている。走行に用いる二つのモータを制御するほうを親機、アームの開閉と缶を押し出す機構を動かす2つのモータを動かすほうを子機としてプログラミングを行った **子機 [#meceb82b] -缶を押すプログラム canpush.nxc task main() {RotateMotor(OUT_B, 30,-60);} -缶を押す機構を引くプログラム canpull.nxc task main() {RotateMotor(OUT_B, 30,60);} -缶を掴むプログラム cancatch.nxc task main () {RotateMotor(OUT_A, 30, 175);}//缶キャッチ -缶を掴む機構を開放するプログラム canrelease.nxc task main() {RotateMotor(OUT_A, 30, -173);//缶開放 } これらの子機のプログラムは親機からの指令で稼働する。缶を押す機構の角度調整には苦労した。 **親機 [#kc50f31d] #define CONN 1 // slave num #define CM (820/35) // rotate tacho / forward CM void FWD(int x) { RotateMotorEx(OUT_AB, 60, x * CM, 0, true, true); } void turnR(int x) { RotateMotorEx(OUT_AB, 60, x * 215 / 100, 100, true, true); } void turnL(int x) { RotateMotorEx(OUT_AB, 60, x * 215 / 100, 100, true, true); } void turnL90() { RotateMotorEx(OUT_AB, 60, -125, 100, true, true); } void turnR90() { RotateMotorEx(OUT_AB, 60, 125, -100, true, true); } void turnR45() { RotateMotorEx(OUT_AB, 60, 70, -100, true, true); } task main() { until (BluetoothStatus(CONN) == NO_ERR);//子機と接続 RemoteStartProgram(CONN, "canrelease.rxe");//アームを開放 FWD(20); Wait(100); turnR90(); Wait(100); FWD(23); Wait(100); //半径の大きい円のそばまで移動 RemoteStartProgram(CONN, "cancatch.rxe");//缶を掴む Wait(3000); FWD(30); Wait(100); //半径が小さいほうの円のそばまで移動 RemoteStartProgram(CONN, "canpush.rxe");//1段目の缶を押し出す Wait(2000); FWD(-10); turnR90(); Wait(100); turnR90(); Wait(100); //向きを反転 RemoteStartProgram(CONN, "canpull.rxe");//2段目の缶を接地 Wait(2000); RemoteStartProgram(CONN, "canpush.rxe");//2段めの缶を押し出す Wait(2000); Wait(100); turnR90(); Wait(100); turnR90(); Wait(100); turnR90(); Wait(100); FWD(10); //半径の小さいほうの円のそばまで移動 RemoteStartProgram(CONN, "canpull.rxe");//3段目の缶を接地 Wait(2000); RemoteStartProgram(CONN, "canpush.rxe");//3段目の缶を押し出す Wait(2000); } 親機のプログラムがRemoteStartProgramのところまで進むと子機がそこに書かれたプログラムを動かす。 缶を開放するとその上に載っていた缶は押し出す機構の上に乗っかるので、その状態で場所を移動することで缶を安定した姿勢で保持したまま場所を移ることができた。 走行に関する制御は時間ではなく進む長さでプログラムした。これにより電池の消耗に関係なく思いどおりの走行が実現できた。旋回の部分のプログラムの微調整には苦労した(思い通りに曲がってくれない)。 *反省 [#o81bbc3f] -2つある缶のタワーのうち1つしか処理できなかった。 -最初に缶をつかむときにセンサーを使いたかった。 時間があればぜひ上記の二つはやりたかった。とくにセンサーを使った缶の位置検出は実現すれば動作の成功確率がかなりあがると考えられるうえ、準備工事までしていたのでとても悔やまれる。