ROS 2とMQTT間の通信を試す
海洋ロボコンをやってた人です。
IoT関連の通信プロトコルとして使用されるMQTTについて、あるキッカケでROS/ROS 2 Bridge用のパッケージもあるぞ!ということを知りました。
せっかくの機会なので、"物は試し"で使ってみたので、その備忘録をまとめます。
DDSを使用せず、軽量かつ低帯域でデータを飛ばしたいとか、ユースケースに応じて技術の引き出しを広げておくことを目的です。
この記事のゴールは、今回使用するmqtt_clinet
(下記)のサンプルが動くこととしますので、よろしくお願いします。
mqtt_clientは、接続されたROS ベースのデバイスまたはロボットがMQTTプロトコルを使用してMQTTブローカー経由でROSメッセージを交換できるようにするROSノードレットまたはROS 2コンポーネントノードを提供するパッケージ
また、誤記等あればご指摘ください。
1. MQTTとは
MQTT (Message Queuing Telemetry Transport) は、TCP/IP上で動く軽量かつシンプルな通信プロトコルの一つで特に、低帯域や低消費電力が求められる IoT(Internet of Things: モノのインターネット)デバイス間での通信に利用されます。
以下、調べた内容で自身のインプット整理としてアウトプットします。
1.1 通信モデル
MQTTは直接デバイス同士が通信するP2P(Peer-to-Peer)とは異なり、Brokerが各メッセージの送受信を仲介することで一対一、一対多の通信を行うブローカード通信モデルを採用。
ROSとは異なり、「Broker」という仲介がいることでデバイス同士が疎結合になり、それぞれが独立性を保ちながらメッセージのやり取りが可能という点が利点。
またBrokerがグローバルIP上にあれば、さまざまな場所にいるデバイスからメッセージを送受信できる点でIoTとの相性が非常に高い。
1.2 Quality of Service
MQTTは、メッセージ配信の信頼性を3つのQuality of Service (QoS) レベルで設定できる。
この詳細については「USAGE OF MQTT, ROS, AND AWS IN THE MANUFACTURING PROCESS OF AIRCRAFTS」で丁寧に解説されているので、日訳+説明補足して記載します。
QoS 0
- クライアントがメッセージをブローカーにパブリッシュするが、確認応答はない(最大一回の配信)。
- メッセージの損失がある可能性がある。
QoS 1
- クライアントがメッセージをパブリッシュし、ブローカーからのPUBACKを待つ(少なくとも一回の配信)。
- PUBACKを受け取らない場合、クライアントはメッセージを再送信(DUPフラグ付き)。
QoS 2
- クライアントがメッセージをパブリッシュし、ブローカーからPUBRECを受け取る(正確に一回の配信)。
- PUBRECを受け取らない場合、クライアントはメッセージを再送信し(DUPフラグ付き)。
- クライアントはPUBRELを送信し、ブローカーからPUBCOMPを受け取ることで処理が完了。
シーケンス図は以下
1.3 通信性能の比較
MQTTの通信性能としては以下2点。
-
小さなメッセージサイズ
メッセージヘッダーは固定長ヘッダの場合2Byteと、データのオーバーヘッドが少なくなる。これにより、低帯域幅のネットワークでも効率的に通信できる。 -
シンプルな制御:コマンドが少なく、デバイスの計算資源やメモリ消費が少ないため、リソースの限られたデバイスに適している。
IoTデバイスの通信モデルとしては、MQTT以外にもKafka, Zenoh, DDSを用いた通信があり、これらの性能比較は以下で日訳としてもまとめられていますね。スループット比較という観点で見るとZenohに軍配が上がっています。
また、ROS 2の通信プロトコルの代替手段として「ROS 2 Alternative middleware report」も公開されており、こちらは下記で私もまとめています。
以上の特徴から
”スマートホーム、産業用IoT、リアルタイムデータ収集”
など、デバイス間の低遅延で高効率な通信が求められる場面で広く利用されているようです。
一方、QoSの設定や、様々なクラウドサービス(AWS IoT, Azure, IBM)などとの統合には以前MQTTのノウハウが多く、標準化が進んでいるようなのでここで差別化されているのだと思います。
2. mqtt_client demo
2.1 mqtt_clientのインストール
下記、package managerでインストールするか、ソースコードから入手します。 今回はソースコードの中身も見たかったので後者のソースコードからで試しました。
sudo apt update
sudo apt install ros-$ROS_DISTRO-mqtt-client
または
mkdir -p mqtt_ws/src && cd ~/mqtt_ws/src
git clone https://github.com/ika-rwth-aachen/mqtt_client.git
cd ~/mqtt_ws
colcon build --packages-up-to mqtt_client --cmake-args -DCMAKE_BUILD_TYPE=Release
2.2 MQTT Brokerの準備
ブローカード通信モデルにあたるBrokerの準備をします。
ここでは軽量なmosquitto
を使いますが、他のBrokerとしてEMQXを使用するのも良さそうです。
- EMQX vs Mosquitto|2023年MQTTブローカーの比較
- EMQX Brokerを用いたROS 2 -MQTT 通信
脱線しましたが、インストールと利用準備は以下で終わります。
sudo apt update
sudo apt install -y mosquitto mosquitto-clients
MQTT Brokerの利用は下記のstartコマンドで起動できます。
sudo systemctl start mosquitto # 開始
sudo systemctl stop mosquitto # 停止
sudo systemctl enable mosquitto # 自動起動有効
sudo systemctl disable mosquitto # 自動起動無効
Brokerの確認は以下で行います。
sudo systemctl status mosquitto
2.3 MQTTとROS 2間で通信する
まずはMQTT BrokerからTopic をSubscribeするコマンドを立ち上げます。
mosquitto_sub -h localhost -p 1883 -t pingpong/ros
次にROS 2のMQTT Bridgeを起動します。
ros2 launch mqtt_client standalone.launch.ros2.xml
最後にROS 2でデータをPublishしてみましょう。
ros2 topic pub /ping/ros std_msgs/msg/String "{data: 'Hello MQTT'}"
下記のようにROS 2でPublishしたStringがMQTT Subscriberで受信できていればOKです。
2.4 シーケンス図
mqtt_clientのイメージもざっくりシーケンス図をChatGPTに書いてもらったので、記載します。
2.5 Primitive Messages
mqtt_clientにはPrimitive 機能が搭載されています。
以下Gitから引用します。
MQTT の「Primitive」は、ROS メッセージと MQTT メッセージのデータ型をシンプルに扱う仕組みで、ROS で扱うデータを、ROS ベースではない他の MQTT クライアントと交換できます。
使い方はparams.ros2.yaml
にprimitive: true
を追記するだけです。
このソースも提供されているので、実際に試してみましょう。
ROS 2 - MQTT Bridge起動。
ros2 launch mqtt_client standalone.launch.ros2.xml params_file:=$(ros2 pkg prefix mqtt_client)/share/mqtt_client/config/params.ros2.primitive.yaml
MQTT BrokerからTopic をSubscribe
mosquitto_sub -h localhost -p 1883 -t pingpong/primitive
ROS 2でデータをPublish
ros2 topic pub /ping/primitive std_msgs/msg/Int32 "{data: 42}"
下記のように通信できていれば確認終了です。
MQTT 使用して、様々なことに着手したいですね。
Reference
- ESP32によるMQTTアプリケーション開発の基礎知識
- ESP32 でtwist messages送る記事
以上です。
Likeいただけると大変励みになりますので、よろしくお願いいたします。
Discussion