#author("2020-02-10T17:19:11+09:00","ameame","ameame")
#author("2020-02-11T11:45:38+09:00","ameame","ameame")
[[2019b/Member]]
#contents
*課題1 お絵描きロボット [#l9677453]
チームメイトの似顔絵を描くロボットの作成
*課題の成果 [#o737873c]
#ref(image1.jpeg)
*ロボットについて [#ve413ced]
最初はロボットの前後と進行方向に垂直にペンを移動させる方法を考えていたが、ロボット自体の構造が複雑になってしまうことやモーターの回転で直線的な位置を管理するのが難しいと考え、ロボット自体が自由に動く仕組みに切り替えた。
**ロボットの説明 [#b71b0f28]
#ref(image2.jpeg)
モーターを3つ使っている。タイヤ2輪にそれぞれモーターをつけ、もう一つのモーターにペンを取り付け回転させることでペンの上げ下げを行う仕組みになっている。ペンの位置を決めやすくするために2つのタイヤの中間にペンが来るようにした。タイヤの上にペンがあるため本体が後ろ寄りにつくせいで重心が後ろになってしまう。倒れないようにするためにキャスターを増やし、4輪にした。
#ref(image0.jpeg)
**ロボットの反省点 [#f918163f]
この方法は安定性が低かった。
タイヤで地面を走るため、
-タイヤと地面の摩擦
-キャスターの角度
-ペンと紙との摩擦

などの要素で位置がずれてしまう。一度位置がずれてしまうとその時の位置をもとに次の位置を目指すためすべての顔のパーツの位置がおかしくなってしまう。実際にタイヤのほこりをふくだけで別の顔が出来上がった。

ロボット自体が走る方法にしても、
-ロボットの重心をもっと中央に寄せる
-ペンを斜めに接地させ摩擦を減らす
-ロボット自体が高く、倒れやすくなっているためもっとコンパクトな作りにする

などの工夫を行うべきであった。
*プログラムについて [#t101f84f]
**使用したプログラム [#ib32c1b0]
mainプログラム内の(数字)は後の説明で使う
mainプログラム内の(数字)は後の説明で使う。
 #define SPEED 50
 #define TIME 500
 
 void turn(float f)
 {
     const float diameter=5.5;
     const float distance=12.5;
     float angle=f*distance/diameter;
     if(f>0)
     {
         RotateMotorEx(OUT_BC,SPEED,angle,100,true,true);
     }
     else
     {
         RotateMotorEx(OUT_BC,SPEED,angle,-100,true,true);
     }
     Wait(TIME);
 }
 void straight(float d)
 {
     const float diameter=5.5;
     const float pi=3.1415;
     float ang=d/(diameter*pi)*360;
     RotateMotorEx(OUT_BC,SPEED,ang,0,true,true);
     Wait(TIME);
 }
 void curve(int Vb,int Vc,int t)
 {
     OnFwd(OUT_B,Vb);
     OnFwd(OUT_C,Vc);
     Wait(t);
     Off(OUT_BC);
     Wait(TIME);
 } 
 
 task main()
 {                                //紙の左上からスタート(1)
     straight(5);                 //反時計回りに顔の輪郭
     curve(0,70,950);
     straight(3);                 //右こめかみ
     curve(0,70,950);
     straight(5);                 //左こめかみ
     curve(10,80,1800);           //輪郭終わり
     RotateMotor(OUT_A,10,20);    //ペンを上げる
     straight(5);                 //目の高さへ(2)
     turn(80);                    //顔の中心を向く
     straight(2);                 //右目の位置へ(3)
     RotateMotor(OUT_A,-10,20);   //ペンを下げる
     straight(3);                 //右目
     RotateMotor(OUT_A,10,20);    //ペンを上げる
     straight(2);                 //左目の位置へ(4)
     RotateMotor(OUT_A,-10,20);   //ペンを下げる
     straight(3);                 //左目
     RotateMotor(OUT_A,10,20);    //ペンを上げる
     turn(90);                    //顔の下を向く
     straight(5);                 //口の位置へ(5)
     RotateMotor(OUT_A,-10,20);   //ペンを下げる
     curve(-20,50,1500);          //口
     RotateMotor(OUT_A,10,20);    //ペンを上げる
     turn(90);                    //顔の中心を向く
     straight(2);                 //鼻の位置へ(6)
     turn(-45);                   //顔の上を向く
     RotateMotor(OUT_A,-10,20);   //ペンを下げる
     straight(2);                 //鼻
     RotateMotor(OUT_A,10,20);    //ペンを上げる
     straight(30);                //ロボット退場
 }
**プログラムの説明 [#cf7c31f8]
3つの関数を使っています。
3つの関数を使っている。
 関数名:関数の意味(数値が指定するもの)
 turn:ロボットがその場で回転する(ロボットの回転する角度、単位は度)
 straight:ロボットが直進する(ロボットの直進する距離、単位はcm)
 curve:ロボットが曲線を描く(右タイヤの速さ,左のタイヤの速さ,走る時間)
***turn [#pa9cff3c]
似顔絵を描く上でロボットは左右に回転できた方が便利である。そのため、括弧の中の数の正負で回転方向を変えられるようにしたいと考えた。しかし、
 RotateMotorEx(OUT_BC,50,90,100,true,true);
 RotateMotorEx(OUT_BC,50,-90,100,true,true);
このように指定する角度の正負を入れ替えても挙動は同じになってしまった。そのため、
 if(f>0)
 {
     RotateMotorEx(OUT_BC,SPEED,angle,100,true,true);
 }
 else
 {
     RotateMotorEx(OUT_BC,SPEED,angle,-100,true,true);
 }
if文を用いて角度の正負を判断し、それぞれ別の命令を出すようにした。
***straight [#t6524dc3]
進みたい距離からタイヤの回転角を決め、進む関数です。
***curve [#xf46986c]
似顔絵にはたくさんの曲線が必要だと考えたため作成した。走る時間と左右のタイヤの速度をそれぞれ指定して曲線(円の一部)を描く。
**mainプログラムの説明 [#c379a39c]
mainプログラム内の(数字)と画像の数字が対応している。
mainプログラム内の(数字)と画像の数字が対応している。mainプログラム内の説明の左右は似顔絵から見た左右である。
#ref(numbered.jpeg)
*まとめ [#r0ce63ae]
途中でロボットの構造を変えるなど計画性のない行動をとってしまった。次回はもっとロボットに時間をかけ、計画的に作成したい。プログラムに関しては関数を利用してシンプルな書き方ができた。しかし、まだ手探りな部分が多いため慣れていきたい。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS