環境
本記事は以下の環境を想定した記事である。
項目 | 値 |
---|---|
OS | Ubuntu 22.04 |
ROS | ROS 2 Humble |
概要
ROS 2のデータのやり取りはROS 2独自のデータ型で行われる。
本記事では、ROS 2のデータ通信インタフェースの概要を示し、そのうちメッセージについて使用方法を解説する。
ROS 2インタフェースの分類
ROS 2では、Pub&Sub通信、Service通信、Action通信の3つの通信方式がある。
これらに対応して、データ通信インタフェースには以下の3種類がある。
- メッセージ:Pub&Sub通信で用いられ、拡張子
.msg
のファイルで定義される。基本となるインタフェースである。 - サービス:Service通信で用いられ、拡張子
.srv
のファイルで定義される。RequestとResponseという2つのメッセージから構成される。 - アクション:Action通信で用いられ、拡張子
.action
のファイルで定義される。Goal, Result, Feedbackという3つのメッセージから構成される。
インタフェースの表記方法
全てのROS 2インタフェースはパッケージの中で定義されるため、ROS 2のインタフェースは以下のような階層構造で定義する。
型名は大文字始まりで記述する。
ROS 2コマンド | C++ | Python | |
---|---|---|---|
Pub&Sub通信 | パッケージ名/msg/型名 |
パッケージ名::msg::型名 |
パッケージ名.msg.型名 |
Service通信 | パッケージ名/srv/型名 |
パッケージ名::srv::型名 |
パッケージ名.srv.型名 |
Action通信 | パッケージ名/action/型名 |
パッケージ名::action::型名 |
パッケージ名.action.型名 |
例えば、std_msgsというパッケージの中のInt32というインタフェースをC++のソースコード内で使用する場合、以下のように書く。
std_msgs::msg::Int32
なお、ROS 1ではこのインタフェースは以下のように表記される。
ROS 2ではパッケージ名の後にメッセージやサービスなどの区別を書くが、ROS 1では区別しないため注意する。
std_msgs::Int32
なお、std_msgsパッケージには以下のリンク先のメッセージが定義されている。
std_msgsの型一覧
メッセージの定義
基本
メッセージは、ROS 2のビルトイン型(ROS 2がサポートしている基本型)もしくは別のパッケージで定義されたメッセージを含むものである。
ROS 2のビルトイン型と、それらに対応するC++、Pythonのデータ型を以下に示す。
型 | C++ | Python |
---|---|---|
byte | unit8_t | builtins.bytes* |
float32 | float | builtins.float* |
float64 | double | builtins.float* |
int8 | int8_t | builtins.int* |
uint8 | uint8_t | builtins.int* |
int16 | int16_t | builtins.int* |
uint16 | uint16_t | builtins.int* |
int32 | int32_t | builtins.int* |
uint32 | uint32_t | builtins.int* |
int64 | int64_t | builtins.int* |
uint64 | uint64_t | builtins.int* |
char | char | builtins.str* |
string | std::string | builtins.str |
wstring | std::u16string | builtins.str |
bool | bool | builtins.bool |
上記の表は、ROS 2公式ドキュメント インターフェイス:フィールド型を参照して作成した。
例えば、std_msgs
パッケージのColorRGBA
というメッセージは、以下のように定義されている。
これはColorRGBA
が、C++においてfloat
で扱われる型で、r
、g
, b
、a
という要素を含んでいることを示す。
float32 r
float32 g
float32 b
float32 a
このメッセージの定義は、std_msgs/msg/ColorRGBA.msgファイルで見ることができる。
別のパッケージで定義されたメッセージを含む例として、geometry_msgs
パッケージで定義されたPose
というメッセージが挙げられる。
このメッセージは3次元空間中のポーズを示すメッセージであり、以下に示すように、点を示すPoint
と回転を示すQuaternion
というメッセージからなる。
これらのメッセージもgeometry_msgs
パッケージで定義されている。
# A representation of pose in free space, composed of position and orientation.
Point position
Quaternion orientation
このメッセージの定義は、geometry_msgs/msg/Pose.msgファイルで見ることができる。
配列
ROS 2のメッセージでは、以下の種類の配列を定義できる。
項番 | 型 | C++ | Python |
---|---|---|---|
1 | 固定長配列 | std::array | builtins.list* |
2 | 可変長配列(要素数の上限なし) | std::vector | builtins.list* |
3 | 可変長配列(要素数の上限あり) | custom_class | builtins.list* |
4 | 文字列(文字数の上限あり) | std::string | builtins.str* |
表中のcustom_class<T, N>
は、ROS 2でこの型を実現するために独自の実装が行われていることを示す。
以下に、メッセージ定義の具体例を表の項番に対応させて示す。
-
int32
型の固定長配列(要素数=5)
int32[5] data_name
-
int32
型の可変長配列(要素数の上限なし)
int32[] data_name
-
int32
型の可変長配列(要素数の上限=5)
int32[<=5] data_name
- 文字列(文字数の上限=10)
string<=10 data_name
文字列
ROS 2のビルドイン型で扱える文字列は、UTF-8であることが期待されている。
そのため、日本語などのマルチバイト文字も人間が考える文字数で扱える。
(参考: ROS 2 Design Unicode Support)
たとえば、以下のように3文字を上限とするメッセージに、"あああ"といった3文字のデータを格納できる。
string<=3 data_name
また、文字列配列では以下のようにして複雑なメッセージを定義できる。
-
文字列配列(要素数の上限なし、文字列1要素の最大文字数=10)
string<=10[] data_name
-
文字列配列(要素数の上限=5、文字列1要素の最大文字数=10)
string<=10[<=5] data_name
定数
以下のようにしてメッセージに定数を定義できる。
定数の要素名は全て大文字で定義する。
以下では、CONSTANT_DATA
という要素名を定義し、その値を12345としている。
int32 CONSTANT_DATA=12345
文字列の場合は、以下のように定義する。
string CONSTANT_DATA="foo"
なお、定数で表現する型はROS 2のビルドイン型である必要であり、以下のように定数配列を定義することはできない。
# 注意:無効なメッセージ定義
int32[] CONSTANT_ARRAY=[1, 2, 3, 4, 5]
これは、ROS 2でメッセージ定義ファイルを解析するスクリプトの実装仕様による。
インタフェースの調べ方
ros2 interface show "インタフェース名"
でそのインタフェースの構造を表示できる。
例として、std_msgs/msg/String
の情報を表示させた結果を以下に示す。
結果から、data
という要素を1つ持つメッセージであることがわかる。
またコメントからは、より意味のある具体的なメッセージを定義することが推奨されていることがわかる。
$ ros2 interface show std_msgs/msg/String
# 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
より実践的な型の例として、sensor_msgs/msg/LaserScan
のインタフェース定義を示した結果を以下に示す。
この型はロボティクスでよく使われる2D LiDAR(Light Detection and Ranging)というセンサ情報を格納するために使われるものである。
大きく分けて以下の3種類の情報が含まれており、汎用的に使える型であることがわかる。
- メッセージのタイムスタンプ等のメタデータの定義
- 最大/最小の角度や最大測定距離等のセンサの特性を示す値
- 最後に
float32
型の配列として距離とレーザ強度の計測値が格納されている。
$ ros2 interface show sensor_msgs/msg/LaserScan
# Single scan from a planar laser range-finder
#
# If you have another ranging device with different behavior (e.g. a sonar
# array), please find or create a different message, since applications
# will make fairly laser-specific assumptions about this data
std_msgs/Header header # timestamp in the header is the acquisition time of
builtin_interfaces/Time stamp
int32 sec
uint32 nanosec
string frame_id
# the first ray in the scan.
#
# in frame frame_id, angles are measured around
# the positive Z axis (counterclockwise, if Z is up)
# with zero angle being forward along the x axis
float32 angle_min # start angle of the scan [rad]
float32 angle_max # end angle of the scan [rad]
float32 angle_increment # angular distance between measurements [rad]
float32 time_increment # time between measurements [seconds] - if your scanner
# is moving, this will be used in interpolating position
# of 3d points
float32 scan_time # time between scans [seconds]
float32 range_min # minimum range value [m]
float32 range_max # maximum range value [m]
float32[] ranges # range data [m]
# (Note: values < range_min or > range_max should be discarded)
float32[] intensities # intensity data [device-specific units]. If your
# device does not provide intensities, please leave
# the array empty.
ソースコード上の使用例
ソースコード上でメッセージを利用してPub&Sub通信を行う実装は、Pub&Sub通信の記事で解説している。
この記事では、std_msgs/msg/String
のメッセージをやりとりするノードを実装している。
備考
上記はすでに用意されているメッセージを使用しているが、自作した独自のメッセージを使用することもできる。
独自のメッセージの作成方法は、カスタムROSメッセージの記事に記載している。