编写可组合节点 (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”