前回の投稿で、python3-ev3devというPythonドライバでLEGO Mindstorms EV3が動作することを確認しました。

http://ros.youtalk.jp/2017/08/21/python3-ev3dev.html

今回はpython3-ev3devで動作するEV3とROSエコシステムを動かすホストPCの間を繋ぐ通信について見ていきます。

通信方法としては、MQTTを採用しようと考えています。

MQ Telemetry Transport(Message Queue Telemetry Transport、略称 MQTT)は、メッセージ指向ミドルウェアのアプリケーション層で使用される、TCP/IPによるPub/Sub型データ配信モデルの軽量なメッセージキュープロトコルである。 非力なデバイスやネットワークが不安定な場所でも動作しやすい様にメッセージ通信電文が軽量に設計されている事が特徴。 Pub/Sub型メッセージング·パターンには、メッセージブローカーが必要である。 ブローカーは、メッセージのTopicに基づいて、それを必要としているクライアントにメッセージ配信をしている。

  • ROS同様にPub/Sub型
  • QoS (Quality of Service) あり
  • 軽量プロトコル

という3点から非力なEV3にはピッタリでしょう。 すでにev3dev OSで使われている実績もあり、安心して使えます。 以降、下記記事を参考にして、

http://www.ev3dev.org/docs/tutorials/sending-and-receiving-messages-with-mqtt/

mosuitto

まずは、ブローカーをセットアップします。

$ sudo apt-get install mosquitto

これだけでMQTTのブローカーがデーモンとして起動するようになります。 これをホストPC側で動かすか、EV3で動かすかは悩ましいところですが、とりあえずEV3で動かしておきます。

paho-mqtt

MQTTのPublisherやSubscriberには、paho-mqttというパッケージを用います。

$ sudo pip3 install paho-mqtt

Publisherテスト

試しにPub/Subの動作テストを行ってみます。 テストコードは下記記事を参考にしています。

https://librabuch.jp/blog/2015/09/mosquiito_paho_python_mqtt/

PublisherはEV3で動かします。 0.1秒ごとにtest/alphabetというトピック名でabcという文字列をPublishしています。

from time import sleep
import paho.mqtt.client as mqtt

if __name__ == '__main__':
    client = mqtt.Client(protocol=mqtt.MQTTv311)
    client.connect('127.0.0.1', port=1883, keepalive=60)

    for i in range(5):
        client.publish('test/alphabet', 'abc')
        sleep(0.1)

    client.disconnect()

MQTTは軽量プロトコルとあるように、トピックの中身を定義するIDLのようなものはないようで、自分で文字列をパースする何かを作らないといけないようです。 データフォーマットも考えないといけませんね。

Subscriberテスト

SubscriberはホストPCで動かします。 on_message関数がコールバック関数になっており、Publisherからデータを受け取ったら、これが呼ばれます。 EV3_HOST_ADRESSは自分のEV3のホスト名に置き換えてください。

import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, respons_code):
    print('status {0}'.format(respons_code))
    client.subscribe(topic)

def on_message(client, userdata, msg):
    print(msg.topic + ' ' + str(msg.payload))

if __name__ == '__main__':
    client = mqtt.Client(protocol=mqtt.MQTTv311)
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect('EV3_HOST_ADRESS', port=1883, keepalive=60)
    client.loop_forever()

ROSと同様にPub/Sub型の通信ができるので、IDLがない以外はスクリプトもROSプログラムっぽく書けるので、MQTTは良さそうですね。

次回からは実際にpython3-ev3devとこのpaho-mqttを使って、EV3のROS対応を進めていきます。 まずはpython-ev3からpython3-ev3devに置き換えて、paho-mqttは使わず以前のプログラムを復活させるところから始めたいと思います。