ros2--节点组件

什么是组件容器

  • 在不同的进程中运行多个节点。这样可以使不同的进程独立开。一个崩溃其他可以正常运行。也更方便调试各个节点。
  • 在同一个进程中运行多个节点。这样可以使得通信更加高效。

组件容器功能就是用来实现将多个包中的多个节点放于同一个进程中执行。

组件容器本质上也是一个包中的一个可执行文件而已,这个可执行文件会启动所有加载到这个组件容器中的节点。

ros2 run rclcpp_components component_container

组件的实现原理

单进程运行所有节点。

可组合节点--节点组件

什么是节点组件

将节点对象(插件)使用rclcpp_components库中的宏RCLCPP_COMPONENTS_REGISTER_NODE()进行注册到一个组件中,最后通过cmake构建将这个组件生成共享库;在通过component_container容器工具就可以使用这个组件,component_container容器工具可以自动加载共享库,并启动拱北封装在共享库中的组件的节点。

为什么需要可组合节点

为了单进程通信,提高通信效率。

创建可组合节点时构造函数为什么需要rclcpp::NodeOption的参数

节点对象包含了很多可配置的属性,包括节点名称、命名空间、参数等,这些选项可以在运行时根据需要进行动态调整。通过将rclcpp::NodeOption作为构造函数的参数,我们可以在创建节点时,为其指定特定的选项。

在定义可组合节点时,使用rclcpp::NodeOption构造参数也是为了运行创建节点时指定节点的参数。

可组合节点的实现

1,创建可组合节点功能包

ros2 pkg create custom_talker --build-type ament_cmake --dependencies rclcpp rclcpp_components --destination-directory src --node-name talker

2,添加节点对象构造参数

Talker::Talker(const rclcpp::NodeOptions & options): Node("talker", options), count_(0){           pub_ = create_publisher<std_msgs::msg::String>("chatter", 10); 

   timer_ =   create_wall_timer(1s, std::bind(&Talker::on_timer, this));

}

3,去main,注册可组合节点

#include "custom_talker/talker.hpp"
#include <chrono>
#include <iostream>
#include <memory>
#include <utility>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

namespace custom_talker{

Talker::Talker(const rclcpp::NodeOptions & options): Node("talker", options), count_(0){  pub_ = create_publisher<std_msgs::msg::String>("chatter", 10);  timer_ = create_wall_timer(1s, std::bind(&Talker::on_timer, this));
}

void Talker::on_timer(){  auto msg = std::make_unique<std_msgs::msg::String>();
  msg->data = "Hello World: " + std::to_string(++count_);  RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", msg->data.c_str());  std::flush(std::cout);  pub_->publish(std::move(msg));
}

}  // namespace custom_talker
#include "rclcpp_components/register_node_macro.hpp"
RCLCPP_COMPONENTS_REGISTER_NODE(custom_talker::Talker)
RCLCPP_COMPONENTS_REGISTER_NODE()

中的参数指定----命名空间::类;

4,修改可组合节点CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(custom_talker)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()
#1--添加依赖包
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rclcpp_components REQUIRED)

include_directories(include)

#2--将组件生成共享库
#add_executable(talker src/talker.cpp)替换
add_library(talker_component SHARED src/talker.cpp)
target_include_directories(talker_component PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)
target_compile_features(talker_component PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
ament_target_dependencies(
  talker_component
  "rclcpp"
  "std_msgs"
  "rclcpp_components"
)
#3--必须注册组件
rclcpp_components_register_nodes(talker_component "custom_talker::Talker")

#4--安装组件所在动态库
# install(TARGETS talker
#   DESTINATION lib/${PROJECT_NAME})
install(TARGETS
  talker_component
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION bin)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

rclcpp_componets_register_nodes()

第一个参数:

是组件的名称,和生成的共享库同名。

第二个参数:

被注册到组件中的插件对象,也就是类对象,如果对象存在于命名空间中,需要指定命名空间。

rclcpp_components_register_nodes(talker_component "custom_talker::Talker")

注意:生成的库一定要加上SHARED生成共享库。

component_container工具

作用

1,启动组件容器工具

ros2 run rclcpp_components component_container

2,查看容器是否成功运行

$ ros2 component list

出现:

/ComponentManager

则成功运行。

3,将包中的插件对象加载到组件容器中

ros2 component load /ComponentManager custom_talker custom_talker::Talker

加载成功会返回成功加载的组件的索引。

参数:

custom_talker-----组件所在包的名称;

custom_talker::Talker---指定的包中的插件的插件名称,也就是类对象名称;

(这个命令并没有指定组件名称,博主猜测应该是通过插件的名称去加载指定的组件到组件容器中。)

组件名称:talker_component

rclcpp_components_register_nodes(talker_component "custom_talker::Talker")

4,使用组件id从容器中卸载组件

ros2 component unload /ComponentManager 1 2

1 2表示卸载两个组件。

launch启动组件

luanch文件定义

1,定义launch文件:

import launch
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode


def generate_launch_description():
    """Generate launch description with multiple components."""
    #--------第一层--定义容器对象--------------#
    container = ComposableNodeContainer(
            name='my_container',
            namespace='',
            package='rclcpp_components',
            executable='component_container',
            #-------------定义节点组件描述对象------------------#
            composable_node_descriptions=[
                #------定义所有需要在一个进程中使用的节点组件--------#
                ComposableNode(
                    package='composition',
                    plugin='composition::Talker',
                    name='talker'),
                ComposableNode(
                    package='composition',
                    plugin='composition::Listener',
                    name='listener')
            ],
            output='screen',
    )

    return launch.LaunchDescription([container])

容器对象的name:

就是启动容器后,容器的名称:

2,安装launch目录

所有的launch功能包在创建launch文件之后,cmake中只需要install launch目录即可:

cmake_minimum_required(VERSION 3.8)
project(component_launch)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

#只需要加这个指令即可
install(
  DIRECTORY launch
  DESTINATION share/${PROJECT_NAME}
)

ament_package()

描述了组件需要启动的所有节点,之后就可以一个指令运行组件,不再需要一步一步启动容器,加载节点组件:

ros2 launch component_launch talker_listener.launch.py

教程

官网英文教程

古月居

官网源码

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值