#contents *課題3 [#c595dffd] 第三回目の課題は、懐中電灯の場所を探しボールを当てるというもの。課題内容は[[こちら:http://yakushi.shinshu-u.ac.jp/robotics/?2015a%2FMission3]]を参照。 *ロボットについて [#f0e02078] 課題3のロボットはは、課題2で使用したロボットをベースにした。ベースにしたロボットは[[課題2のロボット:http://yakushi.shinshu-u.ac.jp/robotics/?2015a%2FMember%2Fahiru%2FMission2]]を参照。 課題3の内容を遂行させるため、特に光センサーへの光の入り方を工夫した。以下、今回の変更点を詳細に記載する。 **今回の変更点 [#rfb64895] 第三回目の課題内容に沿わせるため、第二回目のロボットでは光センサーを下向きに使用していたが、今回は前方にある光源を光センサーによって判断するため、光センサーを横向きに固定し直した。 また、課題2では、アームの挙動を制限しすぎたと感じたため、アームの挙動可能区域に余裕をもたせてある(アームの回転可能角度が100°程度だったものを150°程度に向上させた)。 ***光の入射制限 [#p5d05678] #ref(./mission3_002.JPG,50%) 光を前方からのみ入るように、光センサーの左右に壁を取り付けた。そのようにすることで、斜めからの光入射を抑えられ、より正確な位置が把握できるようになった。 #ref(./mission3_001.JPG,50%) また、天井の電灯等からの直接光を抑えるために、光センサーの上にもブロックを取り付け、光センサーの受光部が影になるようした。また、そのブロックには上の写真にあるような90°の壁を作れるものを使用し、ボールの位置固定にも役立てた。 ***ボールによる受光阻害対処 [#i2431a53] 前方にボールを固定する形式のため、課題2のロボットではボールによって光センサーの受光が阻害されてしまっていた。実際に、光センサーの位置変更のみを行った課題2のロボットでは、ボールの受光阻害により試行毎にかなりの誤差が生じてしまった。それを改善すべく、ボールの固定位置を変更する必要があった。 #ref(./mission3_004.JPG,50%) #ref(./mission3_003.JPG,50%) そこで、上記の写真のように、アームを短く改良し、ボールを持ち上げるような形式をとった。このようにすることで、前方にある光源からの光の通路を確保し、試行毎の誤差を最小限にした。 課題2のロボット作成の際に、既にボールを固定化していたため、今回はボール固定の吟味は不要となり、時間短縮に繋がった。 *プログラムについて [#xd16f873] **第一段階プログラミング [#x5f30d7e] まずは課題に沿った最低限の内容のプログラムを完成させることを目標とした。 #define TURN_TIME 280 //一回転にかかる時間 #define turn_right OnFwd(OUT_A); OnRev(OUT_C); #define turn_left_back OnFwd(OUT_C); OnRev(OUT_A); Wait(FastTimer(1)); //FastTimer(1)で計測された時間逆回転 #define go_forward(t) OnFwd(OUT_AC); Wait(t); Off(OUT_AC); #define go_back(t) OnRev(OUT_AC); Wait(t); Off(OUT_AC); #define short_break Off(OUT_AC); Wait(50); //滑りを防ぐための間隔 #define arm_up OnRev(OUT_B); Wait(45); Off(OUT_B); sub shoot() { //ボールを懐中電灯に当てる動作 arm_up; go_forward(100); go_back(100); } task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); ClearTimer(0); ClearTimer(1); int Smin= 10; while (FastTimer(0) <= TURN_TIME) { //一回転している間に繰り返す内容 turn_right; if(SENSOR_1 > Smin) { //光の最大値計測 Smin=SENSOR_1; //最大値を記録 ClearTimer(1); //最大値から回転終了までの時間計測 } } turn_left_back; //光の最大値の観測地点まで戻る short_break; shoot(); //シュート } ***第一段階プログラム説明 [#x8a9b05d] ここでは、一周するうちにどこが光の強さの最大値かを測定し、一周し終えた時、光の最大値だった場所まで戻るというプログラミングを行った。 光の強さの記録方法として、「測定した値が、その前に設定した最大値より大きければ、その値を最大値として書き換えなさい」というプログラムを、一周する間に幾度も繰り返させる方式をとった。 また、その光の最大値だった部分を0秒としてカウントを初め、最後に書き換えられた最大値の場所から、光測定のための回転を終えるまでの時間を計測した(最大値が更新される毎にタイマーも0秒に戻されるという設定)。光測定のための回転を終えた時に、最大値からの時間を計測していたタイマーに記録された時間の分だけ逆回転することで、光の最大値(光源の方角)へ向き直すことができる。 そこからボールを放ち、懐中電灯に当てるというプログラムを書いた。 ***第一段階プログラムを用いた時の可視化 [#o48c8fe1] 以下の画像は、上記のプログラムを用いた時の再現、簡略説明を兼ね可視化したgif画像である。 #ref(./program_01.gif) **第二段階プログラミング [#t1563708] 第一段階のプログラミングを元に、より正確に位置を把握するためのプログラムである。 以下、第二段階プログラム(完成版)を記載する。 #define TURN_TIME_F 280 //一度目の回転時間(360°回転) #define TURN_TIME_S 50 //二度目の回転時間(光の最大値付近での再計測) #define turn_right OnFwd(OUT_A); OnRev(OUT_C); #define turn_left_back(t) OnFwd(OUT_C); OnRev(OUT_A); Wait(t); //FastTimerを2つ入れる必要があるため、Wait(t)へ変更 #define go_forward(t) OnFwd(OUT_AC); Wait(t); Off(OUT_AC); #define go_back(t) OnRev(OUT_AC); Wait(t); Off(OUT_AC); #define short_break Off(OUT_AC); Wait(50); #define arm_up OnRev(OUT_B); Wait(45); Off(OUT_B); sub shoot() { //ボールを懐中電灯に当てる動作 arm_up; go_forward(100); go_back(100); } ※sub shoot()は変更していない。 task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); ClearTimer(0); ClearTimer(1); int Smin= 10; while (FastTimer(0) <= TURN_TIME_F) { //一度目の回転(360°回転)の内に繰り返す内容 turn_right; if(SENSOR_1 > Smin) { //一度目の光の最大値計測 Smin=SENSOR_1; //最大値を記録 ClearTimer(1); //最大値から一度目の回転終了までの時間計測 } } turn_left_back(FastTimer(1)+20); //計測された最大値から少し多めに戻る short_break; //////////////////////////// // 以下主な変更(追加)点 //////////////////////////// ClearTimer(2); ClearTimer(3); int Tmin= 10; while (FastTimer(2) <= TURN_TIME_S) { turn_right; if(SENSOR_1 > Tmin) { //二度目の光の最大値計測 Tmin=SENSOR_1; //最大値を記録 ClearTimer(3); //最大値から二度目の回転終了までの時間計測 Tmin=SENSOR_1; //最大値を記録 ClearTimer(3); //最大値から二度目の回転終了までの時間計測 } } turn_left_back(FastTimer(3)); //光の最大値の観測地点まで戻る short_break; shoot(); //シュート } ***第二段階プログラムの説明 [#ucfd2615] 第二段階目のプログラムは、第一段階目のプログラムではカバーしきれないモーターの回転出力によって生じる誤差を、最小限にするためのプログラムである。 本体が一回転する内に光の最大値を探すという課題であるが、回転し始めてから90°のところに光源があるのと270°のところに光源があるのでは、一回転し終えてから戻るまでの時間に大きな差がある。 回転し始めてから270°のところにある場合、タイマーによって計測される時間は比較的短いため、戻るための回転角は小さい。よって、戻る時間が短い場合はモーターの出力に関する誤差は少なくなる。 だが、回転し始めてから90°のところにある場合、タイマーによって計測される時間が270°に比べて大分長い。よって戻るための回転角が大きく、戻る時間も長くなるため、モーターの出力に関する誤差が顕著になってくる。 それを補うために、一度計測した最大値付近に再び戻り、その付近を小さい範囲で再び計測し直すというプログラムを作成した。 このようにすることで、360°どの範囲に光源がある場合でも、正確な位置判断が可能になった。 ***第二段階プログラムを用いた時の可視化 [#i9707d29] 下の画像は[[第一段階プログラムを用いた時の可視化>#o48c8fe1]]同様に作成した説明用gif画像である。 #ref(./program_02.gif) *製作時間 [#w0a390ae] ロボット本体・・・1時間 プログラミング(試走含む)・・・1.5時間 *課題を通じての反省 [#vea0fd4f] 「このようにプログラミングをすれば、このような動作になる」ということがプログラミングをしながら明確なイメージできるようになっており、このゼミ全体を通じての成長を感じられた。今までは参考資料に目を通しながら作成していたが、今回は目を通す必要もなく、スムーズに作成できた。 このゼミでは、全てのロボット作りに携わっていたため、ロボットとプログラミングの食い違いは比較的少なかったように思える。プログラムを理解するだけでなく、そのプログラムで実際に動くロボットの構造、性質を理解することが最善の動作に繋がると感じた。これから工学を学んでいく上で、ソフトとハードの関わりをもっと深く学んでいく必要がある。このゼミで得た知識や経験を今後の学習に活かしていけるよう、努力したい。