转自https://www.ncnynl.com/archives/201702/1324.html
ROS是以一种分布式网络通讯的操作系统,它是以master为中心构建的hybrid P2P网络,节点之间的信息传递时会存在一定的时延和阻塞,nodelet就是为了解决这一问题,提供在算法之间具有零拷贝传输的相同进程中运行多个算法的方式。
使用方法
定义将用于动态加载的基类nodelet :: Nodelet。
所有nodelet都将继承这个基类,并且可以使用pluginlib进行动态加载。
它将提供命名空间,自动重映射参数和参数,就像它们是第一个类节点一样。
将有一个nodelet_manager进程,一个或多个nodelet可以加载到其中。
它们之间的任何通信都可以使用带有boost共享指针的零拷贝roscpp发布调用。
nodelet usage
nodelet usage:
nodelet load pkg/Type manager - 在管理器管理器上启动pkg / Type类型的节点
nodelet standalone pkg/Type - 在独立节点中启动pkg / Type类型的节点
nodelet unload name manager - 按名称从manager卸载nodelet节点
nodelet manager - 启动节点管理器节点
API
公共方法:
//动态加载时使用的默认构造函数
Nodelet()
//参数是管理器启动节点所需的参数。这将初始化nodelet基类,然后调用子类的onInit()方法。
void init (const std::string& name, const ros::M_string& remapping_args, const std::vector<std::string>& my_argv);
子类中使用的受保护成员和方法:
std::string getName() //获取节点名称
ros::NodeHandle& getNodeHandle () // 获取节点句柄
ros::NodeHandle& getPrivateNodeHandle () //获取私有节点句柄(在其私有名称空间中提供此nodelets自定义重映射)
ros::NodeHandle& getMTNodeHandle () // 使用Multi Threaded获取节点句柄
ros::NodeHandle& getMTPrivateNodeHandle () //使用Multi Threaded回调队列获取私有节点句柄。 (在其私有命名空间中提供此nodelets自定义重映射)
ros::CallbackQueue& getMTCallbackQueue () // 获取回调队列(可从管理器获取线程池)。
std::vector<std::string> getMyArgv() //获取分离了ROS和nodelet特定args的nodelet命令行参数。
子类中启动ROS API的初始化方法:
virtual void onInit () = 0 //Virtual and must be overridden by subclass. All initialization of the ROS infrastructure must be put into this function.
NODELET ROSCONSOLE宏
- 这些Nodelet封装是rosconsole宏。
- 它们包括详细程度级别DEBUG,INFO,WARN,ERROR和FATAL。
- 这些宏只会在nodelet方法中编译。
- 它们通过在运行的nodelet名称中设置命名的日志记录器来操作,以便您可以区分在运行的同一管理器下的两个相同类型的节点的输出。
- 他们也有优势,你可以转一个具体nodelet进入调试,而不是所有特定类型的节点。
#include "nodelet/nodelet.h"
//... inside a nodelet method
NODELET_DEBUG("My debug statement")
NODELET_DEBUG_STREAM("my debug statement " << (double) 1.0)
NODELET_DEBUG_COND( 1 == 1, "my debug_statement")
NODELET_DEBUG_STREAM_COND( 1 == 1, "my debug statement " << (double) 1.0)
从Nodelet发布
如果希望no-copy pub / sub工作,必须将消息发布为shared_ptr。
线程模型
节点管理器具有线程池,该线程池在管理器内运行的所有节点之间共享。这由参数“num_worker_threads”设置。
在nodelet中运行的代码中有两种可能的线程API。默认线程模型有一个线程用于所有回调。还有一个多线程API。
onInit
这个方法在init上调用,不应该阻塞或做重要的工作。
单线程API
使用方法getNodeHandle()和getPrivateNodeHandle()将保证所有回调串行到达。
多线程API
使用方法getMTNodeHandle()和getMTPrivateNodeHandle()回调将分布在管理器的线程池中。
其他线程
它是节点创建自己的线程进行操作的有效操作。这些线程应该在析构函数中正确清理。
线程共享
所有nodelet共享管理器的线程池。如果nodelet阻塞线程,它们可能会阻止其他nodelet获得回调。确保管理器配置了足够的线程以防止阻止。注意:即使单个线程的节点句柄也可以每个节点使用池的1个线程。