zoukankan      html  css  js  c++  java
  • ROS 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的数据传输更快。    

     

     运行nodelet 

      nodelet用法:

    nodelet manager               - Launch a nodelet manager node.  启动一个manager
    nodelet load pkg/Type manager - Launch a nodelet of type pkg/Type on manager manager. 向manager中加载nodelet
    nodelet standalone pkg/Type - Launch a nodelet of type pkg/Type in a standalone node.
    nodelet unload name manager - Unload a nodelet a nodelet by name from manager. 从manager中移除nodelet

      下面看一个简单的nodelet例子,程序会将内部变量value加上输入in的值,然后再发布到out话题上。首先在终端中运行roscore打开ROS master节点,然后输入下面指令开启一个名字为nodelet_manager的manager节点(A nodelet will be run inside a NodeletManager)

    rosrun nodelet nodelet manager __name:=nodelet_manager

      注意rosrun命令中可以显式设置节点的名称,语法为:rosrun package-name executable-name __name:=node-name  这种方法将使用node-name参数给出的名称覆盖节点的默认名。

      然后向创建的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查看当前运行的节点:

      下面我们在foo话题上发布消息,相当于给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界面中直观地查看节点间的交互方式 :

    rqt_graph 

      也可以在roslaunch文件中使用nodelet. 下面的例子中先创建一个名为standalone_nodelet的manager,然后向其中加载Plus和Plus2这两个nodelet节点:

    <launch>
        <node pkg="nodelet" type="nodelet" name="standalone_nodelet"  args="manager" output="screen"/>
    
        <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>

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

      plus_default.yaml中的内容如下,即Plus2节点中的value值为10:

    value: 10

      下面运行plus.launch文件:

    roslaunch nodelet_tutorial_math plus.launch

      然后在Plus的输入端发布数据:

    rostopic pub -r 10 /Plus/in std_msgs/Float64 1.0 

      查看Plus2的输出(1+10=11):

      查看Plus3的输出(11+2.5=13.5):

       使用rqt_graph命令查看节点:

     

     

     编写nodelet 

       编写一个nodelet(nodelet基于pluginlib插件机制)的步骤如下:

    • 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 <nodelet> item in the <export> part of the package manifest

    • create the .xml file to define the nodelet as a plugin
    • make the necessary changes to CMakeLists.txt

      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_);
        pub = private_nh.advertise<std_msgs::Float64>("out", 10);
        sub = private_nh.subscribe("in", 10, &Plus::callback, this);
      }
    
      void callback(const std_msgs::Float64::ConstPtr& input)
      {
        std_msgs::Float64Ptr output(new std_msgs::Float64());
        output->data = input->data + value_;
        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来完成,通常放在导出类的.cpp文件的末尾。 宏的参数分别为: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如下:

    <library path="lib/libnodelet_math">
      <class name="nodelet_tutorial_math/Plus" type="nodelet_tutorial_math::Plus" base_class_type="nodelet::Nodelet">
        <description> 
          A node to add a value and republish.
        </description>
      </class>
    </library>

     

    参考: 

    nodelet

    ROS中nodelet的使用

    ROS nodelet 使用详解

    ROS与C++入门教程-nodelet-介绍

    nodelet的使用方法以及传输时间测试

    ROS nodelet-----编写一个nodelet插件

  • 相关阅读:
    React全家桶+AntD 共享单车后台管理系统开发
    eclipse中通过Properties Editor插件查看配置文件中Unicode内容
    修改eclipse的编码格式
    后端接收前端数据中文乱码解决方案
    MySQL基础
    wordpress个人常用标签调用
    4gl游标cursor
    尝试写一写4gl与4fd
    foreach循環體控制
    保护wordpress后台登录地址
  • 原文地址:https://www.cnblogs.com/21207-iHome/p/8213411.html
Copyright © 2011-2022 走看看