ROS2(Robot Operating System 2)はRobot OS となっていますがフツーの意味のOSではなく、ミドルウェアです。
ROS2で採用されたDDS(Data Distribution Service)を使ってノード間通信をやってみます。
注:ここでは未だ学習済みモデルは使いません。
ROSチュートリアル(ROS1ですが概観を把握)
コンピュータ間通信はsocketを使えばシンプルに実現できますが、ここではより高信頼性とリアルタイム性、汎用性を持つROS2のDDSを使ってみます。
こんな感じのネットワークを作っていろいろ試してみます。
まずは、Jetson Nano で同じコンピューター内の異なるノードと、違うJetsonのノードとのTOPIC通信です。
環境はJetson Nano + コンテナ
環境構築
OSイメージはともにJetpack 4.5.1
まずここにROS2(Foxy)のドッカーイメージを作成します(4GBで1時間ちょい、2GBで2時間ちょいかかります)。
1 2 3 4 5 |
git clone https://github.com/dusty-nv/jetson-containers cd jetson-containers ./scripts/docker_build_ros.sh foxy |
作成されたイメージ
これを使ってコンテナを作ります(USBカメラを接続しておいてください、今回は使いませんが)
作業用ディレクトリを作っておきます(今回は使いませんが)。
1 |
mkdir /home/jetson/work-ros2 |
コンテナ作成
シンプルなコンテナ
sudo docker create -it --name my_ros2 --gpus all --network host ros:foxy-ros-base-l4t-r32.4.4
カメラやWindowを使う場合
sudo docker create -it --name my_ros2 --gpus all --network host -e DISPLAY=$DISPLAY --device /dev/video0:/dev/video0 -v /tmp/.X11-unix/:/tmp/.X11-unix -v /home/jetson/work-ros2:/work ros:foxy-ros-base-l4t-r32.4.4
コンテナ起動
1 |
sudo docker start -i my_ros2 |
アップデート&アップグレード、エディタもインストールしておきます。
1 2 3 4 |
apt update apt upgrade -y apt install nano |
~/.bashrcに追記しておきます。
1 2 3 4 5 |
nano ~/.bashrc //ROS2環境をアンダーレイに指定 source /opt/ros/foxy/install/setup.bash |
コンテナを一旦終了
Ctrl + D
demo_nodes_cpp(demo_nodes_py)というパッケージを使って通信テスト
Nano(4GB)とNano(2GB)でコンテナ起動
1 |
sudo docker start -i my_ros2 |
4GBでターミナルをもう一つ開いておきます。
1 |
sudo docker exec -it my_ros2 bash |
各ターミナルで共通のDOMAIN_IDを設定(0~65532、例えば10)
1 |
export ROS_DOMAIN_ID=10 |
どれかのターミナルから”Hello World”というメッセージをキャストします。
1 2 3 4 5 |
#C++版 ros2 run demo_nodes_cpp talker #Python版 ros2 run demo_nodes_py talker |
他のターミナルでメッセージを待ち受けます。
1 2 3 4 5 |
#C++版 ros2 run demo_nodes_cpp listener #Python版 ros2 run demo_nodes_py listener |
同じDOMAIN_IDを持っているターミナルが受信します。
Jetson(4GB)のコンテナ同志のノード間通信
違うJetson(2GB)ですが、同じDOMAIN_IDでlistenしています。
違うDOMAIN_IDでターミナルを立ち上げれば、逆方向のノード間通信を同時に行うこともできます。
また、同一コンピュータ内で異なるコンテナ間で通信する場合は、どちらか一方のnetworkオプションは不要です。明示的に指定する場合はhostの代わりにbridge を使います。
ネットワーク越しにコンテナ間で通信する場合、networkオプションはhostです。
では、request & responce (reply) はどうなっているのか?->調査中
同じDOMAIN_IDで送受信を混在させることも出来るようなので、自分のユニークIDを送受信すれば1対1でなくてもいいのかもしれないけど….。
ちなみに、Python版のros2 run demo_nodes_py talkerでメッセージを変更したい場合は
/opt/ros/foxy/src/demo_nodes_py/demo_nodes_py/topics/talker.py
を編集したりします(日本語もいけます)。
メッセージを受けて何かしたい….というような場合もPython版の/opt/ros/foxy/src/demo_nodes_py/demo_nodes_py/topics/listener.py
を編集すれば簡単です。
上記talker.pyのサンプルソースではタイマで断続してメッセージが出されます。
1回だけでいんですけど….という場合は、こちらのページをご参照ください。
Jetsonからラズパイにメッセージを届けてみる(ROS2/DDS)
topicを使って、”Hello World” 以外のメッセージを送ってみる
data: の後ろにメッセージをセットします。
1 |
ros2 topic pub /chatter std_msgs/String "data: Are You Happy ?" |
受ける側はこういう感じ。
1 |
ros2 topic echo /chatter |
日本語も送れるようです。
demo_nodes_cppパッケージのlistner でも受信できます。
1 2 3 4 5 |
ros2 run demo_nodes_cpp listener OR ros2 run demo_nodes_py listener |
また、talkerの送信をtopicのchatterで受けることも出来てしまいます。
topic名はchatter とかgreeting とかありますが、自分で名前をつけることもできるようです。
例えばtopic名をABCとします。
publishします。
1 |
ros2 topic pub /ABC std_msgs/String "data: Are You Happy ?" |
listで確認
1 |
ros2 topic list |
/ABCが確認できると思います。
echoでtopicのメッセージを出力します。
1 |
ros2 topic echo /ABC |
通信メッセージを独自定義して使ってみる
工事中
ROSグラフが大きく複雑で大規模なシステムの場合
ROS 2は互いのノードを分散処理で探します。 しかし、大規模なシステムの場合、ROSグラフに参加する全てのノードを発見するには時間がかかります。そこで、ノード名のリストを取得するなどのROSグラフ関連のクエリにより早く応答するために、専用のデーモンをバックグラウンドで起動しておきます。
開始
1 |
ros2 daemon start |
状態確認
1 |
ros2 daemon status |
停止
1 |
ros2 daemon stop |
ROSグラフが大きく複雑になる大規模なシステムでは有用になります。
Appendix
ROS2 は大規模システムから、マイコンレベルのデバイスにも対応するなど多才です。
コマンドラインでどんなことができるか、チートシートが用意されています。
参照
NVIDIA Jetson プラットフォームでの ROS2 と AI を使用したロボットアプリケーションの実装
Appendix2
いろいろ使いまわせるようにコンテナをイメージにしてDocker Hub にpush しておきます。
pushする場合はHubのあなたのリポジトリ名をつけてイメージを作成しておきます。
コンテナ名がAAAでリポジトリ名がBBB、イメージ名をCCCにするとしたらこんな感じ。
1 |
sudo docker commit AAA BBB/CCC:latest |
で、pushします。
1 2 3 |
sudo docker login sudo docker push BBB/CCC:latest |
イメージをダウンロード
1 |
sudo docker pull BBB/CCC:latest |
Leave a Reply