存储插件开发
存储插件为 Rosbag2 提供实际的底层存储格式。
插件可以实现以下 API 来提供存储插件,这些 API 在 rosbag2_storage::storage_interfaces 中定义:
ReadOnlyInterface—— 只负责文件的读取ReadWriteInterface—— 既可以写新文件,也可以读现有文件。它是 ReadOnly 的超集
创建 ReadWrite 插件
Section titled “创建 ReadWrite 插件”目标:创建一个名为 my_storage 的插件,位于包 rosbag2_storage_my_storage 中,由类 my_namespace::MyStorage 实现。
下面的代码片段展示了提供该插件所需的各个部分。
#include "rosbag2_storage/storage_interfaces/read_write_interface.hpp"
namespace my_namespace {
class MyStorage : public rosbag2_storage::storage_interfaces::ReadWriteInterface{public: MyStorage(); ~MyStorage() override; // IMPORTANT: All cleanup must happen in the destructor, such as closing file handles or database connections
// ReadWriteInterface's virtual overrides here};
// Implementations
} // namespace my_namespace
// The following block exposes our class to pluginlib so that it can be discovered at runtime.#include "pluginlib/class_list_macros.hpp"PLUGINLIB_EXPORT_CLASS(my_namespace::MyStorage, rosbag2_storage::storage_interfaces::ReadWriteInterface)接下来,我们的包必须提供一个名为 plugin_description.xml 的文件。
其内容如下:
<library path="rosbag2_storage_my_storage"> <class name="my_storage" type="MyStorage" base_class_type="rosbag2_storage::storage_interfaces::ReadWriteInterface" > <description>Rosbag2 storage plugin providing the MyStorage file format.</description> </class></library>rosbag2_storage_my_storage 是 package.xml 中库的名称,而 my_storage 是 pluginlib 用来引用该插件的标识符。
最后,CMakeLists.txt 必须把我们的 plugin_description.xml 文件加入 ament index,以便在运行时被发现:
pluginlib_export_plugin_description_file(rosbag2_storage plugin_description.xml)第一个参数 rosbag2_storage 表示我们向哪个库添加插件(对这种插件类型来说,它永远是 rosbag2_storage),第二个参数是插件描述文件的路径。
创建 ReadOnly 插件
Section titled “创建 ReadOnly 插件”当编写只提供读取功能的插件时,改为让你的实现类继承 rosbag2_storage::storage_interfaces::ReadOnlyInterface。
这是唯一的功能性差异,它只需要接口覆盖的子集。
#include "rosbag2_storage/storage_interfaces/read_only_interface.hpp"
namespace my_namespace {
class MyReadOnlyStorage : public rosbag2_storage::storage_interfaces::ReadOnlyInterface{public: MyReadOnlyStorage(); ~MyReadOnlyStorage() override; // IMPORTANT: All cleanup must happen in the destructor, such as closing file handles or database connections
// ReadOnlyInterface's virtual overrides here};
// Implementations
} // namespace my_namespace
// The following block exposes our class to pluginlib so that it can be discovered at runtime.#include "pluginlib/class_list_macros.hpp"PLUGINLIB_EXPORT_CLASS(my_namespace::MyReadOnlyStorage, rosbag2_storage::storage_interfaces::ReadOnlynterface)<library path="rosbag2_storage_my_storage"> <class name="my_readonly_storage" type="my_namespace::MyReadOnlyStorage" base_class_type="rosbag2_storage::storage_interfaces::ReadOnlyInterface" > <description>Rosbag2 storage plugin providing read functionality for MyStorage file format.</description> </class></library>以及在 CMakeLists 中常见的 pluginlib 导出:
pluginlib_export_plugin_description_file(rosbag2_storage plugin_description.xml)提供插件特定的配置
Section titled “提供插件特定的配置”有些存储插件可能具有该格式特有的配置参数,你希望允许用户从命令行提供。
Rosbag2 提供了一个 CLI 参数 --storage-config-file,允许用户传入文件路径。
该文件可以包含任何内容,其格式由存储实现决定,文件路径会一路传递到插件,插件可以按需使用。
建议插件记录该文件的预期格式,以便用户编写格式良好的配置。
从存储插件扩展 CLI
Section titled “从存储插件扩展 CLI”与写出文件相比,命令行参数可能是向用户暴露配置更方便的方式。
创建 ros2 bag 命令的 ros2bag 包为插件扩展 CLI 提供了一个入口点(entrypoint)。
包只需要向 ros2bag.storage_plugin_cli_extension 组暴露一个 Python setuptools 入口点,入口点的键为存储插件的名称。例如,下面是 rosbag2_storage_mcap 的 setup.cfg:
[options.entry_points]ros2bag.storage_plugin_cli_extension = mcap = ros2bag_mcap_cli这在 ros2bag.storage_plugin_cli_extension 组中注册了一个名为 mcap 的插件的入口点,该插件由名为 ros2bag_mcap_cli 的 Python 模块实现。
暴露的入口点可以通过任何方式安装为 Python 模块,例如通过 ament_cmake_python 的 ament_python_install_package 宏,或者使用带 setup.py 的纯 Python ament_python 包。
该入口点可以提供的函数:
get_preset_profiles(): List[Tuple[str, str]]- 提供一个字符串对列表,包含用于写入存储文件的_预设配置(preset profiles)_的(名称,描述)。第一项将用作默认值。考虑把 ‘none’ 作为第一个配置。
注意:对于每个这样的列表,字符串字面量 ‘none’ 将用来表示该功能被禁用/未使用。
注意:任何入口点都可以省略任何扩展函数,对于每个省略的扩展点都会打印警告。当列表值函数未提供或返回 None 时,默认只提供 'none' 选项。