目次
左右の前輪とペンの上げ下げをコントロールするためにそれぞれひとつずつモーターを使用した。ロボットを作ろうとした当初はx、y軸をつかって絵を描くロボットにしようとしたが、期限に間に合わないと思い断念した。以下がその詳細である
こちらは正面図である。
まず、このロボットが自走式であることを考慮し、その上で設計をするとき最も重要になるのは、重心の位置とペンのいちであろと考えた。よって、今回のロボットは上から見たときできるだけ正方形の形にして、失敗したとき(写真なし)のように長方形にしないように組み上げた。また、最も重いCPU部分は重心の位置を決める点において重要な役割を果たすので正方形の中心に置いた。ペンの位置はロボットの回転を考慮すると、両輪の中央になるのがベストであると考え、写真のように設置し た。
次にちょっとした製作者のこだわりポイントである。
まずは、ロボットの搭乗者を余分であるのにあえてのせるこの芸術センスである。また、最もこだわったのが、CPU部分とモーターの連結を簡単にするために写真のように接続部が同一の方向になるようにした。
float GetAngle(float h) { const float diameter = 5.45;//直径は5.45cm const float pi=3.1415;//円周率を設定 float ang = 36/(diameter*pi)*h;動かす角度の式を設定 return ang; }
この関数は、ロボットを指定の角度回転させるために使用しようと考慮していたが、実際には 使用して”いない”。理由は以降で説明する。
float GetDegree(float d) { const float diameter = 5.45;//直径は5.45cm const float pi=3.1415;円周率を設定 float deg = d/(diameter*pi)*360.0;動かす距離の式を設定 return deg; }
この関数は、ロボットを指定の距離だけ移動させるために使用した。非常に使いやすく精度もそこそこであるのでこれからも使用していきたい。
sub go(int l,int r,int t) { OnFwd(OUT_B,l);OnFwd(OUT_C,r);Wait(t); }
このサブルーチンは、ロボットに顔の輪郭を描かせるために使用した。詳しく言えば、左右のタイヤのスピードをいじることで輪郭の曲線を再現しようとしたものである。調整に時間をかけたのであまりお勧めはしない。
sub vertical(int l,int r,int t) { OnFwd(OUT_B,l);OnFwd(OUT_C,r);Wait(t); }
このプログラミングは上に説明したものと全く同じものであるが、プログラミングを製作するうえで、自分が見やすいように作ったものである。詳しく言うと上の関数は輪郭専用にして、これは目、鼻、口を描くとき専用にした。また、最初に説明したGetangle関数がご臨終なさられた理由もこれで、Getangle関数を使用するとき、合わせてRotateMotorExを使用していたが、左右のモーターのパワーのさがありすぎて、こちらでは90度回すのに35度と設定しなければいけなかった。また、なぜか(バッテリー関係なのか、摩擦の関係なのか、はたまたそれ以外か)した回によって微妙に違うことが多々あった。しかし、このサブルーチンは非常に単純明快で、再現性も高かったために使用した。
sub A_up() { RotateMotor(OUT_A,20,20);//ペン上げ } sub A_down() { RotateMotor(OUT_A,20,-20);//ペン下げ }
このサブルーチンはペンの上げ下げに使用した。上があげるようで、下が下げるようである。
task main (){ Wait(2000);//少し待機 int a = GetDegree(5.0); RotateMotor(OUT_BC,SPEED,a);//輪郭(顔のあごと頭をつなぐ直線部分) Wait(2000);り go(0,25,7000);//輪郭(頭) int b = GetDegree(5.0); RotateMotor(OUT_BC,SPEED,b);//輪郭(顔のあごと頭をつなぐ直線部分) go(-1.5,25,4000);輪郭(あご) Wait(2000); int c = GetDegree(2.2); RotateMotor(OUT_BC,SPEED,c)//;少し調整 A_up();//ぺん上げ vertical(-20,20,1800);//方向の変更 A_down();//ペン下げ int d = GetDegree(14.0);//髪の直線を描く RotateMotor(OUT_BC,SPEED,d); A_up();//ペン上げ vertical(20,-20,1900);//方向調整 int e = GetDegree(2.5); RotateMotor(OUT_BC,SPEED,e);//目の書き始めの位置に移動 Wait(2000); vertical(20,-20,1900);//方向調整 int f = GetDegree(3.0); RotateMotor(OUT_BC,SPEED,f);//位置の調整 A_down();//ペン下げ int g = GetDegree(2.2); RotateMotor(OUT_BC,SPEED,g);目一つ書く A_up();//ペン上げ int h = GetDegree(2.0); RotateMotor(OUT_BC,SPEED,h);//位置の調整 A_down();//ペン下げ int i = GetDegree(2.2); RotateMotor(OUT_BC,SPEED,i);//残りの目を描く A_up();ペン上げ int j = GetDegree(3.2); RotateMotor(OUT_BC,-SPEED,j);位置の調整 vertical(-20,20,1900);//方向調整 int k = GetDegree(2.0); RotateMotor(OUT_BC,SPEED,k);//位置調整 A_down();//ペン下げ int l = GetDegree(2.7); RotateMotor(OUT_BC,SPEED,l);//鼻を描く A_up();//ペン上げ int m = GetDegree(3.0); RotateMotor(OUT_BC,SPEED,m);//位置調整 vertical(20,-20,1900);//方向調整 int n = GetDegree(3.0); RotateMotor(OUT_BC,-SPEED,n);//位置調整 A_down();//ペン下げ int o = GetDegree(6.0); RotateMotor(OUT_BC,SPEED,o);//口描く A_up();//ペン上げて終わり
1.大量のサブルーチンと関数を使用した
サブルーチンと関数のしようにより、プログラミングは基本的にコピー&ペーストと数値の設定だけに収まった。
2.ペンの移動の速度を遅すぎず、早すぎないように設定した
上にのせているペンの上げ下げのサブルーチンは、実は遅すぎると動いてくれない。しかし、早いとつっかえてしまうのでプログラミングは実行されず、中断されてしまう。そこで試行錯誤の結果 20%となった。
完成したものがこれである
こだわったのは顔の輪郭で、発表前夜2時まで耐えて整えた。しかしお世辞にも似ているとは言えないと思うので機会があれば挑戦したい。
かなり長く説明したが、自分の当初の計画はこれとはだいぶ違っており、また、こちらのほうが4,5倍の時間をかけているので説明していきたい。
正八角形の各辺の長さをいじると輪郭に近づくと考えたのでそれをえがこうとした。
先にのせたプログラミングの6倍の長さだが、ある一定の動作の繰り返しなのでそれをのせる。
#define SPEED 15
float GetAngle(float h)//上記に同じ { const float diameter = 5.45; const float pi=3.1415; float ang = 36/(diameter*pi)*h; return ang; } float GetDegree(float d)//上記のものと同型 { const float diameter = 5.45; const float pi=3.1415; float deg = d/(diameter*pi)*360.0; return deg; } task main (){ Wait(2000); int a = GetDegree(5.3);// RotateMotor(OUT_BC,SPEED,a);線を描く(輪郭を構成する直線の一つとして) Wait(2000); int aa = GetAngle(20); RotateMotor(OUT_A,20,aa);//ペン上げ Wait(2000); int aaa = GetDegree(1.55); RotateMotor(OUT_BC,SPEED,aaa);//位置調整 Wait(2000); int aaaa = GetAngle(42); RotateMotorEx(OUT_BC,SPEED,aaaa,100,true,true);方向の調整 Wait(2000); int aaaaa = GetAngle(20); RotateMotor(OUT_A,-20,aaaaa);ペン下げ
GetAngleとGetDegreeについては先の説明と同様である。
これをすることによって、どのプログラミングを修正すべきか、観測と考察が簡単になっている。
先ほども説明しているが、RotateMotorExは自分のロボットでは思い切りずれる。また、回転の反動でロボット全体が後進してしまうことが計測の結果判明した。角度のずれはこみこみでプログラミングすれば何とかなるが、後進はさすがに修正しないといけないと考えたので、これを行った。 どの部分化は説明すると int(aaa) = GetDegree(1.55) の部分で、後進しても次の前進で、前の前進の終点とが交わるようになっている。
1.圧倒的な再現性の低さ
下の画像は全く同じプログラミングで描いた絵である。誓って画像の修正やホラー画像ではない。
これはタイヤにかかる摩擦や、後輪の位置などは完全に同じにしている。しかしこれである。
2.前夜の悲劇 夜の九時ごろまで発表前日も教室でプログラミングに精を出していた。しかし、その時にCPUの画面に" Low Battery "の字が映し出された。当の本人たちは嫌な予感がしながらも1000円使って電池の交換を行った。下の写真が交換後ロボットが描いたパートナーの顔であった”なにか”である。
心が本当に折れました。もう、無理であるとここで諦めました。
1.モーターのパワー差を考慮する。
今回ここまで苦労したのは、最初にモーターのパワー差を考慮せずにプログラミングした結果だと思われるので次回以降はきをつけたい。
2.もっと時間をとる
今回は予定の調整を行わなかったので1週間しかこの課題に対して向き合えなかった。このゼミでの課題は自分の想像をはるかに凌駕するものであると今回認知したので次回以降はもっとロングスパンで課題に取り組み、断念などせずに、楽しみながら、真摯にこなしていきたい。