お疲れ様です。秋並です。
今回は、ROS2の基礎的な概念である
- ノード (node)
- トピック (topic)
- メッセージ (message)
- パブリッシャー (publisher)
- サブスクライバー (subscriber)
について、解説したいと思います。
動作環境
ubuntu 22.04
ROS humble
ノード
ノードとは、ロボットシステムにおける最小単位の機能モジュールを指します。
ノード間で通信することで、全体のシステムが構成されることになります。
言葉の説明だけでは分かりにくいと思うので、具体的な例を使って説明します。
例)ノード1→ノード2に情報を渡し、受け取った情報をもとにノード2が処理を行う
- ノード1:カメラから得た画像情報を他のノードに受け渡すノード
- ノード2:ノード1から取得した画像情報をもとにロボットアームを適切な位置に制御するノード
ノードのイメージとしては上記の通りですが、
ここで、「カメラから取得した情報をもとに物体認識をしたい」という別の機能を実装したい場合を考えてみましょう。
それぞれのノードは独立しているので
- ノード1はそのままで、ノード2のみを別のノードに取り換える
ことで、この機能を実装することが出来ます。
このように、ノードを上手く構成することで
他の機能を実装するときに、ノードを使いまわすことが出来る
ことがうれしいポイントです。
そのため、既存のノードと自作のノードを組み合わせることで
一からノードを作成するのと比較して、効率的に開発を進めることが可能になります。
トピック、メッセージ、パブリッシャー、サブスクライバー
ここまでで、「ノード間で情報の受け渡しを行う」ことでシステムが構成されることを説明しましたが、
次に、情報の受け渡しを行う際に必要になる
- トピック (topic)
- メッセージ (message)
について説明します。
先ほどの図でいうと、「情報の受け渡しを行うためのパイプ」がトピック、「受け渡される情報」がメッセージになります。
この際に、「メッセージを特定のトピックに配信する機能」と「特定のトピックから流れてきたメッセージを購読する機能」が必要になるのですが、この機能を持つのが
- パブリッシャー (publisher)
- サブスクライバー (subscriber)
になります。
メッセージの型
トピックで配信/購読するメッセージには変数と同様に型があります。
メッセージの型には、
- ROSで用意されているメッセージ
- 自身で型を定義するカスタムメッセージ
の2種類が存在します。
ここでは、ROSで標準で用意されているメッセージについて説明したいと思います。
std_msgs
最初に、最もシンプルなメッセージが用意されている std_msgs
について説明します(ドキュメントリンク)
例えば、 std_msgs/msg/Int16.msg
は以下のような構成になっています(ドキュメントリンク)
int16 data
メッセージの中身を確認すると、 int16
型の data
という名前の変数で構成されていることが分かります。
sensor_msgs
次に、センサー関連のメッセージが用意されている sensor_msgs
について説明します(ドキュメントリンク)
例えば、sensor_msgs/msg/Image.msg
は以下のような構成になっています(ドキュメントリンク)
std_msgs/msg/Header header
uint32 height
uint32 width
string encoding
uint8 is_bigendian
uint32 step
uint8[] data
メッセージの中身を確認すると、 画像の高さ height
、画像の幅 width
のような、画像に必要ないくつかのデータで構成されていることが分かります。
ここで、上記メッセージの std_msgs/msg/Header header
という箇所に着目してみると、型が std_msgs/msg/Header
というメッセージの型になっていることが分かります。
このように、
- メッセージの定義の中で、他のメッセージの型の変数を定義することが出来る
ということも抑えておくとよいと思います。
テストノードを動かして確認してみる
ここからは実際にROS2を動かして、流れを確認してみましょう。
ターミナルにて以下のコマンドを実行して下さい。(テストコードはここで公開されています)
source /opt/ros/humble/setup.bash
ros2 run demo_nodes_py talker
ターミナルをもう一つ開き以下コマンドを実行して下さい。(テストコードはここで公開されています)
source /opt/ros/humble/setup.bash
ros2 run demo_nodes_py listener
listenerを起動したターミナルで以下のように表示されていたらOKです。
[INFO] [1704025540.482092194] [listener]: I heard: [Hello World: 0]
[INFO] [1704025541.449221536] [listener]: I heard: [Hello World: 1]
[INFO] [1704025542.448992738] [listener]: I heard: [Hello World: 2]
[INFO] [1704025543.453376645] [listener]: I heard: [Hello World: 3]
[INFO] [1704025544.449385635] [listener]: I heard: [Hello World: 4]
実行したノードの処理の流れは以下のようになります。
- talker(ノード1)側で、メッセージに「Hello World: %d」というデータを格納(%dには0からカウントされていく整数が代入される)
- talker(ノード1)がchatter(トピック)にメッセージを配信 (Publish)
- listener(ノード2)はchatter(トピック)から流れてきたメッセージを受信 (Subscribe)
- 受信したメッセージのデータをlistener(ノード2)側で表示
ノード、トピック、メッセージを確認する
ros2にはノードやトピックの状態を確認するために便利なコマンドが用意されています。
たくさんの種類のコマンドがありますが、ここでは頻繁に使用するコマンドを紹介したいと思います
ros2 node
ros2 node
コマンドはノードに関する情報を確認することが出来ます。
試しに、(2つのテストノードは起動したままの状態で)新しいターミナルを起動し以下のコマンドを入力してみてください。
ros2 node list
コマンドを実行すると以下のように、「現時点で存在しているノード」の一覧を確認することが出来ます。
/listener
/talker
ros2 node info
コマンドは、ノードがどのようなパブリッシャーやサブスクライバーを保有しているか等の「ノードの構成」について確認することが出来ます。
ros2 node info /talker
コマンドを実行すると以下のように表示されます。
Subscribers:
Publishers:
/chatter: std_msgs/msg/String
/parameter_events: rcl_interfaces/msg/ParameterEvent
/rosout: rcl_interfaces/msg/Log
Service Servers:
/talker/describe_parameters: rcl_interfaces/srv/DescribeParameters
/talker/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
/talker/get_parameters: rcl_interfaces/srv/GetParameters
/talker/list_parameters: rcl_interfaces/srv/ListParameters
/talker/set_parameters: rcl_interfaces/srv/SetParameters
/talker/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
Service Clients:
Action Servers:
Action Clients:
ros2 topic
ros2 topic
は、トピックに関する情報を確認できるコマンドです。
ros2 topic list
コマンドは、「現時点で存在するトピックの一覧」を確認することが出来ます( /rosout
と /parameter_events
は常に存在するトピックになります)
ros2 topic list
/chatter
/parameter_events
/rosout
ros2 node info
コマンドは、「トピックに関する情報」を確認することが出来ます。
ros2 topic info /chatter
コマンドを実行すると以下のように表示されます。
Type: std_msgs/msg/String
Publisher count: 1
Subscription count: 1
上記の場合 std_msgs/msg/String
という型のメッセージが流れるトピックであるということが分かります。
最後に、以下のコマンドを実行してみてください。
ros2 topic echo /chatter
コマンドを実行すると、以下のような表示が続くと思います。
data: 'Hello World: 0'
---
data: 'Hello World: 1'
---
data: 'Hello World: 2'
---
data: 'Hello World: 3'
---
data: 'Hello World: 4'
これは、 /chatter
トピックから流れてきたメッセージをリアルタイムで表示しており、トピックからどのようなメッセージが流れてきているかを確認するときに使用できます。
逆に、 ros2 topic echo /トピック名
を実行しても何も表示されない場合は「指定したトピックにメッセージが上手く配信できていない」ということになります。
listener
ノードではこのメッセージの中の data
という情報を表示しています。
ros2 interface
ros2 interface
は、メッセージに関する情報を確認できるコマンドです。
ros2 interface show
コマンドは、メッセージの内容について確認することが出来ます。
ros2 interface show std_msgs/msg/String
コマンドを実行すると以下のように表示され、 std_msgs/msg/String
は string
という型の data
という変数で構成されていることが分かります。
# This was originally provided as an example message.
# It is deprecated as of Foxy
# It is recommended to create your own semantically meaningful message.
# However if you would like to continue using this please use the equivalent in example_msgs.
string data
最後に
今回は、
- ROS2の基礎
について解説しました。
この記事が少しでも皆さんのお役に立てれば幸いです。