micro-ROSのembeddedRTPS通信を試してみた
今年もmicro-ROS推しの記事です!
筆者は小さいロボットに組み込めるような技術に関心が強いので、ここ数年マイコンからROS 2の資源へアクセスできるmicro-ROSに興味を持っています。この記事ではイチオシ機能を紹介しようと思います。
マイコンでROS 2という方向性ではmROS 2という実装もあります。動作対象の基板をお持ちの方は是非体験してみて下さい。
micro-ROSとmROS 2、どちらも良さがあるのでどちらも関心を持ってWatch👀しています。
というわけで、この記事を要約するとこのような内容です。
micro-ROSの最新リリース(Humble)
昨年のAdventCalendarへの投稿ではmicro-ROS推しの記事を投稿しましたが、1年経つ間にmicro-ROSに様々な進化がありました。特に先日ROS 2 Humble向けにリリースされた様々な機能はより進化を感じさせる内容ばかりでした。リリース情報から注目の機能を紹介します。
- QoS設定APIが追加された
- Actionに対応した
- 死活監視/セッションタイムアウト機能が追加された
- embeddedRTPSを利用したAgentレス通信の追加(experimental)
- ターゲット環境の拡充やアップグレードが行われた
- ルネサスe2 Studio対応の追加
- CAN/FD通信経路の追加
- Microsoft Azure RTOS対応の追加
- Platform.IO対応の追加
- TI Tiva Cシリーズ対応の追加
- STMicro STM32CubeMX/IDE対応の追加
- Espressif ESP-IDFサポートの更新
- Arduino IDEサポートの更新
- ルネサスe2 Studio対応の追加
- パフォーマンスの大幅な向上やbagfix ←アピール強め
新機能を試してみよう!
ここからはリリースの中でも是非確認しておきたいAgentレス通信について動作を確認してみようと思います。
micro-ROSは標準のROS 2ノードと異なり、Agentと呼ばれるノードがマイコン上のmicro-ROSノードをROS 2の世界へつないでくれる実装になっています。
筆者は、Agentが必要でもmicro-ROSの価値は十分あると思うのですが、Agentとの通信設定などmicro-ROS特有の設定やソフトウェアが求められるので、ROS初心者へオススメするには少し難点かな?とも思います。
コミュニティでもAgentが必要なくなるとより使いやすくなると歓迎する声が多いようです。
Agentレス通信の機能追加については投稿があるので詳細はこちらを確認して下さい。
簡単な説明としては、embeddedRTPSというマイコンからROS 2のDDS通信[1]と直接通信が可能になる機能をmicro-ROSの通信レイヤーとして使用できるようになりますということです。
ESP32用のembeddedRTPS対応を体験する
embeddedRTPS対応機能はまだ実験的な機能なのでST Nucleo F746ZGとESP32で動くコードが公開されている状況です。
筆者のデスクにはESP32製品がたくさん積み上がっているのでESP32向けのembeddedRTPS対応を試してみようと思います。
M5Stackで動くPub/Subの作り方
普通のESP32ボードで確認する方が楽なのですが、せっかくなのでM5Stackの機能も使ったサンプルの作成に挑戦してみます。
サンプルのビルド手順
embeddedRTPSに対応したサンプルはESP32向けmicro-ROS開発環境の
micro_ros_espidf_componentに含まれています。こちらの利用方法を説明していきましょう。
-
ESP32マイコンを用意する
あまり新しすぎる製品には対応していない可能性があるので注意。
M5Stackでは、Basic, Gray, Fire, StickCあたりが選択可能です。 -
ROS 2 Humbleの開発環境を構築する
まずはHumble環境をインストールしましょう。 -
Docker環境を構築する
いくつか手段がありそうですが、dockerイメージをbuildして利用するのが最も動かしやすかったです。 -
適当な場所に
micro_ros_espidf_component
をcloneする
ESP32用にmicro-ROSをビルドするためのパッケージを取得しましょう。$ git clone https://github.com/micro-ROS/micro_ros_espidf_component.git $ cd micro_ros_espidf_component micro_ros_espidf_component$ ls 3rd-party-licenses.txt NOTICE extra_packages CHANGELOG.rst README.md libmicroros.mk CMakeLists.txt colcon.meta network_interfaces CONTRIBUTING.md docker package.xml Kconfig.projbuild esp32_toolchain.cmake.in LICENSE examples
-
docker buildする
適当な名前でdocker buildします。この記事ではesp-idf-microros:demo
というイメージ名にします。micro_ros_espidf_component$ cd docker micro_ros_espidf_component/docker$ docker build . -t esp-idf-microros:demo
なお、M5Stack向けの環境構築のためには次のように変更を行ってからbuildします。筆者がesp-idf向けにパッチを当てたM5Stackとarduinoのcomponentをイメージに含めるための操作を加えています。
--- a/docker/install_micro_ros_deps_script.sh +++ b/docker/install_micro_ros_deps_script.sh @@ -8,3 +8,8 @@ source $IDF_PATH/export.sh pip3 install catkin_pkg lark-parser empy colcon-common-extensions importlib-resources set +u + +cd /opt/esp/idf/components +git clone https://github.com/nomumu/arduino-esp32.git arduino && cd arduino && git checkout 299d0d7 +cd ../ +git clone https://github.com/nomumu/M5Stack.git && cd M5Stack && git checkout 9574dd9
-
通信設定を変更する
これは必須ではありませんが、この記事では作成するM5Stack向けのサンプル用に次のコマンドでPub/Subの作成可能数を増やします。最大リソースの定義などがcolcon.meta
ファイルに定義されているので、目を通しておくとエラーの理解などの役に立つと思います。micro_ros_espidf_component$ sed -i s/PUBLISHERS=2/PUBLISHERS=3/g colcon.meta micro_ros_espidf_component$ sed -i s/SUBSCRIPTIONS=2/SUBSCRIPTIONS=3/g colcon.meta
-
docker runでビルドする
5までがエラーなく進められていればビルドが可能になります。esp-idfの環境はDockerイメージの中に構築が済んでいるはずです。Dockerコンテナにmicro_ros_espidf_component
をマウントしてmicro-ROSのESP32向けファームウェアをビルドする仕組みです。
docker run
コマンドでビルドを行います。micro-ROSのライブラリなどをpre-buildするステップと、esp-idfの機能でサンプルをビルドするステップの2段構えになっています。
このdocker runコマンドは実行時のカレントパスがmicro_ros_espidf_component
である前提で動作するので注意しましょう。embeddedRTPSのサンプルは
examples/int32_publisher_embeddedrtps
にあります。これをビルドするには次のコマンドを実行します。micro_ros_espidf_component$ docker run -it --rm --user espidf --volume="/etc/timezone:/etc/timezone:ro" -v $(pwd):/micro_ros_espidf_component -v /dev:/dev --privileged --workdir /micro_ros_espidf_component esp-idf-microros:demo /bin/bash -c "cd examples/int32_publisher_embeddedrtps; idf.py menuconfig build flash monitor"
このコマンドでは
- サンプルのコンフィグ(menuconfig)
- ビルド(build)
- マイコンへの書き込み(flash)
- 実行ログのモニタ(monitor)
を順番に実行します。
コンフィグメニューが表示されたら、必要な設定を行った後にESCで抜けるとbuildへ進みます。
必要最低限の設定として、micro-ROS Settings
の中のWiFi Configuration
を手元環境に合わせましょう。[2]
ここではint32_publisher_embeddedrtps
のビルドを選択した場合にmicro-ROS over embeddedRTPS (EXPERIMENTAL)
が選択されていることも確認できます。
なお、設定を変更するとメニューを抜ける際に保存するかを聞かれますので、'Y'を選択すると次回からは同じ設定がロードされます。
もし初回の入力も省略したい場合は、サンプルのディレクトリにあるsdkconfig.defaults
へ設定を書き込んでしまうのが楽です。ところで、リポジトリのREADME.mdでは公式のDockerイメージを利用する説明になっていますが、執筆時点でこのイメージはまだ更新が追い付いていないようで目的には合致しなかったので使用しません。
-
pre-buildをcleanする方法
micro-ROSの通信設定を変更したりするとpre-buildからやり直したいことがよくあります。このような時は次のようにするとcleanを実行できます。micro_ros_espidf_component$ make -f libmicroros.mk clean
-
マイコンへの書き込み
6の手順を実行する前にESP32マイコンをUSB接続しておき、ビルドが成功すると次のように書き込みが行われ、シリアルモニタが起動します。Successfully created esp32 image. Generated /micro_ros_espidf_component/examples/int32_publisher_embeddedrtps/build/int32_publisher.bin Executing action: flash Serial port /dev/ttyUSB0 Connecting...... Detecting chip type... Unsupported detection protocol, switching and trying again... Connecting.... Detecting chip type... ESP32 Running ninja in directory /micro_ros_espidf_component/examples/int32_publisher_embeddedrtps/build Executing "ninja flash"... [0/2] Re-checking globbed directories... [1/4] Performing build step for 'bootloader' ninja: no work to do. [1/2] cd /opt/esp/idf/components/esptool_py &...f/components/esptool_py/run_serial_tool.cmak esptool.py esp32 -p /dev/ttyUSB0 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x10000 int32_publisher.bin esptool.py v3.3.2-dev Serial port /dev/ttyUSB0 Connecting..... Chip is ESP32-D0WDQ6-V3 (revision 3) Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None Crystal is 40MHz MAC: 08:3a:f2:68:74:d0 Uploading stub... Running stub... Stub running... Changing baud rate to 460800 Changed. Configuring flash size... Flash will be erased from 0x00008000 to 0x00008fff... Flash will be erased from 0x00001000 to 0x00007fff... Flash will be erased from 0x00010000 to 0x000c0fff... Compressed 3072 bytes to 103... Writing at 0x00008000... (100 %) Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.1 seconds (effective 386.5 kbit/s)... Hash of data verified. Compressed 26048 bytes to 16120... Writing at 0x00001000... (100 %) Wrote 26048 bytes (16120 compressed) at 0x00001000 in 0.8 seconds (effective 247.7 kbit/s)... Hash of data verified. Compressed 724080 bytes to 457679... Writing at 0x00010000... (3 %) Writing at 0x0001c1ad... (7 %) ~~~ Writing at 0x000b62b7... (96 %) Writing at 0x000bbabc... (100 %) Wrote 724080 bytes (457679 compressed) at 0x00010000 in 10.9 seconds (effective 530.5 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin... Executing action: monitor Serial port /dev/ttyUSB0 Connecting.... Detecting chip type... Unsupported detection protocol, switching and trying again... Connecting.... Detecting chip type... ESP32 Running idf_monitor in directory /micro_ros_espidf_component/examples/int32_publisher_embeddedrtps Executing "/opt/esp/python_env/idf4.3_py3.6_env/bin/python /opt/esp/idf/tools/idf_monitor.py -p /dev/ttyUSB0 -b 115200 --toolchain-prefix xtensa-esp32-elf- /micro_ros_espidf_component/examples/int32_publisher_embeddedrtps/build/int32_publisher.elf -m '/opt/esp/python_env/idf4.3_py3.6_env/bin/python' '/opt/esp/idf/tools/idf.py'"... --- idf_monitor on /dev/ttyUSB0 115200 --- --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- ets Jul 29 2019 12:21:46 rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:7220
動作確認
シリアルモニタへPublishing: 1 Publishing: 2...
と出力されている状態で、パソコン側から次のようにトピックを確認してみましょう。ESP32のmicro-ROSアプリとパソコンのROS 2が直接Pub/Subを行っていることが確認できるはずです!
$ ros2 topic list
/freertos_int32_publisher
/parameter_events
/rosout
$ ros2 topic echo /freertos_int32_publisher
data: 519
---
data: 520
---
data: 521
---
もしlistに出てこないなどの場合、次のようにros2 daemonを再起動してみると効果があります。
$ ros2 daemon stop
The daemon has been stopped
$ ros2 daemon start
The daemon has been started
どうやらROS 2のdaemon機能との相性がよくないらしく、再接続時などにうまくいかないことがありました。改善を期待したいですね。
M5Stackで動かしてみた
embeddedRTPSがパソコンのROS 2環境と直接通信できることはわかりました。ではマイコン同士の通信はどうでしょう??
ということで、以前作成したM5Stack向けのサンプルを改造して2つのM5Stack(Basic, Fire)とパソコンが同じトピックを見れるか確認してみました!
各ボタンを/btn/a
、/btn/b
、/btn/c
のトピックへstd_msgs/Boolで投げる簡単な通信を確認します。
このように、Agentも不要で、さらにマイコン同士も特別な処理なしにROS 2の基本的な通信でPub/Subができることが確認できました。
まとめ
今回注目したembeddedRTPS機能は、実験的な実装とはいえ基本的な通信が利用可能な状態になっていることが確認できました。マイコン同士の通信にも利用可能ということがわかったので、これまでAgentの扱いが難しくて利用できなかったシーンなどにも適用の幅が広がるのは間違いないでしょう!
不安定な部分や利用方法の難解さなどはまだあるものの、今後に十分期待してよいと思います。
Discussion