编写可组合节点 (C++)

起点

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

我们将从一个直接从 Node 继承的类开始,并且该类还定义了一个 main 方法。

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_depend/exec_depend”。

类定义

您可能需要对类定义进行的唯一更改是确保“类<https://github.com/ros2/demos/tree/rolling/composition/src/talker_component.cpp>的构造函数”__ 接受“NodeOptions”参数。

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

不再有 Main 方法

使用 pluginlib 样式的宏调用替换您的 main 方法。

#include <rclcpp_components/register_node_macro.hpp>
RCLCPP_COMPONENTS_REGISTER_NODE(palomino::VincentDriver)

Caution

如果您要替换的主要方法包含“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 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}],
        ),
    ]
))

如果您需要多线程,请将可执行文件设置为“component_container”,而不是“component_container”,而是将其设置为“component_container_mt”