ROS-7-Nodelet

  1. nodelet使用背景
    ROS是一种基于分布式网络通讯的操作系统,整个机器人控制系统是由一个Master主节点和若干个功能相对独立的Node子节点组成,这也是ROS系统最主要的特点就是分布式以及模块化的设计。在ROS通讯过程中Master节点存储着各个子节点的topics和services的注册信息,每个功能节点在请求服务之前先向主节点进行注册,然后节点之间就可以直接进行信息传递。ROS的底层通信都是基于XML-RPC协议实现的。
    在这里插入图片描述
    XML-RPC协议是XML Remote Prodecure Call的简称,是一种远程过程调用的分布式网络协议。它允许跨平台的软件间通过发送和接收XML格式的消息进行远程调用,即允许不同的操作系统、不同环境中的程序实现基于Internet过程调用的规范和一系列方法的实现。这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式。
    在这里插入图片描述
    XML-RPC的远程调用过程为:首先客户端发起请求后需要按照协议格式对请求信息进行填充;填充完毕以后XML格式的信息会被转化为数据流,通过传输层进行传输。服务端收到客户端发出来的数据流,会将其再转化为XML格式的信息,然后按照XML-RPC协议获取客户端的请求信息,并对请求信息进行处理,处理完毕以后将反馈信息发送给客户端。

以XML-RPC的方式传输数据存在一定的延时和阻塞。在数据量小、频率低的情况下,传输耗费的时间可以忽略不计。但当传输图像流,点云等数据量较大的消息,或者执行有一定的实时性要求的任务时,因传输而耗费的时间就不得不考虑。Nodelet包就是为改善这一状况设计的,它提供一种方法,可以让多个算法程序在一个进程中用 shared_ptr 实现零拷贝通信(zero copy transport),以降低因为传输大数据而损耗的时间。简单讲就是可以将多个node捆绑在一起管理,使得同一个manager里面的topic的数据传输更快。
 2. 使用nodelet
 2.1首先安装ros-$ROS_DISTRO-nodelet-tutorial-math,之后运行roscore
 nodelet有以下用法:
 nodelet manager用法:启动一个manager
 nodelet load pkg/type manager 向manager下载nodelet
 nodelet standalone pkg/type 在一个standalone node里启动一个pkg/type的nodelet
nodelet unload name manager 从manager中依靠名字来剔除nodelet 
 2.2 启动nodelet manager.
 nodelet manager听取ROS 服务,并且当nodelet动态下载到manager中时它可以进行执行,这里的manager只是个manager,但是大多数时候manger将会加入正在运行的节点来管理他们。如下面的代码所示:

rosrun nodelet nodelet manager __name:=nodelet_manager//运行nodelet package下面的nodelet,并将manager重命名为nodelet_manager

2.3 将nodelet 动态下载到 manager中
 我们使用工具nodelet executable, 如下面代码所示,它将会联系nodelet_manager并且让它实例化一个pkg/type 类型的nodelet_tutorial_math/Plus nodelet,重命名为nodelet1, nodelet1/in话题重映射为foo, value值设为1.1.

rosrun nodelet nodelet load nodelet_tutorial_math/Plus nodelet_manager __name:=nodelet1 nodelet1/in:=foo _value:=1.1

输入rostopic list 查看topic, 输入rosnode list 查看正在运行的节点:

  1. 在/foo话题上发布消息,相当于给上面的nodelet1/in 重新赋值5.0
rostopic pub /foo std_msgs/Float64 5.0 -r 10

使用rostopic echo查看out的结果:

rostopic echo /nodelet1/out

可以看出结果为6.1 (5.0+1.1 = 6.1)
输入rqt_graph命令,可以在GUI界面中直观地查看节点间的交互方式
4. 在同一个standalone manager上运行多个nodelets
我们使用如下的launch文件,

<launch>
  <node pkg="nodelet" type="nodelet" name="standalone_nodelet"  args="manager"/>

  <node pkg="nodelet" type="nodelet" name="Plus"
        args="load nodelet_tutorial_math/Plus standalone_nodelet">
    <remap from="/Plus/out" to="remapped_output"/>
  </node>
  <rosparam param="Plus2" file="$(find nodelet_tutorial_math)/plus_default.yaml"/>
  <node pkg="nodelet" type="nodelet" name="Plus2" args="load nodelet_tutorial_math/Plus standalone_nodelet">
    <rosparam file="$(find nodelet_tutorial_math)/plus_default.yaml"/>
  </node>
  <node pkg="nodelet" type="nodelet" name="Plus3" args="standalone nodelet_tutorial_math/Plus">
    <param name="value" type="double" value="2.5"/>
    <remap from="Plus3/in" to="Plus2/out"/>
  </node>
</launch>
<node pkg="nodelet" type="nodelet" name="Plus" args="load nodelet_tutorial_math/Plus standalone_nodelet" output="screen">
    <remap from="/Plus/out" to="Plus2/in"/>
</node>          

<rosparam param="Plus2" file="$(find nodelet_tutorial_math)/plus_default.yaml"/>
<node pkg="nodelet" type="nodelet" name="Plus2" args="load nodelet_tutorial_math/Plus standalone_nodelet" output="screen">
    <rosparam file="$(find nodelet_tutorial_math)/plus_default.yaml"/>
</node>

<node pkg="nodelet" type="nodelet" name="Plus3" args="standalone nodelet_tutorial_math/Plus" output="screen">
    <param name="value" type="double" value="2.5"/>
    <remap from="Plus3/in" to="Plus2/out"/>
</node>

launch文件中使用remap标签将Plus的输出重映射到Plus2的输入,并将Plus2的输出重映射到Plus3的输入上,可以实现叠加功能。

plus_default.yaml中的内容如下,即Plus2节点中的value值为10:
之后我们可以运行这个plus.launch文件,然后再plus的输入端发布数据:

roslaunch nodelet_tutorial_math plus.launch
rostopic pub -r 10 /Plus/in std_msgs/Float64 1.0 

查看echo /Plus2/out可以看出,它的输出为1+10=11;
查看Plus3的输出,11+2.5=13.5
5. 编写一个类型为plus的nodelet
5.1 编写的步骤如下:
add the necessary #includes
get rid of int main()
subclass nodelet::Nodelet(基类nodelet::Nodelet,任何nodelet继承自它可以使用plugin的方式动态加载)
move code from constructor to onInit() (实现onInit纯虚函数,用于初始化)
add the PLUGINLIB_EXPORT_CLASS macro (加入宏,将子类声明为插件类,并编译为动态库)
add <build_depend> and <run_depend> dependencies on nodelet in the package manifest.
add the item in the part of the package manifest
create the .xml file to define the nodelet as a plugin
make the necessary changes to CMakeLists.txt (comment out a rosbuild_add_executable, add a rosbuild_add_library)
5.2 Plus.cpp文件的代码如下:

#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include <ros/ros.h>
#include <std_msgs/Float64.h>
#include <stdio.h>

#include <math.h> //fabs

namespace nodelet_tutorial_math  // The usage of the namespace is a good practice but not mandatory
{

class Plus : public nodelet::Nodelet
{
public:
  Plus(): value_(0)
  {}

private:
  virtual void onInit() //当nodelet插件类被nodelet_manager加载时,nodelet插件类的onInit方法就会被调用,用于初始化插件类
  {
    ros::NodeHandle& private_nh = getPrivateNodeHandle();
    private_nh.getParam("value", value_);//获取NodeHandle的value参数的值
    pub = private_nh.advertise<std_msgs::Float64>("out", 10);将消息广播到out话题上
    sub = private_nh.subscribe("in", 10, &Plus::callback, this);订阅in话题,并对订阅的消息采用callback函数处理
  }

  void callback(const std_msgs::Float64::ConstPtr& input)
  {
    std_msgs::Float64Ptr output(new std_msgs::Float64());
    output->data = input->data + value_; //用新来的数据和默认value来相加,从而更新output
    NODELET_DEBUG("Adding %f to get %f", value_, output->data);
    pub.publish(output);
  }

  ros::Publisher pub;
  ros::Subscriber sub;
  double value_;
};

PLUGINLIB_DECLARE_CLASS(nodelet_tutorial_math, Plus, nodelet_tutorial_math::Plus, nodelet::Nodelet);//注意为了允许类被动态加载,它必须被标记为导出类。这通过特殊宏PLUGINLIB_EXPORT_CLASS/PLUGINLIB_DECLARE_CLASS来完成,宏的参数分别为:pkg, class_name, class_type, base_class_type. 
}

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

...
<build_depend>nodelet</build_depend>
<run_depend>nodelet</run_depend>

<export>
  <nodelet plugin="${prefix}/nodelet_math.xml" />
</export>
...
插件描述文件是一个XML文件,用于存储有关插件的所有重要信息。 它包含有关插件所在的库的信息,插件的名称,插件的类型等 。nodelet_math.xml如下:

相关链接:nodelet的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值