[[2019a/Member]] #contents *課題 [#xb13a38e] 詳しくは2019年度前期 課題2を参照~ #ref(2019a/Member/Hinata/Mission2/2019a-mission2.png,100%,a) 私は以下のコースを走る~ ・A地点から出発 → M → K(直進) → L(ピンポン玉をつかむ) → K(右折) → J(一時停止の後、左折) → I(直進) → H(直進) → G(左折) → F → E → D(一時停止の後、直進) → C(直進) → B(一時停止) → シュート→ A地点に入る(ゴール) *ロボットについて [#ye6c477a] **本体 [#nfcc25e5] #ref(2019a/Member/Hinata/Mission2/q2.JPG,100%,q2) #ref(2019a/Member/Hinata/Mission2/q3.JPG,100%,q3) ロボットはNXTを使用している。~ バッテリーの上に載っているモーターにより枠が動く機構を搭載した~ 基本のロボットにアームを取り付けられるようにわずかに改造している。ボールが非常に軽かったので枠に入れて転がすだけの構造が重量の観点からも良いものとなった~ **アーム [#a3ef95c7] #ref(2019a/Member/Hinata/Mission2/q1.JPG,100%,q1) 赤線で囲まれたところがアームだ。単純な枠の上げ下げのみを目的としているので単純な作りになった~ センサーのケーブルがこのアームに干渉しないように、かつ移動の邪魔にならないような位置はこの辺りがベストだと考えた。重心ができるだけ車軸の上に来るように努めた~ アームは単純な上下運動のみだ *プログラム [#fcd1ec0a] **基本事項 [#b7c19ed8] 細かい制御のために黒線の右側をトレースするものと左側をトレースするプログラムをそれぞれ書き、その2つを適宜交換させて稼働させた~ またライントレースの際に直線で走る明るさの基準は45とした~ 詳しいライントレースの原理については「http://yakushi.shinshu-u.ac.jp/robotics-jr/robotics-jr-2013.pdf」の項目8を参照してほしい **定義 [#u5eb353b] ***アームについて [#gb048f4f] #define arm_down OnFwd(OUT_A,15);Wait(1000);Off(OUT_A); //アームの上下動作 #define arm_up OnRev(OUT_A,15);Wait(1000);Off(OUT_A); ***基本骨子 [#a32ed531] #define Baced 45 //中間となる明るさの定義 #define speed 20 #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);//簡略化のための定義 ここではマクロをさらに見やすくするための定義が書かれている。これが無いと全体がもっさりとしたものになる ***移動に使用するマクロ [#x3fbb24f] #define Deep_turn_R OnRL(-speed,speed); //Deepで両車輪を回し、深く曲がる #define turn_R OnRL(0,speed); //片方の車輪のみを動かす #define Straight OnRL(speed,speed); //直進 #define Deep_turn_L OnRL(speed,-speed); #define turn_L OnRL(speed,0); #define turning_R OnRL(-speed,speeed);; //時計回りに回転 #define turning_L OnRL(speed,-speed); //反時計回りに回転 #define cross_line OnFwd(OUT_BC,15);Wait(400); //交差点を横切る ここまでがライントレースに用いるマクロ。後述のサブルーチンに頻繁に登場する 出来るだけ見やすく表記することに努めた。 出来るだけ見やすく表記することに努めた。~ 交差点は,曲がった分の誤差を本体を旋回させ元の位置に戻るように調節する、その後直進する。といった単純かつ調整の利くものにした ***その他の行動 [#v2983288] #define tea_time Off(OUT_BC);Wait(1000); //一時停止 別にお茶は飲まない #define kick OnFwd(OUT_BC,50);Wait(200); //最後のシュートに使用 キック機能はない **サブルーチン関数 [#q923bfc4] #ref(2019a/Member/Hinata/Mission2/無題あ.png,100%,bb) これはライントレースのイメージ画像 #ref(2019a/Member/Hinata/Mission2/aaaa.jpg,100%,aaaa) 主に使用する右側、左側のライントレースが一つずつ。ボールを捕獲する道なりで使用する専用の左側トレースをひとつ。計三つのサブループチンを活用した。 ***右側のトレース [#l6a68ec9] void R_trace(int Z){ //道の右側をトレースして交差点で停止する SetSensorLight(S1); long t0; t0=CurrentTick(); //タイマーをセット while (CurrentTick()-t0<Z) { //Z秒以上深く右に曲がるまで永続 while (CurrentTick()-t0<Z) { //Z/1000秒以上連続して右に曲がるまで永続する if (SENSOR_1 < Baced-15) { //基準の明るさからー15の時の動作(黒線の上) Deep_turn_R; } else if (SENSOR_1 < Baced-5) {turn_R;//基準の明るさからー5のとき(やや黒線より) t0=CurrentTick();} else if (SENSOR_1 < Baced+5) {Straight; //いい感じの位置 t0=CurrentTick();} else if (SENSOR_1 < Baced+10) {turn_L; //黒線からやや離れている t0=CurrentTick();} else {Deep_turn_L; //黒線から完全に離れている t0=CurrentTick();} } turning_L; //左に旋回 Wait(400); cross_line; //直進して交差点を渡る } 右側をトレースして交差点をわたるサブ関数~ Zの時間以上右に曲がれば交差点と判断するようになっている。~ Z/1000秒以上連続して右に曲がるまで続けると交差点と判断するようになっている。~ コースのL〜K、F〜B間で使用。黄緑色の部分で作動する ***左側のトレース1 [#a2cabf16] void L_trace_A(int X){ //上記のR_traceの左バージョン SetSensorLight(S1); long t0; t0=CurrentTick(); while (CurrentTick()-t0<X) { if (SENSOR_1 < Baced-15) { Deep_turn_L; } else if (SENSOR_1 < Baced-5) {turn_L; t0=CurrentTick();} else if (SENSOR_1 < Baced+5) {Straight; t0=CurrentTick();} else if (SENSOR_1 < Baced+10) {turn_R; t0=CurrentTick();} else {Deep_turn_R; t0=CurrentTick();} } turning_R; //右旋回 Wait(400); cross_line; //交差点の横断 } こちらはR_traceと違い左側をトレースしながら移動するようになっている~ 左に曲がり続ける(黒が続く)と交差点と判断される~ 連続して左に曲がり続ける(黒が続く)と交差点と判断される~ コースのM〜K、J〜Gで使用。基本の左側トレース。紫色の区間 ***左側トレース2 [#e0804cf8] void L_trace_B(int Y){ //左側トレース第二弾 SetSensorLight(S1); long t0; t0=CurrentTick(); while (CurrentTick()-t0<Y) { if (SENSOR_1 < Baced-15) {Deep_turn_R; t0=CurrentTick();} else if (SENSOR_1 < Baced-5) {turn_L; t0=CurrentTick();} else if (SENSOR_1 < Baced+5) {Straight; t0=CurrentTick();} else if (SENSOR_1 < Baced+10) {turn_R; t0=CurrentTick();} else {Deep_turn_R; //右に曲がり続けたときに止まるようになっている else {Deep_turn_R; //上記のものと違い、白を感知して右に連続して曲がり続けたときに止まるようになっている } } turning_L; //左旋回 Wait(200); } こちらは先の交差点を渡るものと違いK〜L間でのみ使用される、コースの先が無いときに用いるサブ関数となっている~ 時間Yの調整により使用に至る。オレンジ色の区間で動作する~ 時間Yの調整により使用に至る。オレンジ色の区間で動作する。~ 黒線から外れた時に停止する。言い換えると白を感知して停止するL_trace_A **メインタスク [#ia72e381] 特別なことは一切していない~ 前述のマクロとサブルーチンですべて完結している~ ボールを捕獲した後にロボットを反転させる予定だったが、実験の結果より反転のプログラムは特に必要ないことが分かったので省略した task main(){ L_trace_A(370); //左側トレースから開始 L_trace_B(200); arm_down; //アームをさげてボールをキャッチ tea_time; //ボール安定のために一時停止 R_trace(370); //右側トレース区間 L_trace_A(220); //KからJへ tea_time; //J 一時停止 L_trace_A(340); L_trace_A(340); L_trace_A(340); //Gへ到達 R_trace(370); //右側のトレース tea_time; //D 一時停止 R_trace(320); //D〜B区間 tea_time; //B 一時停止 arm_up; kick; } *まとめ [#pbb79780] センサーに使った値がよかったのか道はかなりスムーズに進めた。急なカーブも難なく渡れる結果には満足している。~ 交差点の識別からの立ち上がりが大味になってしまったが、スムーズな移動にかなり助けられた。~ **反省 [#g49f736c] スムーズな移動ではあったが、時折ボールを上手くとらえることができなかった。~ これはロボット本体が大きく、それによって振れ幅も大きくなることが主な原因と考えられる~ 更に足回りを小型に改良できれば精度も上がっただろう。 だが悲しいかな、私にそのような技量は備わっていなかった。~ また、黒のマッキーでコースを書いたのだが部分にムラができて黒を黒と認識できない場合もあり調整に苦労した