今回の課題の目的は下の図のようなコースを作成し、「ミッション」を遂行するためのロボットを作成する。
次のコース(第1コース)で黒い線に沿って動き、紙コップを移動させるロボットを製作する。
Aをスタート ,Bを直進 ,Cを右折 ,Fを直進 ,Rを左折(一時停止) ,Pを直進 ,X地点の紙コップを取得してコースに戻る ,Qを左折 ,Sを直進(一時停止) ,Y地点に紙コップを置いてコースに戻る ,Sを直進(一時停止) ,Fを左折(一時停止) ,Cを右折(一時停止) ,D地点へ(ゴール)。
ロボットを作る前にグループの中で様々なことを考えた。例えば、光センサーをつける場所、紙カップをとる部分の構造、などである。結局、上の図のようにロボットを作った。ロボットを正確に動くため光センサーをつける場所はできるだけ床に近いである。
また、紙カップを取る部分の構造上の図である。紙カップをとる部分の構造は紙カップより大きく作った。なぜなら、取るときに紙カップが入るようになるためである。また、紙カップを取る部分が上げ下げるときにはできるだけ滑らかに動くため2つのモータを使った。ただし、図のようにモータは紙カップを取る部分の左側と右側にある。
コース上に動けるようになるためにはLine Traceを使った。Line Traceのプログラムでは資料の練習問題49と同様に5段階(白い、白いと境界付近の間、境界付近、黒いと境界付近の間、黒い)を使ってロボットを動く。そのためには5段階の明るさを実際にコースの上で測定しなければならない。5つの測定できた値は以下のものである;
段階 | 白い | 白いと境界付近の間 | 境界付近 | 黒いと境界付近の間 | 黒い |
明るさ値 | 52以下 | 45−52 | 38−45 | 33−38 | 33以上 |
次に、段階によって違う動くを考えましょう。下の図のように(A)と(B)の場合によってコースに戻る方法が違う。
まず(A)の場合は白くなったら右側に戻る動く。そのことから5段階の明るさを使って左側と右側のモータのスピードによってロボットを動く。(注意:左側のモータが正のスピードのとき右に曲がる、右側のモータのスピードが正のとき左に曲がる。負のスピードの場合は逆)みぎ5段階の明るさとモータのスピードは以下のものである;
段階 | 方向 | (左側モータのスピード、右側モータのスピード) |
白い | 左旋回 | (SPEED_CURVE,-SPEED_CURVE) |
白いと境界付近の間 | 左折 | (SPEED_TURN,0) |
境界付近 | 直進 | (SPEED_STRAIGHT,SPEED_STRAIGHT) |
黒いと境界付近の間 | 右折 | (0,SPEED_TURN) |
黒い | 右旋回 | (-SPEED_CURVE,SPEED_CURVE) |
ただし、SPEED_STRAIGHT=30,SPEED_CURVE=30,SPEED_TURN=40 のときロボットがうまくLine Traceできるから個の値を使った。 説明したものより(A)のときのLine Trace のプログラム以下のようになる。
#define THRESHOLD 45 //しきいの値 #define SPEED_STRAIGHT 30 #define SPEED_CURVE 30 #define SPEED_TURN 40 #define OnRL(speedR,speedL) OnFwd(OUT_A,speedR);OnFwd(OUT_B,speedL); #define go_forward OnRL(SPEED_STRAIGHT,SPEED_STRAIGHT); //直進 #define turn_left0 OnRL(SPEED_CURVE,-SPEED_CURVE); //左旋回 #define turn_left1 OnRL(SPEED_TURN,0); //左折 #define turn_right1 OnRL(0,SPEED_TURN); //右折 #define turn_right0 OnRL(-SPEED_CURVE,SPEED_CURVE); //右旋回
sub moveA1() { SetSensorLight(S1); //端子は1番である long t0=CurrentTick(); while(CurrentTick()-t0<150){ //時間が150以下のとき if (SENSOR_1 < THRESHOLD -12) { //黒いなら turn_right0; //右旋回 }else{ t0=CurrentTick(); //時間リセット if (SENSOR_1 < THRESHOLD -7) { //黒いと境界付近の間なら turn_right1; //右折 } else if (SENSOR_1 < THRESHOLD +7) { //黒いと境界付近の間 go_forward; //直進 } else if (SENSOR_1 < THRESHOLD +12) { //白いと境界付近の間なら turn_left1; //左折 } else { //白いなら turn_left0; //左旋回 } } } PlaySound(SOUND_LOW_BEEP); //音を出す }しかし、このsubスクリプトでは急なカーブのところでは交差点に判断したりしなかったりすることが問題だった。そのため、交差点かどうか判断するための時間を延ばして問題が解決できるようになった。下のsubスクリプトのように交差点かどうか判断するための時間をdとし、時間dは違うカーブによって設定できる。
sub moveA2(int d) { SetSensorLight(S1); long t0=CurrentTick(); while(CurrentTick()-t0<d){ //時間がd以下のとき繰り返す if (SENSOR_1 < THRESHOLD -12) { turn_right0; } else{ if (SENSOR_1 < THRESHOLD -7) { turn_right1; } else if (SENSOR_1 < THRESHOLD +7) { go_forward; } else if (SENSOR_1 < THRESHOLD +12) { turn_left1; } else { turn_left0; } } } PlaySound(SOUND_LOW_BEEP); }
(B)のときのLine Trace プログラム は(A)のときの反対側に動く。subスクリプトを書くときにただ左と右と右から左を変える。だから(A)のときと同じように2つsubスクリプトは以下のものである:
sub moveB1() { SetSensorLight(S1); long t0=CurrentTick(); while(CurrentTick()-t0<150){ if (SENSOR_1 < THRESHOLD -12) { turn_left0; } else{ t0=CurrentTick(); if (SENSOR_1 < THRESHOLD -7) { turn_left1; } else if (SENSOR_1 < THRESHOLD +7) { go_forward; } else if (SENSOR_1 < THRESHOLD +12) { turn_right1; } else { turn_right0; } } } PlaySound(SOUND_LOW_BEEP); }
(B)のとき時間kは違うカーブによって設定できる
sub moveB2(int k) { SetSensorLight(S1); long t0=CurrentTick(); while(CurrentTick()-t0<k){ if (SENSOR_1 < THRESHOLD -12) { turn_left0; } else{ if (SENSOR_1 < THRESHOLD -7) { turn_left1; } else if (SENSOR_1 < THRESHOLD +7) { go_forward; } else if (SENSOR_1 < THRESHOLD +12) { turn_right1; } else { turn_right0; } } } PlaySound(SOUND_LOW_BEEP); }
交差点判断した後もちろんコースに戻る必要がある。そのため、マクロの説明は以下のものである:
#define left(t) OnFwd(OUT_A,30);Wait(t);Off(OUT_A); //leftの移動 #define leftback(t) OnFwd(OUT_A,-30);Wait(t);Off(OUT_A); //leftbackの移動 #define right(t) OnFwd(OUT_B,30);Wait(t);Off(OUT_B); //rightの移動 #define rightback(t) OnFwd(OUT_B,-30);Wait(t);Off(OUT_B); //rightback(の移動 #define straight(t) OnFwd(OUT_AB,20);Wait(t);Off(OUT_AB); //straightの移動 #define straightback(t) OnFwd(OUT_AB,-20);Wait(t);Off(OUT_AB); //straightbackの移動
今回の課題では一時止まる(1秒)操作がある。そのため、マクロの説明は以下のものである:
#define short_break Off(OUT_AB); Wait(1000); //1秒止まる
#define getcup(t) OnFwd(OUT_C,35);Wait(t);Off(OUT_C); //紙コップを取得する #define returncup(t) OnFwd(OUT_C,-35);Wait(t);Off(OUT_C); //紙コップを置く
私のコースは第一コースだったから下の図のようにオレンジ色の矢印の順番に沿って動くロボットを制作した。ただし緑色のところは紙コップを取得すると置く操作ことである。
オレンジ色の矢印の順番に沿ってMainプログラムを説明していく。
task main() { sub moveA1(); //ここは番号1の移動(Start点) left(2000); //ここからは番号2の移動 sub moveA2(6000); sub moveA1(); //ここまでは番号2の移動 sub moveA2(2000); //ここは番号3の移動 sub moveA1(); //ここからは番号4の移動 left(2000); sub moveA2(15000); //ここまでは番号4の移動 sub moveA1(); //ここからは番号5の移動 sub moveA2(700); //ここまでは番号5の移動 sub moveA1(); //ここからは番号6の移動 short_break; //一時停止 rightback(1300); left(1700); sub moveB1(); short_break; //一時停止 leftback(700); straight(700); //紙コップを取得するためコースの外に移動する straight(2000); right(1300); leftback(2000); straight(800); right(500); getcup(1200); //紙コップを取得する straight(800); /ここまでは番号6の移動(コースに戻る) sub moveB2(8000); //ここは番号7の移動 sub moveB1(); //ここからは番号8の移動 leftback(1500); straight(2500); short_break; //一時停止 sub moveA1(); //ここまでは番号8の移動 rightback(4000); //紙コップを置くためコースの外に移動する straightback(500); returncup(1800); //紙コップを置く straight(1000); right(500); //ここまでは番号8の移動 (コースに戻る) sub moveA2(1500); //ここからは番号9の移動 sub moveA1(); short_break; //一時停止 left(2000); sub moveA2(700); //ここまでは番号9の移動 sub moveA1(); //ここからは番号10の移動 short_break; //一時停止 rightback(500); left(1500); sub moveA1(); sub moveA1(); sub moveA1(); straight(3000); //Finish点 }
以下の動画リンクのように今回の課題は成功したがミッションを遂行するための時間は2分だった。それはロボットのスピードが遅かったと考えられる。スピードが遅かったのおかけでロボットがコースにはずれないが次回の課題はスピードが速いでもロボットがコースにはずれないロボットを作りたいと思う。また、今回Line Trace のsubスクリプトをロボットの動きによって使ったおかけでロボットが正確に動けるようになった。
https://www.youtube.com/watch?v=7jxSA9LWHlA&feature=share (課題の結果はこのリンクに見てください。)
松本成司(2013)「自律型ロボットを作ろう!(2013年度版)」(マインドストームを使ったロボット製作の体験教室資料), [online] http://yakushi.shinshu-u.ac.jp/robotics-jr/robotics-jr-2013.pdf(参照2017-1-7).