[[授業時に配布した資料:http://yakushi.shinshu-u.ac.jp/robotics-ev3/]]をアップしました。 下記のメモより詳しく書いてあります。 目次 #contents * 参考サイト [#t34f3fc4] - http://www.ev3dev.org/ (ev3devの開発元) - https://media.readthedocs.org/pdf/python-ev3dev/latest/python-ev3dev.pdf (python-ev3のPDF文書) - http://openrtm.org/openrtm/ja/node/5806 (産総研OpenRTM-aistのページ、日本語) * 準備 [#q864ac9b] http://www.ev3dev.org/docs/getting-started/ を参考に。 ** OSのイメージをダウンロード [#sb77d4ec] %% https://github.com/ev3dev/ev3dev/releases/download/ev3dev-jessie-2015-12-30/ev3-ev3dev-jessie-2015-12-30.img.xz %% %% https://github.com/ev3dev/ev3dev/releases/download/ev3dev-jessie-2016-12-21/ev3dev-jessie-ev3-generic-2016-12-21.zip %% %% https://github.com/ev3dev/ev3dev/releases/download/ev3dev-jessie-2017-02-11/ev3dev-jessie-ev3-generic-2017-02-11.zip %% https://github.com/ev3dev/ev3dev/releases/download/ev3dev-jessie-2017-06-09/ev3dev-jessie-ev3-generic-2017-06-09.zip ** microSDまたはmicroSDHCにコピー [#jeaf4320] microSDXCは使えない。microSDのデバイス名が /dev/sdb とすると、以下のようにddでイメージをメディアに書き込む。 xzcat ~/Download/ev3dev-jessie-ev3-generic-yyyy-mm-dd.img.xz | sudo dd bs=4M of=/dev/sdb デバイス名が不明な場合は cat /proc/partitions などのコマンドで調べる。 ** 起動 [#c943330c] microSDを本体のカードスロットにセットして電源ON(真ん中の四角いボタンを押す)。microSDが入っていれば、本体のOSではなくmicroSDのOS(ev3dev)が起動する ** ネットワークの接続 [#z38ad46a] wifiのドングルを使うのがおそらく最も簡単。 brickmanのメニューが表示されたら、 「Wireless and Networks」→「Wi-Fi」で無線ネットワークを選ぶ。 「Powered」をチェックすると「StartScan」で無線ネットワークをスキャンできる。 無線ネットワークを選択して接続できたら、ディスプレイ上部に表示されている、DHCPで取得したアドレスを確認しておく。 ** sshでログイン [#ia48be56] IPアドレスが192.168.2.30の場合、パソコン側から ssh robot@192.168.2.30 でログインできる(デフォルトのUIDは「robot」、パスワードは「maker」)。 Windowsの場合はTeraTermなどを使えばよい。 localhost:~$ ssh robot@192.168.2.30 robot@192.168.2.30's password: _____ _ _____ _|___ / __| | _____ __ / _ \ \ / / |_ \ / _` |/ _ \ \ / / | __/\ V / ___) | (_| | __/\ V / \___| \_/ |____/ \__,_|\___| \_/ Debian jessie on LEGO MINDSTORMS EV3! The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Mon Dec 26 10:13:57 2016 from 192.168.2.21 robot@ev3dev:~$ * Python でインタラクティブに動かす [#s538f8e8] ** python-ev3devのインストール [#i9d40f09] (ev3dev-jessie-2017-06-09版ではイメージに含まれているのでインストール不要) python-ev3devをインストールする。(以前はOSイメージに入っていたはずだが、ev3dev-jessie-2017-02-11版には含まれていない。2017-04-24追記) robot@ev3dev:~$ sudo apt-get install python-ev3dev ** pythonの起動 [#id4e94b7] python3 というコマンドでpython 3.4を起動できる。 robot@ev3dev:~$ python3 Python 3.4.2 (default, Oct 8 2014, 14:47:30) [GCC 4.9.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> pythonコマンドでは、最近のev3devがサポートしていない python 2.7 が起動してしまうので、特に理由がない限り python3 を使う。 // robot@ev3dev:~$ python // Python 2.7.9 (default, Aug 13 2016, 17:33:10) // [GCC 4.9.2] on linux2 // Type "help", "copyright", "credits" or "license" for more information. // >>> ** モジュールのインポート [#gb5bbf8b] >>> import ev3dev.ev3 as ev3 ** モータのインスタンスを生成 [#u9916a64] >>> m = ev3.LargeMotor('outA') モータの各ポート名は、'outA' 'outB' 'outC' 'outD'。 小さい方のモータは、MediumMotor。 モータ・クラスについては http://www.ev3dev.org/docs/drivers/tacho-motor-class/ を参考に。 ** モータのリセット [#g87607de] >>> m.reset() ** モータを回転させる [#s3b12bed] モータのリセット後は、duty_cycle_sp(デューティ・サイクルのセットポイント)とspeed_spが0になっている。 %%回転させるためには、duty_cycle_spに0以外の-100から100までの値を指定し、%% speed_spに %%0から1050%% -1000から+1000までの値を指定する。 最新のev3devでは、run-direct以外では常にレギュレーションがONになっているので、 duty_cycle_spを指定せずに、speed_spだけを指定する。 参考URL: https://sites.google.com/site/ev3python/learn_ev3_python/using-motors >>> m.run_forever(speed_sp=500) あるいは、以下でも同じ動作。 >>> m.speed_sp=500 >>> m.run_forever() ** モータを止める [#p1e18470] >>> m.stop() モータの止め方は'coast' 'brake' 'hold'の3種類。デフォルトは'coast'。指定の方法は、 >>> m.stop(stop_action='brake') のように値を渡すか、 >>> m.stop_action='brake' >>> m.stop() のようにする。 %% 新しいカーネル(Linux ev3dev 4.4.9-11-ev3dev-ev3)では、stop_commandがstop_actionに、 stop_commandsがstop_actionsに変更になっている。また、speed_spの値を指定しておかないとモータは回らない(-1000〜1000)。%% ** モータを一定時間回す [#vc2bab9e] >>> m.run_timed(time_sp=3000, speed_sp=500, stop_action='brake') timeで指定する時間の単位は1/1000秒。 ** モータを一定時間回す(sleep関数を使う方法) [#h602c8c4] >>> import time >>> m.run_forever(speed_sp=500) >>> time.sleep(3) >>> m.stop() sleep関数を使うためにtimeモジュールをインポート。sleepで指定する時間の単位は1秒。 ** モータを一定時間回す(タイマ関を使う方法) [#q4697311] 上記のsleepを使った方法だと、sleepしている間は他の命令は実行できません。 他の命令を実行したい場合には次のようにタイマを使えば簡単です。 >>> import time >>> ts = ev3.TouchSensor('in1') >>> t0 = time.time() >>> m.run_forever(speed_sp=500) >>> while time.time()-t0 < 3: >>> if ts.value() == 1: >>> m.stop() >>> m.stop() ** モータを特定の角度だけ回す [#mfa5974d] >>> m.run_to_rel_pos(position_sp=360, speed_sp=500, stop_action='hold') これは >>> m.reset() >>> m.run_to_abs_pos(position_sp=360, speed_sp=500, stop_action='hold') と同じ。 ** センサーの種類 [#i38f24e1] -TouchSensor タッチセンサ -ColorSensor カラーセンサ -UltrasonicSensor 超音波センサ -GyroSensor ジャイロセンサ -SoundSensor NXTのサウンドセンサ -LightSensor NXTのライトセンサ -InfraredSensor EV3の赤外線センサ(距離測定用) ** 超音波センサを使う [#n9745bd7] >>> us = ev3.UltrasonicSensor() >>> us.value() 112 デフォルトの単位はcm(US-DIST-CM)のはずだが、なぜかmmで値が表示されている。 ** 光センサを使う [#e95a60a1] モード一覧 >>> cs=ev3.ColorSensor() >>> cs.modes ['COL-REFLECT', 'COL-AMBIENT', 'COL-COLOR', 'REF-RAW', 'RGB-RAW', 'COL-CAL'] デフォルトのモードはCOL-REFLECT。 白い紙の1cmほど上で測ってみると >>> cs.value() 58 黒い紙だと大抵ひと桁の値になる。 ** タッチセンサを使う [#f3986658] >>> ts = ev3.TouchSensor('in3') >>> ts.value() 0 >>> ts.value() 1 タッチセンサが押されていない状態で0、押された状態で1。 ** ジャイロセンサを使う [#d647d973] >>> gs = ev3.GyroSensor() >>> gs.modes ['GYRO-ANG', 'GYRO-RATE', 'GYRO-FAS', 'GYRO-G&A', 'GYRO-CAL'] >>> gs.mode u'GYRO-ANG' >>> gs.value() -135 >>> gs.mode = 'GYRO-RATE' # モードの変更 >>> gs.value() 0 ** 応用 [#v7ce3ef9] >>> import ev3dev.ev3 as ev3 >>> import time >>> ts = ev3.TouchSensor('in1') >>> cs = ev3.ColorSensor('in2') >>> while ts.value() == 0: ... if cs.value() > 30: ... m.run_forever(speed_sp=500) ... else: ... m.stop(stop_action='brake') ... time.sleep(0.1) ... ** pythonの終了 [#s5162f6e] control-D * スクリプトの作成と実行 [#hbba8002] ** スクリプトの編集 [#a0a3146c] エディタ(nanoまたはvi)で次のようなスクリプトを作る。ファイル名は例えばtest.pyのようにpyという拡張子を付けておくと便利。 robot@ev3dev:~$ nano test.py #!/usr/bin/python3 # -*- coding: utf-8 -*- import ev3dev.ev3 as ev3 import time motor_left = ev3.LargeMotor('outA') motor_left.run_forever(speed_sp=500) time.sleep(3) motor_left.stop(stop_action='brake') ** スクリプトを実行可能に [#ze46f97b] robot@ev3dev:~$ chmod +x test.py ** スクリプトの実行 [#f870f300] robot@ev3dev:~$ ./test.py ここで./は現在のフォルダ(ディレクトリ)を表す(ファイル名だけだとパスがつながっていないのでエラーになる) * ipython notebookで使う (obsolete) [#k7f451a3] https://ipython.org/ipython-doc/1/interactive/public_server.html を参考に ** ipython-notebookのインストール [#a62079cd] robot@ev3dev:~$ sudo apt-get update robot@ev3dev:~$ sudo apt-get install ipython-notebook ** ipythonの設定 [#oa2c4567] nbserverという名のプロフィールを作ってみる robot@ev3dev:~$ ipython profile create nbserver この命令を実行すると ~/.ipython/profile_nbserver というディレクトリが作成される。 その中の ipython_notebook_config.py というファイルを編集して、 とりあえず以下の指定をする。 c.NotebookApp.ip = '*' c.NotebookApp.open_browser = False ** notebook serverの起動とアクセス [#zf20811a] robot@ev3dev:~$ ipython notebook --profile=nbserver でサーバを起動すると、パソコンのブラウザから http://192.168.2.30:8888/ のようなアドレスでnotebookにアクセスできる (ev3のIPアドレスが192.168.2.30の場合)。デフォルトのポートは8888。 * jupyter notebook で使う [#jf42d8d8] ** Jupyter notebook のインストール [#n970fb72] Debian jessieにはjupyterパッケージがないので jessie-backportsからインストールする。 まず、/etc/apt/sources.list.d/jessie-backports.list というファイルを新規に作成して次の一行を書いておく。 deb http://ftp.jp.debian.org/debian jessie-backports main contrib non-free updateした後、jupyter-notebookというパッケージをインストールすれば、とりあえずjupyterでpythonを使う上で必要なものも自動的にインストールしてくれる。 robot@ev3dev:~$ sudo apt-get update robot@ev3dev:~$ sudo apt-get install -t jessie-backports jupyter-notebook 次に設定ファイルを作成して編集しておく。 robot@ev3dev:~$ jupyter-notebook --generate-config とすると /home/robot/.jupyter/jupyter_notebook_config.py というファイルが生成されるのでこれを編集。 とりあえずリモートから使うために以下の項目を設定しておく(もとのファイルではコメントアウトされている)。 c.NotebookApp.ip = '*' c.NotebookApp.notebook_dir = '/home/robot/jupyter' c.NotebookApp.open_browser = False ここで指定した作業用のディレクトリを作成しておく。 robot@ev3dev:~$ mkdir ~/jupyter IPアドレスやパスワードでアクセスを制限したい場合は、 http://jupyter-notebook.readthedocs.io/en/latest/public_server.html あたりを参考に。 ** Jupyter notebookを起動 [#ze58f8a2] notebook を起動する robot@ev3dev:~$ jupyter-notebook これでパソコンのブラウザを開いて http://192.168.2.30:8888/ のようなURLでアクセスできる。 デフォルトのポートは8888番(設定ファイルで変更可能)。 * MQTTを使った通信 [#g90e4a99] MQTTという軽量プロトコルを使った通信が http://www.ev3dev.org/docs/tutorials/sending-and-receiving-messages-with-mqtt/ で紹介されている。 MQTTではpublisher(出版者)が発するメッセージをbroker(仲介者)がsubscriber(購読者)へ配信する。 MQTTは、EV3間の通信だけでなく他のデバイス間でもいろいろと使える。 ** ブローカのインストール [#gbde9fb5] サーバソフト(ブローカ)としてオープンソースのmosquittoを使う。 ネットワークに接続されている機器ならどれにインストールしてもかまわないが、 以下では、 一方のEV3を他方のEV3のリモコンとして使う簡単な例を挙げ、 EV3の一つをbrokerとしても使う方法を紹介する (他のEV3やパソコンにインストールする必要はない)。 上のev3devのサイトではpublisher側(リモコン側)にブローカをインストールしているが、 パソコンなどからでも直接コントロールできるように、リモコン側のEV3ではなく実際に動く側のEV3にブローカをインストールする(もちろんリモコン側にブローカをインストールした場合でも、そのブローカのEV3を起動しておけば、パソコンともう一方のEV3の間の通信は可能)。 robot@ev3dev:~$ sudo apt-get update robot@ev3dev:~$ sudo apt-get install mosquitto インストールが完了すればサーバが立ち上がる。チェックするには robot@ev3dev:~$ sudo service mosquitto status デフォルトのポートは1883番。 ** クライアントのインストール [#tb7a187f] ブローカにメッセージを送信したり、ブローカからメッセージを購読したりするデバイスやそのためのソフトをMQTTのクライアントと呼ぶ。ブローカ(サーバ)をインストールしたEV3を同時にクライアントとして動作させることも可能。 pythonからMQTTを使うために、各EV3(とパソコン)に[[paho:https://eclipse.org/paho/]]のpython用ライブラリをインストール。(その前にpythonパッケージをインストールするためのツールとしてpipをインストールしておく) robot@ev3dev:~$ sudo apt-get install python3-pip robot@ev3dev:~$ sudo pip3 install paho-mqtt // robot@ev3dev:~$ sudo easy_install paho-mqtt パソコン上にもpaho-mqttをインストールしておくと便利。 paho-mqtt詳細については、 https://pypi.python.org/pypi/paho-mqtt を参照のこと。 ** サンプルプログラム [#oe24c9cc] 一方のEV3に接続したモータをアクセルのように使って他方のEV3のモータのスピードをコントロールするプログラムを作ってみる。ただしブローカは%%コントローラ側(パブリッシャー側)%%受信側のEV3で動作させている。 パブリッシャー(送信側)のプログラム #!/usr/bin/python3 import paho.mqtt.client as mqtt # pahoのライブラリをインポート import ev3dev.ev3 as ev3 import time ts = ev3.TouchSensor('in1') # プログラム停止用のタッチセンサ m = ev3.LargeMotor('outA') # コントローラとして使うモータ m.reset() speed_A = 0 # 相手側モータのspeed_spとして送信する値を格納するための変数 client = mqtt.Client() # MQTTのクライアントを生成 client.connect("192.168.2.30",1883, 60) # ブローカ(192.168.2.30)の1883番portに接続 # (60秒以上接続がないと切断) while (ts.value() == 0): # タッチセンサが押されていない間だけ繰り返し pos = m.position # 現在のモータのポジションを取得 if (pos > 90): speed_A = 900 elif (pos < -90): speed_A = -900 else: speed_A = pos*10 # ポジションからspeed_spの値を計算(90度で最大900になるようにした) client.publish("ev3/outA", speed_A) # "ev3/outA"というトピックスでspeed_Aの値をブローカに送る time.sleep(0.01) client.disconnect() # 切断 サブスクライバ(受信側)のプログラム #!/usr/bin/python3 import paho.mqtt.client as mqtt import ev3dev.ev3 as ev3 import time ts = ev3.TouchSensor('in1') # プログラム停止用のタッチセンサ m = ev3.LargeMotor('outA') # 動作確認用のモータ m.reset() def on_connect(client, userdata, flags, rc): # ブローカに接続した時に実行される関数(コールバック関数)を定義しておく print("Connected with result code "+str(rc)) client.subscribe("ev3/outA") # "ev3/outA"というトピックスを購読 m.run_direct() # モータの属性変更が即時に反映されるモード def on_message(client, userdata, msg): # メッセージを受け取った時に実行される関数(コールバック関数)を定義しておく m.speed_sp = int(msg.payload) # payloadという変数にメッセージが入る # メッセージ自体はutf-8の文字列なので int に変換しておく client = mqtt.Client() # MQTTのクライアントを生成 client.on_connect = on_connect # 上で定義したコールバック関数を渡す client.on_message = on_message # 上で定義したコールバック関数を渡す client.connect("localhost",1883, 60) # ブローカ(自分自身なのでlocalhost)の1883番ポートに接続 (Keep Alive は60秒) client.loop_start() # メッセージ受信ループの開始 while(ts.value() == 0): # タッチセンサが押されていない間、繰り返し time.sleep(0.01) client.loop_stop() # 受信ループを停止 client.disconnect() # 接続を切断 m.stop() # モータ停止 **MQTTでパソコンからEV3を操作する [#m41a65ec] 上のsubscriber側のプログラムはそのまま使える。 publisher側のプログラムをパソコンで作成してもよいが、mosquitto-clients というツールを使えばシェルから(コマンドラインで)直接メッセージをパブリッシュできる。 まずはパソコンに mosquitto-clients をインストール $ sudo apt-get install mosquitto-clients メッセージを送ってみる $ mosquitto_pub -h 192.168.2.30 -t 'ev3/outA' -m "30" 別のターミナルを開いて自分自身でトピックをsubscribeすることもできる $ mosquitto_sub -h 192.168.2.30 -t 'ev3/outA' 上の mosquitto_pub で値をいろいろ送信してみると、その都度その値がターミナルに表示される。 Control + C で終了。 2016年5月31からのこのページのだいたいの訪問者数: 本日&counter(today); 昨日&counter(yesterday); 合計&counter(all);