課題1の車軸回りを参考にして、同じように細めに作りました。
前回の課題であった壊れやすさを補うために様々な改良が施されています。
たとえばL字型の部品を使ってモーターを固定している点などです。
前回より強固な車軸ができたと思います。
ここが一番の課題でした。
最初の計画ではプーリの回転を使った機構を考えていましたが、思うようにボールをつかめなかったので急遽変更しました。
受け取るときはふたを被せるようにしてボールを押さえつけることで固定します。
打ち出すときはふたの一番奥についている棒ではじいて打ち出します。
打ち出す棒がまっすぐなのでボールがふたの中のどの位置にあってもまっすぐに打ち出すことがで来ます。
この機構を動かすためにはモーターを非常に不安定な場所につけなければいけません。
また、モーターがうまく収まらず、歯車同士のかみ合わせが非常に悪くなってしまいました。
このかみ合わせを直すために大小さまざまな歯車を組み合わせました。
これによって何とか動くまでにかみ合わせを修正できました。
歯車をうまくかみ合わせるのが非常に難しく、最終的に少し歯車間に隙間ができてしまいました。
また、ライントレース用の光センサーと車軸との距離をできるだけ近付くようにするのが大変でした。
#define BLACK_high 36 //一番黒いしきい値 #define BLACK_low 38 //少し黒いしきい値 #define WHITE_low 42 //少し白いしきい値 #define WHITE_high 44 //一番白いしきい値 #define turn_left_senkai OnRev(OUT_A); OnFwd(OUT_C); //左旋回 #define turn_left_kaiten Off(OUT_A); OnFwd(OUT_C); //左前進 #define turn_right_kaiten OnFwd(OUT_A); Off(OUT_C); //右前進 #define turn_right_senkai OnFwd(OUT_A); OnRev(OUT_C); //右旋回 #define go_fwd OnFwd(OUT_AC); //前進 #define short_break Off(OUT_AC); Wait(100); //小休止 #define SHOTBALL OnFwd(OUT_B); Wait(500); //ボールを撃つ #define CATCHBALL OnRev(OUT_B); Wait(500); //ボールを受け取る #define time2 10 //シュートしない側が交差点から一回目に前進する時間 #define time3 10 //シュートしない側が交差点から二回目に前進する時間 #define nMAX 300 //交差点と判断する基準 #define STEP 1 //ライントレース時の待ち時間 task main(){ SetSensor(SENSOR_2,SENSOR_LIGHT); int nOnline=0; int nCross=0; int counter=0; while (nCross < 2) { //交差点までのライントレース while (nOnline < nMAX) { if(SENSOR_1 < BLACK_high) { turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low) { turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); //交差点を感知してwhileから抜ける short_break; nCross++; nOnline=0; } turn_left_senkai; Wait(70); until(FastTimer(1) > 4500); CATCHBALL; turn_left_senkai; Wait(70); while (FastTimer(0) <= time2){ if(SENSOR_1 < BLACK_high) { turn_right_senkai; } else if (SENSOR_1 < BLACK_low) { back_turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { back_turn_left_kaiten; } else { turn_left_senkai; } Wait(STEP); } nCross=0; turn_right_senkai; wait(70); until(FastTimer(1) > 6000); SHOTBALL; turn_left_senkai; Wait(70); while (nCross < 1){ while (nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low){ turn_right_kaiten; } else if (SENSOR_1 < WHITE_low){ go_fwd } else if (SENSOR_1 < WHITE_high){ turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); short_break; nCross++; nOnline=0; } while (FastTimer(0) <= time2){ if(SENSOR_1 < BLACK_high) { turn_right_senkai; } else if (SENSOR_1 < BLACK_low) { back_turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { back_turn_left_kaiten; } else { turn_left_senkai; } Wait(STEP); } turn_right_senkai; Wait(70); until(FastTimer(1) > 7500); CATCHBALL; turn_left_senkai; Wait(70); while(counter < 1){ while(nOnline < nMAX){ if (SENSOR_1 < 38){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < 39){ turn_right_kaiten; } else if (SENSOR_1 < 42){ go_fwd; } else if (SENSOR_1 < 44){ turn_left_kaiten; } else { turn_left_senkai; } } nOnline=0; } Wait(STEP); } short_break; turn_left_senkai; Wait(150); go_rev; Wait(100); SHOTBALL; }
#define BLACK_high 36 //一番黒いしきい値 #define BLACK_low 38 //少し黒いしきい値 #define WHITE_low 42 //少し白いしきい値 #define WHITE_high 44 //一番白いしきい値 #define turn_left_senkai OnRev(OUT_A); OnFwd(OUT_C); //左旋回 #define turn_left_kaiten Off(OUT_A); OnFwd(OUT_C); //左前進 #define turn_right_kaiten OnFwd(OUT_A); Off(OUT_C); //右前進 #define turn_right_senkai OnFwd(OUT_A); OnRev(OUT_C); //右旋回 #define go_fwd OnFwd(OUT_AC); //前進 #define short_break Off(OUT_AC); Wait(100); //小休止 #define SHOTBALL OnFwd(OUT_B); Wait(500); //ボールを撃つ #define CATCHBALL OnRev(OUT_B); Wait(500); //ボールを受け取る #define TURNSTEP 10 //横のセンサーを使う時の繰り返しの待ち時間 #define time2 10 //シュートしない側が交差点から一回目に前進する時間 #define time3 10 //シュートしない側が交差点から二回目に前進する時間 #define nMAX 300 //交差点と判断する基準 #define STEP 1 //ライントレース時の待ち時間 task main(){ SetSensor(SENSOR_2,SENSOR_LIGHT); int nOnline=0; int nCross=0; ClearTimer(0); while(nCross <= 1){ while(nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_left_senkai ; nOnline++ ; } else if(SENSOR_2 < BLACK_low){ turn_left_kaiten; } else if(SENSOR_2 < WHITE_low){ go_fwd; } else if(SENSOR_2 < WHITE_high){ turn_right_kaiten; } else { turn_right_senkai; } } nOnline == 0; nCross ++; short_break; cross_line; } nCross=0; go_fwd; Wait(500); OnRev(OUT_A); OnFwd(OUT_C); Wait(100); //ボールに向く CATCHBALL; OnFwd(OUT_AC); Wait(200); //ボールを取る until(SENSOR_1 < BLACK_low){ turn_left_kaiten; } //コースに戻る while(nCross <= 1){ if(SENSOR_1 < BLACK_high){ turn_left_senkai; nOnline ++; } else if(SENSOR_2 < BLACK_low){ turn_left_kaiten; } else if(SENSOR_2 < WHITE_low){ go_fwd; } else if(SENSOR_2 < WHITE_high){ turn_right_kaiten; } else { turn_right_senkai; } } nCross=0; turn_left_senkai; Wait(70); until(FastTimer(1) > 4500); SHOTBALL; turn_right_senkai; Wait(70); while(nCross <= 1){ if(SENSOR_1 < BLACK_high){ turn_left_senkai; nOnline ++; } else if(SENSOR_2 < BLACK_low){ turn_left_kaiten; } else if(SENSOR_2 < WHITE_low){ go_fwd; } else if(SENSOR_2 < WHITE_high){ turn_right_kaiten; } else { turn_right_senkai; } } nCross=0; while (FastTimer(0) <= time2){ if(SENSOR_1 < BLACK_high) { turn_right_senkai; } else if (SENSOR_1 < BLACK_low) { back_turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { back_turn_left_kaiten; } else { turn_left_senkai; } Wait(STEP); } turn_left_senkai; Wait(70); until(FastTimer(1) > 6000); CATCHBALL; turn_right_senkai; Wait(70); while (nCross < 1){ while (nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low){ turn_right_kaiten; } else if (SENSOR_1 < WHITE_low){ go_fwd } else if (SENSOR_1 < WHITE_high){ turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); short_break; nCross++; nOnline=0; } turn_left_senkai; Wait(70); until(FastTimer(1) > 7500); SHOTBALL; }
#define BLACK_high 36 //一番黒いしきい値 #define BLACK_low 38 //少し黒いしきい値 #define WHITE_low 42 //少し白いしきい値 #define WHITE_high 44 //一番白いしきい値 #define turn_left_senkai OnRev(OUT_A); OnFwd(OUT_C); //左旋回 #define turn_left_kaiten Off(OUT_A); OnFwd(OUT_C); //左前進 #define turn_right_kaiten OnFwd(OUT_A); Off(OUT_C); //右前進 #define turn_right_senkai OnFwd(OUT_A); OnRev(OUT_C); //右旋回 #define go_fwd OnFwd(OUT_AC); //前進 #define short_break Off(OUT_AC); Wait(100); //小休止 #define SHOTBALL OnFwd(OUT_B); Wait(500); //ボールを撃つ #define CATCHBALL OnRev(OUT_B); Wait(500); //ボールを受け取る #define time2 10 //シュートしない側が交差点から一回目に前進する時間 #define time3 10 //シュートしない側が交差点から二回目に前進する時間 #define nMAX 300 //交差点と判断する基準 #define STEP 1 //ライントレース時の待ち時間
まずはライントレース時のしきい値とライントレースするときによく使う一連の動きを定義しておきます。
続いてこの課題で重要な動きであるボールの発射と受け取りの動作を定義します。
最後に時間関係の定数を定義します。
task main(){ SetSensor(SENSOR_2,SENSOR_LIGHT); int nOnline=0; int nCross=0; int counter=0; while (nCross < 2) { //交差点までのライントレース while (nOnline < nMAX) { if(SENSOR_1 < BLACK_high) { turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low) { turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); //交差点を感知してwhileから抜ける short_break; nCross++; nOnline=0; } turn_left_senkai; Wait(70); until(FastTimer(1) > 4500); CATCHBALL; turn_left_senkai; Wait(70);
まずはスタート位置から二回交差点をこえるまでライントレースを行います。
二回目の交差点をこえたら左に旋回してパスをもらう準備をします。
スタートしてからの時間がある点をこえたときにパスをします。
そのままボールを持ちながら進む方向へと向きを変えます。
while (nCross < 1){ while (nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low){ turn_right_kaiten; } else if (SENSOR_1 < WHITE_low){ go_fwd } else if (SENSOR_1 < WHITE_high){ turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); short_break; nCross++; nOnline=0; } while (FastTimer(0) <= time2){ if(SENSOR_1 < BLACK_high) { turn_right_senkai; } else if (SENSOR_1 < BLACK_low) { back_turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { back_turn_left_kaiten; } else { turn_left_senkai; } Wait(STEP); } nCross=0; turn_right_senkai; wait(70); until(FastTimer(1) > 6000); SHOTBALL; turn_left_senkai; Wait(70);
第一パスを終えたらそのままライントレースを行い交差点まで行きます。
交差点をこえた時から時間をはかり二つの交差点の中心までライントレースします。
中心についたら右に旋回してパスを待ちます。
再びスタートしてからの時間がある点をこえたときにパスをします。
パスを打ち終わったら元の向きに戻ります。
while (nCross < 1){ while (nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low){ turn_right_kaiten; } else if (SENSOR_1 < WHITE_low){ go_fwd } else if (SENSOR_1 < WHITE_high){ turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); short_break; nCross++; nOnline=0; } while (FastTimer(0) <= time2){ if(SENSOR_1 < BLACK_high) { turn_right_senkai; } else if (SENSOR_1 < BLACK_low) { back_turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { back_turn_left_kaiten; } else { turn_left_senkai; } Wait(STEP); } turn_right_senkai; Wait(70); until(FastTimer(1) > 7500); CATCHBALL; turn_left_senkai; Wait(70);
ここは第一から第二とほぼ同じ動きをします。
違うところは交差点から時間で進むときの距離が短いことです。
while(counter < 1){ while(nOnline < nMAX){ if (SENSOR_1 < 38){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < 39){ turn_right_kaiten; } else if (SENSOR_1 < 42){ go_fwd; } else if (SENSOR_1 < 44){ turn_left_kaiten; } else { turn_left_senkai; } } nOnline=0; } Wait(STEP); } short_break; turn_left_senkai; Wait(150); go_rev; Wait(100); SHOTBALL; }
まずはゴール近くの交差点までひたすらライントレースをします。
この交差点を基準にすることで時間指定するよりも誤差が格段に減り、シュート成功確率も跳ね上がります。
あとは左に旋回し、後ろに少し下がってからシュートを打ちます。
後ろに下がるのは規定に「輪の中に入った状態でシュートをしてはいけない」とあるからです。
#define BLACK_high 36 //一番黒いしきい値 #define BLACK_low 38 //少し黒いしきい値 #define WHITE_low 42 //少し白いしきい値 #define WHITE_high 44 //一番白いしきい値 #define turn_left_senkai OnRev(OUT_A); OnFwd(OUT_C); //左旋回 #define turn_left_kaiten Off(OUT_A); OnFwd(OUT_C); //左前進 #define turn_right_kaiten OnFwd(OUT_A); Off(OUT_C); //右前進 #define turn_right_senkai OnFwd(OUT_A); OnRev(OUT_C); //右旋回 #define go_fwd OnFwd(OUT_AC); //前進 #define short_break Off(OUT_AC); Wait(100); //小休止 #define SHOTBALL OnFwd(OUT_B); Wait(500); //ボールを撃つ #define CATCHBALL OnRev(OUT_B); Wait(500); //ボールを受け取る #define TURNSTEP 10 //横のセンサーを使う時の繰り返しの待ち時間 #define time2 10 //シュートしない側が交差点から一回目に前進する時間 #define time3 10 //シュートしない側が交差点から二回目に前進する時間 #define nMAX 300 //交差点と判断する基準 #define STEP 1 //ライントレース時の待ち時間
ここはシュートする側とほぼ同じになります。
進む時間に微妙な違いがあります。
task main(){ SetSensor(SENSOR_2,SENSOR_LIGHT); int nOnline=0; int nCross=0; ClearTimer(0); while(nCross <= 1){ while(nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_left_senkai ; nOnline++ ; } else if(SENSOR_2 < BLACK_low){ turn_left_kaiten; } else if(SENSOR_2 < WHITE_low){ go_fwd; } else if(SENSOR_2 < WHITE_high){ turn_right_kaiten; } else { turn_right_senkai; } } nOnline == 0; nCross ++; short_break; cross_line; } nCross=0; go_fwd; Wait(500); OnRev(OUT_A); OnFwd(OUT_C); Wait(100); //ボールに向く CATCHBALL; OnFwd(OUT_AC); Wait(200); //ボールを取る
まずは交差点までライントレースをします。
交差点をこえたら一定時間直進をし、そのまま右に旋回しボールに向きます。
ライントレースしながらの時間指定だとしきい値によって進む速度が変動してしまいうまくボールが取れなかったので直進することにしました。
ボールに向いたらそのまま直進しボールを取ります。
until(SENSOR_1 < BLACK_low){ turn_left_kaiten; } //コースに戻る while(nCross <= 1){ if(SENSOR_1 < BLACK_high){ turn_left_senkai; nOnline ++; } else if(SENSOR_2 < BLACK_low){ turn_left_kaiten; } else if(SENSOR_2 < WHITE_low){ go_fwd; } else if(SENSOR_2 < WHITE_high){ turn_right_kaiten; } else { turn_right_senkai; } } nCross=0; turn_left_senkai; Wait(70); until(FastTimer(1) > 4500); SHOTBALL; turn_right_senkai; Wait(70);
ボールを取ったらラインを感知するまで左に進み、ラインに乗ったらライントレースを開始します。
交差点までライントレースをして、交差点を感知したらコース内側を向いてパスの準備をします。
スタートしてからの時間がある点をこえたところでパスをして、そのまま元の向きに戻ります。
while (FastTimer(0) <= time2){ if(SENSOR_1 < BLACK_high) { turn_right_senkai; } else if (SENSOR_1 < BLACK_low) { back_turn_right_kaiten; } else if (SENSOR_1 < WHITE_low) { go_fwd; } else if (SENSOR_1 < WHITE_high) { back_turn_left_kaiten; } else { turn_left_senkai; } Wait(STEP); } turn_left_senkai; Wait(70); until(FastTimer(1) > 6000); CATCHBALL; turn_right_senkai; Wait(70);
第一パスを終えたら再び時間指定付きライントレースを行います。
ここの距離は短いので誤差は少なくて済みます。
ある点まですすんだらコース内側を向き、パスの準備をします。
スタートしてからの時間がある点をこえたところでパスをして、そのまま元の向きに戻ります。
while (nCross < 1){ while (nOnline < nMAX){ if(SENSOR_1 < BLACK_high){ turn_right_senkai; nOnline++; } else { if (SENSOR_1 < BLACK_low){ turn_right_kaiten; } else if (SENSOR_1 < WHITE_low){ go_fwd } else if (SENSOR_1 < WHITE_high){ turn_left_kaiten; } else { turn_left_senkai; } nOnline==0; } Wait(STEP); } PlaySound(SOUND_UP); short_break; nCross++; nOnline=0; } turn_left_senkai; Wait(70); until(FastTimer(1) > 7500); SHOTBALL; }
第二パスを終えたら次の交差点までライントレースをします。
交差点をこえたら少し進んでから左に旋回してコース内側を向きます。
スタートしてからの時間がある点をこえたところでパスをして、役目を終えます。
今回は二つのロボットを使うということで役割分担をしっかりとして各々の負担を減らすよう心がけました。
ロボット自体はほとんど同じ形にすることでシュート位置のずれなどを極力なくしました。
前回の課題では準備不足が祟って失敗してしまったので今回は早めに準備をしようという話になりました。
しかしテスト期間と重なったのもあってかなかなか4人で集まる時間が作れず、各々の作業は終わっているのに合わせて確認することができない、という日々が続いてしまいました。
結局集まれるようになったのは本番の一週間前からでほとんど余裕がありませんでした。
しかしここでプログラムを合わせるとロボットが命令どうりにうごかない、という大変なことが起こってしまいました。
これによって動作を一つずつ確認しながらプログラムを合わせていくという途方もない作業が必要となり、実際に合わせて動かす時間がほとんどありませんでした。
そんな不完全なまま本番に臨んでしまい、結果は散々たるものでした。
今回の敗因はお互いの認識に若干の誤差があったため思うようにプログラムが合わなかった点にあると思います。
これは社会にでてからチームでプログラムを作るときにとても大事なことです。
もっと深く話し合ってお互いの認識が一致しているか確認してから作業をすべきでした。
このゼミはこれで終わりですが、ここでの失敗を別の機会に生かしたいと思います。