ROS2 Jazzy:编写可组合节点(C++)

ROS2 Jazzy:编写可组合节点(C++)

起始状态

假设你有一个常规的rclcpp::Node可执行文件,你希望它能和其他节点在同一个进程中运行,以实现更高效的通信。

让我们从一个直接继承Node且定义了主函数的类开始:

cpp 复制代码
namespace palomino
{
    class VincentDriver : public rclcpp::Node
    {
        // ...
    };
}

int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<palomino::VincentDriver>());
    rclcpp::shutdown();
    return 0;
}

通常在 CMake 中,这段代码会被编译成一个可执行文件:

cmake 复制代码
# ...
add_executable(vincent_driver src/vincent_driver.cpp)
# ...
install(TARGETS vincent_driver
    DESTINATION lib/${PROJECT_NAME}
)

代码更新

添加包依赖

你的package.xml文件应该添加对rclcpp_components的依赖,如下所示:

xml 复制代码
<depend>rclcpp_components</depend>

或者,你也可以分别添加build_dependexec_depend

类定义

你可能需要对类定义进行修改,就是确保类的构造函数接受一个NodeOptions参数:

cpp 复制代码
VincentDriver(const rclcpp::NodeOptions & options) : Node("vincent_driver", options)
{
  // ...
}

不再需要主函数

pluginlib风格的宏调用替换你的main函数:

cpp 复制代码
#include <rclcpp_components/register_node_macro.hpp>
RCLCPP_COMPONENTS_REGISTER_NODE(palomino::VincentDriver)
注意事项

如果被替换的main函数中包含MultiThreadedExecutor,请务必注意并确保容器节点是多线程的。详情请参阅下面的相关部分。

CMake 修改

第一步

CMakeLists.txt中添加rclcpp_components作为依赖:

cmake 复制代码
find_package(rclcpp_components REQUIRED)
第二步

add_library替换add_executable,并使用一个新的目标名称:

cmake 复制代码
add_library(vincent_driver_component src/vincent_driver.cpp)
第三步

将其他使用旧目标的构建命令替换为作用于新目标的命令。例如,ament_target_dependencies(vincent_driver ...)要改为ament_target_dependencies(vincent_driver_component ...)

第四步

添加一个新命令来声明你的组件:

cmake 复制代码
rclcpp_components_register_node(
    vincent_driver_component
    PLUGIN "palomino::VincentDriver"
    EXECUTABLE vincent_driver
)
第五步,也是最后一步

将 CMake 中所有作用于旧目标的安装命令修改为安装库版本。例如,将目标安装到lib/${PROJECT_NAME}替换为库安装命令:

cmake 复制代码
ament_export_targets(export_vincent_driver_component)
install(TARGETS vincent_driver_component
        EXPORT export_vincent_driver_component
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
)

运行节点

关于节点组合的详细内容,请参考《在单个进程中组合多个节点》教程。简单来说,如果你在 Python 启动文件中有如下代码:

python 复制代码
from launch_ros.actions import Node

# ..

ld.add_action(Node(
    package='palomino',
    executable='vincent_driver',
    # ..
))

你可以将其替换为:

python 复制代码
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode

# ..
ld.add_action(ComposableNodeContainer(
    name='a_buncha_nodes',
    namespace='',
    package='rclcpp_components',
    executable='component_container',
    composable_node_descriptions=[
        ComposableNode(
            package='palomino',
            plugin='palomino::VincentDriver',
            name='vincent_driver',
            # ..
            extra_arguments=[{'use_intra_process_comms': True}],
        ),
    ]
))
注意事项

如果你需要多线程支持,不要将executable设置为component_container,而是设置为component_container_mt


作者:小芝,一个干了二十多年的C++开发。开发过桌面软件,干过古早功能手机游戏开发,也弄过客户端APP。现在对AI开发和机器人开发有兴趣,同时也在了解产品相关知识。若喜欢本文,欢迎点赞、在看、留言交流。

为了防失联,欢迎关注本智践行(gh_157cc95c7163)。

或加小芝微信chunjuz2025,防失联。

相关推荐
崎岖Qiu14 小时前
【OS笔记36】:文件存储空间管理(一)- 空闲区表法
笔记·操作系统·存储管理·文件系统·os
柏木乃一2 天前
进程(11)进程替换函数详解
linux·服务器·c++·操作系统·exec
羑悻的小杀马特4 天前
【Linux篇章】穿越网络迷雾:揭开 HTTP 应用层协议的终极奥秘!从请求响应到实战编程,从静态网页到动态交互,一文带你全面吃透并征服 HTTP 协议,打造属于你的 Web 通信利刃!
linux·运维·网络·http·操作系统·网络通信
彩妙不是菜喵5 天前
操作系统中的Linux:进程详解--->(深入浅出)从入门到精通
linux·操作系统
农民真快落5 天前
【操作系统】手撸xv6操作系统——types.h/param.h/memlayout.h/riscv.h/defs.h头文件解析
操作系统·risc-v·嵌入式软件·xv6
小当家.1055 天前
操作系统期末考试基础知识点速成:高频考点与题集精要
考研·操作系统·计算机基础·速成·大学·期末考试
seasonsyy5 天前
为虚拟机分配内存和磁盘容量
windows·操作系统·内存·vmware·磁盘空间
想用offer打牌5 天前
一站式讲清IO多路复用(轻松愉悦版)
后端·面试·操作系统
seasonsyy6 天前
在虚拟机中安装操作系统需要U盘吗?
windows·操作系统·vmware·虚拟机
fakerth6 天前
【OpenHarmony】升级服务组件(UpdateService)
操作系统·openharmony