掘金 人工智能 06月23日 18:03
ROS2 Jazzy:编写可组合节点(C++)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何在ROS2中将C++节点编写为可组合节点,以便在同一进程中与其他节点一起运行,从而提高通信效率。文章首先阐述了将常规的rclcpp::Node可执行文件转换为可组合节点的基本步骤,包括修改类定义、替换main函数和更新CMakeLists.txt文件。此外,还提供了关于节点组合和多线程支持的注意事项,并提供了示例代码,帮助读者快速上手。作者是一位经验丰富的C++开发者,分享了其在AI和机器人开发领域的经验。

⚙️ **修改类定义:** 确保类的构造函数接受一个NodeOptions参数,例如 `VincentDriver(const rclcpp::NodeOptions & options) : Node("vincent_driver", options)`。

💡 **替换main函数:** 使用pluginlib风格的宏调用替换main函数,例如 `#include RCLCPP_COMPONENTS_REGISTER_NODE(palomino::VincentDriver)`。

🛠️ **CMakeLists.txt修改:** 调整CMakeLists.txt文件,添加对rclcpp_components的依赖,用add_library替换add_executable,并使用新的目标名称,最后声明你的组件。

🚀 **节点运行:** 通过ComposableNodeContainer在Python启动文件中组合节点,并注意多线程支持,如果需要多线程,使用component_container_mt。

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

起始状态

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

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

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 中,这段代码会被编译成一个可执行文件:

# ...add_executable(vincent_driver src/vincent_driver.cpp)# ...install(TARGETS vincent_driver    DESTINATION lib/${PROJECT_NAME})

代码更新

添加包依赖

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

<depend>rclcpp_components</depend>

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

类定义

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

VincentDriver(const rclcpp::NodeOptions & options) : Node("vincent_driver", options){  // ...}

不再需要主函数

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

#include <rclcpp_components/register_node_macro.hpp>RCLCPP_COMPONENTS_REGISTER_NODE(palomino::VincentDriver)
注意事项

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

CMake 修改

第一步

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

find_package(rclcpp_components REQUIRED)
第二步

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

add_library(vincent_driver_component src/vincent_driver.cpp)
第三步

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

第四步

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

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

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

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 启动文件中有如下代码:

from launch_ros.actions import Node# ..ld.add_action(Node(    package='palomino',    executable='vincent_driver',    # ..))

你可以将其替换为:

from launch_ros.actions import ComposableNodeContainerfrom 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,防失联。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

ROS2 C++ 可组合节点 rclcpp_components
相关文章