目次
・ボールを離れた場所から缶に当てるロボットとボールを回収するロボット
左図が作成するコースです。右図が使用した全体図です。
私はボールを回収するロボットを作成しました。
◦競技時間はロボットAがSTART A地点のスタートラインを横切って、ロボットBがGOAL B地点のゴールラインに達するまで、あるいは審判が続行不能と判断するまで。
◦ロボットAはSTART A地点から出発し、P地点におかれた赤いボールを拾って350mlのアルミ缶に当てる。その後、ロボットBがボールを回収する。引き続き青いボールについても同様の動作を繰り返す。ロボットBはボールを回収した後、最終的にGOAL Bまでボールを運ぶ。
◦アルミ缶は中身が入っているものを使う。
◦RISのチームはアルミ缶の上に灯台としてランタンを置く。
◦ボールがアルミ缶に当たる前にロボットBがボールに触ってはいけない。
◦ロボットAはセンターラインを超えては行けない。
◦アルミ缶を5cm以上動かした場合は減点
1:缶の位置を測定
2:通信ができないため相手がボールを缶にあてるまでの時間あらかじめ計測し、その時間は止まる。
3-1:同じ場所からもう一度測定し、距離が近くなっていればそれがボールとなる。それを掴みゴールに持っていく
3-2:同じ距離ならボールは缶より奥にあるため缶の真横より後ろに移動する。
4:缶より後ろにいるため測定で一番近いのがボールとなる。それを掴みゴールに持っていく
時間が足りず、2つ目を回収するプログラムは無理でした。
下の写真が全体像です。説明は同じ班のものを引用します。
リンク:http://yakushi.shinshu-u.ac.jp/robotics/?2015b%2FMember%2FfujiTaka%2FMission3
今回使ったモーターは3つ。車輪部分に2つとアームを動かすのに1つ。出来ればアーム部分をボールをつかむ動作と投げる動作に分け、それぞれに1つずつモーターを使いたかったが、旋回などを行うためにどうしても車輪部分に2つのモーターが必要だったため断念した。なので、ロボット制作の中ではボールをつかむ動作と投げる動作をどうやって1つのモーターで行うかに1番悩んだ。また、使った光センサーは2つで、それぞれライントレースとランプの方向を探すのに使った。
アーム部分で大量に棒などを固定するためのパーツが必要となったために、土台部分は出来るだけそれらの部品を使わないようにつくった。しかし、ボールを乗せる土台を付けた他はほとんどドライブベースと同じである。
ボールをつかんだり、投げたりする部分である。制作初期の段階ではボールを乗せる土台に坂を作り、アームで抑え込んでいたボールを離すと自動的にボールが前に転がっていくというものを想定していた。しかし、完成したロボットを実際に動かしてみると、ボールが転がる勢いがなさ過ぎて真っ直ぐ転がらない、紙の折り目によっては戻ってきてしまうという問題があった。そこで、ボールを抑えつける部分の後ろに新たに部品を付けることによって、アームが持ち上がると新たに付けた部品がボールを押し出すようにした。これにより、ボールの勢いの問題は解消され、強くまっすぐにボールを投げられるようになった。ただし、新たに取り付けた部品より後ろ側にボールがあると、新たな部品がボールを抑え込んでしまうため拾える範囲は多少狭まったが、そこはプログラムを正確にすることでなんとかなった。また、そのままモーターにアームを接続するとアームの上げ下げが早くなりすぎてしまうため、4つの歯車を挟み勢いを弱めている。
ライントレースのための光センサーはボールを乗せる土台に付いている。ランプの方向を探すための光センサーはとても高いところに付いているが、これはランプの高さに合わせた結果である。実験段階ではランプを缶の上に乗せていなかったためそのままアームに付けていた。しかし、缶の上に乗せてみたところ光センサーがほとんど反応せず、無理やり高さをつけたことでこのようなこととなった。光センサーを部品で囲っているのは、正面の光のみを感知し、より正確にランプの方向を知るためである。
赤い丸が付いているモータを回すことで、アームが矢印の方向に動きボールをつかむことができます。
黄色い丸が超音波センサです。これを使うことにより、距離を測定することができます。ボールか否かの判断はプログラムで行います。
センサが低い位置についている理由は、今回の目標物(ボール)が小さいため高い位置だと判断できないからです。
黄色い丸が光センサです。ボールを回収後ライントレースをしてゴールに向かいます。
#define SPEED 50 //高速度 #define SPEED_SLOW 45 //低速度 #define go(d) RotateMotorEx(OUT_BC,45,d,0,false,true);reset; //サーボモータでの前進 #define right(d) RotateMotor(OUT_C,45,d);reset; //サーボモータでの右回転 #define left(d) RotateMotor(OUT_B,50,d);reset; //サーボモータでの左回転 #define reset ResetTachoCount(OUT_BC); //モータの回転角のリセット #define off Off(OUT_BC); //平面移動の停止 #define catch(p) RotateMotor(OUT_A,p,45); //アームの操作 #define go2(p) Off(OUT_BC);OnFwd(OUT_BC,p); //前進 #define right2(p,P) Off(OUT_BC);OnFwd(OUT_C,p);OnFwd(OUT_B,P); //右回転 #define left2(p,P) Off(OUT_BC);OnFwd(OUT_B,p);OnFwd(OUT_C,P); //左回転 #define THE 53 //光センサで使う中間値 #define tmax 115 //交差点判断で使用
const float diameter=5.45; //タイヤの直径[cm] const float track=10.35; //タイヤのトレッド幅[cm] const float pi=3.1415; //円周率
・距離d[cm]前進
void fwdDist(float d){ long angle; angle=d/(diameter*pi)*360.0; //角度計算 RotateMotorEx(OUT_BC,SPEED_SLOW,angle,0,true,true); //サーボモータでの前進 }
・角度ang度の時計回りの旋回
void turnAng(long ang){ long angle; angle=track/diameter*ang; //角度計算 RotateMotorEx(OUT_BC,SPEED_SLOW,angle,100,true,true); //サーボモータでの回転 }
・自身の周囲ang度の範囲を調べ障害物までの距離を返す
int searchDirection(long ang){ long angle,tacho_min=0,tacho_corr; int d_min=300; //仮の最小値 angle=(track/diameter)*ang; //旋回角度からタイヤの回転を計算 turnAng(ang/2); //指定された角度からの半分を旋回 ResetTachoCount(OUT_BC); //角度計測をリセット OnFwdSync(OUT_BC,SPEED_SLOW,-100); //反時計回りに旋回 while(MotorTachoCount(OUT_B)<=angle){ //自身の周囲ang度の範囲を調べる if(SensorUS(S4)<d_min){ //最小値を更新 d_min=SensorUS(S4); tacho_min=MotorTachoCount(OUT_B); } } OnFwdSyncEx(OUT_BC,SPEED_SLOW,100,RESET_NONE); until(MotorTachoCount(OUT_B)<=tacho_min||SensorUS(S4)<=d_min); Wait(180); //微調整 Off(OUT_BC);Wait(500); return d_min; //戻り値 }
・以下はメインプログラム
task main(){ SetSensorLowspeed(S4); //超音波センサ SetSensorLight(S1); //光センサ go2(50); //前進 Wait(1500);off; catch(30); //アームを開く int d=searchDirection(450); //缶の位置を測定 Wait(65000); //通信ができないためプログラムで停止 int d2=searchDirection(450); //距離の変化を調べる
缶かボールかを判断
if(d2<d){ //缶よりボールが近い場合 d=d2; searchDirection(450); //ボールの方向を向く fwdDist(d-10.0);catch(-70); //近づきボールをつかむ left(360);go(950); //ライントレースのためにコースに出る } else { //缶よりボールが遠い場合 reset; left(400); //缶の左に移動する Wait(500); go(700); Wait(500); right(450); go(650); int d3=searchDirection(450); //缶の横からボールを調べる d=d3; fwdDist(d-10.0); //ボールに近づく catch(-70); left(850);go(100); //ライントレースのためにコースに出る }
ライントレース
long t0=0; t0=CurrentTick(); //時間 while(CurrentTick()-t0<tmax){ //ゴールで交差点判断をするので交差点判断をしたらゴール if(SENSOR_1<THE){ //黒の場合 if(SENSOR_1>35){ //白よりの黒の場合 left2(45,10); t0=CurrentTick(); //交差点でないため時間(t0)を初期化 } else if(SENSOR_1<35){ //最も黒い場合 left2(35,-40); } } else if(SENSOR_1>THE){ //白の場合 if(SENSOR_1<65){ //黒よりの白の場合 right2(45,10); t0=CurrentTick(); } else if(SENSOR_1>65){ //最も白い場合 right2(40,-40); t0=CurrentTick(); } else{ go2(50);t0=CurrentTick(); //中間値の場合 } } } right(80); //交差点判断で少し左向きになるため修正 }
今回は大きいもの(缶)と小さいもの(ボール)の2種類を判断しなければなりません。その為、超音波センサが高い位置では使えないため低い位置に取り付けました。縦でなく横なのは、縦ではボールを判断できない時があるからです。
私のプログラムは、まず缶より手前にボールがあるかを調べます。ここでボールがないとなると缶より奥もしくは、缶より遠くにあることになります。何回か練習で試したところ、缶の近くで止まることがわかりました。その為ボールは缶の奥にあるということになります。ボールが缶の奥にあるときはボールを正面からはみつけられないため、缶の真横より後ろに回り込むようにすることでボールを感知できるようにプログラムしました。
今回は班の人がみんないなくなったため別の班と組むことになりました。 異なる機器を使用したため連携がうまくいかないことがありました。
プログラムはテスト期間と重なったためあまり時間が取れなかったことと、ペアの人がいないため一人で作らなければならずよいプログラムを作ることができませんでした。
ロボットを他の班のように面白いアイデアで作ることができればプログラムをもっと簡略化できると思いました。
本番ではボールを一度もゴールに持って行けませんでした。 原因としては、作成に時間をあまりかけることができなかったことと、一人のためアイデアの量が少なかったことだと思います。
他の班のように面白いアイデアを思いつくように、もっとゆとりをもって行うようにしていきたいです。