Skip to content

消息定义编码

消息定义可以存入 ROS 2 bag,方便后续解码消息。本文介绍如何在 bag 中编码消息定义。

bag 中存储的消息定义并不参与 bag 回放。但一些 bag 分析工具无法预先获取所有消息定义,需要在运行时根据消息定义生成反序列化器。

运行时反序列化消息时,反序列化器需要知道该消息类型的定义,以及其所有字段类型的定义(字段类型的字段类型,以此类推)。这组递归包含所有字段类型的定义,称为完整消息定义(complete message definition)。

这种编码由 .msg 和 .srv 格式的定义拼接而成:各定义以人类可读的形式写出,再用分隔符连接。

顶层消息定义排在最前面,不带分隔符。每个依赖的 .msg 定义前面都有一个两行分隔符:

  • 一行恰好包含 80 个 = 字符
  • 一行为该类型,内容为 MSG: <package resource name>。MSG: 与包资源名之间的空格必不可少。包资源名不含文件扩展名。

例如,my_msgs/msg/ExampleMsg 的 ros2msg 形式的完整消息定义是:

# defines a message that includes a field of a custom message type
my_msgs/BasicMsg my_basic_field
================================================================================
MSG: my_msgs/msg/BasicMsg
# defines a message with a primitive type field
float32 my_float

另一个例子是 my_msgs/srv/ExampleSrv 的 ros2msg 形式的服务消息定义:

# defines a service message that includes a field of a custom message type
my_msgs/BasicMsg request
---
my_msgs/BasicMsg response
================================================================================
MSG: my_msgs/msg/BasicMsg
# defines a message with a primitive type field
float32 my_float

按名称指定的类型的 IDL 定义,与所有依赖类型的定义一起存储。 IDL 定义可以按任意顺序存储。每个定义前面都有一个两行分隔符:

  • 一行恰好包含 80 个 = 字符,然后
  • 一行为该定义,内容只包含 IDL: <package resource name>。IDL: 与包资源名之间的空格必不可少。包资源名不含文件扩展名。

例如,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 消息定义的知名格式,除了各自的规范之外,读者不需要任何额外知识即可反序列化消息。

.msg 和 .idl 消息定义按各自规范编码,而规范将注释视为合法语法。bag 写入器可以去掉注释,也可以原样保留。