ROS 2がインストールできないSBC（Single board computer）で素のFast DDSを使ってROS 2と通信を行う

## 軽量なコンピュータでROS 2を使用したい

ROSを活用したロボットの制作などを進めていくと、そのロボットに搭載するコンピュータをどうするかが常に課題として付き纏います。マイコンであればmicroROSやｍROSを用いることで、より簡単に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のライブラリは以下の３種類がよくで使われており、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) の設計がどうなっているのかドキュメントをみてみましょう。

https://design.ros2.org/articles/topic_and_service_names.html

注目すべきは"ROS Specific Namespace Prefix"という箇所です。以下の表が掲載されており、つまりはROS 2の通信は、DDS通信のTopic名に対して、この表に書かれているPrefixを付与しているということです。

![スクリーンショット 2024-01-02 14.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179542/d07e14b6-6afc-f7b7-90f5-db4cc07a100f.png)

逆の考え方をしてみると、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のリポジトリです。

https://github.com/ros2/rosidl

では、DDSの通信ライブラリだけでで、ROS 2のstd_msgsやgeometry_msgsで通信するためには、ROS 2で定義されているものと同じ定義のIDLファイルを用意する必要があります。しかし、当然ながらそんなことをしていては、日が暮れてしまいますので、GitHubを泳いでいると、先ほどのRTI Connext DDSを開発しているRTIがなんと自社のRTI Connext DDS用にIDLの定義ファイルを公開してくれています。

https://github.com/rticommunity/ros-data-types

ここにあるIDLファイルを使用すれば良いわけですが、IDLはそのままでは当然コンパイルできるわけではないので、IDLファイルをCなどのソースコードに変換するツールを各社用意しており、今回Fast DDSとFast DDSを開発しているeProsimaが公開しているFast DDS Genを用いてIDLを変換し、使用していきたいと思います。

IDLファイルをCに変換すると言っても、ご存知の通り、geometry_msgsであれば、ほとんどのメッセージの型にstd_msgsのHeaderが含まれていたり、依存関係があります。ですので、この依存関係を解きながらFast DDS Genで変換可能としたのが以下となります。

https://github.com/tatsuyai713/ros-data-types-for-fastdds

材料としてはこれだけ揃っていれば、とりあえずまずは通信できるところまでは行けそうです。

## Fast DDSとROS Data Typeなどのライブラリ類のインストール

先ほど書いた通り、Fast DDSなどのROS 2のバックエンドのライブラリは比較的軽量で、コンパイルに対する依存関係も少なくてすみます。基本的には、Fast DDSであれば以下のライブラリがあればOKだと思います。

- foonathan_memory
- asio
- boost
- fastcdr
- tinyxml2

そして、こちらの私が用意したリポジトリにインストールスクリプトを入れています。ここには、Ubuntu用とArchlinux用が今のところ入っています。

https://github.com/tatsuyai713/FastDDS-ROS2-Compatible-Workspace/tree/master

このスクリプトで、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には用意されていません。そこで、今回以下の３つのサンプルを用意しました。

- 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と通信させることをしている人もいて、この方法はなかなか便利ですので、ぜひご活用ください。

https://github.com/eyr1n/ROSImageViewer