0. 简介

ros1中我们会经常使用Nodelets来完成多个Node节点的管理。但是在ROS2中如何使用多节点组合去完成管理,这也是我们需要去了解和学习的。

1 . ROS 1 - Node 和 Nodelets

在ROS1中你可以写一个节点也可以写一个小节点(Nodelet)。 ROS 1 的节点会被编译成一个可执行文件。 ROS 1的小节点会被编译成一个动态链接库。当程序运行的时候会被动态的加载到容器进程里面。Nodelet包就是为改善这一状况设计的,它提供一种方法,可以让多个算法程序在一个进程中用 shared_ptr 实现零拷贝通信(zero copy transport),以降低因为传输大数据而损耗的时间。简单讲就是可以将多个node捆绑在一起管理,使得同一个manager里面的topic的数据传输更快。

1.1 pkg组织框架:

  • nodelet头文件(include/)
  • nodelet源文件(src/)
  • nodelet_plugins.xml
  • package.xml
  • CMakeLists.txt
  • launch文件

1.2 需要的操作步骤:

  • 在.cpp和.h中添加相应的头文件;
  • 去掉main函数;
  • .h中声明子类,.cpp中定义子类;
  • .cpp中将原node中类构造函数代码移动到onInit()中,用于初始化;
  • .cpp中添加PLUGINLIB_EXPORT_CLASS宏,讲子类声明为插件类,并编译为动态库;
  • package中添加<build_depend> <run_depend>依赖,添加export;
  • 编写plugin.xml使nodelet称为一个插件;
  • CMakeLists做相应修改:添加nodelet依赖;没有main因此无executable,而是lib。

1.3 NodeLets子类

MyNodeletClass.h

#include <nodelet/nodelet.h>namespace example_pkg
{class MyNodeletClass : public nodelet::Nodelet{public:virtual void onInit();};
}

注意:在nodelet::Nodelet基类当中,onInit()被声明为纯虚函数,因此在子类中必须对其进行重写(override)。所有的初始化工作都应该在这个函数中完成。

MyNodeletClass.cpp

#include <pluginlib/class_list_macros.h>// watch the capitalization carefully
PLUGINLIB_EXPORT_CLASS(example_pkg::MyNodeletClass, nodelet::Nodelet)namespace example_pkg
{void MyNodeletClass::onInit(){NODELET_DEBUG("Initializing nodelet...");}
}

注意:为了允许类被动态加载,它必须被标记为导出类。这通过特殊宏PLUGINLIB_EXPORT_CLASS / PLUGINLIB_DECLARE_CLASS来完成,通常放在导出类的.cpp文件的末尾。宏的参数分类为:pkg,class_name,class_type ,base_class_type。

1.4 nodelet_plugins.xml

该文件应与package.xml放置在同一路径下。插件描述文件是一个XML文件,用于存储有关插件的所有重要信息。它包含有关插件所在的库的信息,插件的名称,插件的类型等。

<library path="lib/libMyNodeletClass"><class name="example_pkg/MyNodeletClass" type="example_pkg::MyNodeletClass" base_class_type="nodelet::Nodelet"><description>This is my nodelet.</description></class>
</library>

1.5 package.xml

package.xml文件中,为了让pluginlib查询ROS系统上的所有可用插件,每个包必须显式指定它导出的插件。应添加如下:

...
<build_depend>nodelet</build_depend>
<run_depend>nodelet</run_depend>
<export><nodelet plugin="${prefix}/nodelet_plugins.xml" />
</export>
...

1.6 mynodelet.launch

launch file中做了两件事情:启动一个nodelet manager,加载nodelet到manager中。

<launch><node pkg="nodelet" type="nodelet" name="standalone_nodelet"  args="manager" output="screen"/><node pkg="nodelet" type="nodelet" name="MyNodeletClass" args="load example_pkg/MyNodeletClass standalone_nodelet" output="screen"></node>
</launch>

2. ROS 2 - 统一API

在ROS2里面,推荐编写小节点——我们称之为组件Component。 这样我们就更容易为已经存在的代码添加一些通用的概念,比如生命周期. 使用不同的API所带来的麻烦完全被ROS2给避免了。节点进和小节点在ROS2中完全使用相同的API。

你也可以继续使用节点的风格的主函数,但是一般是并不推荐的

通过把进程的结构变成一个部署是的选项,用户可以自由的在下面的模式进行选择

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

在未来的roslaunch版本中,会支持配置进程的结构,官网说明。

这些demos使用rclcpp_components, ros2componentcomposition包里面可执行文件,并且可以使用以下指令运行。

第一个终端,运行组件容器:

ros2 run rclcpp_components component_container

使用ros2命令行确认正在运行中的容器

$ ros2 component list
/ComponentManager

在第二个终端(查看talker源码(https://github.com/ros2/demos/blob/foxy/composition/src/talker_component.cpp)).这个指令会返回已启动的模块id,其跟节点名字一样独一无二。

$ ros2 component load /ComponentManager composition composition::Talker
Loaded component 1 into '/ComponentManager' container node as '/talker'

第二个终端的另一条指令(查看listener代码(https://github.com/ros2/demos/blob/foxy/composition/src/listener_component.cpp)):

$ ros2 component load /ComponentManager composition composition::Listener
Loaded component 2 into '/ComponentManager' container node as '/listener'

ros2命令行实用程序现在是可以用来检查容器的状态:

$ ros2 component list
/ComponentManager1  /talker2  /listener

使用launch操作组合,命令行工具用来调试和诊断组件配置,它通常是在同一时间启动一组组件(的方式)更方便。为了使得该操作自动化(完成),我们可以使用ros2 launch功能指令。

ros2 launch composition composition_demo.launch.py

最后可以使用专属的ID来卸载组件容器的节点。

$ ros2 component unload /ComponentManager 1 2
Unloaded component 1 from '/ComponentManager' container
Unloaded component 2 from '/ComponentManager' container

下面我们来看一下函数结构

2.1 CMakeList.txt

为了使component_container能够找到所需的组件,必须在索引中注册该组件rclcpp_components_register_nodes,以便工具可以发现它:

add_library(talker_component SHAREDsrc/talker_component.cpp)
target_compile_definitions(talker_componentPRIVATE "COMPOSITION_BUILDING_DLL")
ament_target_dependencies(talker_component"rclcpp""rclcpp_components""std_msgs")
rclcpp_components_register_nodes(talker_component "composition::Talker")
set(node_plugins "${node_plugins}composition::Talker;$<TARGET_FILE:talker_component>\n")
add_executable(manual_compositionsrc/manual_composition.cpp)
target_link_libraries(manual_compositiontalker_componentlistener_componentserver_componentclient_component)
ament_target_dependencies(manual_composition"rclcpp")add_executable(linktime_compositionsrc/linktime_composition.cpp)
set(libstalker_componentlistener_componentserver_componentclient_component)

2.2 package.xml

package.xml文件中,需要添加对应的rclcpp_components的components依赖:

<build_depend>example_interfaces</build_depend>
<build_depend>rclcpp</build_depend>
<build_depend>rclcpp_components</build_depend>
<build_depend>rcutils</build_depend>
<build_depend>std_msgs</build_depend><exec_depend>example_interfaces</exec_depend>
<exec_depend>launch_ros</exec_depend>
<exec_depend>rclcpp</exec_depend>
<exec_depend>rclcpp_components</exec_depend>
<exec_depend>rcutils</exec_depend>
<exec_depend>std_msgs</exec_depend><test_depend>ament_cmake_pytest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>launch</test_depend>
<test_depend>launch_testing</test_depend>
<test_depend>launch_testing_ros</test_depend>
<test_depend>launch_testing_ament_cmake</test_depend>
<test_depend>rmw_implementation_cmake</test_depend>

…详情请参照古月居

ROS到ROS2的多节点组合运行相关推荐

  1. ros下创建节点后运行总是出现[rospack] Error: package '***' not found

    ros下创建节点后运行总是出现[rospack] Error: package '***' not found 这是由于没有配置环境的原因所造成的,解决方法:输入命令行source ~/catkin_ ...

  2. ROS2 基础概念 节点

    ROS2 基础概念 节点 1. Nodes 2. 重映射 3. 环境设置 3.1. ROS_DOMAIN_ID 3.2. ROS_LOCALHOST_ONLY 1. Nodes 每个节点应负责单个模块 ...

  3. ROS 和 ROS2 架构和通信

    ROS 和 ROS2 架构和通信 1. ROS 架构设计 1.1 OS 层 1.2 中间层 1.3 应用层 2. ROS 的通信机制 2.1 话题通信机制 2.1.1 Talker 注册 2.1.2 ...

  4. ROS小车——发布与订阅节点(7)【ROS保姆注释教学】

    文章目录 前言 1.编写发布节点 2.修改CmakeLists 3.运行程序 4.编写订阅节点 5.修改CmakeLists 前言 本系列博客参照<ROS机器人编程原理与应用>一书,搭载平 ...

  5. SLAM导航机器人零基础实战系列:(二)ROS入门——10.在实际机器人上运行ROS高级功能预览...

    SLAM导航机器人零基础实战系列:(二)ROS入门--10.在实际机器人上运行ROS高级功能预览 摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了 ...

  6. ros系统的安装及小海龟运行

    系列文章目录 ros系统的安装 ros系统的安装 系列文章目录 一. VM安装ubuntu 二.unbunt系统的安装 三.ros的部署 3.1软件仓库的导入 3.2安装ros 3.3环境变量的设置以 ...

  7. k8s pod之间不能通信_Kubernetes的工作由两个pod组成(必须在不同的节点上运行并相互通信)...

    我正在尝试创建一个包含两个pod的Kubernetes作业,这两个pod必须在我们的Hybrid集群中的不同节点上进行调度 . 我们的要求是其中一个pod在Windows Server节点上运行而另一 ...

  8. ros 坐标系间位姿变换节点pose2pose,线程处理数据python示例

    ros 坐标系间位姿变换节点pose2pose,线程处理数据python示例 #!/usr/bin/env python # coding=utf-8 #coding:utf-8import rosp ...

  9. Hadoop源码分析笔记(十一):数据节点--数据节点整体运行

    数据节点整体运行 数据节点通过数据节点存储和文件系统数据集,管理着保存在Linux文件系统上的数据块,通过流式接口提供数据块的读.写.替换.复制和校验信息等功能.建立在上述基础上的数据节点,还需要维护 ...

最新文章

  1. html使用element ui_Kendo UI for jQuery使用教程:自定义小部件(二)
  2. 江苏省对口单招计算机原理,江苏省对口单招计算机原理教案
  3. 足不出户,确保交付——独家交付秘籍(第二回)
  4. python网络爬虫(三)数据抓取
  5. 使用displsy:flex + overflow:hidden时子元素被压缩
  6. NYOJ 1272:表达式求值(2016河南省ACM-A)
  7. rhel5编译安装2.6.29.2内核
  8. c++入门 简单语句 空语句 作用域和块 复合语句
  9. 单链表创建以及头插、尾插(二)-(B站)史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】
  10. debian重启ssh服务_Win10自带的ssh客户端key权限设置
  11. Java——entity(实体类)的写法规范
  12. python可视化小案例giao
  13. lawson算法_案例研究:Lawson合并后整合架构的新方法
  14. 体检之一:体检豪华套餐
  15. Apple Watch如何重新配对
  16. 成型滤波器设计matlab,MATLAB+VHDL脉冲成型滤波器的设计 附代码
  17. 固定资产YTD折旧额SQL
  18. C# 开发企业订货系统构架,手机版本订货/订单系统
  19. 机器学习#假设空间与版本空间
  20. python 爬虫 教务系统模拟登陆 并下载课表

热门文章

  1. 泛函分析——内积空间定义的概念
  2. 【python】字符串前加u,r,b,f的含义
  3. 天池比赛——用户情感可视化分析
  4. 浙江大学计算机科学与技术学院导师,浙江大学计算机科学与技术学院导师介绍:杨莹春...
  5. 025 京东网站案例
  6. 自建网站教程!如何用云服务器搭建个人网站?
  7. 3.Linux文件系统
  8. css做八边形图片有边框
  9. C++实现的简单k近邻算法(K-Nearest-Neighbour,K-NN)
  10. 米氏散射多次散射计算程序