#author("2020-01-09T16:00:11+09:00","kzy_k","kzy_k") [[2019b/Member]] #contents *課題2の概要 [#u3a97da7] -図の赤い線の経路を黒い線にそって動くロボットを作成する。 #ref(2019b/Member/kzy_k/Mission2/2019b-mission2'.png,100%,課題図) -ただし、交差点や丁字路では1秒一時停止する。~ また、I地点にある球をつかみI'地点で離す。 *ロボットの説明 [#y255cad1] -ロボットの全体像は以下である #ref(2019b/Member/kzy_k/Mission2/IMG_20191220_172047.jpg,10%,ロボ図) #br #br -黒い線に沿って行くためには線を検知しなければならないので光学センサーを車輪の間にできるだけ近づけて装着する。~ あまり車輪から離れていると、カーブのときなどにセンサーが大きくずれてしまいトレースができないからである。 #ref(2019b/Member/kzy_k/Mission2/IMG_20191211_201823.jpg,10%,センサー図) #br #br -ボールをつかむ機構はギアでモーターの前後の回転を左右の回転に変換することで実現させた。 #ref(2019b/Member/kzy_k/Mission2/gear.png,60%,ギア図) *プログラムの説明 [#g3d09da0] **ライントレース [#p0575474] -今回の課題の主要部分である。~ 基本原理として取り付けたセンサーにより得た地面の明るさの値により本体の動きを制御して線上を走らせる。~ センサーの値が35以下だと左旋回(左の車輪を前に回転、右の車輪をを後ろに回転)~ 43以下で左折(左の車輪を前に回転、右の車輪は停止)~ 57以下で直進~ 65以下で右折~ 65以上で右旋回~ センサーの値から判断して動くということwhile文でループすることで、本体が常に線の左側に沿って進むようになる。 #ref(2019b/Member/kzy_k/Mission2/トレース.png,40%,ライントレース) #br #br -さらにこれに交差点を認識する機構を組み込む。~ 交差点に差し掛かるとセンサーは通常より長い間黒(センサー値が35以下)を認識し続けるので、これを利用して黒の時間が一定時間を超えればトレースのループから抜けるようにする。~ 具体的には、t0という変数にまず初めにループの外で現在時刻を記録させる。そして左旋回(センサーが35以下)を実行してるとき以外で逐一t0を更新させる。~ そしてwhileのループが成立するために現在の時刻とt0の差がある値以下という条件を付けくわえれば、ずっと黒だとループから抜けることができる。 #ref(2019b/Member/kzy_k/Mission2/交差点.png,40%,交差点) #br #br -ただし、急カーブなどは交差点でないがずっと黒であり続けるので上の機構が働きループから抜けてしまう。それを阻止するため、ループが始まってからある時間までは、ループを抜けるという機構を実行させなくする。~ 具体的には、ループの外でt_startという変数にCurrentTick()で現在時刻を記録させる。そうすればCurrentTick()-t_start<t_minはループが始まってからの時間となり、whileのループが成立するために、その始まってからの時間がある値より小さいという条件を論理和で上の条件とつなげば、初めはずっと黒でもループから抜けないということが実現できる。 #br #br -また、ループを強制終了させるという機構を組み込む。上と同様にt_startを使いループが始まってからの時間が強制終了させたい時間以下であるという条件をこれまでの条件にまとめて論理積でつなげば実現できる。 #br #br -以下がこれらをすべてまとめたライントレースのプログラムである。ここではループから抜けるようなずっと黒である時間を100、また初めのループからの脱出を無視する時間t_min、強制終了時間t_maxを引数として指定している。 #define t 50 #define SPEED 30 void gf (long x,long y){ OnFwd(OUT_C,x);OnFwd(OUT_B,y); } void turn_right (long z){//右回転 OnFwd(OUT_C,25);OnFwd(OUT_B,-20);Wait(z);Off(OUT_BC); } void turn_left (long w){//左回転 OnFwd(OUT_C,-25);OnFwd(OUT_B,20);Wait(w);Off(OUT_BC); } void left_line(long t_min,long t_max) { SetSensorLight(S1); long t0=CurrentTick(); long t_start=CurrentTick(); while((CurrentTick()-t0<=100||CurrentTick()-t_start<t_min)&& (CurrentTick()-t_start<t_max)){//100以上黒で外れるが始めてからtmin以内だったら外れない。tmax経ったら強制終了 if(SENSOR_1 < (t-15)){//真っ黒 gf(-SPEED,SPEED);//左旋回 } else{ t0=CurrentTick(); if(SENSOR_1<(t-7)){ //黒 gf(0,SPEED);//左折 } else if(SENSOR_1 <(t+7)){ //灰 gf(SPEED,SPEED); //直進 } else if(SENSOR_1>t+15){ //白 gf(SPEED,0); //右折 } else{ //真っ白 gf(SPEED,-SPEED); //右旋回 } } //else } //while Off(OUT_BC); } これは線の左側をトレースするプログラムであるが、課題を達成するためには右側をトレースするプログラムも必要である。右側のライントレースは左と動きを対称的に逆にするだけでよい。つまり左旋回、左折を右旋回、右折。右旋回、右折を左折、左旋回にする。 **ボールをつかむ [#ldbcd658] -ボールをつかむ機構はセンサーを使いボールを認識させて掴むという案もあったが、センサーの感度が悪く難しかったので、時間指定をして掴むようにした。~ まず、H地点から少し進む~ ボールをつかむ~ 線をまたぎ、右側をH'の交差点に差し掛かるまでトレースする。この際紙の境界線の少しの出っ張りを越えるが、ここで止まってしまうことがあったためt_minで無視させた。~ 回れ右をする~ ボールを離す~ 少しバックをする~ 周れ左をする~ この過程を時間や周る角度を調節することで実現した。 #ref(2019b/Member/kzy_k/Mission2/ボール掴み.png,100%,ボール掴み図) #br -以下がプログラムである #define SPEED 30 #define halfturn_time 3000 #define quarterturn_time 500 #define catch_release_time 1900 void gf (long x,long y){ OnFwd(OUT_C,x);OnFwd(OUT_B,y); } void turn_right (long z){//右回転 OnFwd(OUT_C,25);OnFwd(OUT_B,-20);Wait(z);Off(OUT_BC); } void turn_left (long w){//左回転 OnFwd(OUT_C,-25);OnFwd(OUT_B,20);Wait(w);Off(OUT_BC); } void release (){ OnFwd(OUT_A,30);Wait(catch_release_time);Off(OUT_A); } void catch(){ OnFwd(OUT_A,-30);Wait(catch_release_time);Off(OUT_A); } void catch_ball()//ボールつかみ { gf(SPEED,SPEED);Wait(500); gf(0,0);catch();//つかむ gf(20,0);Wait(1000);right_line(3000,100000);//置く向こう側まで進む turn_right(halfturn_time);//uターン gf(0,0);release();//はなす gf(-SPEED,-SPEED);Wait(t_3);//バック turn_left(quarterturn_time);//少しターン } **つなぎのプログラム [#hdf28aee] -まっすぐ線を越えるためのプログラムと少し回転して線を渡るプログラムをあらかじめ作っておく。 void closs_line1()//線を渡る { gf(20,20);Wait(t_4); } void closs_line2()//線を渡り向こうへ { gf(20,0);Wait(1300); } **メインプログラム [#x141ec72] *感想 [#c7b4dde9] *改善点 [#p8f38731]