前言
本章是详细介绍ROS2通信中间件中rmw模块软件框架。
不了解背景的同学请先看:
- ROS2软件架构全面解析-学习如何设计通信中间件框架: link
rmw框架
- rmw是为兼容各种DDS组件而设计的中间件抽象层:the middleware abstraction layer called rmw (ROS MiddleWare)
- 用户可以根据性能、软件许可或支持的平台等各种约束条件,选择不同的RMW 实现,也就是基于DDS协议的组件
- 提供丰富的自由度让用户选择DDS协议实现组件,只要实现了rmw Layer规定的接口就可以装载到ROS2系统中完成消息传递
rmw软件架构
- rmw Layer本人划分是主要两个文件夹:rmw、rmw_implementation
- rmw Layer主要的内容是规定DDS组件的功能接口:rmw.h、init.h 头文件,本身逻辑功能不多。rmw_validate_node_name实现在rmw Layer validate_node_name.c文件中,对node name 有效性进行验证,算逻辑代码多的文件了。
- rmw_implementation模块中有一个动态函数调用框架,能够把DDS实现组件的函数接口直接提供给rcl Layer调用,能够让rcl Layer调用到DDS组件中。
//function.cpp
RMW_INTERFACE_FN(
rmw_send_response,
rmw_ret_t, RMW_RET_ERROR,
3, ARG_TYPES(const rmw_service_t *, rmw_request_id_t *, void *))
- rmw_send_response就是在rcl Layer service.c文件中调用的,rmw implementation通过RMW_INTERFACE_FN进行封装动态调用到选择的DDS组件。主要功能是在RMW_INTERFACE_FN Macro中。
#define CALL_SYMBOL(symbol_name, ReturnType, error_value, ArgTypes, arg_values) \
if (!symbol_ ## symbol_name) { \
/* only necessary for functions called before rmw_init */ \
symbol_ ## symbol_name = get_symbol(#symbol_name); \
} \
if (!symbol_ ## symbol_name) { \
/* error message set by get_symbol() */ \
return error_value; \
} \
typedef ReturnType (* FunctionSignature)(ArgTypes); \
FunctionSignature func = reinterpret_cast<FunctionSignature>(symbol_ ## symbol_name); \
return func(arg_values);
// cppcheck-suppress preprocessorErrorDirective
#define RMW_INTERFACE_FN(name, ReturnType, error_value, _NR, ...) \
void * symbol_ ## name = nullptr; \
ReturnType name(EXPAND(ARGS_ ## _NR(__VA_ARGS__))) \
{ \
CALL_SYMBOL( \
name, ReturnType, error_value, ARG_TYPES(__VA_ARGS__), \
EXPAND(ARG_VALUES_ ## _NR(__VA_ARGS__))); \
}
- RMW_INTERFACE_FN Macro用于定义一个函数,CALL_SYMBOL Macro调用负责动态加载调用传入名字的函数体
- 比如rmw implementation设置的cyclonedds就会调入到如下代码实现
// rmw_node.cpp rmw_cyclonedds_cpp文件夹目录
extern "C" rmw_ret_t rmw_send_response(
const rmw_service_t * service,
rmw_request_id_t * request_header, void * ros_response){}
rmw集成方式
- rmw模组通过CMake会编译为rmw库,然后再rcl CMakeList中引入编译,使用的时候直接引入头文件就可以使用接口函数
// rmw CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(rmw)
# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()
//rcl CMakeLists.txt
# specific order: dependents before dependencies
ament_target_dependencies(${PROJECT_NAME}
"rcl_interfaces"
"rcl_logging_interface"
"rcl_yaml_param_parser"
"rcutils"
"rmw"
"rmw_implementation"
${RCL_LOGGING_IMPL}
"rosidl_runtime_c"
"tracetools"
)
- rmw implementation package.xml支持集成rmw_connextdds、rmw_cyclonedds、rmw_fastrtps几种DDS实现,具体使用是通过RMW_IMPLEMENTATION系统属性设置的。
DDS组件
- 目前提供三种DDS实现:connextdds、cyclonedds、fastrtps。
- 还有一个dds_common作为一个共有的DDS模块,提供功能支持对其他差异化DDS。