はじめに
「お絵かきロボット」を作る課題
先生曰く「グループ三人の中で誰か識別できる程度の顔を描きなさい」とのこと
ほかの制限は
・マクロや関数、サブルーチンなどを使い、main関数がなるべく単純になるようにプログラムを作ること
・定数名やマクロなどは分かりやすい名前を用いること
・余裕をもってA4の紙の中に収まる大きさにすること。いくら小さくてもよい
・ペン以外はキットの部品を使うこと
いや〜きついっす(素)
課題自体は3週間ほど前から提示されてましたがEV3班は見捨てられていて開発環境について先生からの指示がなく、開発環境が整ったのは期限前日の18時でした。なんてこったい
ロボットの説明と開発環境
今回使用したキットは教育版レゴ社マインドストーム EV3を使用しました
今回、先生から開発環境やプログラミング言語の支持がなかったのも、このEV3をしようするのが今回の授業で初めてだったからだそうですそれじゃあ仕方ないね
ペンはアームを動かすことで上げ下げできるようにしました
このペンの上げ下げが僕らを苦しめることになるがそれは後述
モーターは車輪を動かす用のモーターを2つと、アーム用のモーター1つ
EV3のOSは「linax debian」を使用
パソコン側はwindows8.1だとEV3との通信の互換性が悪いと聞いていたので、linax ubuntuを使用する予定でしたが
「Tera Term」というソフトウェアを使用しwin8.1からEV3に転送できました
開発言語も最初はC#を使用する予定でしたが最終的にはpythonに決定しました
プログラム
・定義
m1 = ev3.LargeMotor('outA') m2 = ev3.LargeMotor('outB') m3 = ev3.MediumMotor('outC') ts = time.sleep m1stop = m1.stop(stop_command='brake') m2stop = m2.stop(stop_command='brake') m3stop = m3.stop(stop_command='brake') m1run = m1.run_forever m2run = m2.run_forever m3run = m3.run_forever
↑これが定義文です
これを利用すれば例えば『ev3.LargeMotor('outA')』と書かなければいけないものを『m1』と省略できます
「LargeMotor」は車輪用の大きなモーターのことです
これは先生から教えてもらっていたので大丈夫だったのですが、問題はアーム用の小さなモーターの方
「でかいのが『Large』なんだから小さい方は『Small』じゃね」
普通そうなるよね、でもこれ「MediumMotor」だったのモーターのサイズ2種類しか無いんだから普通は大と小だろ
↑アーム周りの動作ギミック
このペンの上げ下げの動作ですが、重力の関係からかアームを下げるパワーと時間を、上げる時と同じにしてしまうとペン先を地面に強く押し付けてしまってペン先が◯にます
例
m1run(duty_cycle_sp=『数字』)←これで『数字』%のパワーでモーター1を回転(逆回転は「-」をつければよい)
m1stop←これでモーター1を急停止
ts(『数字』)←これで『数字』秒間動作を継続
これらを利用して
m1run(duty_cycle_sp=『70』)~ m2run(duty_cycle_sp=『70』)~ ts(3.0)~ m1stop~ m2stop~
これで「左右のモーターを70%の力で3.0秒間前進した後急停止」という動作をEV3さんがしてくれます
その他、m1run(duty_cycle_sp=『正の実数』)でペンを持ち上げる、その逆でペンを下げます
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
ここからは実践編です
m1run(duty_cycle_sp=70) m2run(duty_cycle_sp=-20) ts(0.4) m1run(duty_cycle_sp=90) m2run(duty_cycle_sp=20) ts(0.7) m1run(duty_cycle_sp=70) m2run(duty_cycle_sp=-20) ts(0.8) m1run(duty_cycle_sp=-30) m2run(duty_cycle_sp=1) ts(0.4) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=-40) ts(0.4) m1run(duty_cycle_sp=-40) m2run(duty_cycle_sp=0) ts(0.4) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=-40) ts(0.4) m1run(duty_cycle_sp=-40) m2run(duty_cycle_sp=0) ts(0.4) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=-40) ts(0.4) m1run(duty_cycle_sp=-40) m2run(duty_cycle_sp=0) ts(0.4) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=-40) ts(0.4) m1run(duty_cycle_sp=-40) m2run(duty_cycle_sp=0) ts(0.4) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=-40) ts(0.4) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=50) ts(0.1) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=30) m2run(duty_cycle_sp=35) ts(2.0) m1stop m2stop ts(0.2) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=-25) ts(0.5) m1run(duty_cycle_sp=50) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=0) ts(1.0) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=50) ts(0.1) m1run(duty_cycle_sp=-20) m2run(duty_cycle_sp=-20) m3run(duty_cycle_sp=0) ts(0.6) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=-25) ts(0.5) m1run(duty_cycle_sp=30) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=0) ts(0.6) m1stop m2stop m3stop ts(0.3) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=50) ts(0.1) m1run(duty_cycle_sp=-30) m2run(duty_cycle_sp=-30) m3run(duty_cycle_sp=0) ts(1.0) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=-25) ts(0.5) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=-20) m2run(duty_cycle_sp=-20) m3run(duty_cycle_sp=0) ts(0.15) m1stop m2stop m3stop ts(0.1) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=50) ts(0.1) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=90) m2run(duty_cycle_sp=30) m3run(duty_cycle_sp=0) ts(0.5) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=-30) m2run(duty_cycle_sp=-30) m3run(duty_cycle_sp=0) ts(0.65) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=-30) ts(0.5) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=-20) m2run(duty_cycle_sp=-20) m3run(duty_cycle_sp=0) ts(0.3) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=50) ts(0.1) m1run(duty_cycle_sp=-50) m2run(duty_cycle_sp=-50) m3run(duty_cycle_sp=0) ts(0.4) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=-30) ts(0.5) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=-20) m2run(duty_cycle_sp=-20) m3run(duty_cycle_sp=0) ts(0.3) m1stop m2stop m3stop ts(0.2) m1run(duty_cycle_sp=0) m2run(duty_cycle_sp=0) m3run(duty_cycle_sp=55) ts(0.2) m1run(duty_cycle_sp=90) m2run(duty_cycle_sp=-90) m3run(duty_cycle_sp=0) ts(1.0) m1run(duty_cycle_sp=-90) m2run(duty_cycle_sp=90) m3run(duty_cycle_sp=0) ts(1.0) m1stop m2stop m3stop ts(1)
このプログラムで何度も繰り返し動作させて最も良く描けたものはこれです↓
別の試し描きの線と被ってしまっていますが、輪郭があって、糸目があって、口があって、鼻がある
確かに人の顔です
苦節12時間、努力した甲斐がありました
問題点とその反省
今回人の顔は描けましたが、誰だかわかるほど細かくかけていないことと、絵が大きく、A4サイズの紙から少しはみ出してしまう問題が起きました
多くのRCX班やNXT班が制作したロボットと比べて、わたしたちの班のロボットはペン先とタイヤの軸との距離が離れており
そのため回転最小半径が大きくなってしまったのが絵の大型化に継ががったのではないかと思われます
あってはならないはずのおまけ
「今日は徹夜だな、初徹夜記念に撮っとくか」「うえーい」
↓
「徹夜でパソコンいじりながらカップラーメンとか俺ら工学部っぽくなったな」
↓
深夜テンション
健気に絵を描くEV3さんに愛着すら湧いてきます