- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2019-11-14T14:29:36+09:00","kzy_k","kzy_k")
#author("2019-11-14T19:38:12+09:00","kzy_k","kzy_k")
[[2019b/Member]]
#contents
*&size(30){ロボットの説明} [#v0568466]
*&size(30){プログラムの説明} [#m6c9b088]
*課題1の概要 [#g624efbc]
-マインドストームを使った似顔絵を描くロボットの作成。~
似顔絵はA4用紙に収まるようにする。~
以下が実際に描いた似顔絵である。
#ref(2019b/Member/kzy_k/Mission1/1573726947481.jpg,20%,似顔絵)
*ロボットの説明 [#u03f8611]
**全体 [#v3a4fa5d]
-我々の班はペン先がx軸y軸の二つの自由度で動くことにより似顔絵を描くロボットを制作した。
#ref(2019b/Member/kzy_k/Mission1/1573708728203.jpg,20%,全体図)
**各部分 [#z12af1cc]
-動力源はモーターなので回転運動を上下運動に変換する必要がある。この機構を二つ作りそれぞれx軸y軸としてペン先を動かす。
#ref(2019b/Member/kzy_k/Mission1/モーター.jpg,50%,簡易図)
#ref(2019b/Member/kzy_k/Mission1/1573708721218.jpg,20%,変換機構)
#br
-ペン先を紙から離したり付けたりするためにペンのついている棒を押さえつけたり離したりする機構を3つ目のモーターを使い作った。
#ref(2019b/Member/kzy_k/Mission1/1573708714711.jpg,20%,ペンの上下機構)
*プログラムの説明 [#e6e29f28]
**プログラムの基本骨格部分 [#eb9633e2]
-gtというサブルーチンを次のように定義する。
sub gt(float x,float y,float z)
{
const float axis = 100.0;
const int rep = z;
const float rotation = 180.0;
const float correction = 0.5;
float angle_x = ((rotation/axis)*x)/rep + sign(x)*correction;
float angle_y = ((rotation/axis)*y)/rep + sign(y)*correction;
repeat(rep)
{
RotateMotor(OUT_B,SPEED,angle_x);
RotateMotor(OUT_C,SPEED,angle_y);
}
Wait(400);
}
これは可動範囲を100等分してx軸y軸を決め、移動したい分の値を入力して、それをモーターの回転角度に変換して回転させるというサブルーチンである。~
RotateMotorでは角度が入力された分に達するまで次の動作が実行されない。そのためzという引数を入れて細かく等分して、x軸y軸をそれぞれ交互に少しづつrepeatで繰り返し動かし、なめらかな斜めの線や曲線描く。~
correctionは補正のための値である。
#br
-gtはの入力値は移動分だったので動作前の位置情報log_x,log_yを使って入力する値を直接座標の値にした関数gfを定義する。
#define gf(x,y,z) gt(x-log_x,y-log_y,z);log_x=x;log_y=y;
#br
-ペン先を上下させる関数pu,pdを定義する。
#define pu OnFwd(OUT_A,20);Wait(500);Off(OUT_A);
#define pd OnFwd(OUT_A,-SPEED);Wait(300);Off(OUT_A);Wait(600);
**動作のプログラムの内容部分 [#l03ca0ab]
-定義された関数などを使うことでペン先を以下のプログラムで思うように動かす。
task main()
{
ResetTachoCount(OUT_BC);
float log_x = 0;
float log_y = 0;
//輪郭
pu;
gf(0.0,100.0,2);
pd;
gf(0.0,35.0,1);
gf(35.0,0.0,30);
gf(45.0,0.0,1);
gf(100.0,35.0,30);
gf(100.0,100.0,1);
gf(0.0,100.0,1);
pu;
//目
gf(25.0,45.0,2);
pd;
gf(45.0,45.0,1);
pu;
gf(60.0,45.0,1);
pd;
gf(80.0,45.0,1);
pu;
//鼻
gf(40.0,35.0,2);
pd;
gf(35.0,25.0,10);
gf(45.0,28.0,1);
pu;
//口
gf(30.0,15.0,2);
pd;
gf(60.0,15.0,2);
pu;
gh;
}
**プログラム全体 [#w3f83bf6]
-以下が実際に使ったプログラム全体である。
#define SPEED 12
#define gf(x,y,z) gt(x-log_x,y-log_y,z);log_x=x;log_y=y;
#define pu OnFwd(OUT_A,20);Wait(500);Off(OUT_A);
#define pd OnFwd(OUT_A,-SPEED);Wait(300);Off(OUT_A);Wait(600);
#define gh gf(0,0,1);
sub gt(float x,float y,float z) //(行き先の座標 , 繰り返しの回数)
{
const float axis = 100.0; //軸
const int rep = z; //繰り返し回数
const float rotation = 180.0; //軸を端から端まで動かすのに必要な角度
const float correction = 0.5; //補正
float angle_x = ((rotation/axis)*x)/rep + sign(x)*correction;
float angle_y = ((rotation/axis)*y)/rep + sign(y)*correction;
repeat(rep)
{
RotateMotor(OUT_B,SPEED,angle_x);
RotateMotor(OUT_C,SPEED,angle_y);
}
Wait(400);
}
task main()
{
ResetTachoCount(OUT_BC);
float log_x = 0;
float log_y = 0;
//輪郭
pu;
gf(0.0,100.0,2);
pd;
gf(0.0,35.0,1);
gf(35.0,0.0,30);
gf(45.0,0.0,1);
gf(100.0,35.0,30);
gf(100.0,100.0,1);
gf(0.0,100.0,1);
pu;
//目
gf(25.0,45.0,2);
pd;
gf(45.0,45.0,1);
pu;
gf(60.0,45.0,1);
pd;
gf(80.0,45.0,1);
pu;
//鼻
gf(40.0,35.0,2);
pd;
gf(35.0,25.0,10);
gf(45.0,28.0,1);
pu;
//口
gf(30.0,15.0,2);
pd;
gf(60.0,15.0,2);
pu;
gh;
}
*感想 [#l5b2c4ba]
-図を描くロボットは状況を判断させて動かすロボットと違い一定の動作をただ実行するロボットである。それゆえ、今回行ったように関数などを事前に決めておいてあとはペン先を思い通りに動かすように値だけを変えるようにするのが楽であることがわかった。
-x-y直交座標にすることでx軸y軸に平行な線を描く分には簡単である。しかし、曲線などは上下運動をx,yそれぞれ異なる時間の媒介関数に従って動かさなければならないので少し複雑になってしまう。
-モーターは入力の通りに正確に動いてくれないので微妙な調節が必要であった。
-ペン先の高さについても近すぎると摩擦が大きく動きにくくなり、遠すぎれば描かれないので微妙な調節が大変であった。
*改善点 [#w2e34a19]
-x-y直交座標だと曲線、特に円を描くのが難しいので円をたくさん使うような図を描く場合はペンを固定してタイヤを動かして図を描くようなロボットのほうが有利である。
-今回のプログラムではモーターの一定の角度の回転で動く上下分はいつでも一定としたが、厳密にはモーターの初期位置により同じ動かしたい量でも回転角度は変わってくる。そのことを含めたプログラムを作るべきであった。