[[2011b]] 目次 #contents *メンバー [#p417b474] -ろにゃ……情報工学科。理数科高校出身。プログラミング勉強してる。 -鍾馗……電気電子工学科。普通科高校出身。プログラムはこれまで書いたことなし。相方君に迷惑をかけっぱなし。 *課題 [#xd426fe4] -A4の紙に相棒の顔を描くロボットの作成。 以下ルール -筆又はペンは各チームで用意する。種類は問わない。 -ロボット構成にあたり、使用する機材は「Mindstorms Robotics Invention System」にあるパーツのみ。それ以外は筆又はペンを除き使用できない。 -用紙はA4のコピー用紙。これの上に書くことができるように作成。 -A4用紙をセロハンテープなどで止めるなど固定することは不可。 -ロボットが絵を描き始めたら書き終わるまでロボットに触れてはいけない。 -期間は約2週間。 以下努力義務 -相棒の顔に見える絵を描くこと。 *ロボットの構造 [#h1ab4866] **方針 [#f642be3d] 紙上の描きたい場所を走行してペンを上下させるだけで描けそうな「紙の上を走行するロボ」を作成することにした。 **走行ユニット(ドライブベース) [#nb987470] ***ver1.0 [#bf063255] &ref(2011b/A1/課題1左/後輪-1.jpg,50%,後輪); &ref(2011b/A1/課題1左/走行ユニット.jpg,50%,走行ユニット); &ref(2011b/A1/課題1左/後輪-1.jpg,50%,後輪); &ref(2011b/A1/課題1左/走行ユニット.jpg,50%,走行ユニット); -先生が猛プッシュしていた3輪(と言っても厳密には4輪じゃんと思うのはどこも一緒)に即決定。 -しかし車体が傾き重心が上に行く -後輪はうまく動作しない ***ver2.0 [#g9b4e4e0] ver1.0から反省しバージョンアップ。後輪をキャスターからヒントを得て作り直しました。 &ref(2011b/A1/課題1左/後輪改.jpg,100%,後輪改); -確かな3輪になりました。 -動作が改善されて自由自在の動きを実現。 -車体が水平になりより安定。 **筆ペンユニット [#uf0b41d9] &ref(2011b/A1/課題1左/筆ペンユニット1.jpg,100%,筆ペンユニット1); &ref(2011b/A1/課題1左/筆ペンユニット2.jpg,100%,筆ペンユニット2); &ref(2011b/A1/課題1左/筆ペンユニット3.jpg,100%,筆ペンユニット3); -線を描くときの紙との摩擦が少なそうな筆ペンを使用することに決定。線の太さが一定にならないのはデメリットですが、今回はそこまで求められていません。 -筆を上下させるユニット(以後筆ペンユニットと呼称)は筆ペンを垂直に動かすことにしました。初めはブロックでできたスライドユニットをブロックで囲む摩擦感たっぷりの構造でしたが、相方君が1日を潰して改良してくれました。多謝。 -↑の摩擦感たっぷりの状態でも正常に稼働しました。電池6本直列は伊達ではないようです。 -上下するやつのストッパーが上下させるやつに引っかかった時に空回りするよう白いギアを使用。こうすることでプログラムでモーターの回転する秒数指定を多めに指定しても、上下するやつが上下させるやつから飛び出してしまうこともなく、またモーターに負荷をかけず安全に停止することができます。 **全体的な構造 [#d1b14845] &ref(2011b/A1/課題1左/正面.jpg,100%,正面); &ref(2011b/A1/課題1左/右側面.jpg,100%,右側面); &ref(2011b/A1/課題1左/後方.jpg,100%,後方); &ref(2011b/A1/課題1左/左側面.jpg,100%,左側面); -いろいろと試行錯誤してみたのですが、写真のようにRCXの上に筆ペンユニットを置くような形に決定しました。重心が高くなりましたが許容範囲です。 -試行錯誤の結果ロボの形を作ってからRCXののせる場所を考えるとうまくいかなかったので、RCXを中心に何をどこに配置するかを考えた結果この形に至りました。非常にすっきりとした形になっています。 *プログラム [#b235bec9] ** ろにゃver [#m227cd50] ***方針[#n40cd08a] 輪郭以外の顔のパーツを直線だけで構成することで 輪郭を書く→(紙の外に出て位置を調整→ペンを上下させつつまっすぐに紙上を通り抜ける)→以下()内繰り返し という手順によって紙をずらすことなく似顔絵が描ける。 予定図は↓ &ref(2011b/A1/課題1左/似顔絵予定図.jpg,100%,似顔絵予想図); ***結果 [#e5daa575] &ref(2011b/A1/課題1左/完成.jpg,100%,完成図); 顔の形にするのに必死で似てるかどうかとか問題にできなかった。 鼻の形も妥協している。 ***コード [#n0529129] //AとCのモーターをOffで止める void OFF(){ Off(OUT_A+OUT_C); } //整数値を引数に取ってその秒数分直進させる関数 void go_straight(int t){ OnFwd(OUT_A+OUT_C); Wait(t); } /*整数値を引数に取ってその秒数分 左のタイヤを固定して右のタイヤを正回転させ左折させる関数*/ void turn_left(int t){ OnFwd(OUT_C);Off(OUT_A); Wait(t); } /*整数値を引数に取ってその秒数分 右のタイヤを固定して左のタイヤを正解点させ右折させる関数*/ void turn_right(int t){ OnFwd(OUT_A);Off(OUT_C); Wait(t); } //整数値を引数にとってその秒数分右回転で超信地旋回させる関数 void right_PivotTurn(int t){ OnFwd(OUT_A);OnRev(OUT_C); Wait(t); OFF(); } //整数値を引数にとってその秒数分左回転で超信地旋回させる関数 void left_PivotTurn(int t){ OnFwd(OUT_C);OnRev(OUT_A); Wait(t); OFF(); } //ペンを上げる関数 void pen_up(){ OnRev(OUT_B); Wait(015); Off(OUT_B); } //ペンを下げる関数 void pen_down(){ OnFwd(OUT_B); Wait(015); Off(OUT_B); } //メインルーチン task main(){ int i; //輪郭を描く pen_down(); for(i=0;i<2;i++){ go_straight(050); turn_right(210); } pen_up(); //位置を調整 go_straight(010); turn_right(090); go_straight(200); //目を描く right_PivotTurn(105); go_straight(140); pen_down(); go_straight(010); pen_up(); go_straight(005); pen_down(); go_straight(010); pen_up(); go_straight(150); OFF(); //位置を調整 left_PivotTurn(055); go_straight(065); left_PivotTurn(055); //口を描く go_straight(140); pen_down(); go_straight(030); pen_up(); go_straight(180); //位置を調整 right_PivotTurn(050); go_straight(150); right_PivotTurn(050); go_straight(190); right_PivotTurn(050); //鼻を書く go_straight(165); pen_down(); go_straight(005); pen_up(); go_straight(200); OFF(); } **鍾馗ver [#t78fb0be] ***方針 [#kb23810b] とりあえず -直線を多用することによって、プログラムを作りやすくする。 -30度45度の折れ線を使って計算しやすくする。 この2つに注意して下のような図面もどきを作って見ました。 #ref(2011b/A1/課題1左/課題1下書き.jpg,wrap,100%,図面もどき) 描くときの方針としては、 -まず顔の輪郭左上から書き始め、 -次に髪を描き、 -最後に目、口、鼻の順に描く、 ことにしました。なんか少し複雑な気がしましたがこの時点では無視しました。 ---- 顔の輪郭から、髪の毛までは一筆書きです。しかしながら、お絵かきロボットは旋回軸と筆が紙に描く部分がが約3cmずれているので下記のようにただタイヤを反転させるだけではうまくいきません。 #ref(2011b/A1/課題1左/折れ線0.png,100%,折れ線失敗図) そこで以下のようにお絵かきロボットを動かすことにしました。 #ref(2011b/A1/課題1左/折れ線2.png,100%,折れ線1) まず、折れ曲がり地点で筆を上げた後、旋回軸が折れ曲がり地点と重なるように前進させます。 #ref(2011b/A1/課題1左/折れ線3.png,100%,折れ線2) 旋回させます。 #ref(2011b/A1/課題1左/折れ線4.png,100%,折れ線3) 折り返し地点に筆が来るように後進させます。そのあと筆を下して前進。 こうすることで(理論上は)綺麗な折れ線が書け(るはずであり)ます。 ---- 実はこの時点で、360度が何秒旋回すればいいのか、直進1秒が何センチ進むかを計測しておけば簡単に完成だと思っていました。 そして実行した結果は以下のとおり。 #ref(2011b/A1/課題1左/課題1初め書き.png,wrap,100%,これはひどい) なんということでしょう。想像以上のひどさです。(実はこの絵、顔の輪郭は修正されている時のものなので、はじめはもっとひどいものでした) ---- そんなこんなで修正したのがこれになります。 #ref(2011b/A1/課題1左/課題1完成書き.jpg,wrap,100%,顔に見えなくはない) 目は始め三角形の予定でしたが、心が折れたためにボツにしました(線が想像以上に太いためうまくかけてもごちゃごちゃになるとの判断もありました)。 あと、ロボット自体が紙からはみ出すと、大きく紙がずれるので、絵自体は小さめになっています。 #ref(2011b/A1/課題1左/課題1大きさ比べ.jpg,wrap,100%,大きさはA4の紙) ***コード [#pe14f6e6] 書きながら直進、右旋回、左旋回の3つを関数にして書きました。 書くときは直進しかしないので関数に。 旋回は方針に書きましたように前進→旋回→後進を一セットとしていますので関数を使った方がよいと判断しました。 ですがこのため調整の時、後進した直後に前進をするなど無駄な動きをするようになってしまいました(修正するのが面倒くさいとも言う。「実際旋回して直進書き」と言う動きをなるべく1行で済ましていたので、ごちゃごちゃさせたくありませんでした)。 ちなみに角度、直進時間の定義ですが調整の結果使わなくなった物と一つしか使わない物は抜きましたので、刃こぼれを起こしています(ちなみに最初は定義を23個も使っていました)。 #define mae OnFwd(OUT_A+OUT_C);Wait(15);Off(OUT_A+OUT_C); //旋回時の微調整 #define usiro OnRev(OUT_A+OUT_C);Wait(13);Off(OUT_A+OUT_C); //旋回時の微調整 //15度=8.75 #define p 28 //45度 #define r 43 //75度 #define s 53 //90度 #define t 78 //120度 #define u 95 //150度 #define a 60 //直進時間 #define b 42 // #define c 23 // #define d 40 // #define e 20 // #define f 28 // #define h 12 // void migi(int x) //筆を動かさないで右旋回 { mae;OnFwd(OUT_A);OnRev(OUT_C);Wait(x);Off(OUT_A+OUT_C);usiro; } void hidari(int x) //筆を動かさないで左旋回 { mae;OnFwd(OUT_C);OnRev(OUT_A);Wait(x);Off(OUT_A+OUT_C);usiro; } void kaku(int y) //書きながら前進 { OnFwd(OUT_B);Wait(8);Off(OUT_B); //筆を下げる OnFwd(OUT_A+OUT_C);Wait(y);Off(OUT_A+OUT_C); OnRev(OUT_B);Wait(8);Off(OUT_B); //筆を上げる } task main() //メインタスク44 { //顔 kaku(a); hidari(p);kaku(b); hidari(s);kaku(b); hidari(p);kaku(a); //髪 usiro;migi(u);usiro;kaku(c); usiro;migi(u);usiro;kaku(d); mae;hidari(t);mae;kaku(e); usiro;migi(82);usiro;kaku(f); hidari(r);kaku(d); usiro;migi(u);usiro;kaku(c); //目に移動 migi(t); OnFwd(OUT_A+OUT_C);Wait(30);Off(OUT_A+OUT_C); //左目の上を描く hidari(r);kaku(h); OnFwd(OUT_A+OUT_C);Wait(h);Off(OUT_A+OUT_C); //次は右目。下側も描く。 kaku(h); //口まで移動 migi(s); OnFwd(OUT_A+OUT_C);Wait(e);Off(OUT_A+OUT_C); migi(s); OnFwd(OUT_A+OUT_C);Wait(h);Off(OUT_A+OUT_C); //まっすぐな口 kaku(h); //鼻まで移動 migi(t); OnFwd(OUT_A+OUT_C);Wait(f);Off(OUT_A+OUT_C); //真っ直ぐな鼻 usiro;hidari(17);kaku(9); } *その他(反省など) [#n8252bc2] **ろにゃ [#q9850bf3] -次はマシンの特性と課題の意図を理解してマシンを作りたい。 -修正しやすいプログラムを書くよう意識したい。 **鍾馗 [#m491eac3] -メンバー紹介に本名使おうとした愚かな俺(鍾馗)を笑ってください。 -電池を新品に変えたら1秒間あたりの旋回角度が変わったため再調整が必要になりました。 -また、多少はずれても顔に見えるようなものにしたかったです。 -動きが素早すぎました。もう少しギア比を変えて遅くした方がよかったかもしれません。 -ただし自分の場合コンパクトさを利用して、紙からロボットが出ないようにしていたのでこれが最善だったのかもしれません。 -もう少しプログラムを綺麗に仕立て上げたかったです。 -