- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2020-02-13T13:33:00+09:00","sumi","sumi")
#author("2020-02-15T23:09:28+09:00","sumi","sumi")
目次
#contents
[[2019b/Member]]
*課題3 [#cf9550fe]
[[2019b/Mission3]]を参照
自分たちの班はC>E>Fとボールをとり、F`>E`>C`とボールを置こうとした
*ロボットの説明 [#td67ecdc]
#ref(2019b/Member/sumi/Mission3/3_robot_all.jpg,50%,本体)
今回の課題では、前回の課題で得られたすべての機構はロボットの進行方向と同一にしたほうが正確性が高いというのをもとに、アーム、レーン、センサーのすべてを進行方向に設置した。
コントロールユニットは2つ使用しており、片方がライントレース用、もう片方がボールの確保と設置用となっている。お互いに通信させている。
**ボールを確保する機構 [#b854d808]
#ref(2019b/Member/sumi/Mission3/catch.jpg,50%,ロボットレーン)
これが今回ボールを確保する機構である。今回の課題では空き缶の上においてあるボールを確保する必要があった。そこで出る問題は、空き缶の軽さである。これによって、ボールを水平方向から確保するには抑えのような機構が必要になる。しかし、それでは必要になる機構が多くなってしまうので結果としてボールに対して鉛直方向からの力での確保が必須と考えたのでこの形となった。この機構は、レーンの下に輪ゴムを使ってボールを支えることで、ボールの自重では下に落ちず、ロボットの力で落とすことができるようになっている。
**ボールを空き缶の上に設置する機構 [#qf1aed33]
#ref(2019b/Member/sumi/Mission3/set.jpg,100%,ロボットアーム)
ボールをキャッチする機構をそのまま缶の上に押さえつけ、、その上にある機構の出っ張りによりボールが一つずつ出てくるようになっている。
#ref(2019b/Member/sumi/Mission3/set2.jpg,100%,ロボットアーム2)
このアームには、直接ボールを掴むなどの機構などはなく先ほど説明したレーンとの組み合わせによりボールを缶の上に置くようになっている。具体的には、レーンの上のボールの下に缶があればアームでボールを上から押さえつけ、その状態でレーンを上げることによってボールを設置するという輪ゴムの性質を活かした機構となっている。
**ライントレースについて [#r7d9bd2a]
#ref(2019b/Member/sumi/Mission3/raintresu.jpg,100%,ロボット目)
今回のライントレースでは、光センサーを2つ使用して首振りによる確保したボールの落下を防いで、正確性を向上させた。
**超音波センサーについて [#rcc4a8a1]
#ref(2019b/Member/sumi/Mission3/3_sensor_us.jpg,100%,ロボット目)
前々から薄々きづいていたのだがこの超音波センサーの精度はお世辞にも良いものとは言えない。そこで今回は缶とボールに対して鉛直方向から観測することで、缶とボールがそこに存在するかどうかについての判断をさせた。
*プログラムについて [#t2a941ee]
今回、自分はプログラムの作成が本番に間に合わなかった。そこで、本番に使用したプログラミングをを載せておく。
**レース開始前のプログラムについて [#yf2084bc]
今回の課題では2つのコントロールユニットを使用するので完全に通信してしているかや、正確性(超音波センサー、アームやレーンの初期位置など)の確保のためのプログラムを作成した。
***通信が正常かどうかの確認 [#w8e7911f]
void m_con(){//接続
int x;
while(x!=4){
ReceiveRemoteNumber(MAILBOX1,false,x);
}
PlayTone(700,200);
}
これはマスター側のプログラムで、これを押してスレイブからの反応があれば音がなるようになっている。
#define con 4
void s_con(){//接続
SendResponseNumber(MAILBOX1,con);PlayTone(700,200);
}
返す番号は4でこれをマスターの1のメールボックスにかえす。これにより接続が完了しているか否かについて知ることができる。
***アームやレーンの初期位置の固定化 [#f081cbb6]
void reset(){//初期位置
ResetTachoCount(OUT_BC);
OnFwd(OUT_B,20);Wait(800);
OnFwd(OUT_C,45);Wait(1200);
RotateMotor(OUT_B,-20,10);
OnFwd(OUT_C,-20);Wait(1700);
OnFwd(OUT_B,-20);Wait(400);
Off(OUT_BC);
}
これによって、アームやレーンのセッティングのし忘れが起きたときのリスクをなくしている。
アーム、レーンをともに最初に目一杯後ろにそらしたあと、その療法を適切な位置に前方方向に倒している。
**ライントレースについて [#tb6ef1fe]
#define st 2
#define t 52
#define sp 40
int y;
void gf (long x,long y){
OnFwd(OUT_B,x);OnFwd(OUT_C,y);
}
void line_trace(long t_min) {//止まる命令が来るまでライントレース
SetSensorLight(S1);
SetSensorLight(S2);
long t_start=CurrentTick();PlayTone(700,200);
while(y!=st){
ReceiveRemoteNumber(MAILBOX1,true,y);
if(SENSOR_1<t-7){
if(SENSOR_2<t-7){
if((CurrentTick()-t_start)<t_min){gf(sp,sp);}
else{break;}
}
else if(SENSOR_2<t+7){
gf(0,sp);
}
else {
gf(-sp,sp);
}
}//if1
else if(SENSOR_1<t+7){
if(SENSOR_2<t-7){
gf(sp,0);
}
else if(SENSOR_2<t+7){
gf(sp,sp);
}
else {
gf(0,sp);
}
}//if2
else{
if(SENSOR_2<t-7){
gf(sp,-sp);
}
else if(SENSOR_2<t+7){
gf(sp,sp);
}
else {
gf(sp,sp);
}
}//if3
}//while
gf(0,0);
PlayTone(1400,200);
} //trace
これが本番で使用したライントレースである。これは自分が作成しようとしていた比例制御を用いたものではなく、課題2のときに培われたノウハウを用いて作成している。課題2のときとは違い、センサーが2つあることによりさらに細かな判断を行うようになっている。右のセンサーに対して3つの、更に左のセンサーに対しても3つの合計3✕3の9つの判断を行うようにしている。
交差点前の時間計測を無視するために引数としてt_minを用いている。これはスレイブ側のプログラムなので、マスターからのgoの指示で動き、stopの指示で停止するようにしている。
**超音波センサーの仕様と設定 [#vfaeb502]
#define go 1
#define st 2
void observe(){
int c=0;
long sum=0;
float a;
SendRemoteNumber(1,MAILBOX1,go);//go命令
SetSensorLowspeed(S4);
while(c!=10){
sum=sum+SensorUS(S4);
c=c+1;
}
a=sum/10;//十回平均
while(SensorUS(S4)>0.5*a){
}//while
SendRemoteNumber(1,MAILBOX1,st);//stop命令
}//void
今回は、超音波センサーの仕様にあたって一つの懸念があった。それはセンサーの制度の問題である。
そこで今回は、超音波センサーの値は平均をとり、それを利用してレーン上のボールがあるかどうかの判断を行うようにしている。また、先ほど説明した、スレイブにgoとstopのコマンドを送るかどうかの判断はここで行っており、アームとレーンの初期位置ついての準備が完了すれば、goの1を、超音波センサーの地面との距離が計測し続けていた値の半分付近に達すると、空き缶上のボール、または空き缶を発見したとして、stopの2を送るようにしている。
**スレイブ側のマシンを待機させるプログラム [#ca24ded5]
#define go 1
int y;
void waiting(){
while(y!=go){ReceiveRemoteNumber(MAILBOX1,true,y);}
}
スレイブ側がマスターからのgoの指示が来るまで待つためのものである。
**ボールを失った缶をコースから排除するプログラム [#a1341ef5]
#define sp 40
void move_can(){
OnFwdSync(OUT_BC,sp,0);Wait(3500);
OnFwdSync(OUT_BC,-sp,0);Wait(2900);
}
ボールをとった以降にコース上にある缶ははっきり言って邪魔である。そこで、ライントレースをする前にその邪魔な缶を排除するためのプログラムがこれである。
**缶の上にボールを設置するプログラム [#me971e93]
#define spd 30
#define go 1
void put_ball(){
OnFwd(OUT_B,spd);Wait(1000);//キャッチ機構を後ろに傾ける
OnFwd(OUT_C,2 * spd);//アーム機構を後ろへ
RotateMotor(OUT_B,4 * spd,-5);Wait(8000);//キャッチを少し前え倒し、この反動でボールの引っ掛かりをなくす
Off(OUT_BC);
RotateMotor(OUT_B,spd,-120);Wait(600);//空き缶の上にキャッチ機構をセット
RotateMotor(OUT_C,spd,-65);Wait(400);//ボールを突く
RotateMotor(OUT_B,spd + 10,50);Wait(500);//アームでボールを抑えたままキャッチ機構を上げる
OnFwd(OUT_C,2 * spd);Wait(1000);//アーム機構を後ろに倒す
RotateMotor(OUT_B,spd,70);//キャッチの機構も後ろへ
RotateMotor(OUT_C,spd,-40);//アームの機構を前へ
RotateMotor(OUT_B,spd,-30);//キャッチの機構を少し前へ
SendRemoteNumber(1,MAILBOX1,go);//スレイブにgoの指示
}
C`,F`,E`の点上にある缶の上にボールを設置するためのプログラミング
**メインプログラム [#w77d160a]
これがマスター側のメインプログラムである。
#define tt 700//四半回転時間
#define bt 1500//半回転時間
task main(){
m_con();//スレーブとの接続を確認
reset();//アーム、レーンを初期位置にセット
observe();//go命令を出し、C上のボールを観測したらstopの指示を与える
catch();//C地点のボールをつかみ、goの指示を与える
Wait(7000);//C地点の缶の排除の完了まで待機
observe();//goの指示、E上のボールを観測したらstopの指示
catch();//E地点のボールをつかみ、goの指示
Wait(7000);//E地点の缶の排除の完了まで待機
observe();//goの指示、F上のボールを観測したらstopの指示
catch();//F地点のボールをつかみ、goの指示を出す
Wait(7000);//F地点の缶の排除の完了まで待機
SendRemoteNumber(1,MAILBOX1,go);//goの指示
Wait(10000);//少し待つ
observe();//F’地点の缶を観測したらstop指示
put_ball();//F’地点の缶にボールを置く
observe();//E’地点の缶を観測したらstop指示
put_ball();//E’地点の缶にボールを置く
observe();//C’地点の缶を観測したらstop指示
put_ball();//C’地点の缶にボールを置く
}
これはスレイブ側のプログラミングである。
task main(){
s_con();//マスターとの接続を確認
waiting();//go命令待ち
line_trace(10000);//C地点までライントレース
waiting();//マスターがC地点のボールを取りgo指示が来るまで待つ
move_can();//C地点の缶の排除
waiting();//goの指示を待つ
line_trace(20000);//E地点の缶までライントレース
waiting();//マスターがE地点のボールを取りgoの指示が来るまで待つ
move_can();//E地点の缶の排除
waiting();//goの指示を待つ
gf(sp,sp);Wait(400);turn_r();//E地点の缶を排除し、線に戻る
line_trace(8000);//F地点の缶までトレース
waiting();//マスターがF地点のボールを取りgoの指示が来るまで待つ
move_can();//F地点の缶を排除
waiting();//go待ち
gf(sp,sp);Wait(400);turn_r();//F地点の缶を排除後、線に戻る
line_trace(3000);//交差点Gまでライントレース
turn_l();line_trace(1500);//G-H
turn_l();line_trace(1000);//H-H'
turn_r();line_trace(1000);//H'-G'
gf(sp,sp);Wait(300);turn_r();line_trace(5000);//G'-F'
waiting();//マスターがF'地点にボールを置きgoの指示が来るまで待つ
OnFwdSync(OUT_BC,-sp,0);Wait(1000);gf(-sp,sp);Wait(tt);;line_trace(1000);//F'-G'-D'
turn_r();line_trace(1000);//D'-E'
waiting();//マスターがE'地点にボールを置きgoの指示が来るまで待つ
OnFwdSync(OUT_BC,-sp,0);Wait(bt);//E'-D'
gf(sp,sp);Wait(300);gf(sp,-sp);Wait(tt*2);line_trace(10000);//D'-C'
}
*今回の反省点 [#k516037a]
今回の課題ではまず、ロボットをコンパクトにしすぎたことがあげられる。これにより、ロボットの作成途中でパーツに負荷がかかりすぎたことによる破損やモーターの回転が何らかの障害により阻害されるなどの問題が発生した。
また、そのほかにもボールを同時に3つ運ぼうと欲張ったことで、プログラミングの難化、設計にボールをためておく場所の工夫など考慮しなければいけない問題が増えた気がした。ボールを1つづつ運べば、コース取りや正確性に気を使う必要はなかったかもしれない。
*最後に [#ua93159f]
この講義を通して、いかにロボットの制御や設計が難しいか学ぶことができ、それと同時に班員と協力し、一つの大きな課題に向き合うことの楽しさを味わうことができた。紆余曲折はあったが非常に有意義な授業であったと思う。