軽量なコンピュータでROS 2を使用したい
ROSを活用したロボットの制作などを進めていくと、そのロボットに搭載するコンピュータをどうするかが常に課題として付き纏います。マイコンであればmicroROSやmROSを用いることで、より簡単にROS 2の世界とつながるものの、結局無線で操作するとかになると、WiFiを使うことが難しく、なかなか良い解決策はなく最後はUbuntuを使えるSBCを搭載してROS 2を使うという場合が多いと思います。
ROS 2を使うためには?
基本的にSBCなどでROS 2を使用するためにはUbuntuが必須と言われています。一部ちょっと変な人の間で、Mac+Homebrewを使用してビルドしてしまっている人がいたり、DebianでもROS 2を自前でビルドする人もいますが、OSの更新などで問題が出てしまっても、自分で対応できる人に限られてきます。ですので、基本的にはUbuntuが入ることが前提になってきます。
そもそもROS 2の通信って?
少しROS 2を勉強したり、近藤さんの本で勉強した人であれば、ROS 2通信のバックエンドはDDSなるものが使われていると知っているかと思います。だいたいDDSのライブラリは以下の3種類がよくで使われており、ROS 2 HumbleのデフォルトはFast DDSが使用されています。
- Fast DDS
- Cyclone DDS
- RTI Connext DDS
ちなみにRTI Connext DDSは商用のDDSのライブラリで、各種の規格に適合しており、商用の通信ライブラリとしてはそれなりに実績があるようです。
ROS 2におけるDDS通信
ROS 2はバックエンドの通信ライブラリにDDSを使用していると書きましたが、ということは通常のDDSの通信としてROS 2の通信が見えるはずです。そこで、RMW (ROS Middleware Interface) の設計がどうなっているのかドキュメントをみてみましょう。
注目すべきは"ROS Specific Namespace Prefix"という箇所です。以下の表が掲載されており、つまりはROS 2の通信は、DDS通信のTopic名に対して、この表に書かれているPrefixを付与しているということです。
逆の考え方をしてみると、DDSの通信Topicで、上記のPrefixを付与して送信したDDS TopicはROS 2の各ノードで見ることができるということを意味しています。
Fast DDSのライブラリのみを使用してROS 2と通信するための準備
先ほど書いた通り、ROS 2のTopic名はPrefixをつけているだけで、DDSでもPrefixをつけたTopicであればROS 2で読むことができると書きました。ただここには問題があります。それは、ROS 2で扱える標準的なTopicの型をDDSでどのように用意するかという点です。つまり、ROS 2をこれまで使ってきた人は気軽にstd_mdgsやgeometry_msgsを使用してTopic通信していると思いますが、素のDDSの場合は、そのような定義はありません。では、このようなTopicの型の定義は一体DDSではどうなっているかというと、IDLというファイルで通信の型を定義して、そのデータをシリアライズして通信しています。ROS 2も先ほど書いたように、バックエンドはDDSを使用しているので、いわゆる皆さんが使い慣れた.msgファイルといったROS 2の独自のメッセージ定義についても、実は裏ではIDLファイルに変換され、DDSの通信で使用できるように変換されています。それがこのrosidlのリポジトリです。
では、DDSの通信ライブラリだけでで、ROS 2のstd_msgsやgeometry_msgsで通信するためには、ROS 2で定義されているものと同じ定義のIDLファイルを用意する必要があります。しかし、当然ながらそんなことをしていては、日が暮れてしまいますので、GitHubを泳いでいると、先ほどのRTI Connext DDSを開発しているRTIがなんと自社のRTI Connext DDS用にIDLの定義ファイルを公開してくれています。
ここにあるIDLファイルを使用すれば良いわけですが、IDLはそのままでは当然コンパイルできるわけではないので、IDLファイルをCなどのソースコードに変換するツールを各社用意しており、今回Fast DDSとFast DDSを開発しているeProsimaが公開しているFast DDS Genを用いてIDLを変換し、使用していきたいと思います。
IDLファイルをCに変換すると言っても、ご存知の通り、geometry_msgsであれば、ほとんどのメッセージの型にstd_msgsのHeaderが含まれていたり、依存関係があります。ですので、この依存関係を解きながらFast DDS Genで変換可能としたのが以下となります。
材料としてはこれだけ揃っていれば、とりあえずまずは通信できるところまでは行けそうです。
Fast DDSとROS Data Typeなどのライブラリ類のインストール
先ほど書いた通り、Fast DDSなどのROS 2のバックエンドのライブラリは比較的軽量で、コンパイルに対する依存関係も少なくてすみます。基本的には、Fast DDSであれば以下のライブラリがあればOKだと思います。
- foonathan_memory
- asio
- boost
- fastcdr
- tinyxml2
そして、こちらの私が用意したリポジトリにインストールスクリプトを入れています。ここには、Ubuntu用とArchlinux用が今のところ入っています。
このスクリプトで、Fast DDSをインストールすると、必要なライブラリ類は/opt/fast-dds以下に保存され、他の/usr/local/lib以下に入るようなライブラリと競合しないようにしています。
続いて、Fast DDSでROS Data Typeを扱うことができるよにうに、各種ライブラリをビルドしていきます。fastdds_ws内にある、build_libraries.shを実行すると、ビルドすることができ、build_libraries.sh installとすることで、/opt/fast-dds-libs/に各種のROS Data Typeのライブラリやtf2といったライブラリをインストールすることができます。
ROS 2っぽくFast DDSを使用する
Fast DDSでROS Data Typeのデータを扱うことはできるようになりましたが、ROS 2だと周期実行や独自のメッセージの定義など、いろいろと便利な機能がありますが、当然素のFast DDSには用意されていません。そこで、今回以下の3つのサンプルを用意しました。
- CustomROSTypeDataPublisher : 独自のメッセージ形式をIDLで定義し、それを使用してメッセージをPublishする
- CustomROSTypeData Subscriber : 独自のメッセージ形式をIDLで定義し、それを使用してメッセージをSubscribeする
- CyclicROSDataPublisher : Timerを使用して周期的にROSのTopicを出力する。Sleepを用いないので、プログラムの処理時間を考慮した周期実行を実現できる
これらは、先ほどのリポジトリのfastdds_wsの中にeProsimaが用意しているサンプルとともに入っています。
これらのビルドには、build_app.shを実行することでビルドすることができ、これらのサンプルはyamlーcppを用いた、設定ファイルを読み込む例も書かれているので、ぜひ活用してください。
まとめ
今回、ROS 2をUbuntuをインストールできないような軽量なSBCでFast DDSだけでROS 2の世界と通信する方法を書きました。この方法を用いれば、Archlinuxなどの軽量なLinux DistributionでもROS 2と通信することができるようになります。またFast DDS自体があまり他のライブラリとの依存関係が少ないこともあり、トラブルも少なくDebianなど様々な環境に入れることができます。Fast DDSがAndroidにも入れられることを利用して、AndroidタブレットをROS 2と通信させることをしている人もいて、この方法はなかなか便利ですので、ぜひご活用ください。