白いホイールを投げるロボットを作成し、以下の動きをするようにプログラムを作成せよ。
1. 全方向から懐中電灯の方向を探しだし、懐中電灯に向けてブロックを投げる。懐中電灯は動かさない。 2. 懐中電灯をゆっくり動かしたとき懐中電灯に向かって進み、懐中電灯の動きを止めればブロックを投げる。 3. 懐中電灯をゆっくり動かしたとき懐中電灯に向かって進み、懐中電灯の動きを止め れば50cmの距離まで近づいてブロックを投げる。
モータ、光センサ、タッチセンサはそれぞれ2個まで使用可。
懐中電灯の代わりに携帯のライトなどを利用してもよい。
片方のモーターで移動
もう一方でブロッックを投げる
光センサーに光の強弱を認識させる
2個の光センサーで光の強さを比較させ、より光の強い方に移動する。
光源との距離はおおよその光量から認識する
光源を探し、その方向に進ませる。
光源の静止を認識し、ブロックを投げる。
移動部分にデファレンスギアを用いた。
デファレンスギアはタイヤの進行方向を合わせるためにギアを組み合わせた結果、若干車高が高くなった。
光センサーは前方に2個取り付けた。
重心は若干前方に偏ってしまったがシャフトで支えることでバランスをとった。
モーターの回転の方向によって常に片方のギアしか回らないギアである。
ディファレンシャルギアは今回の課題において最も重要な機構であり、
同時に製作時に最も苦労した所である。
ロボットを前進させるためにはタイヤを一定の方向にそろえる必要があり、
ギヤを複数組み合わせなければならなかった。
その際、「タイヤの軸の位置がうまい具合に合わない」
「ギヤ比の違いによりかなりのトルクをかけなければ回らない」といった問題が発生した。
これらの問題は多くのギアの組み合わせを試すことよって解決した。
ロボットに前方に2個の光センサーを取り付けた。
本来なら、センサーの間に「ついたて」を取り付けたほうが光を読み取りやすいらしいのだが試験的に「ついたて」の有無での課題の成功率を調べたが、ほとんど大差がなかったので「ついたて」を取り外すことにした。
モーターも用いてブロックを弾き飛ばす発射装置を製作した。
自由に発射台の角度を変更できるようにブロックを取り付けたのである程度の飛距離の調整が可能。
また、全体的に傾いているのでブロックを発射する際に飛ばし損ねても自動的に戻ってくるのでほぼ確実にブロックを投げることができる。
写真の黄色い出っ張りはロボットが移動するときにブロックが落ちないようにするためである。
はじめはキャスターを用いていたが、キャスターの摩擦、タイヤが反転するのに必要な距離などを考え車体をシャフトを用いて「点」で支えることにした。
キャスターの短所
・摩擦が大きく前に進みにくい
・タイヤを反転させるのにある程度の距離を必要とし、今回のように方向転換を短い距離で繰り返すロボットに向かない
シャフトについて
意外にもシャフトはキャスターよりも摩擦が小さいためよりスムーズに移動できる。
だが、絨毯のように床が柔らかいところではかえって引っかかってしまう欠点をもつ。
#define left OnFwd(OUT_A) #define right OnRev(OUT_A);Wait(30); task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); //センサー1に光センサーをセット SetSensor(SENSOR_3,SENSOR_LIGHT); //センサー2に光センサーをセット int light ; //変数「light」を定義 int direction ; //変数「direction」を定義 int count ; //変数「count」を定義 light = 0; direction = 1; count = 0; while (direction <2) { if (SENSOR_3 > light){ //光センサーが「light」の値よりも大きい値を得たとき light =SENSOR_3 ; //その時に得た値を「light」に代入 right //次の方向に移動 direction=2; count=0; //「count」の値を0にする } else{right;count=count+1;direction=2;} //光センサーが「light」よりも小さな値を得たとき、「count」値+1 } while (direction <3) //「direction」が1〜8の時、上と同様の動作を繰り返す { if (SENSOR_3 > light){ light =SENSOR_3 ; right direction=3; count=0; } else{right;count=count+1;direction=3;} } while (direction < 4) { if (SENSOR_3 > light){ light =SENSOR_3 ; right direction=4; count=0; } else{right;count=count+1;direction=4;} } while (direction < 5) { if (SENSOR_3 > light){ light =SENSOR_3 ; right direction=5; count=0; } else{right;count=count+1;direction=5;} } while (direction<6) { if (SENSOR_3 > light){ light =SENSOR_3 ; right direction=6; count=0; } else{right;count=count+1;direction=5;} } while(direction<7) { if (SENSOR_3 > light){ light =SENSOR_3 ; right direction=7; count=0; } else{right;count=count+1;direction=7;} } while(direction<8) { if (SENSOR_3 > light){ light =SENSOR_3 ; right direction=8; count=0; } else{right;count=count+1;direction=8;} } while(direction<9) //「direction」の値が9よりも小さい、つまり8の時 { if(count<1) //「count」が0の時、停止 { Off(OUT_A+OUT_C); direction=9; } if(count<2) //「count」が1のとき方向7に移動 { left ; Wait(30); Off(OUT_A+OUT_C); direction=9; } if(count<3) //「count」が2のとき方向6に移動 { left ; Wait(60); Off(OUT_A+OUT_C); direction=9; } if(count<4) //「count」が3のとき方向5に移動 { left ; Wait(90); Off(OUT_A+OUT_C); direction=9 ; } if(count<5) //「count」が4のとき方向4に移動 { left ; Wait(120); Off(OUT_A+OUT_C); direction=9 ; } if(count<6) //「count」が5のとき方向3に移動 { left ; Wait(150); Off(OUT_A+OUT_C); direction=9 ; } if(count<7) //「count」が6のとき方向2に移動 { left ; Wait(180); Off(OUT_A+OUT_C); direction=9 ; } if(count<8) //「count」が7のとき方向1に移動 { left ; Wait(210); Off(OUT_A+OUT_C); direction=9 ; } else { left ; Wait(240); Off(OUT_A+OUT_C); direction=9 ; } while(direction<10) //「direction」が9のときブロックを投げる { OnFwd(OUT_C); Off(OUT_A+OUT_C) ; } } }
ロボットを中心に方向を8分割し、一つづつ光量を確認していく。
ひとつ前の方向と現在の方向における光量を比較し、より明るい方角をロボットに覚えさせた。
8つの方向を調べ終わると8つの方向で最も明るい方向に戻り、ブロックを投げる。
<例1>
ロボットの明るさが上の図より
1>2>3>4>5>6>7>8
のとき、ロボットは方向1を最大値に設定し方向8の時点で「count」の値が「8」となり45×7°左周りに回転し光源の方向を向く
<例2>
ロボットの明るさが上の図より
6>8>7>5>4>3>2>1
のとき、
ロボットは方向5の時点で方向5を最大値として認識。「count」の値は「5」。
方向6が方向5よりも明るいことを知ると「count」の値を「0」にリセット。~ その後、方向7、8を調べるごとに「count」の値を+1加算していく。~
そうしてすべての方向を調べ終わった時点で「count」の値は「2」。 したがって、ロボットは45×2°左に回転して方向6で停止→ブロックを投げる。
#define THRESHOLD 60 //闘値を設定 task main () { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensor(SENSOR_3,SENSOR_LIGHT); while(true){ if(SENSOR_1 > THRESHOLD){ //左センサーの光が強く if(SENSOR_3 > THRESHOLD){ //かつ右センサーの光が強い Off(OUT_A); // 回転を止め Wait(30); OnFwd(OUT_C); //球を投げる Wait(80); Off(OUT_C); } else { //右の光が弱く、かつ左の光が強い OnFwd(OUT_A); //左周りに回転する Wait(20); } } else { //左の光が弱く if(SENSOR_3 > THRESHOLD){ //かつ右の光が強い OnRev(OUT_A); Wait(20); }else{ //それ以外(右と左ともに光が弱い)のとき Off(OUT_A); } } } }
#define THRESHOLD 70 //光度「70」を定義 int run_count; //変数「count」を定義 task main () { SetSensor(SENSOR_1,SENSOR_LIGHT); //センサー1に光センサーをセット SetSensor(SENSOR_3,SENSOR_LIGHT); //センサー2に光センサーをセット SetPower(OUT_A,7); //モーターの出力を7とする SetPower(OUT_C,7); count = 0 ; //前進の回数を数える while(run_count <= 3) { //前進が3回以下のとき if(SENSOR_1 > THRESHOLD) { if(SENSOR_3 > THRESHOLD) { //センサー1、3が閾値以上;前方に光源;前進 OnFwd(OUT_C); Wait(30); OnRev(OUT_C); Wait(30); count += 1; //現在の「count」の値+1 } else { OnFwd(OUT_C); //右へ曲がる run_count = 0; //「count」の値を0の戻す } } else { if(SENSOR_3 > THRESHOLD) { OnRev(OUT_C); //左へ曲がる } else { Off(OUT_C); //停止 run_count = 0; //「count」の値を0に戻す } } } while(run_count > 3) //「count」の値が3よりも大きいとき { if(SENSOR_1 < X) { if(SENSOR_3 < X) //両方の光センサーが閾値以下のとき(50センチ以上の距離があるとき) { Off(OUT_C); //停止する Wait(100); OnFwd(OUT_A); //ブロックを光源に向かって投げる Wait(80); Off(OUT_A); //発射装置の動作を停止する。 } } else //両方の光センサー閾値以上の時(50センチよりも近い位置にいる時) { OnFwd(OUT_C); Wait(170); //180度方向転換する OnFwd(OUT_C); Wait(30); //前進 OnRev(OUT_C); Wait(30); OnFwd(OUT_C); Wait(170); //再度180度方向転換する } }
製作する過程ででたアイデアを紹介する。
モータに棒状のブロックを付け、引っかけるようにしてブロックを投げる発射台である。
しかし、うまい具合に次弾を装填できずに廃案となった。
この発射台は上記の発射台の原型となっており、これをもとに様々な改良が加えらた。
ダルマ落としを参考に考えた発射台である。
3つのブロックを貫くようにシャフトを差し込むことで
一番下のブロックを打ち出すと上から次のブロックが落ちてくる仕組みである。
これによってスムーズに4連射することができた。
現状での欠点はモーターの回転速度の調整がきわめて難しいということだ。
また、一度でも詰まると継続は困難である。
お気付きの点、アドバイスをお願いします
ロボット、プログラムともとても良くできています。
課題1で相対的に最も明るい方向を探すことができるプログラムにすれば、より良い評価になります。I