[[2013a/Member]] #contents *課題について [#w301accd] *課題について [#ne4d392e] -ライントレースを行いつつ、空き缶を運搬する。コースは下図の通り。 #ref(2013a/Member/donky/Mission1/IMG_0217.JPG,10%,コース図) *ロボット本体紹介 [#ubc72b3d] *ロボット本体紹介 [#rae32843] **ロボットの特徴 [#t8df27a4] **ロボットの特徴 [#e517eb0d] -1巨大なアームと下あご #ref(2013a/Member/donky/Mission1/IMG_0220.JPG,10%,ハサミ部分) 空き缶を保持したままライントレースするために巨大なアームを取り付けました。 -2本体を安定させるための重り #ref(2013a/Member/donky/Mission1/IMG_0219.JPG,10%,ロボット本体) ロボット本体後部に取り付けている緑の部品は、巨大なアームによるロボット本体の前かがみ現象を解決するために装着しました。 *コース攻略法 [#d8eeb012] *コース攻略法 [#aae72a31] **1 垂直カーブ部分 [#ic4141ac] **1 垂直カーブ部分 [#w09cd101] 右折のプログラムを二種類に分けることで素早く稼動できる。 **2 交差点部分 [#ye46f503] **2 交差点部分 [#y1705265] 交差点判別のプログラムの他に、急左折のあとに前進のプログラムを組むことで交差点を素早く突破できることが判明、タイマーによりプログラムを変えることで実用できた。 **3 急カーブ部分 [#d413c952] **3 急カーブ部分 [#h37cc678] 急カーブではロボットが脱線することが多かったのでタイマーを使い急カーブ部分で細かく敷居値を判定するプログラムに切り替えて対応した。 **4 空き缶運搬 [#m953ceb6] **4 空き缶運搬 [#oed0b9c1] タイマーでアームに取り付けたモーターを稼働させ、空き缶の保持と設置のプログラムを稼働させた。 *プログラムの紹介 [#v88611c8] #define THRESHOLD 45 #define HIPOWER 7 #define LOWPOWER 1 *プログラムの紹介 [#s7cb083f] #define THRESHOLD 42 #define HIPOWER 9 // 直線用の強めのパワー #define LOWPOWER 1 // カーブ、旋回用の弱めのパワー #define set_power_H SetPower(OUT_AC,HIPOWER); #define set_power_L SetPower(OUT_AC,LOWPOWER); #define go_forward set_power_H; OnFwd(OUT_AC); #define turn_left_A set_power_L; OnFwd(OUT_C); OnRev(OUT_A); #define turn_left_B set_power_L; OnFwd(OUT_C); Off(OUT_A); #define turn_right_A set_power_L; OnFwd(OUT_A); OnRev(OUT_C); #define turn_right_B set_power_L; OnFwd(OUT_A); Off(OUT_C); #define STEP 1 #define nMAX 8 #define short_break Off(OUT_AC); Wait(100); #define CROSS_TIME 20 #define cross_line go_forward; Wait(CROSS_TIME); short_break; task main() #define go_forward set_power_H; OnFwd(OUT_AC); // 前に進む動作 #define turn_left1 set_power_L; Off(OUT_A); OnFwd(OUT_C); // 左にカーブする動作 #define turn_right1 set_power_L; OnFwd(OUT_A); Off(OUT_C); // 右にカーブする動作 #define turn_left2 set_power_L; OnRev(OUT_A); OnFwd(OUT_C); // 左に旋回する動作 #define turn_right2 set_power_L; OnFwd(OUT_A); OnRev(OUT_C); // 右に旋回する動作 #define STEP 1 // 1回の判断で動作させる時間 #define nMAX 7 // 通常のカーブとして許容できる繰り返しの最大値 #define short_break Off(OUT_AC); Wait(100); // 小休止 #define CROSS_TIME 20 // 交差点通過にかかる時間 #define cross_line go_forward;Wait(CROSS_TIME);short_break; // 交差点を通過する動作 task main() { SetSensor(SENSOR_2, SENSOR_LIGHT); ClearTimer(0); int nOnline=0; while (FastTimer(0) <= 1000) { if (SENSOR_2 < THRESHOLD -3){ turn_left_A; } else if (SENSOR_2 < THRESHOLD -1){ turn_left_B; } else if (SENSOR_2 < THRESHOLD +3){ go_forward; } else if (SENSOR_2 < THRESHOLD +7){ turn_right_B; } else { turn_right_A; } SetSensor(SENSOR_2,SENSOR_LIGHT); // 「2」に光センサーを設置 ClearTimer(0); // タイマーをリセット while (FastTimer(0) <= 1000) { // 10秒間通常のライントレース(線の右側) if (SENSOR_2 < THRESHOLD-3) { // 光センサーの値が39未満の時、右に旋回 turn_right2; } else if (SENSOR_2 < THRESHOLD-1) { // 光センサーの値が41未満の時、右にカーブ turn_right1; } else if (SENSOR_2 < THRESHOLD+2) { // 光センサーの値が44未満の時、直進 go_forward; } else if (SENSOR_2 < THRESHOLD+10) { // 光センサーの値が52未満の時、左にカーブ turn_left1; } else { // その他の時は左に旋回 turn_left2; } Wait(STEP); } Off(OUT_AC); OnRev(OUT_B); Wait(100); Off(OUT_B); PlaySound(SOUND_FAST_UP); while (FastTimer(0) <= 3950) { if (SENSOR_2 < THRESHOLD -7) { turn_left_A; go_forward; } else { if (SENSOR_2 < THRESHOLD -5) { turn_left_B; } else if (SENSOR_2 < THRESHOLD +4) { go_forward; } else if (SENSOR_2 < THRESHOLD +5) { turn_right_B; } else { turn_right_A; } nOnline=0; } Wait(STEP); int nOnline=0; // 続けて黒になった回数を数える PlaySound(SOUND_UP); // ピロピロ〜と高い音を鳴らす Off(OUT_AC); // タイヤを止める OnRev(OUT_B);Wait(120);Off(OUT_B); // 上あごを動かして、缶を挟む→1.2秒で停止 ClearTimer(0); // タイマーをリセット while (FastTimer(0) <= 1600) { // 16秒間交差点のプログラム→線の右側をライントレース if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD-3)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が39未満の時、右に旋回 turn_right2; nOnline++; // カウンタを増やす } else { if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD-1)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が41未満の時、右にカーブ turn_right1; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD+2)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が44未満の時、直進 go_forward; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD+10)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が52未満の時、左にカーブ turn_left1; } else if ((nOnline < nMAX)&&(SENSOR_2 >= THRESHOLD+10)){ // 黒がnMAX回繰り返さない、かつ、光センサーの値が52以上の時、左に旋回 turn_left2; } nOnline=0; // カウンタをリセット } if(nOnline >= nMAX) { // 黒がnMAX回繰り返された時、交差点を渡る動作 short_break; // 小休憩 turn_left2; Wait(nMAX*STEP); // 進行方向修正 cross_line; // 交差点を渡る nOnline=0; // カウンタをリセット } } OnRev(OUT_B); Wait(30); Off(OUT_B); PlaySound(SOUND_FAST_UP); while (FastTimer(0) <= 4700) { if (SENSOR_2 < THRESHOLD -3){ turn_left_A; } else if (SENSOR_2 < THRESHOLD -1){ turn_left_B; } else if (SENSOR_2 < THRESHOLD +3){ go_forward; } else if (SENSOR_2 < THRESHOLD +7){ turn_right_B; } else { turn_right_A; } Wait(STEP); } OnRev(OUT_B); Wait(30); Off(OUT_B); PlaySound(SOUND_FAST_UP); while (FastTimer(0) <= 6700) { if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD -7)) { turn_left_A; nOnline++; } else { if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD -5)) { turn_left_B; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD +4)) { go_forward; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD +5)) { turn_right_B; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD +10)) { turn_right_A; } nOnline=0; } if (nOnline >= nMAX) { short_break; turn_right_B; Wait(nMAX*STEP); cross_line; nOnline=0; } } OnFwd(OUT_A);OnRev(OUT_C);Wait(350); Off(OUT_AC); OnFwd(OUT_B); Wait(100); OnRev(OUT_AC);Wait(150); OnFwd(OUT_A);OnRev(OUT_C);Wait(200); PlaySound(SOUND_FAST_UP); while (true) { if (SENSOR_2 < THRESHOLD -3){ turn_left_A; } else if (SENSOR_2 < THRESHOLD -1){ turn_left_B; } else if (SENSOR_2 < THRESHOLD +3){ go_forward; } else if (SENSOR_2 < THRESHOLD +7){ turn_right_B; } else { turn_right_A; PlaySound(SOUND_UP); // ピロピロ〜と高い音を鳴らす Off(OUT_AC); タイヤを止める OnRev(OUT_B);Wait(120);Off(OUT_B); // 上あごを動かして、缶を挟む→1.2秒で停止 OnFwd(OUT_AC);Wait(50);Off(OUT_AC); // 0.5秒間前進(次の左沿いにライントレースする動作をしやすくするため) ClearTimer(0); // タイマーをリセット while (FastTimer(0) <= 3500) { // 35秒間交差点のプログラム→線の左側をライントレース if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD-3)) { 黒がnMAX回繰り返さない、かつ、光センサーの値が39未満の時、左に旋回 turn_left2; nOnline++; // カウンタを増やす } else { if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD-1)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が41未満の時、左にカーブ turn_left1; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD+2)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が44未満の時、直線 go_forward; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD+10)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が52未満の時、右にカーブ turn_right1; } else if ((nOnline < nMAX)&&(SENSOR_2 >= THRESHOLD+10)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が52以上の時、右に旋回 turn_right2; } nOnline=0; // カウンタをリセット } if(nOnline >= nMAX) { // 黒がnMAX回繰り返された時、交差点を渡る動作 short_break; // 小休憩 turn_right2; Wait(nMAX*STEP); // 進行方向修正 cross_line; // 交差点を渡る nOnline=0; // カウンタをリセット } } Wait(STEP); } PlaySound(SOUND_UP); // ピロピロ〜と高い音を鳴らす Off(OUT_AC); // タイヤを止める OnRev(OUT_B);Wait(120);Off(OUT_B); // 上あごを動かして缶を挟む→1.2秒で停止 OnFwd (OUT_AC);Wait (50); // 0.5秒間前進(次の右沿いにライントレースする動作をしやすくするため) ClearTimer(0); // タイマーをリセット while (FastTimer(0) <= 1800) { // 18秒間交差点のプログラム→線の右側をライントレース if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD-3)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が39未満の時、右に旋回 turn_right2; nOnline++; // カウンタをリセット } else { if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD-1)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が41未満の時、右にカーブ turn_right1; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD+2)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が44未満の時、直進 go_forward; } else if ((nOnline < nMAX)&&(SENSOR_2 < THRESHOLD+10)) { // 黒がnMAX回繰り返さない、かつ、光センサーの値が52未満の時、左にカーブ turn_left1; } else if ((nOnline < nMAX)&&(SENSOR_2 >= THRESHOLD+10)){ // 黒がnMAX回繰り返さない、かつ、光センサーの値が52以上の時、左に旋回 turn_left2; } nOnline=0; } if(nOnline >= nMAX) { // 黒がnMAX回繰り返された時、交差点を渡る動作 short_break; // 小休憩 turn_left2; Wait(nMAX*STEP); // 進行方向修正 cross_line; // 交差点を渡る nOnline=0; // カウンタをリセット } } PlaySound(SOUND_UP); // ピロピロ〜と高い音を鳴らす Off(OUT_AC); // タイヤを止める OnRev(OUT_B);Wait(120);Off(OUT_B); // 上あごを動かして缶を挟む→1.2秒で停止 ClearTimer(0); // タイマーをリセット while (FastTimer(0) <= 1600) { // 16秒間通常のライントレース(線の右側) if (SENSOR_2 < THRESHOLD-3) { // 光センサーの値が39未満の時、右に旋回 turn_right2; // 光センサーの値が41未満の時、右にカーブ turn_right1; } else if (SENSOR_2 < THRESHOLD+2) { // 光センサーの値が44未満の時、直進 go_forward; } else if (SENSOR_2 < THRESHOLD+10) { // 光センサーの値が52未満の時、左にカーブ turn_left1; } else { その他の時は左に旋回 turn_left2; } Wait(STEP); } PlaySound(SOUND_UP); // ピロピロ〜と高い音を鳴らす OnFwd(OUT_A); OnRev(OUT_C);OnRev(OUT_B);Wait(50);Off(OUT_ABC); // 缶をつかみながら0.5秒間右に旋回(ターンして缶を置きに行くのに缶を倒さないようにするため) ClearTimer(0); // カウンタをリセット while (FastTimer(0) <= 500) { // 5秒間通常のライントレース(線の左側) if (SENSOR_2 < THRESHOLD-3) { // 光センサーの値が39未満の時、左に旋回 turn_left2; } else if (SENSOR_2 < THRESHOLD-1) { // 光センサーの値が41未満の時、左にカーブ turn_left1; } else if (SENSOR_2 < THRESHOLD+2) { // 光センサーの値が44未満の時、直進 go_forward; } else if (SENSOR_2 < THRESHOLD+10) { // 光センサーの値が52未満の時、右にカーブ turn_right1; } else { // その他の時は右に旋回 turn_right2; } Wait(STEP); } PlaySound(SOUND_UP); // ピロピロ〜と高い音を鳴らす Off(OUT_AC); // タイヤを止める OnFwd(OUT_B);Wait(100);Off(OUT_B); // 1秒間上あごを動かして缶を離す OnRev(OUT_AC);Wait(100);Off(OUT_AC); // 1秒間後進 OnRev(OUT_A); OnFwd(OUT_C);Wait(80);Off(OUT_AC); // 0.8秒間左に旋回 ClearTimer(0); // タイマーをリセット while (FastTimer(0) <= 2000) { // 20秒間通常のライントレース(線の右側) if (SENSOR_2 < THRESHOLD-3) { // 光センサーの値が39未満の時、右に旋回 turn_right2; } else if (SENSOR_2 < THRESHOLD-1) { // 光センサーの値が41未満の時、右にカーブ turn_right1; } else if (SENSOR_2 < THRESHOLD+2) { // 光センサーの値が44未満の時、直進 go_forward; } else if (SENSOR_2 < THRESHOLD+10) { // 光センサーの値が52未満の時、左にカーブ turn_left1; } else { // その他の時は左に旋回 turn_left2; } Wait(STEP); } } *まとめ [#s9aa44f5] **課題について [#n1014589] *まとめ [#zc91b1c6] **課題について [#j4705986] 結果として課題攻略には失敗してしまいました。(練習時には成功有り) ***原因の考察 [#m5ef1c1d] ***原因の考察 [#b4eaf86a] -タイマーの多用 タイマーを多用しすぎたために時間が少しずれると関連して他のプログラムまで動作がずれてしまっていた。タイマーを使用する際は短い時間かつカウント開始条件を指定することが大切だと思う。 -アームの固定力 アームの固定力が少し弱かった。もっとコンパクトな設計を心掛けたい。 **感想 [#u8529aeb] **感想 [#u1a1faf0] いろいろと失敗してしまったので悔しいです。しかし改善点やプログラミングのコツなど、失敗することで多くのものを吸収できました。次回の課題では確実に動作するプログラミングを作成するために取り組んでいきたいです。