- 追加された行はこの色です。
- 削除された行はこの色です。
[[2019a/Member]]
#contents
*課題内容 [#hfbc2c28]
**コース図 [#wbebb906]
課題2で作成したものを2枚くっつけます.
#ref(mission3.png,zoom,400x600)
**ルール [#b4f505e8]
+図の黄色い丸にあるピンポン玉を左下の円内にあるプラ容器へと運ぶ.
+フィールドは課題2で使用した紙を使用する。
+生協のお弁当の四角いプラ容器2つをそれぞれ円内に置き、片方に玉を2個入れる。
+残りの2個の玉は((課題2))と同じ位置に置く。その際、ゴムタイヤやプレートの上に置いてもよい。
+プラ容器には色をつけたり文字や記号を書いてもよい。
+プラ容器は両面テープ等でフィールドに固定してもよい。
+2枚の紙の境界にはそれぞれ幅1cm、合計2cmの黒線を描いてもよい。
**点数計算 [#ga6fffd2]
点数については
+基本得点20点
+技術得点20点
の合計40点で審査します.細かな内訳は
#ref(http://yakushi.shinshu-u.ac.jp/robotics/?2019a%2FMission3#zb7e8fa1);
をご覧ください.
*ロボットについて [#p90c0617]
**ロボット本体 [#a41ea091]
#ref(robotbody.jpg,zoom,400x600);
ロボット本体は課題2#ref(http://yakushi.shinshu-u.ac.jp/robotics/?2019a%2FMember%2FOrangestar%2FMission2);で作ったものを改良して作りました.
NXTが2つ載せられるようにして,それでいてかつ小型でライントレースの際に起こる左右の揺れの影響を受けにくいようにしました.
**アームとその周辺 [#k5532227]
#ref(arm01.png,zoom,400x600);
アームもできるだけ小型化しました.モーターに直接部品をつなげて回転運動を利用してボールをつかみます.
#ref(arm02.png,zoom,400x600);
ボールを離す動作です.先ほどと逆向きに回転させます.
#ref(sholder.png,zoom,400x600);
アームそのものを上げ下げするためのモーターです.取り付けた理由として,今回使うプラ容器にある程度の高さがあるため,このままでは容器の中のピンポン玉が取れなくなってしまうからです.
**全体像 [#g8421242]
#ref(robot.jpg,zoom,400x600);
ロボットの全体像です.コンパクトに仕上ったと思います.
*プログラムについて [#g86dfaec]
**ルートについて [#qf6cda12]
#ref(route.JPG,zoom,400x600);
A'からスタートし,まずL'にあるピンポン玉をつかみ旋回して容器に入れます.
そこから直線を突っ切って容器の中のピンポン玉を掴みゴールにある容器に入れ替えます.
それを2回繰り返します.(図にある赤の点線です.この点線の動作を2回繰り返します.)
最後にLにあるピンポン玉を掴みゴールにある容器に入れて終了という計画です.
今回はロボット本体とボールを掴む機構を2台のロボットに分割して制御します.
本体を制御するロボットを「親」,アームを制御するロボットを「子」と呼ぶことにします.
親のプログラムは課題2のものをベースにします.
**ライントレースについて [#db19273d]
課題2の時と同じです
#ref(linetrace.png,zoom,600x400);
光センサーが黒を認識すると左,白を認識すると右へ行くようプログラミングしてやれば左側をトレースできます.
**ロボット間での通信について [#u2d420b9]
Bluetoothでロボットを接続し,メールボックスに数字を送ってやり取りします.親側のロボットに数字を送るSendRemoteNumberというプログラムを書いて,子のほうにはメールボックスの中にこの数字があればこの動きをするというプログラムをします.
**親のプログラム [#c17dad0b]
#define SIGNALON1 11
#define SIGNALOFF1 12
#define SIGNALON2 13
#define SIGNALOFF2 14
#define turn_right OnFwd(OUT_C,25);OnRev(OUT_B,15);//右折
#define turn_left OnFwd(OUT_B,25);OnRev(OUT_C,15);//左折
#define rotate_right OnFwd(OUT_C,20);OnRev(OUT_B,25);//右旋回
#define rotate_left OnFwd(OUT_B,20);OnRev(OUT_C,25);//左旋回
#define go_straight OnFwd(OUT_BC,20);//直進
#define go_straight2 OnFwd(OUT_BC,15);//ゆっくり直進
#define turn OnRev(OUT_C,25);OnFwd(OUT_B,25);Wait(1500);Off(OUT_BC);//180°旋回
#define catch OnRev(OUT_A,25);Wait(500);Off(OUT_A);//ピンポン玉をつかむ
#define release OnFwd(OUT_A,25);Wait(500);Off(OUT_A);//ピンポン玉を離す
#define osidasi OnFwd(OUT_BC,100);Wait(100);Off(OUT_BC);//加速してピンポン玉を押し出す
#define black 20//黒の値は20
#define white 50//白の値は50
#define lightgray 40//灰白色は40
#define darkgray 28//灰黒色は28
#define turn2 OnRev(OUT_B,28);OnFwd(OUT_C,20);Wait(1500);Off(OUT_BC);
#define sakittyo OnFwd(OUT_C,20);OnFwd(OUT_B,23);Wait(1150);Off(OUT_BC);
#define turn3 OnRev(OUT_B,30);Wait(4800);Off(OUT_BC);
#define turn4 OnRev(OUT_B,30);Wait(5200);Off(OUT_BC);
#define back OnRev(OUT_C,20);OnRev(OUT_B,28);Wait(3000);Off(OUT_BC);
#define osidasi OnFwd(OUT_BC,100);Wait(100);Off(OUT_BC);
#define arm_down OnFwd(OUT_A,25);Wait(1500);Off(OUT_A);
#define arm_up OnRev(OUT_A,35);Wait(1500);Off(OUT_A);
#define center 45
まずは直進,右左折などのマシンの操作から,黒や白の値などを定義しておきます.
sub followline_L(int stop_time)
{
long t0=CurrentTick();
while(CurrentTick()-t0<stop_time){//現在の時刻が一定の値を超えるまで
if(SENSOR_1<black){//センサーが黒の時
rotate_left;//左旋回
}else if(SENSOR_1<darkgray){//センサーが黒灰なら
turn_left;//左折
}else if(SENSOR_1>lightgray){//センサーが白灰なら
turn_right;//右折
t0=CurrentTick();//時間をリセット
}else if(SENSOR_1<35){//明るさ35以下で
go_straight;//直進
t0=CurrentTick();//時間をリセット
}else{//それ以外は
rotate_right;//右旋回
t0=CurrentTick();//時間をリセット
}
}
Off(OUT_BC);//時刻が一定の値を超えると停止
Wait(1000);//1秒間停止
}
黒線n右側をライントレースするサブルーチン
sub followline_R(int stop_time)
{
long t0=CurrentTick();
while(CurrentTick()-t0<stop_time){//現在の時刻が一定の値を超えるまで
if(SENSOR_1<black){//センサーが黒の時
rotate_right;//右旋回
}else if(SENSOR_1<darkgray){//センサーが黒灰なら
turn_right;//右折
}else if(SENSOR_1>lightgray){//センサーが白灰なら
turn_left;//左折
t0=CurrentTick();//時間をリセット
}else if(SENSOR_1<35){//センサーが35以下なら
go_straight;//直進
t0=CurrentTick();//時間をリセット
}else{//それ以外は
rotate_left;//左旋回
t0=CurrentTick();//時間をリセット
}
}
Off(OUT_BC);//一定の時間を超えると停止
Wait(1000);//一秒間停止
}
右側をライントレースするサブルーチン
sub followline_R2(int stop_time)
{
long t0=CurrentTick();
while(CurrentTick()-t0<stop_time){//時刻がある一定の値より小さいとき
if(SENSOR_1<black){//黒なら
rotate_right;//右旋回
t0=CurrentTick();//時間をリセット
}else if(SENSOR_1<darkgray){//灰黒色なら
turn_right;//右折
t0=CurrentTick();//時間をリセット
}else if(SENSOR_1>lightgray){//灰白色なら
turn_left;//左折
}else if(SENSOR_1<35){//明るさ35以下で
go_straight2;//ゆっくり直進
t0=CurrentTick();時間をリセット
}else{//それ以外なら
rotate_left;//左旋回
}
}
Off(OUT_BC);//停止
Wait(2000);//2秒間停止
}
白から黒へ,黒から白へ移動するためのサブルーチン
sub Blackto_White()//黒から白へ
{
while(SENSOR_1<darkgray){灰黒色の間
OnFwd(OUT_BC,15);//直進
}
Off(OUT_BC);//停止
}
sub Whiteto_Black()//白から黒まで直進
{
while(SENSOR_1>darkgray){//灰黒色まで
OnFwd(OUT_BC,15);//直進
}
Off(OUT_BC);//停止
}
sub Whiteto_Black_R()//白から黒まで右旋回
{
while(SENSOR_1>darkgray){//灰黒色まで
OnFwd(OUT_C,20);
OnRev(OUT_B,20);}//右旋回
Off(OUT_BC);
}
sub Blackto_White_R()//黒から白へ右旋回
{
while(SENSOR_1<darkgray){//灰黒の間
OnFwd(OUT_C,20);
OnRev(OUT_B,20);//右旋回
}
Off(OUT_BC);
}
sub Blackto_White_L()//黒から白へ左旋回
{
while(SENSOR_1<lightgray){//薄灰のとき
OnFwd(OUT_B,20);
OnRev(OUT_C,20);//左に旋回
}
Off(OUT_BC);
}
sub Whiteto_Black_L()白から黒へ左旋回
{
while(SENSOR_1>black){//黒の時
OnFwd(OUT_B,20);
OnRev(OUT_C,20);//左旋回
}
Off(OUT_BC);
}
**子のプログラム [#rd65a026]
#define SIGNALON1 11
#define SIGNALOFF1 12
#define SIGNALON2 13
#define SIGNALOFF2 14
#define CONN 1
task main()
{
int msg;
while(true){
ReceiveRemoteNumber(MAILBOX1,true,msg);
if(msg==SIGNALON1){//メールボックスに11があるとき
OnRev(OUT_A,20);Wait(1000);//アームを閉じる
}else if(msg==SIGNALOFF1){//メールボックスに12があるとき
Off(OUT_A);//アームを止める
}else if(msg==SIGNALON2){//メールボックスに13があるとき
OnFwd(OUT_A,20);Wait(1000);//アームを開く
}else if(msg==SIGNALOFF2){//メールボックスに14があるとき
Off(OUT_A);//アームを止める
}
}
}
**メインプログラム [#kb08ddd6]
task main()
{
SetSensorLight(S1);
RemoteStartProgram(CONN,"kodomo.nxc");//子のプログラムを遠隔でスタート
followline_R(200);
Blackto_White();
followline_L(150);
Blackto_White_R();
followline_R2(150);
SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);//子のメールボックスに11を送信
Wait(1000);
arm_up;
turn;
SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);//子のメールボックスに12を送信
Wait(1000);
followline_R(150);
Blackto_White_L();
followline_L(100);
Blackto_White();
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
followline_R(150);
Blackto_White();
turn2;
sakittyo;
arm_down;
SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);
Wait(1000);
arm_up;
turn3;
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
followline_R(200);
Blackto_White();
turn2;
SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);
Wait(1000);
turn3;
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
followline_R(200);
Blackto_White();
turn2;
sakittyo;
arm_down;
SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);
Wait(1000);
arm_up;
turn3;
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
Blackto_White_R();
followline_R(200);
Blackto_White();
turn2;
SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);
Wait(1500);
turn4;
arm_down
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
followline_L(200);
Blackto_White();
followline_R(200);
Blackto_White();
followline_L(200);
Blackto_White();
followline_R(200);
Blackto_White();
followline_L(150);
Blackto_White_R();
followline_R2(125);
SendRemoteNumber(CONN,MAILBOX1,SIGNALON1);
Wait(1000);
arm_up;
turn;
followline_R(100);
Blackto_White_L();
followline_L(100);
Blackto_White();
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
Whiteto_Black();
Blackto_White();
followline_R(200);
Blackto_White();
turn2;
sakittyo;
SendRemoteNumber(CONN,MAILBOX1,SIGNALON2);
Wait(1000);
*最後に [#a0057f12]
ロボコンの結果は2位でした.この結果はチームの力なくしては達成できませんでした.電池が少なくなり出力に影響したり,思い通りに動かないことが多々ありましたが,ここまでたどり着けて良かったと思います.