- 追加された行はこの色です。
- 削除された行はこの色です。
[[2019a/Member]]
目次
#contents
*課題3 [#d5962a7c]
ピンポン玉または青と赤のボールを運搬して、所定の容器の中に入れる。
#ref(2019a/Member/tsukue/Mission3/field.jpg,50%,画像1)
**フィールドの説明 [#sbe3faab]
--フィールドは課題2で使用した紙を使用する。
--生協のお弁当の四角いプラ容器2つをそれぞれ円内に置き、片方に玉を2個入れる。
--残りの2個の玉は課題2と同じ位置に置く。その際、ゴムタイヤやプレートの上に置いてもよい。
--プラ容器には色をつけたり文字や記号を書いてもよい。
--プラ容器は両面テープ等でフィールドに固定してもよい。
--2枚の紙の境界にはそれぞれ幅1cm、合計2cmの黒線を描いてもよい。
**基本ルール [#tb9f413f]
--競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
--図のA地点または(および)A'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域からはみ出していてもよい。
--開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
--競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
--途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。
--競技終了後、ロボットが、ゴールのプラ容器に触れていてはいけない。
--競技終了後、もともと玉が入っていたプラ容器が、ゴールのプラ容器に触れていてはいけない。
詳細は[[こちら:http://yakushi.shinshu-u.ac.jp/robotics/?2019a%2FMission3]]。
*ロボット [#pf42f547]
#ref(2019a/Member/tsukue/Mission3/robot1.jpg,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/robot2.jpg,50%,画像1)
(この画像のみアームの構造が旧型である)
#ref(2019a/Member/tsukue/Mission3/robot3.JPG,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/robot4.jpg,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/robot5.jpg,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/robot6.jpg,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/robot7.jpg,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/robot8.jpg,50%,画像1)
*プログラム [#v09a4685]
**マスター [#v3fd8025]
***定数、マクロ [#ebb204f8]
*マスターのプログラム [#v09a4685]
**定数、マクロ [#ebb204f8]
#define KOSATEN 37
#define completed 15
#define turn_left OnRev(OUT_A,70);OnFwd(OUT_B,70); //左に回転する
#define go_left OnRev(OUT_A,85);Off(OUT_B); //左に進む
#define go_straight OnRev(OUT_AB,70); //まっすぐ進む
#define go_right OnRev(OUT_B,85);Off(OUT_A); //右に進む
#define turn_right OnRev(OUT_B,100);OnFwd(OUT_A,100); //右に回転する
#define short_break Off(OUT_AB);Wait(1000);
#define brake Off(OUT_AB)
completed は通信に使う(後述)。
brake は「ブレーキ」を意味するが、break として捉えてほしい。
***サブルーチン [#a6f8fad4]
-ライントレース
**サブルーチン [#a6f8fad4]
***ライントレース [#nba5f481]
光センサーを2つ取り付けており、課題2のプログラムを流用できないため、新たに作り直した。左右の値の差を求め、差が大きければ曲がり、0に近ければ直進する仕組みとなっている。
#ref(2019a/Member/tsukue/Mission3/lt1.JPG,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/lt2.JPG,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/lt3.JPG,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/lt4.JPG,50%,画像1)
#ref(2019a/Member/tsukue/Mission3/lt5.JPG,50%,画像1)
sub follow_line() //交差点までライントレース
{
while((SENSOR_1>KOSATEN)||(SENSOR_2>KOSATEN)){
int d=SENSOR_1-SENSOR_2;
if (d<-6){
turn_right;
}else if (d<-3){
go_right;
}else if (d<=3){
go_straight;
}else if (d<=6){
go_left;
}else {
turn_left;
}
}
PlaySound(SOUND_CLICK);
brake;Wait(200);
}
sub follow_line2(int followtime) //一定時間までライントレース
{
long t0=CurrentTick();
while(CurrentTick()-t0<followtime){
int d=SENSOR_1-SENSOR_2;
if (d<-6){
turn_right;
}else if (d<-3){
go_right;
}else if (d<=3){
go_straight;
}else if (d<=6){
go_left;
}else {
turn_left;
}
}
PlaySound(SOUND_CLICK);
brake;Wait(200);
}
***交差点での動作 [#z45684b3]
ライントレースの性質上、T字路の行き止まりでない方向から進入すると分岐している方向に向いてしまうため、直進のプログラムは2通り作った。
sub chokusinL() //交差点を直進(左)
{
go_left;Wait(500);
}
sub chokusinR() //交差点を直進(右)
{
go_right;Wait(500);
}
sub sasetsu() //交差点を左折
{
turn_left;Wait(500);
go_left;Wait(500);
}
sub usetsu(int migi) //交差点を右折
{
turn_right;Wait(500);
go_right;Wait(migi);
}
sub turn_behind() //振り向く
{
turn_left;Wait(1000);
while(SENSOR_1>KOSATEN){
turn_left;
}
} //(線を認識するまで回転)
Off(OUT_BC);
}
sub backleft() //後退し右を向く
{
OnFwd(OUT_A,100);Off(OUT_B);Wait(1500);
turn_right;Wait(600);
Off(OUT_AB);
}
sub backright() //後退し左を向く
{
OnFwd(OUT_B,100);Off(OUT_A);Wait(1400);
turn_left;Wait(500);
Off(OUT_AB);
}
-通信
前述のとおりアーム関連はスレーブで制御するため、メッセージで指示を出し、completed と完了の合図が来るまで待つような仕組みとなっている。
***通信 [#y0325372]
アーム関連はスレーブで制御するため、メッセージで指示を出し、completed と完了の合図が来るまで待つような仕組みとなっている。
sub ball_catch() //玉をつかむ
{
int msg;
SendRemoteNumber(1,MAILBOX1,12);
while(msg==completed){
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
}
sub ball_release() //玉を放す
{
int msg;
SendRemoteNumber(1,MAILBOX1,11);
while(msg==completed){
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
}
sub arm_up() //アームを上げる
{
int msg;
SendRemoteNumber(1,MAILBOX1,13);
while(msg==completed){
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
}
sub arm_down() //アームを下げる
{
int msg;
SendRemoteNumber(1,MAILBOX1,14);
while(msg==completed){
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
}
sub up_catch() //アームを上げながら閉じる
{
int msg;
SendRemoteNumber(1,MAILBOX1,16);
while(msg==completed){
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
}
sub down_release() //アームを下げながら開く
{
int msg;
SendRemoteNumber(1,MAILBOX1,17);
while(msg==completed){
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
}
***task main [#c6912e8f]
**task main [#c6912e8f]
あとはサブルーチンを組み合わせるだけだ。
task main()
{
SetSensorLight(S1); //右カラーセンサー
SetSensorLight(S2); //左カラーセンサー
arm_up(); short_break; ball_release();
go_straight; Wait(2000); //A→M
follow_line(); //M→K
chokusinR(); follow_line2(1500); short_break; //K→L
arm_down(); short_break; ball_catch(); short_break;
arm_up(); short_break; //玉をつかむ
turn_behind(); follow_line(); //L→K
chokusinL(); follow_line(); //K→M
usetsu(500); follow_line();
sasetsu(); follow_line(); //M→B
chokusinL(); follow_line(); //B→X
usetsu(500); follow_line(); //X→X'
sasetsu(); follow_line(); //X'→B'
chokusinR(); follow_line(); //B'→M'
sasetsu(); follow_line(); //M'→K'
sasetsu(); follow_line2(1000); short_break; //K'→J'
ball_release(); short_break; //玉を放す
backleft(); //J'→K'
follow_line2(3700); short_break; //K'→L'
arm_down(); short_break; ball_catch(); short_break;
arm_up(); short_break; //玉をつかむ
turn_behind(); OnFwd(OUT_AB,30); Wait(100); follow_line(); //L'→K'
usetsu(500); follow_line2(500); short_break; //K'→J'
ball_release(); short_break; //玉を放す
backright(); follow_line(); //J'→K'
chokusinL(); follow_line(); //K'→M'
usetsu(500); follow_line(); //M'→B'
chokusinL(); follow_line(); //B'→X'
usetsu(500); follow_line(); //X'→X
sasetsu(); follow_line(); //X→B
sasetsu(); follow_line(); //B→C
usetsu(400); follow_line2(1650); short_break; //C→I
arm_down(); short_break; ball_catch(); short_break;
up_catch(); short_break; //玉をつかむ
backleft(); //I→C
follow_line(); //C→B
usetsu(500); follow_line(); //B→X
usetsu(500); follow_line(); //X→X'
sasetsu(); follow_line(); //X'→B'
sasetsu(); follow_line(); //B'→C'
usetsu(700); follow_line2(900); short_break; //C'→I'
down_release(); short_break; //玉を放す
arm_up(); short_break;
backright(); //I'→C'
}
**スレーブ [#e8faa47f]
***定数 [#k3e7c833]
*スレーブのプログラム [#h92f623c]
**定数 [#k3e7c833]
すべてマスターと対応している。
#define ball_release 11
#define ball_catch 12
#define arm_up 13
#define arm_down 14
#define completed 15
#define up_catch 16
#define down_release 17
***task main [#k7227ad9]
**task main [#k7227ad9]
マスターの指示に従って動作し、完了したら completed とメッセージを送る。
task main()
{
int msg;
while(true){
ReceiveRemoteNumber(MAILBOX1,true,msg);
if(msg==ball_release){
OnFwd(OUT_A,50);Wait(500);Off(OUT_A);Wait(500);
SendResponseNumber(MAILBOX1,completed);
} //玉をつかむ
if(msg==ball_catch){
OnRev(OUT_A,50);Wait(600);Off(OUT_A);Wait(500);
SendResponseNumber(MAILBOX1,completed);
} //玉を放す
if(msg==arm_up){
OnFwd(OUT_B,50);Wait(600); OnFwd(OUT_B,5);Wait(500);
SendResponseNumber(MAILBOX1,completed);
} //アームを上げる
if(msg==arm_down){
OnRev(OUT_B,30);Wait(600); OnFwd(OUT_B,5);Wait(500);
SendResponseNumber(MAILBOX1,completed);
} //アームを下げる
if(msg==up_catch){
OnFwd(OUT_B,40);OnRev(OUT_A,15);Wait(300);
SendResponseNumber(MAILBOX1,completed);
} //アームを上げながら閉じる
if(msg==down_release){
OnRev(OUT_B,10);OnFwd(OUT_A,20);Wait(150);
SendResponseNumber(MAILBOX1,completed);
} //アームを下げながら開く
Wait(100);
msg=0;
}
}
アームが重力で落ちてくるのを防ぐため、アームの上げ下げのプログラムは Off(OUT_B)から OnFwd(OUT_B,5) に置き換えている。
*まとめ [#d918eade]