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,防失联。

相关推荐
OpenAnolis小助手18 小时前
朗空量子与 Anolis OS 完成适配,龙蜥获得抗量子安全能力
安全·开源·操作系统·龙蜥社区·龙蜥生态
墨夏2 天前
跨平台开发下的策略模式
设计模式·操作系统
fakerth2 天前
OpenHarmony介绍
操作系统·openharmony
程序员老刘4 天前
操作系统“卡脖子”到底是个啥?
android·开源·操作系统
有信仰4 天前
操作系统——虚拟内存和物理内存
操作系统
望获linux8 天前
【实时Linux实战系列】实时数据流处理框架分析
linux·运维·前端·数据库·chrome·操作系统·wpf
unfetteredman9 天前
Mac查看端口使用信息
操作系统·mac
闪电麦坤959 天前
操作系统:RPC 中可能遇到的问题(Issues in RPC)
rpc·操作系统
闪电麦坤9510 天前
操作系统:远程过程调用( Remote Procedure Call,RPC)
rpc·操作系统
丐中丐99912 天前
Android系统中如何在Native层调用java实现的系统服务
android·操作系统