目次
モーターでタイヤを動かし、ペンを搭載したロボット全体を移動させて似顔絵を描く。モーターは全部で3つあり、2つはタイヤを回すために、残り1つはペンの上げ下げのために使用されている。
ペンは2つのタイヤの間にあり、輪ゴムで固定されている。
最初、ペンの接地地点を前輪の前にくるようにした。しかし、曲線から直線に切り替えるときに変な出っ張りが現れてしまい、なめらかな線を描くことはできなかった。そのため、できる限りペン先が2つのタイヤの中心にくるようにした。結果、輪郭をなめらかな線で描くことができた。
後輪は小さなタイヤ1つとなっているため、後輪の方に重心が寄るとバランスを崩しやすく、転倒することもあった。そのため、できる限り前輪の方に重心を寄せ、安定するようにした。
タイヤの間にペンが入るくらいのスペースがあり、かつ片方のタイヤだけを回して曲がったときに自分が望むサイズの弧を描けるように調整した。それにより、プログラム面での苦労を減らすことができた。
#define SPEED 30 float GetAngle(float d) { const float diameter = 5.45; const float pi=3.1415; const float distance=12.5; float ang = (distance*d)/diameter; return ang; } sub fwd(int t) { RotateMotorEx(OUT_BC,SPEED,t,0,false,true); } sub fwd_B(int b) { RotateMotor(OUT_B,SPEED,b); } sub fwd_C(int c) { RotateMotor(OUT_C,SPEED,c); } sub turn_right(int r) { int angle = GetAngle(r); RotateMotorEx(OUT_BC,25,angle,100,true,true); } sub turn_left(int l) { int angle = GetAngle(l); RotateMotorEx(OUT_BC,25,angle,-100,true,true); } sub up() { RotateMotor(OUT_A,15,30); } sub down() { RotateMotor(OUT_A,-10,30); } task main() { up(); down(); fwd(180); fwd_B(810); fwd(180); fwd_B(427); fwd(45); fwd_B(427); up(); turn_left(90.0); fwd(30); down(); fwd(270); up(); turn_right(105.0); fwd(15); turn_right(110.0); fwd(54); down(); fwd(54); up(); fwd(54); down(); fwd(54); up(); fwd(54); turn_left(100.0); fwd(220); turn_left(90.0); fwd(100); down(); fwd(90); fwd_B(60); up(); turn_left(100.0); fwd(100); down(); fwd_C(427); }
float GetAngle(float d) { const float diameter = 5.45; const float pi=3.1415; const float distance=12.5; float ang = (distance*d)/diameter; return ang; }
括弧内に方向転換したい角度を入れ、タイヤの回転角度を計算する。計算した角度はロボットを回転させるプログラムで使用する。
sub fwd(int t) { RotateMotorEx(OUT_BC,SPEED,t,0,false,true); }
括弧内にタイヤの回転角度を入れ、その分直進する。
sub fwd_B(int b) { RotateMotor(OUT_B,SPEED,b); }
括弧内にタイヤの回転角度を入れ、左に曲がる。
sub fwd_C(int c) { RotateMotor(OUT_C,SPEED,c); }
左旋回のプログラムと同様に、タイヤの回転角度を入力し、右に曲がる。
sub turn_right(int r) { int angle = GetAngle(r); RotateMotorEx(OUT_BC,25,angle,100,true,true); }
括弧内に方向転換した角度を入れ、右に回る。計算して出した角度はここで使用する。
sub turn_left(int l) { int angle = GetAngle(l); RotateMotorEx(OUT_BC,25,angle,-100,true,true); }
右回転のプログラムと同様に、方向転換した角度を入力し、左に回る。
sub up() { RotateMotor(OUT_A,15,30); } sub down() { RotateMotor(OUT_A,-10,30); }
ペンを上げてペン先を紙面から浮かせるプログラムと、ペンを下げてペン先を紙面につけるプログラム。
up(); down(); fwd(180); fwd_B(810); fwd(180); fwd_B(427); fwd(45); fwd_B(427); up();
直進と左旋回で輪郭を描いた。顎よりも頭頂部の方を横に長くしたかったため、頭頂部を描く際に旋回のみで描くのではなく、直進も少し挟んだ。
turn_left(90.0); fwd(30); down(); fwd(270); up();
輪郭を描き終わったとき、ロボットは前髪を描くところの近くに位置しているため、方向転換と軽く位置調整を行い、直進して前髪を描いた。
turn_right(105.0); fwd(15); turn_right(110.0); fwd(54); down(); fwd(54); up(); fwd(54); down(); fwd(54); up();
目を描くために位置と向きを調整し、直進しながらペンを上げ下げし、2つの線を描いた。複雑に描くことができなかったため、線で目を描くことになった。
fwd(54); turn_left(100.0); fwd(220); turn_left(90.0); fwd(100); down(); fwd(90); fwd_B(60); up();
位置と向きを調整し、口を描いた。口がただの棒にならないように気持ちカーブを入れた。
turn_left(100.0); fwd(100); down(); fwd_C(427);
鼻についても口と同様に、微々たるカーブをつけた。鼻は顔のパーツの中でも向きが大きく異なるため、最後に描いた。
サブルーチンでいくつかの一連の命令をまとめ、task mainのプログラムをシンプルなものにした。
スピードが速いとロボットが重いせいで曲がるときにバランスを崩しがちだったため、全体的に動作を遅くした。
OnFwdだと電池残量に影響されたり、進む距離の調整に手間がかかったりした。また、ロボットの重量が変わったときの挙動の変化も大きかった。
今回のお絵かきロボットの作成に想像以上の時間がかかり驚いた。また、ロボットは自分が望む動きをしないということを痛感した。今後は今回の反省を活かした取り組みをしていきたい。