A3の紙に相棒の似顔絵を書くロボットを作成する。(製作者:PuKKu,Kata)
目次
プログラムの作成をより簡単に、そして、移動距離が長くなるにつれて大きくなる誤差を最小限にするために、縦と横の線を組み合わせて似顔絵を描くようなロボットを作成することにした。
授業の最初に作成したロボットは左右2つのモーターで動きをコントロールしていたが、今回は、前後だけなので3つしかないモーターを有効に活用するために1つのモーターで4つのタイヤを動かすことにした。
モーターを1つ使い、レールの中にアームを通して、タイヤでアームをスライドさせることで、横の線を引くことにした。
最後のモーターを用いて、ペンを上げたり下ろしたりする動力へと活用することにした。当初は、ペンを垂直に持ち上げる方式を考えたが、アームの部分が重くなりすぎたので、斜めにペンを上げ下ろしすることにした。
アームやRCXなどを支える土台であるため、全体のバランスが取れるようにすることが重要になった。前後のコントロールをする1つのモーターを土台の真ん中に位置するように設置することで、バランスが安定した。
レールの中をアームが動くようにした。しかし、アームの上にモーターやペンを持つところなどが設置されるために左右のバランスが崩れてしまった。そのためアームがコントロールされるタイヤから浮き上がってしまい、動かなくなった。そこで、右図のように自由に動くことができるタイヤで支えることによって、安定してアームの伸び縮みができるようになった。また、伸びすぎて戻らなくなることを避けるために、下図のようにストッパーを設置することで、より安定性を増すことができた。
当初、上下にペンを動かすことを中心に考えていたため、初期の段階では、右図の試作のように簡易な方法でペンを固定していた。だが、これだと線(特に横の線)を引くときにペンが大きく動いてしまい、なかなか安定して顔を描くことができないため、右図の完成版のように改良を加えた。
ペンの上げ下ろしに関しては、最初は左図の初期のようにして行っていた。しかし、コントロールがうまくできないため、左図の完成版のようにギアで速度を遅くすることで細かな調節を行えるように調節を行った。
全てのパーツを組み合わせてみたが、バランスが悪く、思うように似顔絵を描くことができなかった上、後退したときにひっくり返ってしまった。
RCXを横にして本体にしっかりと固定することで、動作中に部品が外れることはなくなった。また、揺れが小さくなった。
#define PEN 50 //ペンの上げ下げ時間 #define REST Wait(50); //停止時間 #define GO(t) OnFwd(OUT_C);Wait(t);Off(OUT_C); //前進 #define BACK(t) OnRev(OUT_C);Wait(t);Off(OUT_C); //後退 #define RIGHT(t) OnFwd(OUT_A);Wait(t);Off(OUT_A); //右 #define LEFT(t) OnRev(OUT_A);Wait(t);Off(OUT_A); //左 #define ZoomLevel 1 //似顔絵の拡大係数 sub pen_up(){ //ペンを上げる動作 OnFwd(OUT_B); Wait(PEN); Off(OUT_B); } sub pen_down(){ //ペンを下げる動作 OnRev(OUT_B); Wait(PEN); Off(OUT_B); } task main(){ repeat(2){ //眉毛二本(右へアームを伸ばしながら横線を1本ずつ) RIGHT(40*ZoomLevel); REST; pen_down(); RIGHT(40*ZoomLevel); pen_up();REST; } GO(10*ZoomLevel); LEFT(30*ZoomLevel); REST; pen_down(); //右目(左へアームを縮めながら横線) LEFT(10*ZoomLevel); pen_up();REST; LEFT(70*ZoomLevel); REST; pen_down(); //左目(右目と同様にして横線) LEFT(10*ZoomLevel); pen_up();REST; GO(30*ZoomLevel); RIGHT(45*ZoomLevel); REST; pen_down(); //鼻(前進しながら縦線⇒左へアームを縮めながら横線) GO(20*ZoomLevel); REST; LEFT(10*ZoomLevel); pen_up();REST; GO(30*ZoomLevel); RIGHT(45*ZoomLevel); REST; pen_down(); //口(左へアームを縮めながら横線) LEFT(60*ZoomLevel); pen_up();REST; LEFT(40*ZoomLevel); BACK(90*ZoomLevel); REST; pen_down(); //輪郭(前進しながら左の線) GO(100*ZoomLevel); REST; pen_up(); REST; pen_down(); //輪郭(右へアームを伸ばしながら下の線) RIGHT(140*ZoomLevel); REST; pen_up(); REST; pen_down(); //輪郭(後退しながら右の線) BACK(160*ZoomLevel); REST; pen_up(); REST; pen_down(); //輪郭(左へアームを縮めながら上の線) LEFT(140*ZoomLevel); REST; GO(50*ZoomLevel); //輪郭(前進しながら左の線) pen_up(); }
※ただし、このプログラムでの「右」・「左」とは、頭の方を下(手元)にして見たときのものである。具体的には、下の図のロボットが描いた似顔絵に示してある通りである。
このロボットが縦と横の線を利用して似顔絵を描くため、先に描きたい顔を作成し、そのマス目に合わせてプログラムを作成した。そのため、時間の調節が容易に行うことができた。左図は、描こうとした顔の図であり、右図は、プログラムの実行順番(Start→Goal)の図である。
ただ、ロボットのない状態でプログラムを作成したために紙の大きさに合わせて似顔絵の大きさを自由に描こうとしたが、アームの長さの制限により、似顔絵の拡大係数は1しか使うことができなかった。また、横の線(特に輪郭の横の線)を描くことができないことが多々生じたので輪郭の各線の引き終わりにペンを上げて、アームのゆがみを取り除くようにした。
#define MOVE_TIMEAX 10 //メガネの横移動時間 #define MOVE_TIMECY 5 //メガネの縦移動時間 #define MOVE_TIMEBZ 30 //ペンの上げ下げ時間 #define PAUSE 100 //静止時間 #define Z_UP OnFwd(OUT_B); Wait(MOVE_TIMEBZ); Off(OUT_B); Wait(PAUSE); //ペンを上げる #define Z_DOWN OnRev(OUT_B); Wait(MOVE_TIMEBZ); Off(OUT_B); Wait(PAUSE); //ペンを下げる #define X_RIGHT OnRev(OUT_A); Wait(MOVE_TIMEAX); Off(OUT_A); Wait(PAUSE); //メガネの横線(右へ) #define X_LEFT OnFwd(OUT_A); Wait(MOVE_TIMEAX); Off(OUT_A); Wait(PAUSE); //メガネの横線(左へ) #define Y_FRONT OnRev(OUT_C); Wait(MOVE_TIMECY); Float(OUT_C); Wait(PAUSE); //メガネの縦線(前へ) #define Y_BACK OnFwd(OUT_C); Wait(MOVE_TIMECY); Float(OUT_C); Wait(PAUSE); //メガネの縦線(後ろへ) task main() { Wait(100); //1秒待ってからスタート Z_DOWN; //メガネ始め Y_FRONT; //フレーム右 X_RIGHT; Y_BACK; X_LEFT; OnRev(OUT_A); Wait(40); Off(OUT_A); //メガネのつなぎ Wait(PAUSE); Y_FRONT; //フレーム左 X_RIGHT; Y_BACK; X_LEFT; Z_UP; //メガネ終わり OnFwd(OUT_A); Wait(20); Off(OUT_A); //鼻始め Wait(PAUSE); OnRev(OUT_C); Wait(10); Off(OUT_C); //顔の中心へペンを移動 Wait(PAUSE); Z_DOWN; OnRev(OUT_C); Wait(10); Off(OUT_C); //鼻の線 Wait(PAUSE); Z_UP; //鼻終わり OnRev(OUT_C); Wait(10); Off(OUT_C); //口始め Wait(PAUSE); OnRev(OUT_A); Wait(20); Off(OUT_A); //口の端へペンを移動 Wait(PAUSE); Z_DOWN; OnFwd(OUT_A); Wait(MOVE_TIMEAX); Float(OUT_A); //口の線 Wait(PAUSE); Z_UP; //口終わり OnFwd(OUT_A); Wait(5); Float(OUT_A); //輪郭始め・ペンの位置を調整 Wait(PAUSE); OnRev(OUT_C); Wait(MOVE_TIMECY); Float(OUT_C); //ペンの位置を調整 Wait(PAUSE); Z_DOWN; OnRev(OUT_A); Wait(50); Float(OUT_A); //アームを伸ばし、顎を描く Wait(PAUSE); OnFwd(OUT_C); Wait(50); Float(OUT_C); //顔の左の線 Wait(PAUSE); OnFwd(OUT_A); Wait(50); Float(OUT_A); //頭 Wait(PAUSE); OnRev(OUT_C); Wait(50); Float(OUT_C); //顔の左の線 Wait(PAUSE); Z_UP; //輪郭終わり }
ロボットの向きと顔の向きがあっていなかったため、プログラムの前後左右が逆になってしまった。
上の顔を描いた当初のプログラム。まだまだ簡略化できる部分もたくさんあるし、#defineもうまく使えていない。メガネのためだけに#defineを使ってしまっていて、ほかのパーツに応用できていない。
普段、何気なくペンなどで字や絵などを描いているが、実際にこれをロボットにやらせるとなると、なかなか大変なものであった。日頃、私たちが何気なくしていることは簡単なことでも様々な調節をしながら、行っていることを改めて実感させられた。
ペンを上げ下げさせる仕組み考え、作成するのに一番苦労したが最終的にはちゃんと似顔絵が描けたのでよかった。時間があれば、安定して同じ顔が描けるようにしたかった。
コメントをどうぞ