消息定义编码
消息定义可以存入 ROS 2 bag,方便后续解码消息。本文介绍如何在 bag 中编码消息定义。
bag 中存储的消息定义并不参与 bag 回放。但一些 bag 分析工具无法预先获取所有消息定义,需要在运行时根据消息定义生成反序列化器。
运行时反序列化消息时,反序列化器需要知道该消息类型的定义,以及其所有字段类型的定义(字段类型的字段类型,以此类推)。这组递归包含所有字段类型的定义,称为完整消息定义(complete message definition)。
ros2msg 编码
Section titled “ros2msg 编码”这种编码由 .msg 和 .srv 格式的定义拼接而成:各定义以人类可读的形式写出,再用分隔符连接。
顶层消息定义排在最前面,不带分隔符。每个依赖的 .msg 定义前面都有一个两行分隔符:
- 一行恰好包含 80 个
=字符 - 一行为该类型,内容为
MSG: <package resource name>。MSG:与包资源名之间的空格必不可少。包资源名不含文件扩展名。
ros2msg 示例
Section titled “ros2msg 示例”例如,my_msgs/msg/ExampleMsg 的 ros2msg 形式的完整消息定义是:
# defines a message that includes a field of a custom message typemy_msgs/BasicMsg my_basic_field================================================================================MSG: my_msgs/msg/BasicMsg# defines a message with a primitive type fieldfloat32 my_float另一个例子是 my_msgs/srv/ExampleSrv 的 ros2msg 形式的服务消息定义:
# defines a service message that includes a field of a custom message typemy_msgs/BasicMsg request---my_msgs/BasicMsg response================================================================================MSG: my_msgs/msg/BasicMsg# defines a message with a primitive type fieldfloat32 my_floatros2idl 编码
Section titled “ros2idl 编码”按名称指定的类型的 IDL 定义,与所有依赖类型的定义一起存储。 IDL 定义可以按任意顺序存储。每个定义前面都有一个两行分隔符:
- 一行恰好包含 80 个
=字符,然后 - 一行为该定义,内容只包含
IDL: <package resource name>。IDL:与包资源名之间的空格必不可少。包资源名不含文件扩展名。
ros2idl 示例
Section titled “ros2idl 示例”例如,my_msgs/msg/ComplexMsg 的 ros2idl 形式的完整消息定义是:
================================================================================IDL: my_msgs/msg/ComplexMsg// generated from rosidl_adapter/resource/msg.idl.em// with input from my_msgs/msg/ComplexMsg.msg// generated code does not contain a copyright notice
#include "my_msgs/msg/BasicMsg.idl"
module my_msgs { module msg { struct ComplexMsg { my_msgs::msg::BasicMsg my_basic_field; }; };};================================================================================IDL: my_msgs/msg/BasicMsg// generated from rosidl_adapter/resource/msg.idl.em// with input from my_msgs/msg/BasicMsg.msg// generated code does not contain a copyright notice
module my_msgs { module msg { struct BasicMsg { float my_float; }; };};为什么以人类可读的形式存储消息定义?
Section titled “为什么以人类可读的形式存储消息定义?”这些格式在设计上力求变动最小:现在录制的 bag 里的定义,理想情况下几年后仍能直接解析,无需任何格式迁移。MSG 和 OMG IDL 4.2 都是 ROS 2 消息定义的知名格式,除了各自的规范之外,读者不需要任何额外知识即可反序列化消息。
为什么这些示例包含注释?
Section titled “为什么这些示例包含注释?”.msg 和 .idl 消息定义按各自规范编码,而规范将注释视为合法语法。bag 写入器可以去掉注释,也可以原样保留。