[[2015a/Member]]
#contents
* 今回の課題について [#r00b1864]
今回の課題は次のコースをライントレースをすることである。
#ref(./2015a-mission2.png,50%)

私の担当はBからAのコースです。
ただラインをたどるだけではなく
( 1 ) B地点からA地点へ (Q交差点では直進、P三叉路では直進)
( 2 )PとQで2秒間停止
( 3 )エリアAの三叉路付近からボールをゴール(図の茶色の枠)に入れる。
と言う3つの条件を満たさなくてはいけない。
*ロボット本体について [#oeb7edf7]
ライントレースをしてコースを進む車体とボールをつかむためのアームに分けて説明する。

**車体について [#of6e552c]
#ref(./IMG_0555.JPG,10%)

付属のマニュアルに書いてあるロボットを使った。

モーターCを右のタイヤ(写真の下側)を、モーターAを左タイヤ(写真の上側)を動かすことにした。

二つのモーターを使って前進、後進、その場で旋回、片方のモーターだけを使ってゆっくり車体の向きを変えることができる。

OnRevで前進、OnFwdで後進する。




**アームについて [#x5441150]
#ref(./IMG_0552.JPG,10%)
決まった時間がたつとアームが下がりボールを捕まえるようになっている。

モーターBを使って動かす。


#ref(./IMG_0605.JPG,10%)
OnRevでアームを持ち上げる。赤い矢印はモーターB、青い矢印はアームの動く向き。


#ref(./IMG_0606.JPG,10%)
OnFwdでアームを下げる。赤い矢印はモーターB、青い矢印はアームの動く向き。







モーターBを回転させることでアームを下げてボールを捕まえたり、シュートの直前に捕まえるときと逆にモーターを回して開いたりする。




**全体 [#ld0055da]
#ref(./IMG_0551.JPG,20%)
この写真がロボットの完成品の全体である。

ボールをシュートする時はアームを持ち上げて一度後ろに下がってから、ボールに体当たりをする。



*一つ目のプログラムについて [#e500d461]
**定義について [#xa13aeb5]
 
***しきい値の基準とモーターを動かす時の力の定義、1回の判断でロボットを動作させる時間の定義 [#y00419af]

 #define threshold 45 //しきい値の基準
 #define HIPOWER 7
 #define LOWPOWER 2
 #define set_power_H SetPower(OUT_AC,HIPOWER); //モーターを動かす力、主に前進するとき
 #define set_power_L SetPower(OUT_AC,LOWPOWER); //モーターを動かす力、主に曲がるとき
 #define step 3 //1回の判断でロボットを動作させる時間

今回の課題ではモーターを動かす時の力は、前進の時は大きく曲がるときは小さくなっている。

1回の判断でロボットを動作させる時間はあまり考えず、うまくいったときのものをそのまま使った。


***ロボットの動きに関する定義 [#k121acd6]
 #define go_forward set_power_H; OnRev(OUT_AC); //前進
 #define turn_left1 set_power_L; OnRev(OUT_C);OnFwd(OUT_A); //左に旋回
 #define turn_left0 set_power_L; OnRev(OUT_C);Off(OUT_A); //ゆっくり左に曲がる
 #define turn_right1 set_power_L; OnRev(OUT_A);OnFwd(OUT_C); //右に旋回
 #define turn_right0 set_power_L; OnRev(OUT_A);Off(OUT_C); //ゆっくり右に曲がる

OnRevで前進、OnFwdで後進する。

モーターを動かす時の力は、前進の時は大きく曲がるときは小さくなっている。


***交差点の横断に関する定義 [#o3c6526d]
 #define max 5 //連続して右旋回できる最大値
 #define short_break Off(OUT_AC);Wait(10); //小休止
 #define closs_line OnRev(OUT_AC);Wait(20);short_break;Wait(190); //交差点を渡る。わたってから「小休止」と合わせて2秒間止まる。


連続して旋回できる最大値はあまり考えず、うまくいったときのものをそのまま使った。

講義中に使った資料に小休止が入っていたのでここにも書いてあるが、なくても良いと思う。

(1)PとQで2秒間停止 を成功させるために交差点を渡った後二秒間停止するようにプログラムを作った。


***タイマーに関する定義 [#lb42fec4]
 #define Qkara 600 //Qについてから交差点を渡るまでの時間。下の図の�,良�分
 #define Pmade1 210 //Qの交差点を渡ってからボールをつかむまでの時間。下の図の�△良�分
 #define Pmade2 810 //ボールを掴んでからPに着くまでの時間。下の図の��の部分
 #define last 1210 //PについてからエリアAにつくまでの時間。下の図の�い良�分

Qkaraを一つ目のタイマーで測る。Pmade1とPmade2を二つ目のタイマーで測る。lastを三つ目のタイマーで測る。

タイマーを使って交差点があっても交差点とみなさないプログラム(普通のライントレース)と交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース)を使い分ける。

Pmade1とPmade2の間でボールを捕まえる。

lastの後にボールをシュートするので合計で28秒くらいの時間がかかる。


***アームの動作に関する定義 [#ia3e5033]
 #define ageru OnRev(OUT_B);Wait(9);Off(OUT_B); //アームを上げる
 #define sageru  OnFwd(OUT_B);Wait(15);Off(OUT_B); //アームを下げる
 #define utu OnFwd(OUT_AC);Wait(50);ageru;OnRev(OUT_AC);Wait(50);Off(OUT_AC); //ボールをシュートする。

シュートする時はアームを持ち上げて一度後ろに下がってから、ボールに体当たりする。

OnRevでアームを持ち上げる。OnFwdでアームを下げる。

シュートする時はアームを持ち上げて一度後ろに下がってから、ボールに体当たりする。







**サブルーチンについて [#ha47a244]

***交差点があっても交差点とみなさないプログラム(普通のライントレース) [#dbad66d1]


下の図の�◆↓�を移動する時のプログラム。急カーブを交差点と誤認する心配がない。

線の右側を走るためにしきい値が小さいときは右に、大きいときは左に曲がるようにした。





まっすぐ進むときはモーターの力を大きく、曲がるときは小さくした。



 sub line_traceN() //交差点があっても交差点とみなさないプログラム(普通のライントレース)
 {
  if(SENSOR_2 < threshold -8) { turn_right1; } //しきい値が37より小さい時は右に旋回
 else if (SENSOR_2 < threshold -6) { turn_right0;} //しきい値が37以上で39より小さい時はゆっくり右に曲がる
 else if (SENSOR_2 < threshold -3) { go_forward;} //しきい値が39以上で42より小さい時は前進
 else if (SENSOR_2 < threshold -2) { turn_left0;} //しきい値が42の時はゆっくり左に曲がる
 else  { turn_left1;} //しきい値が43以上の時は左に旋回
 Wait(step); //1回の判断でロボットを動作させる時間
 }

しきい値が37より小さい時は右に旋回。しきい値が37以上で39より小さい時は左のタイヤだけ動かしてゆっくり右に曲がる。

しきい値が39以上で42より小さい時は前進。

しきい値が42の時は右のタイヤだけを動かしてゆっくり左に曲がる。しきい値が43以上の時は左に旋回。








***交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) [#x52d885b]

明るさの判断を繰り返しているときに連続して黒(しきい値37以下)が続いたらそこを交差点とみなして、車体の向きを直してから通過する。





下の図の� ↓い鯀�るプログラム。交差点を見つけて渡ることが出来るが、急カーブを交差点と誤認識してしまう。








黒が連続した時以外は上に書いてあるサブルーチンと同じ動きをして線の右側を走る。


 sub line_traceK() //交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) 
 {
  int nOnline=0; //カウンタを0にする。
   while (nOnline < max) { //黒が連続したとき以外は上のサブルーチンと同じ動きをする。
      if (SENSOR_2 <  threshold-8) {turn_right1; nOnline++;} //しきい値が37より小さい時は右に旋回しながらひとつカウントを増やす
       else {if (SENSOR_2 < threshold -6) { turn_right0;} //しきい値が37以上で39より小さい時はゆっくり右に曲がる
       else if (SENSOR_2 <  threshold-3) {go_forward;} //しきい値が39以上で42より小さい時は前進
       else if  (SENSOR_2 < threshold -2) {turn_left0;} //しきい値が42の時はゆっくり左に曲がる
       else {turn_left1;} //しきい値が43以上の時は左に旋回
       nOnline=0; } //しきい値が37以上の時はカウントをゼロにする 
   Wait(step); //1回の判断でロボットを動作させる時間
  } 


しきい値が37より小さいときだけひとつカウントを増やす。5回連続でしきい値が37より小さいとき、そこを交差点とみなす。

しきい値が37以上なら0から数えなおしをする。





しきい値が37より小さい値を5回以上連続でとるとそこを交差点と判断して、車体を道に対してまっすぐにしてから交差点を渡る。


    short_break //小休止
    turn_left1; Wait(max*step); //車体を道に対してまっすぐにするために左に旋回
    closs_line; //交差点を渡り2秒間停止する。小休止の中の0.1秒+1.9秒で計2秒停止する
    nOnline=0; // 渡り終わったらカウンタをリセットする。
  }

交差点を渡ったら2秒間停止する。小休止の中の0.1秒+1.9秒で計2秒停止する。

渡り終わったらカウンタをリセットする。


 



**task main() について [#vcaa89a9]

急カーブのあるところでは交差点があっても交差点とみなさないプログラム(普通のライントレース)を使う。急カーブがなく、渡るべき交差点のあるところでは交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) を使う。

タイマーを使って二つのサブルーチンを切り替えてゴールに向かう。


 task main()
 {
 SetSensor(SENSOR_2, SENSOR_LIGHT); //光センサーを2番に接続
 ClearTimer(0); //一つ目のタイマーで時間を計り始める

 while (FastTimer(0) <= Qkara) {line_traceK(); } //Qを通過までの間。赤い線�,良�分
                                                       PlaySound(SOUND_UP); //音を鳴らす
交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) でQに向かい、Qを通過する。

 ClearTimer(1); //2つ目のタイマーで時間を計り始める

ここで使うタイマーを変更します。


 while (FastTimer(1) <= Pmade1) {line_traceN();} //ボールの近くに移動。黄色の線�△良�分
 sageru; //ボールを捕まえる。黄色の×印のあたりでボールを捕まえる。
                                                       PlaySound(SOUND_UP); //音を鳴らす
 while (FastTimer(1) <= Pmade2) {line_traceN();} //Pに移動。オレンジ色の線��の部分
                                                        PlaySound(SOUND_UP); //音を鳴らす

Qを通過後、ボールの近くに移動してボールを捕まえる。そのあとPの近くまで移動する。急カーブを移動するため交差点があっても交差点とみなさないプログラム(普通のライントレース)を使う。


 ClearTimer(2); //3つ目のタイマーで時間を計り始める

もう一度使うタイマーを変更する。


 while (FastTimer(2) <= last) {line_traceK();} //Pを通過してエリアAに向かう水色の線�い良�分
                                                      PlaySound(SOUND_UP); //音を鳴らす

線の右を走るので、Pを交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) で通過してからそのままエリアAに向かう。

線の右側を走ればPからAの間にあるカーブを交差点とみなしてしまう事は無くなる。


 utu; //ボールをシュートする。水色の×印のあたりでシュートする。
 }

 エリアAに入る場所の三叉路を交差点とみなして進み、三叉路を closs_lineで渡ってからボールをシュートする。
 エリアAに入る場所の三叉路を交差点とみなして進み、三叉路を渡ってからボールをシュートする。

#ref(./b.JPG,20%)




3つのタイマーを使って時間ごとに行う動作を変える。

プログラムの横に書いてある番号と写真の番号が同じになっている。

音を鳴らすのはどのタイミングで次に動作に移ったかを分かり易くするためである。

Pを通過した後は急なカーブがないので、交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース)でエリアAまで進むことにした。

ボールをシュートする時にはアームをあげて体当たりしてゴールに入れるようになっている。

*問題点 [#oc37101c]

一つ目 光センサーを車体の先端に付けると車体が曲がったとき大きく位置が変わってしまい、コースを外れてしまう。

二つ目 アームがボールをつかむ前に弾き飛ばしてしまう。

三つめ コースBからAの左側を走ると三叉路Pを直進してしまい三叉路Pで2秒間停止することが困難。

四つ目 コースを進むうちに時間のずれが蓄積する。そのため思わぬところで次の動作に移ってしまい急カーブを交差点と判断したり、交差点を渡れなかったりした。

五つ目 まっすぐゴールに向かってシュートできない。
 

*解決方法 [#b6da9d3c]

一つ目 車体の中心近くに光センサーを取り付けて、車体が回転してもセンサーの位置が変わらないようにした。

二つ目 車体に固定されている下の黄色の部品は初めは
#ref(./IMG_0516.JPG,20%)
この写真のようになっていたが実際に動かしてみると下に固定された黄色の部品がボールを捕まえる前に弾き飛ばしてしまうことが多かったので、片方を外してボールを弾き飛ばさないようにした。

三つ目 線の右側を走るプログラムを作った。線の右側を走るとPとQは交差点であり、交差点を渡った後に二秒間停止するプログラムを作れば、確実に(2)PとQで2秒間停止を達成できる。

四つ目 タイマーを複数使うことで時間のずれが蓄積しないようにした。

五つ目 PからエリアAまで交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) 
で移動する。エリアAに入る場所の三叉路を交差点とみなして進む。車体がゴールにまっすぐ向いたままに保たれるので、まっすぐシュートを打てるようになった。

*二つ目のプログラムについて [#t46e46eb]

一口コメントを参考にして時間に頼らずにBからAまで線をたどるプログラムをつくった。

線をたどるだけならタイマーを使わずに済むが、ボールを捕まえてシュートするためにはタイマーを使わなければならなかった。



**考察と反省 [#v9cd4c52]

このプログラムを作ってからすぐにロボットを分解してしまったので、少しだけしかロボットを動かすことが出来ませんでした。



連続して右旋回できる最大値と1回の判断でロボットを動作させる時間をもう少し調整すれば成功する確率を上げられた思う。




**定義について [#y13c7921]

 #define threshold 45 //しきい値の基準
 #define HIPOWER 7
 #define LOWPOWER 2
 #define set_power_H SetPower(OUT_AC,HIPOWER); //モーターを動かす力、主に前進するとき
 #define set_power_L SetPower(OUT_AC,LOWPOWER); //モーターを動かす力、主に曲がるとき
 #define step 3 //1回の判断でロボットを動作させる時間
 #define go_forward set_power_H; OnRev(OUT_AC); //前進
 #define turn_left1 set_power_L; OnRev(OUT_C);OnFwd(OUT_A); //左に旋回
 #define turn_left0 set_power_L; OnRev(OUT_C);Off(OUT_A); //ゆっくり左に曲がる
 #define turn_right1 set_power_L; OnRev(OUT_A);OnFwd(OUT_C); //右に旋回
 #define turn_right0 set_power_L; OnRev(OUT_A);Off(OUT_C); //ゆっくり右に曲がる
 #define short_break Off(OUT_AC);Wait(10); //小休止
 #define closs_line OnRev(OUT_AC);Wait(20);short_break;Wait(190); //交差点を渡る。わたってから「小休止」と合わせて2秒間止まる。
 #define ageru OnRev(OUT_B);Wait(9);Off(OUT_B); //アームを上げる
 #define sageru  OnFwd(OUT_B);Wait(15);Off(OUT_B); //アームを下げる
 #define utu OnFwd(OUT_AC);Wait(50);ageru;OnRev(OUT_AC);Wait(50);Off(OUT_AC); //ボールをシュートする。

ほとんどの定義は一つ目のプログラムと同じである。説明は上に書いてある。



 #define max 12 //連続して右旋回できる最大値
 #define bmade 810 //ボールを捕まえるまで
 #define last 1810 //エリアAまで

一つ目のプログラムとは異なる定義。

連続して右旋回できる最大値を増やすことで急カーブを交差点と誤認識せず、交差点を渡れるようにした。

タイマーを使ったのはボールの近くに行くまでの時間を計る事と

もう一つはエリアAについてエリアAに入る三叉路を渡った後のタイミングでボールをシュートできるようにするために使った。




**サブルーチンについて [#s7c13e45]

 sub line_traceK() //交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) 
 {
 int nOnline=0; //カウンタを0にする。
  while (nOnline < max) { //黒が連続したとき以外は上のサブルーチンと同じ動きをする。
     if (SENSOR_2 <  threshold-8) {turn_right1; nOnline++;} //しきい値が37より小さい時は右に旋回しながらひとつカウントを増やす
      else {if (SENSOR_2 < threshold -6) { turn_right0;} //しきい値が37以上で39より小さい時はゆっくり右に曲がる
      else if (SENSOR_2 <  threshold-3) {go_forward;} //しきい値が39以上で42より小さい時は前進
      else if  (SENSOR_2 < threshold -2) {turn_left0;} //しきい値が42の時はゆっくり左に曲がる
      else {turn_left1;} //しきい値が43以上の時は左に旋回
      nOnline=0; } //しきい値が37以上の時はカウントをゼロにする 
  Wait(step); //1回の判断でロボットを動作させる時間
 } 
  short_break //小休止
   turn_left1; Wait(max*step); //車体を道に対してまっすぐにするために左に旋回
   closs_line; //交差点を渡り2秒間停止する。小休止の中の0.1秒+1.9秒で計2秒停止する
   nOnline=0; // 渡り終わったらカウンタをリセットする。
  }


連続でしきい値が37を下回った時にそこを交差点とみなすサブルーチン、一つ目のプログラムと同じである。説明は上に書いてある。

**task main について [#qf74b6d1]

サブルーチンは一つしかないので一つ目のプログラムと違い交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) を使い続ける。



タイマーを使ったのはボールの近くに行くまでの時間を計る事と

もう一つはエリアAについてエリアAに入る三叉路を渡った後のタイミングでボールをシュートできるようにするために使った。


 task main()
 {
 SetSensor(SENSOR_2, SENSOR_LIGHT); //光センサーを2番に接続
 ClearTimer(0); //一つ目のタイマーで時間を計り始める
 while (FastTimer(0) <= bmade) {line_traceK(); } //ボールを捕まえるまでの間。赤い線の部分
                                                      PlaySound(SOUND_UP); //音を鳴らす

交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) でQに向かい、Qを通過する。


 sageru; //ボールを捕まえる。黄色の×印のあたりでボールを捕まえる。
                                                      PlaySound(SOUND_UP); //音を鳴らす



 ClearTimer(1); //2つ目のタイマーで時間を計り始める

ここで使うタイマーを変更する。

 while (FastTimer(1) <= last) {line_traceK();} //エリアAに着くまで水色の線の部分
                                                     PlaySound(SOUND_UP); //音を鳴らす

ボールを捕まえた後Pに向かう。 連続して右旋回できる最大値を上げてあるので急カーブを交差点とみなさずに進むことが出来る。

Pを交差点とみなして渡りエリアAに向かう。

 utu; //ボールをシュートする。水色の×印のあたりでシュートする。
 }

 エリアAに入る場所の三叉路を交差点とみなして進み、三叉路を closs_lineで渡ってからボールをシュートする。
 エリアAに入る場所の三叉路を交差点とみなして進み、三叉路を渡ってからボールをシュートする。


#ref(./p.JPG,20%)

 




*問題点(一つ目のプログラムの時に見つけた五つの問題点がこちらのプログラムでも起きるが、同じ方法で解決できる。) [#ja3cd6a6]




一つ目 光センサーを車体の先端に付けると車体が曲がったとき大きく位置が変わってしまい、コースを外れてしまう。

二つ目 アームがボールをつかむ前に弾き飛ばしてしまう。

三つめ コースBからAの左側を走ると三叉路Pを直進してしまい三叉路Pで2秒間停止することが困難。

四つ目 コースを進むうちに時間のずれが蓄積する。そのため思わぬところで次の動作に移ってしまい急カーブを交差点と判断したり、交差点を渡れなかったりした。

五つ目 まっすぐゴールに向かってシュートできない。
 

六つ目 交差点を曲がり道と誤認識してしまう。



*解決方法 [#b6da9d3c]

一つ目 車体の中心近くに光センサーを取り付けて、車体が回転してもセンサーの位置が変わらないようにした。

二つ目 車体に固定されている下の黄色の部品は初めは
#ref(./IMG_0516.JPG,20%)
この写真のようになっていたが実際に動かしてみると下に固定された黄色の部品がボールを捕まえる前に弾き飛ばしてしまうことが多かったので、片方を外してボールを弾き飛ばさないようにした。

三つ目 線の右側を走るプログラムを作った。線の右側を走るとPとQは交差点であり、交差点を渡った後に二秒間停止するプログラムを作れば、確実に(2)PとQで2秒間停止を達成できる。

四つ目 タイマーを複数使うことで時間のずれが蓄積しないようにした。

五つ目 PからエリアAまで交差点を渡ることが出来るプログラム(交差点があれば交差点を渡るライントレース) 
で移動する。エリアAに入る場所の三叉路を交差点とみなして進む。車体がゴールにまっすぐ向いたままに保たれるので、まっすぐシュートを打てるようになった。

六つ目 連続して右旋回できる最大値が大きすぎるのが原因だった。連続して右旋回できる最大値を少し小さくすることで解決した。(20から始めて12まで下げた。)




*感想 [#p726a8ff]

大体28秒くらいでスタートからシュートするところまでできた。最後までできて良かった。

他のチームのように付属のマニュアルにないロボットを作れないのが残念だった。

OnRevで前進、OnFwdで後進する。どうしてこうなるのか分からない。

「Pmade」と「Qmade」と言う定義をそれぞれ「Pまで」と「Qまで」のつもりで作ったが、チームのメンバーに英単語のmadeと勘違いされてしまった。もう少し分かり易いものを作るべきだった。「Qまで」は不要になったので消した。


ロボコンの後に書き直しているので、以前のものと少し違います。次の動作に移るタイミングやシュートの成功率が上がるようになっています。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS