[[2013b/Member]]
*課題2 [#gde868f5]
**課題のポイント [#h7f5fefb]
#ref(2013b/Member/trtr/Mission2/robocon2013b.png,17.4kb,コース)
***缶を運ぶ…ライントレースの技術や運んでいく方法が試される [#ibe08eb6]
***缶を積む…どんな方法で積むか、確実に積むことができるかが試される [#i6742c22]
***二台のロボットを使ってその連携ができているか…一台ずつ動きを分担するか合体させるか、その連携はとれているか試される [#h94ef63e]
**ロボットについて [#t636a00b]
僕達のグループは二台のグループで缶を運ぶ役と缶を積み上げる役に分担した。僕と6638さんは積むロボット、kkさんとmatsuroさんは缶を運ぶロボットを担当した。最初僕たちのロボットが積み上げる作業を全て一体で行う予定だった。でもロボットの変更で缶の押さえつけをもう一体のロボットにしてもらわないといけなくなった。
***試作品について[#e927d353]
今回の課題で積み上げを行うロボットを作る際に一番の壁はモータの数でした。4つのモーターが必要なのに3つしか使えなかったのでどこかにDFを使い、二つの動作を一つのモータで動かす必要がありました。僕たちははじめアームの開閉と上下運動をDFを使えば一つのモーターでできると思いました。仕組みは�い鬟癲璽拭爾撚鵑鍬△�DFに動力が伝わり小さな歯車が�,鉢�に動力が伝わる。�,魯◆璽爐粒�閉��はアームの上下運動を行う。そして�,離◆璽爐�ストッパーまで行くと��のほうだけが回転する。こういう仕組みでアームの開閉運動と上下運動を行おうとしていた。しかしアームが重くてうまく回らないためこの案は没になった。このことで最高でもふたつ缶を積み上げることしかできなくなってしまった。
#ref(2013b/Member/trtr/Mission2/写真6.JPG,32KB,robot6)
***ロボコン当日のロボット [#h8112edb]
ロボットの全体図。
#ref(2013b/Member/trtr/Mission2/写真.JPG,104kb,robot1)
横のアームで缶を挟みながらロボットの背中の部分にあるタイヤで缶を上にあげる。そしてゴールから離れるときアームを開き缶を離す。
#ref(2013b/Member/trtr/Mission2/写真 3.JPG,104kb,robot2)
駆動輪の部分。DFとストッパーを使い左輪の後ろ回転を止めることで前進と後ろ右回りのみの動きになった。しかしこの右回転がうまく動作しなかった。原因としては四輪のため回転するときに動かないタイヤが摩擦を大きくしてしまったこと、タイヤのトルクを考えたギヤの付け方ができなかったことだと思う。
#ref(2013b/Member/trtr/Mission2/写真 4.JPG,116kb,robot3)
ここからが缶を運ぶロボット。写真だけ載せておくが詳細は下記のURLを見てほしい。担当の二人のページです。
[http://yakushi.shinshu-u.ac.jp/robotics/?2013b%2FMember%2Fmatsuro%2FMission2]
[http://yakushi.shinshu-u.ac.jp/robotics/?2013b%2FMember%2Fkk%2FMission2]
#ref(2013b/Member/trtr/Mission2/写真 5.JPG,160kb,robot4)
#ref(2013b/Member/trtr/Mission2/bou2.JPG,88kb,robot5)
**プログラムについて [#m9cfc359]
***缶を積み上げるロボット [#z08f6162]
#define HP 3
#define LP 0
#define THRESHOLD 36//ライントレース用閾値
#define turn_right1 OnFwd(OUT_A);//右折マクロ
#define go_forward OnFwd(OUT_AC);//直進マクロ
#define turn_left1 OnFwd(OUT_C);//左折マクロ
#define TIME_TRACE1 3//トレースの1回の判断で待つ時間
#define TIME_TRACE2 500//下記「//4.〜5.」で本体を90度回転させる地点を指定する値
#define NB_COUNT 4//交差点識別用の黒の回数を数える値
#define MESSSAGE_CAN 11//缶が運ばれてきたことを判断するため通信で送る値
缶を積むサブルーチン
sub stack_can() {
OnRev(OUT_B);
*/このサブルーチンを走らせる前ではアームユニットは上がっているため
ユニットを降下させつつアームを開く/*
Wait(120);
Off(OUT_B);
OnFwd(OUT_B);//缶をつかみつつ持ち上げる
Wait(120);
Off(OUT_B);
}
}
プログラム本体
task main()
{
SetSensor(SENSOR_2,SENSOR_LIGHT);
int nbk=0//閾値以下となった回数をカウントする変数
int ncros=0//交差点の回数をカウントする変数
SetPower(OUT_AB,LP);
SetPower(OUT_C,HP);
//1.黒線に当たるまで前進
OnFwd(OUT_AC);
until (SENSOR_2>=THRESHOLD);
//2.左折しライントレース
turn_left1;OnRev(OUT_A);
Wait(80);//90度旋回
ClearTimer(0);
while(ncros=0){//交差点を通過するまでライントレース(この時コース上の缶はコの字型のシャーシの中に入る)
while(nbk<NB_COUNT){
if(SENSOR_2<THRESHOLD-3){turn_left1;nbk++;}
else if(SENSOR_2<THRESHOLD+3){OnFwd(OUT_AC);nbk=0;}
else{turn_right1;nbk=0;}
Wait(TIME_TRACE1);
}
Off(OUT_AC);
turn_left1;
Wait(nbk*TIME_TRACE1);
}
//3.交差点を通過後缶を掴んで持ち上げる
OnFwd(OUT_B);
Wait(120);
Off(OUT_B);
//4.タイマーをリセットし適当な地点につくまでライントレース
ClearTimer(0);
while(FastTimer(0)<TIME_TRACE2){//1
if(SENSOR_2<THRESHOLD-3){turn_left1;}
else if(SENSOR_2<THRESHOLD+3){OnFwd(OUT_AC);}
else{turn_right1;}
Wait(TIME_TRACE1);
}//1
//5.90度右旋回し半円の中央にある缶を回収する
turn_right1;Wait(80);//90度右旋回
OnFwd(OUT_AC);
repeat(2){
until(SENSOR_2<THRESHOLD);
until(SENSOR_2>THRESHOLD);
}//ラインを2回またぐ
Off(OUT_AC);
stackile_can();//缶を積む
turn_right1;Wait(90);//90度+a旋回
//6.ゴール直前の交差点までライントレース
ncros=0;
while(ncros<2){//1
while(nbk<NB_COUNT){//2
if(SENSOR_2<THRESHOLD-3){turn_left1;nbk++;}
else if(SENSOR_2<THRESHOLD+3){OnFwd(OUT_AC);}
else{turn_right1;}
Wait(TIME_TRACE1);
}//2
Wait(50);
turn_right1;Wait(NB_COUNT*TIME_TRACE1);
nbk=0;
ncros++;;
}//1
//7.ゴール中央へ移動し待機
turn_left1;Wait(NB_COUNT*TIME_TRACE1/2);
OnFwd(OUT_C);OnRev(OUT_A);Wait(40);//90度左旋回
go_forward;Wait(60);
OnRev(OUT_A);Wait(120);//135度左旋回
//8.通信をして缶を回収し積み上げる動作を繰り返す
ClearMessage();
repeat(2){
until(Message()==MESSAGE_CAN);
stackile can();
ClearMessage();
}
//9.缶を置いてゴールから出る
OnRev(OUT_B);
Wait(120);
Off(OUT_B);
OnRev(OUT_AC);
Wait(400)
Off(OUT_AC);
}
***改正版 [#h7f70a7d]
****関数 [#w22e7054]
#define HP 7
#define LP 2
#define THRESHOLD 36//ライントレース用閾値
#define turn_right1 OnFwd(OUT_A);
#define go_forward OnRev(OUT_A);
#define TIME_TRACE1 3//トレースの1回の判断で待つ時間
#define TIME_TRACE2 500//「4」で本体を90度回転させる地点を指定する値
#define NB_COUNT 4//交差点識別用の値
#define STACK 11//
某コンビニの入店音
task play_music()
{
PlayTone(740,28);Wait(5);
PlayTone(587,28);Wait(5);
PlayTone(440,28);Wait(5);
PlayTone(587,28);Wait(5);
PlayTone(659,28);Wait(5);
PlayTone(880,61);Wait(5);
PlayTone(440,28);Wait(5);
PlayTone(659,28);Wait(5);
PlayTone(740,28);Wait(5);
PlayTone(659,28);Wait(5);
PlayTone(440,28);Wait(5);
PlayTone(587,80);
}
****プログラムの本体 [#g03f46f4]
task main()
{
SetSensor(SENSOR_2,SENSOR_LIGHT);
SetPower(OUT_A,HP);
int nbk=0;
int ncros=0;
1.黒線に当たるまで前進
OnRev(OUT_A);
until (SENSOR_2<=THRESHOLD);
2.左折しライントレース
turn_right1;
Wait(400);
ClearTimer(0);
while(FastTimer(0)<=1000){
if(SENSOR_2<THRESHOLD){go_forward;}
else{turn_right1;}
Wait(TIME_TRACE1);
}
//缶積み
start play_music;
SetPower(OUT_BC,2);
OnFwd(OUT_B);Wait(68);Off(OUT_B);
stop play_music;
while(ncros<2){//1
while(nbk<NB_COUNT){//2
if(SENSOR_2<THRESHOLD){go_forward;nbk++;}
else{turn_right1;nbk=0;}
Wait(TIME_TRACE1);
}//2
Wait(50);
turn_right1;Wait(NB_COUNT*TIME_TRACE1);
nbk=0;
ncros++;
go_forward;Wait(60);
}//1
while(nbk<NB_COUNT){//1
if(SENSOR_2<THRESHOLD){go_forward;nbk++;}
else{turn_right1;nbk=0;}
Wait(TIME_TRACE1);
}//1
turn_right1;Wait(350);
go_forward;Wait(200);
turn_right1;Wait(170);
until(Message()==STACK);
start play_music;
OnFwd(OUT_C);Wait(1000);
OnRev(OUT_B);Wait(68);Off(OUT_BC);
stop play_music;
turn_right1;Wait(350);Off(OUT_A);
ClearMessage();
repeat(2){
until(Message()==STACK);
OnFwd(OUT_B);Wait(68);Off(OUT_B);
ClearMessage();
until(Message()==STACK);
OnFwd(OUT_C);Wait(1000);
OnRev(OUT_B);Wait(68);Off(OUT_BC);
turn_right1;Wait(350);Off(OUT_A);
ClearMessage();
}
OnRev(OUT_A);
Wait(170);
go_forward;
Wait(600);
Off(OUT_A);
}
***缶を運ぶロボット [#k60cc7cf]
•定義文
#define WHITE 46//白の値
#define BLACK 40//黒(ライン上)の値
//境界の値は上の二つから+、-をもちいて作っています。
#define CATCH 44 //缶をつかんだ時の光センサー3の値
#define power SetPower(OUT_AC,1);//モーターの出力を7段階中の1にする 定義です。
#define go_forward power;OnFwd(OUT_AC);//パワーを抑えた前進
#define go_back power;OnRev(OUT_AC);//パワーを抑えた後退
#define LEFT power;OnRev(OUT_A);OnFwd(OUT_C); //パワーを抑えた左その場旋回
#define left power;Off(OUT_A);OnFwd(OUT_C); //パワーを抑えた左回り
#define RIGHT power;OnFwd(OUT_A);OnRev(OUT_C); //パワーを抑えた右その場旋回
#define right power;OnFwd(OUT_A);Off(OUT_C); //パワーを抑えた右回り
#define PUSH power;OnRev(OUT_B);Wait(3);Off(OUT_B);Wait(20);
//缶を押し出す動作です。モーターの向きからOnRevで棒が飛び出し、OnFwdで戻ります。Floatで 優しく仕舞います。
•サブルーチン
ライントレース(右側)
sub trace1_R(){
if (SENSOR_1 < BLACK){
RIGHT;
} else if (SENSOR_1 < BLACK +2){ //黒寄りの境界の値
right;
} else if (SENSOR_1 > WHITE -2){ //白寄りの境界の値
left;
} else if (SENSOR_1 > WHITE){
LEFT;
}
}
ライントレース(左側)
sub trace1_L(){
if (SENSOR_1 < BLACK){
LEFT;
} else if (SENSOR_1 < BLACK +2){
left;
} else if (SENSOR_1 > WHITE -2){
right;
} else if (SENSOR_1 > WHITE){
RIGHT;
}
}
交差点を判断するライントレース(右側)
sub trace2_R(){
while (FastTimer(0) < 25){ //交差点と判断するまでの時間です。
if (SENSOR_1 < BLACK){
RIGHT;
}else if (SENSOR_1 < BLACK +2){
ClearTimer(0);
right;
}else if (SENSOR_1 > WHITE -2){
ClearTimer(0);
left;
}else if (SENSOR_1 > WHITE){
ClearTimer(0);
LEFT;
}else{
ClearTimer(0);
go_forward;
}
}
if(FastTimer(0) >= 25){ //交差点での動作です。
ClearTimer(0);
LEFT;
Wait(40);
go_forward;
Wait(20);
Off(OUT_AC);
ClearTimer(0);
}
}
交差点を判断するライントレース(左側)
sub trace2_L(){
while (FastTimer(0) < 25){
if (SENSOR_1 < BLACK){
LEFT;
}else if (SENSOR_1 < BLACK +2){
ClearTimer(0);
left;
}else if (SENSOR_1 > WHITE -2){
ClearTimer(0);
right;
}else if (SENSOR_1 > WHITE){
ClearTimer(0);
RIGHT;
}else{
ClearTimer(0);
go_forward;
}
}
if(FastTimer(0) >= 25){
ClearTimer(0);
RIGHT;
Wait(40);
go_forward;
Wait(20);
Off(OUT_AC);
ClearTimer(0);
}
}
缶の受け渡し(右側トレース時)
sub trace3_R(){
while (FastTimer(0) < 25){
if (SENSOR_1 < BLACK){
RIGHT;
}else if (SENSOR_1 < BLACK +2){
ClearTimer(0);
right;
}else if (SENSOR_1 > WHITE -2){
ClearTimer(0);
left;
}else if (SENSOR_1 > WHITE){
ClearTimer(0);
LEFT;
}else{
ClearTimer(0);
go_forward;
}
}
if(FastTimer(0) >= 25){
go_forward;
Wait(10);
LEFT;
Wait(70);
Off(OUT_AC);
Wait(100);
PUSH;
go_back; //ハサミの接触を避けるため
Wait(100);
Off(OUT_AC);
ClearTimer(0);
}
}
缶の受け渡し(左側)
sub trace3_L(){
while (FastTimer(0) < 25){
if (SENSOR_1 < BLACK){
LEFT;
}else if (SENSOR_1 < BLACK +2){
ClearTimer(0);
left;
}else if (SENSOR_1 > WHITE -2){
ClearTimer(0);
right;
}else if (SENSOR_1 > WHITE){
ClearTimer(0);
RIGHT;
}else{
ClearTimer(0);
go_forward;
}
}
if(FastTimer(0) >= 25){
RIGHT;
Wait(70);
Off(OUT_AC);
PUSH;
go_back;
Wait(50);
Off(OUT_AC);
ClearTimer(0);
}
}
メインタスク
task main()
{
SetSensor(SENSOR_1, SENSOR_LIGHT);
SetSensor(SENSOR_3, SENSOR_LIGHT);
ClearTimer(0);
int n=0;
while(n==0){
Wait(100); //相手を待つ時間
until(SENSOR_1 < BLACK){ //黒になるまで直進、ラインを感知してトレースを開始します。
go_forward;}
Off(OUT_AC);
Wait(100);
go_back; //感知から動作までに進んでしまった分戻ります。
Wait(15);
Off(OUT_AC);
Wait(30);
n++;
}
while(n==1){
if (SENSOR_3 > CATCH){
PlaySound(SOUND_UP); //缶をつかんだ合図
ClearTimer(0);
until(FastTimer(0) > 500){ //�,播呂覦銘屬泙任了�間です。
trace1_R();}
LEFT; //�,播呂襪箸�の動作です。
Wait(55);
go_forward;
Wait(20);
until(SENSOR_1 < BLACK){
go_forward;}
ClearTimer(0);
until(FastTimer(0) > 500){ //�,鯏呂蟒�えてからのトレース
trace1_R();}
ClearTimer(0);
trace3_R();
n++;
} else if (SENSOR_1 < BLACK){
RIGHT;
} else if (SENSOR_1 < BLACK +2){
right;
} else if (SENSOR_1 > WHITE -2){
left;
} else if (SENSOR_1 > WHITE){
LEFT;
}
}
while(n==2){ //二つ目の缶を運ぶプログラムです。
RIGHT;
Wait(40);
go_forward;
Wait(150);
until(SENSOR_1 < BLACK){
right;}
if (SENSOR_3 > CATCH){
until(SENSOR_1 < BLACK){
LEFT;}
ClearTimer(0);
trace3_L();
n++;
} else if (SENSOR_1 < BLACK){
LEFT;
} else if (SENSOR_1 < BLACK +2){
left;
} else if (SENSOR_1 > WHITE -2){
right;
} else if (SENSOR_1 > WHITE){
RIGHT;
}
}
}
**反省 [#g0c01249]
今回の課題は結果からいうととてもよかったものとは言えない。特に僕が担当したロボットの積み上げのロボットがうまく機能しなかったがためにロボコンもうまくいかなかった。反省点は多々あるが特にロボットの組み立てが最後の最後までうまくいかず最終の形にしたのも本番直前だっだことが問題だった。ギアのトルクに関してや三輪を導入すればよかったことなどはもう少し早くロボットの形が定まっていれば思いついたことだと思う。本当に他のメンバーには迷惑をかけてしまった。でもこの授業を受けてプログラミングに関しての知識、ロボットを組み立てる(まあ今回はレゴだが…(笑))楽しさを知れてよかった。今更ながら後悔しているのは機械システム工学科に所属していながら、その知識を生かせなかったことだ。まだ専門科目はあまり受けていないが材料力学、機構学などの知識は生かすことができるはずなのに時間をあまり費やさなかったために充分に生かせなかった。だからつぎこういう機会があったら習ったことを試しながらやりたいと思う。