[[2017b/Member/masato/Mission1]] #contents *課題2 [#o0bf25a7] 今回の課題は下図のようなコースを各チームで作成し、ミッションを遂行することである。 #ref(./2017b-mission2.png,100%,課題2) ミッションとは指定された3つのコースのうち1つを選択し、ライントレースしながら紙コップを指定の場所まで運ぶことである。自分の場合は Aをスタート、Bを直進、Cを直進、D地点の紙コップを取得して来たコース戻りCへ向かう、Cを左折、Fを直進、Rを左折(一時停止)、Pを直進、X地点に紙コップを置いてコースに戻る、Qを左折、Sを右折(一時停止)、Fを左折(一時停止)、Cを右折(一時停止)、D地点へ(ゴール) (一時停止の指定がある場所は、1秒間停止すること) *ロボットの構造 [#hf2b1920] キットについていた説明書の基本の光センサロボットに紙コップを掴むためのアームを後ろ側に取り付けた。アームは3つ目のモーターを使って、上下に動くようになっていて、アームを下に降ろし掴むというよりは中に入れて引きずっていくようにした。 #ref(./IMG_0143.jpg,15%,ロボットの構造) #ref(./IMG_0153.JPG,15%,ロボットの構造) *プログラム [#s089f2e2] **マクロ [#r522c306] #define speed_fast 20 //直線上での速さ #define speed_curve 25 //曲がる時の速さ **各定義 [#k5a7f9b0] #define speedRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL); //タイヤBを speedR%,タイヤCをspeedL%の速さでそれぞれ進ませる(+:前進,-:後進) #define go_fwd speedRL(speed_fast,speed_fast); //前進 #define turn_right_high speedRL(-speed_curve - 5,speed_curve); //右旋回 #define turn_right_low speedRL(0,speed_curve + 10); //右折 #define turn_left_high speedRL(speed_curve ,-speed_curve - 10); //左旋回 #define turn_left_low speedRL(speed_curve + 10,0); //左折 #define turn_left_90 OnFwd(OUT_B,25); OnFwd(OUT_C,-25); Wait(1100); //左90度回転 #define turn_left_150 OnFwd(OUT_B,25); OnFwd(OUT_C,-25); Wait(2500); Off(OUT_BC); //左150 度回転 #define turn_right_150 OnFwd(OUT_B,-25); OnFwd(OUT_C,25); Wait(2500); Off(OUT_BC); //右150度回転 #define turn_left_180 OnFwd(OUT_B,25); OnFwd(OUT_C,-25); Wait(3100); Off(OUT_BC); //左180度回転 #define turn_right_180 OnFwd(OUT_B,-25); OnFwd(OUT_C,25); Wait(3100); Off(OUT_BC); //右180度回転 #define arm_down OnFwd(OUT_A,-10); Wait(1000); Off(OUT_A); // アームダウン #define arm_up OnFwd(OUT_A,20); Wait(1000); Off(OUT_A); //アームアップ **ライントレースサブルーチン,交差点認識 [#x706e03a] 自分のコースの場合光センサが黒線のラインと左側の白い部分の境界線上を走ることにした。ライントレースをする上で重要な明るさを5段階に分けて測り各動作を決定した。暗い順に左旋回、左折、直進、右折、右旋回するようになっている。測った結果しきい値は60になった。 #define threthold 60 //しきい値 交差点認識に関しては時間ではなく最も黒い時が連続して何回続いたかという方法を採用した。調べた結果160回が最適だと判断した。 #define nMAX 160 //交差点認識のための最も黒い時の回数 sub follow_line() //ライントレース { SetSensorLight(S1); int n = 0; //nは続けて黒になった回数 while(n <= nMAX){ //最も黒い時がnMAX以下のときライントレースを繰り返す if(SENSOR_1 < threthold -15 ){ turn_left_high; n++; //回数を増やす }else { if (SENSOR_1 < threthold -7){ turn_left_low; }else if (SENSOR_1 < threthold +6){ go_fwd; }else if (SENSOR_1 < threthold +10){ turn_right_low; }else{ turn_right_high; } n = 0; //最も黒い時の回数の初期化 } } Off(OUT_BC); Wait(1000); PlaySound(SOUND_CLICK); //交差点で音を鳴らす Wait(1000); } **交差点での行動サブルーチン [#h47071d4] 3パターンを用意した。 sub inter_left() //交差点左折 { OnFwd(OUT_BC,25); Wait(1000); Off(OUT_BC); turn_left_90; Off(OUT_BC); Wait(1000); } sub inter_straight() //交差点直進 { OnFwd(OUT_BC,25); Wait(500); Off(OUT_BC); } 通常は上記の2パターンで大丈夫だと思うが自分の場合は直角の部分が曲がりにくかったのでもうひとつ余分に作った sub inter_left_90() //交差点を90度左折 { OnFwd(OUT_BC,25); Wait(600); Off(OUT_BC); turn_left_90; Off(OUT_BC); Wait(1000); } **EF間(急カーブ)でのライントレースサブルーチン [#m39d9563] 通常のライントレースでは急カーブがうまく行かなかったので仕方なくそれ専用のライントレースサブルーチンを作った。このサブルーチンはnMAX_EFが指定された回数になるまでライントレースを繰り返すようになっている。 #define nMAX_EF 3800 //交差点認識のための最も黒い時の回数(EF間のみ) sub follow_line_EF() //EF間で適用したライントレース { SetSensorLight(S1); int n = 0; while(n <= nMAX_EF){ if(SENSOR_1 < threthold -15 ){ OnFwd(OUT_B,50); OnFwd(OUT_C,-60); n++; }else { if (SENSOR_1 < threthold -7){ turn_left_low; }else if (SENSOR_1 < threthold + 6){ go_fwd; }else if (SENSOR_1 < threthold + 10){ turn_right_low; }else{ OnFwd(OUT_B,-30); OnFwd(OUT_C,20); } } } Off(OUT_BC); Wait(1000); } **コップを掴む、離すサブルーチン [#kd0778cb] sub catch_cup() //コップを掴む { turn_left_180; Wait(500); arm_down; Wait(500); turn_right_180; } sub release_cup() //コップを離す { turn_left_180; Wait(500); arm_up; Wait(500); turn_right_180; } **タスクメイン [#p9ace022] task main() { follow_line(); inter_straight(); //C直進 follow_line(); Off(OUT_BC); follow_line(); inter_left_90(); //B左折 OnFwd(OUT_B,25); //微調整 Wait(500); Off(OUT_B); follow_line(); inter_left(); //P左折 follow_line(); inter_straight(); //Q直進 OnFwd(OUT_C,30); //微調整 Wait(1100); Off(OUT_C); follow_line(); inter_left(); //R左折 follow_line(); inter_left_90(); //E左折 follow_line_EF(); follow_line(); inter_left_90(); //F左折 OnFwd(OUT_B,25); //微調整 Wait(500); Off(OUT_B); follow_line(); catch_cup(); //コップ掴む inter_straight(); //S直進 follow_line(); inter_straight(); //S直進 follow_line(); release_cup(); //コップ離す inter_left(); //Q左折 OnFwd(OUT_C,30); //微調整 Wait(800); Off(OUT_C); follow_line(); inter_straight(); //R直進 follow_line(); inter_left(); //P左折 follow_line(); inter_left(); //B左折 OnFwd(OUT_B,25); //微調整 Wait(700); Off(OUT_B); follow_line(); inter_straight(); OnFwd(OUT_BC,30); //Aの中にゴール Wait(800); }