#author("2020-02-03T14:00:49+09:00","Nishi","Nishi")
#author("2020-02-03T14:05:39+09:00","Nishi","Nishi")
[[2019b/Member]]

目次
#contents

*ロボット [#j6ac264d]
**ロボットの説明 [#sf1a50ae]
#ref(./IMG_3668a.jpg,10%);
 モーターでタイヤを動かし、ペンを搭載したロボット全体を移動させて似顔絵を描く。モーターは全部で3つあり、2つはタイヤを回すために、残り1つはペンの上げ下げのために使用されている。
#ref(./IMG_3656a.jpg,6%);
ペンは2つのタイヤの間にあり、輪ゴムで固定されている。
**ロボットの特徴 [#pe246614]
***ペン先が2つのタイヤの中心にくるようにした [#sb609469]
 最初、ペンの接地地点を前輪の前にくるようにした。しかし、曲線から直線に切り替えるときに変な出っ張りが現れてしまい、なめらかな線を描くことはできなかった。そのため、できる限りペン先が2つのタイヤの中心にくるようにした。結果、輪郭をなめらかな線で描くことができた。
***重心をなるべく前輪の方に寄せた [#h4de07ff]
 後輪は小さなタイヤ1つとなっているため、後輪の方に重心が寄るとバランスを崩しやすく、転倒することもあった。そのため、できる限り前輪の方に重心を寄せ、安定するようにした。
***前輪のタイヤ幅を調整した [#r818c26e]
 タイヤの間にペンが入るくらいのスペースがあり、かつ片方のタイヤだけを回して曲がったときに自分が望むサイズの弧を描けるように調整した。それにより、プログラム面での苦労を減らすことができた。

*プログラム [#i8ba8e2e]
**プログラム全体 [#o9c982b0]
 #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);
 }

**プログラムの説明(定義、関数など) [#ebf904c5]
***角度の計算 [#td7b3367]
 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;
 }
 括弧内に方向転換したい角度を入れ、タイヤの回転角度を計算する。計算した角度はロボットを回転させるプログラムで使用する。
***直進 [#jd6cab58]
 sub fwd(int t)
 {
     RotateMotorEx(OUT_BC,SPEED,t,0,false,true);
 }
 括弧内にタイヤの回転角度を入れ、その分直進する。
***左旋回 [#a9a8b694]
 sub fwd_B(int b)
 {
     RotateMotor(OUT_B,SPEED,b);
 }
 括弧内にタイヤの回転角度を入れ、左に曲がる。
***右旋回 [#ubac5920]
 sub fwd_C(int c)
 {
     RotateMotor(OUT_C,SPEED,c);
 }
 左旋回のプログラムと同様に、タイヤの回転角度を入力し、右に曲がる。
***右回転 [#s0f83052]
 sub turn_right(int r)
 {
     int angle = GetAngle(r);
 
     RotateMotorEx(OUT_BC,25,angle,100,true,true);
 }
 括弧内に方向転換した角度を入れ、右に回る。計算して出した角度はここで使用する。
***左回転 [#o8621ee8]
 sub turn_left(int l)
 {
     int angle = GetAngle(l);
 
     RotateMotorEx(OUT_BC,25,angle,-100,true,true);
 }
 右回転のプログラムと同様に、方向転換した角度を入力し、左に回る。
***ペンの上げ(up)下げ(down) [#j0521397]
 sub up()
 {
     RotateMotor(OUT_A,15,30);
 }
 
 sub down()
 {
     RotateMotor(OUT_A,-10,30);
 }
ペンを上げてペン先を紙面から浮かせるプログラムと、ペンを下げてペン先を紙面につけるプログラム。
**プログラムの説明(task main) [#x6451f12]
***輪郭 [#e2281577]
     up();
     down();
     fwd(180);
     fwd_B(810);
     fwd(180);
     fwd_B(427);
     fwd(45);
     fwd_B(427);
     up();
 直進と左旋回で輪郭を描いた。顎よりも頭頂部の方を横に長くしたかったため、頭頂部を描く際に旋回のみで描くのではなく、直進も少し挟んだ。
***前髪 [#x6e0bd1e]
     turn_left(90.0);
     fwd(30);
     down();
     fwd(270);
     up();
 輪郭を描き終わったとき、ロボットは前髪を描くところの近くに位置しているため、方向転換と軽く位置調整を行い、直進して前髪を描いた。
***目 [#h758677f]
     turn_right(105.0);
     fwd(15);
     turn_right(110.0);
     fwd(54);
     down();
     fwd(54);
     up();
     fwd(54);
     down();
     fwd(54);
     up();
 目を描くために位置と向きを調整し、直進しながらペンを上げ下げし、2つの線を描いた。複雑に描くことができなかったため、線で目を描くことになった。
***口 [#d1ba2874]
     fwd(54);
     turn_left(100.0);
     fwd(220);
     turn_left(90.0);
     fwd(100);
     down();
     fwd(90);
     fwd_B(60);
     up();
 位置と向きを調整し、口を描いた。カーブをつけようとしたが、線が短いのも
 位置と向きを調整し、口を描いた。口がただの棒にならないように気持ちカーブを入れた。
***鼻 [#d098b61c]
     turn_left(100.0);
     fwd(100);
     down();
     fwd_C(427);

 鼻についても口と同様に、微々たるカーブをつけた。鼻は顔のパーツの中でも向きが大きく異なるため、最後に描いた。
**プログラムの特徴 [#e6929075]
***サブルーチンを多用した [#hfb72c3a]
 サブルーチンでいくつかの一連の命令をまとめ、task mainのプログラムをシンプルなものにした。
***ロボットの移動のスピードは少し遅めにした [#r38a2602]
 スピードが速いとロボットが重いせいで曲がるときにバランスを崩しがちだったため、全体的に動作を遅くした。
***タイヤを回すためのプログラムでOnFwdではなくRotateMotor(EX)を使用した [#jb85880a]
 OnFwdだと電池残量に影響されたり、進む距離の調整に手間がかかったりした。また、ロボットの重量が変わったときの挙動の変化も大きかった。

*反省・改善点 [#o5e4b511]
- バランスのために重心を前輪の方に寄せたが、後ろのタイヤを増やして安定させてもよかった。
- ロボットが重いせいか方向転換する際にタイヤが浮き、思った通りにロボットが動かないことがあった。タイヤの回転速度や使用パーツの見直しをすべきだった。
- ロボットが縦に長く、かつ比較的重量のあるNXT本体が上の方にあったため不安定だった。ペンの上げ下げのためのモーターやNXT本体の向きや位置を変え、重心を下の方に寄せることも考えるべきだった。
- どこからどこまでが何のプログラムかが分かりにくくなっているため、改行やスラッシュを使い見やすくするべきだった。
*感想 [#rcb67273]
#ref(./IMG_3673a.jpg,15%);
 今回のお絵かきロボットの作成に想像以上の時間がかかり驚いた。また、ロボットは自分が望む動きをしないということを痛感した。今後は今回の反省を活かした取り組みをしていきたい。

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