ROS专题----nodelet简明笔记

ROS专题----nodelet简明笔记

------

此页面包含使用nodelet的教程。强烈建议您已经回顾了pluginlib教程做这些教程了。

  1. 运行节点这将显示如何在系统中运行节点。
  2. 将节点移植到节点

来自使用nodelet的其他包/堆栈的教程:

------

$ roslaunch nodelet_tutorial_math plus.launch ... logging to /home/relaybot/.ros/log/7f42ed06-088b-11e7-99c2-70f1a1ca7552/roslaunch-relaybot-desktop-8447.log Checking log directory for disk usage. This may take awhile. Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http://relaybot-desktop:34104/ SUMMARY ======== PARAMETERS  * /Plus2/value: 10  * /Plus3/value: 2.5  * /rosdistro: kinetic  * /rosversion: 1.12.7 NODES   /     Plus (nodelet/nodelet)     Plus2 (nodelet/nodelet)     Plus3 (nodelet/nodelet)     standalone_nodelet (nodelet/nodelet) ROS_MASTER_URI=http://localhost:11311 core service [/rosout] found process[standalone_nodelet-1]: started with pid [8485] process[Plus-2]: started with pid [8486] process[Plus2-3]: started with pid [8487] process[Plus3-4]: started with pid [8488] [ INFO] [1489489721.430571269]: Loading nodelet /Plus of type nodelet_tutorial_math/Plus to manager standalone_nodelet with the following remappings: [ INFO] [1489489721.430679072]: /Plus/out -> /remapped_output [ INFO] [1489489721.439768636]: waitForService: Service [/standalone_nodelet/load_nodelet] has not been advertised, waiting... type is nodelet_tutorial_math/Plus [ INFO] [1489489721.444581734]: Loading nodelet /Plus2 of type nodelet_tutorial_math/Plus to manager standalone_nodelet with the following remappings: [ INFO] [1489489721.451421641]: waitForService: Service [/standalone_nodelet/load_nodelet] has not been advertised, waiting... [ INFO] [1489489721.872693083]: Initializing nodelet with 4 worker threads. [ INFO] [1489489721.886004455]: waitForService: Service [/standalone_nodelet/load_nodelet] is now available. [ INFO] [1489489721.891109441]: waitForService: Service [/standalone_nodelet/load_nodelet] is now available.

------

#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
{

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

private:
  virtual void 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);
}

------

<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="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" 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>

------

运行节点

建立

我们假设nodelet_tutorial_math已经被编译并且roscore正在运行。

rosmake nodelet_tutorial_math
roscore

打开经理

一个nodelet会内运行NodeletManager。节点管理器是一个c ++程序,它被设置为监听ROS服务,并且是动态加载节点的可执行文件。在这种情况下,我们将运行一个独立的管理器,但在许多情况下,这些管理器将嵌入在运行的节点中。

rosrun nodelet nodelet manager __name:= nodelet_manager

为了清楚起见,我们已将此节点重命名为nodelet_manager。

启动节点

Nodelet也通过使用nodelet可执行文件远程启动。

这个代码做什么:这里调用的nodelet可执行文件将联系nodelet_manager并要求它实例化nodelet_tutorial_math / Plus节点的一个实例。它将通过名称nodelet1,以及任何重新映射,如果应用于nodelet中的代码。参数也出现在右边的命名空间中。

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

如果你做一个rostopic列表,你会看到:

/ foo
/ nodelet1 / out

如果你看看rosnode列表的输出,你会看到:

/ nodelet1
/ nodelet_manager

测试操作

在单独的端子运行:

rostopic pub / foo std_msgs / Float64 5.0 -r 10
rostopic echo / nodelet1 / out

将显示:6.1是5.0 + 1.1。

在roslaunch文件中使用

下面是一个示例启动文件(在nodelet_tutorial_math pkg 中可用),其中多个nodelet在同一独立管理器上运行:

<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>

------

将节点移植到nodelet

工作进行中...(参见nodelet_tutorial_math一个例子)

  • 添加必要的#includes
  • 去掉int main()
  • 子类nodelet :: Nodelet
  • 将代码从构造函数移动到onInit()
  • 添加PLUGINLIB_EXPORT_CLASS宏
  • 在包清单中对节点添加<build_depend>和<run_depend>依赖项。
  • 请在包清单的<export>部分中添加<nodelet>项
  • 创建.xml文件以将nodelet定义为插件
  • 对CMakeLists.txt进行必要的更改(注释掉一个rosbuild_add_executable,添加一个rosbuild_add_library)

最小节点

MyNodeletClass.h

#include <nodelet / nodelet.h>

命名空间example_pkg
{

    class MyNodeletClass:public nodelet :: Nodelet
    {
        上市:
            virtual void onInit();
    };

}}

MyNodeletClass.cpp

//这应该是在实现(.cpp文件)
#include <pluginlib / class_list_macros.h>

//仔细观察大小写
PLUGINLIB_EXPORT_CLASS(example_pkg :: MyNodeletClass,nodelet :: Nodelet) 

命名空间example_pkg
{
    void MyNodeletClass :: onInit() 
    {
        NODELET_DEBUG(“正在初始化nodelet ...”);
    }}
}}

nodelet_plugins.xml

<library path =“lib / libMyNodeletClass”>
  <class name =“example_pkg / MyNodeletClass”type =“example_pkg :: MyNodeletClass”base_class_type =“nodelet :: Nodelet”>
  <description>
  这是我的节点。
  </ description>
  </ class>
</ library>

package.xml

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

mynodelet.launch

<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>

------

nodelet

高水平

Nodelets旨在提供一种在单个进程中在单个机器上运行多个算法的方法,而不会在传递消息进程时产生复制成本。roscpp具有在同一节点内的发布和订阅调用之间进行零拷贝指针传递的优化。为了做到这一点,nodelet允许将类动态加载到同一个节点,然而它们提供了简单的单独命名空间,使得尽管nodelet在同一个进程中,它仍然像一个独立的节点。这进一步扩展了,它在运行时使用pluginlib是动态可加载的。

应用程序

  • 高吞吐量数据流可以由许多节点组成,然后加载到同一进程,以避免复制和网络流量。

设计目标

  • 使用现有的C ++ ROS接口。
  • 允许节点之间的数据的零拷贝传递
  • 动态加载为插件以打破构建时间依赖性
  • 位置透明,除了性能改进
  • 在节点或节点中编写代码将有最小的不同。

技术

  • 定义将用于动态加载的基类nodelet :: Nodelet。所有nodelet都将继承这个基类,并且可以使用pluginlib进行动态加载。
  • 它将提供命名空间,自动重映射参数和参数,就像它们是第一个类节点一样。
  • 将有一个nodelet_manager进程,一个或多个nodelet可以加载到其中。它们之间的任何通信都可以使用带有boost共享指针的零拷贝roscpp发布调用。

基本用法

节点使用:
nodelet加载pkg /类型管理器 - 在管理器管理器上启动pkg / Type类型的节点
nodelet standalone pkg / Type  - 在独立节点中启动pkg / Type类型的节点
nodelet unload name manager  - 按名称从manager卸载nodelet节点
nodelet管理器 - 启动节点管理器节点

对于命令行和启动文件示例,请参阅本教程运行节点

API

Nodelet基类:

nodelet :: Nodelet

公共方法:

切换行号

   1 Nodelet()//动态加载时使用的默认构造函数
   2 void  init(const  std :: string&name,const  ros :: M_string&remapping_args,const  std :: vector < std :: string >&my_argv); //这个方法是一个nodelet应该如何启动。参数是管理器启动节点所需的参数。这将初始化nodelet基类,然后调用子类的onInit()方法。
   3 

子类中使用的受保护成员和方法:

切换行号

   1 std :: string              getName()//获取nodelet的名称
   2 ros :: NodeHandle&         getNodeHandle()//获取节点句柄(提供此节点的自定义重映射和名称)
   3 ros :: NodeHandle&         getPrivateNodeHandle()//获取私有节点句柄(在其私有命名空间中提供此节点的自定义重映射)
   4 ros :: NodeHandle&         getMTNodeHandle()//使用Multi Threaded回调队列获取节点句柄。(提供此节点的自定义重映射和名称)
   5 ros :: NodeHandle&         getMTPrivateNodeHandle()//使用多线程回调队列获取私有节点句柄。(在其私有命名空间中提供此节点定制重新映射)
   6 ros :: CallbackQueue&      getMTCallbackQueue()//获取回调队列(从管理器可用线程池)
   7 std :: vector < std :: string > getMyArgv()//获取命令行参数到剥离ROS和nodelet特定args的nodelet。  
   8 

用于在子类中启动ROS API的初始化方法:

切换行号

   1 virtual  void  onInit()= 0  // Virtual,并且必须被子类覆盖。必须将ROS基础结构的所有初始化都放入此函数中。
   2 

NODELET ROSCONSOLE MACROS

这些是rosconsole宏周围的节点感知包装器。它们包括详细程度级别DEBUG,INFO,WARN,ERROR和FATAL。这些宏只会在nodelet方法中编译。

它们通过在运行的nodelet的名称中设置命名的日志记录器来操作,以便您可以 区分在运行的两个相同类型的节点的输出 同一位经理。他们也有优势,你可以转一个具体nodelet进入调试,而不是所有特定类型的节点。

切换行号

   1 #包括“nodelet / nodelet.h”
   2 
   3 // ...在一个nodelet方法
   4 NODELET_DEBUG(“ 我的调试语句”)
   5 NODELET_DEBUG_STREAM(“ 我的调试语句” <<(double)1.0)
   6 NODELET_DEBUG_COND(1 == 1,“ my debug_statement ”)
   7 NODELET_DEBUG_STREAM_COND(1 == 1,“ 我的调试语句” <<(double)1.0)

从Nodelet发布

如果希望no-copy pub / sub工作,您必须将消息发布为shared_ptr。有关更多详细信息,请参阅roscpp / Overview / Publishers和订阅者#Intraprocess_Publishing

线程模型

节点管理器具有线程池,该线程池在管理器内运行的所有节点之间共享。这由参数“num_worker_threads”设置。

在nodelet中运行的代码中有两种可能的线程API。默认线程模型有一个线程用于所有回调。还有一个多线程API。

onInit

这个方法在init上调用,不应该阻塞或做重要的工作。

单线程API

使用方法getNodeHandle()和getPrivateNodeHandle()将保证所有回调串行到达。

多线程API

使用方法getMTNodeHandle()和getMTPrivateNodeHandle()回调将分布在管理器的线程池中。

其他线程

它是节点创建自己的线程进行操作的有效操作。这些线程应该在析构函数中正确清理。

线程共享

所有nodelet共享管理器的线程池。如果nodelet阻塞线程,它们可能会阻止其他nodelet获得回调。确保管理器配置了足够的线程以防止阻止。注意:即使单个线程的节点句柄也可以每个节点使用池的1个线程。

------

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大数据文摘

业界 | 大乌龙,俄罗斯最先进的机器人里头竟然是个小伙子

动动退,扭扭腰~~~你看现在的机器人多么自然,是不是边上的主持人和它比起来更像机器人。

9230
来自专栏AI科技评论

大讲堂 | 面向实际应用的欠驱动机械手设计

机械手作为机器人的末端执行器,对机器人实际的操作和抓取性能有着决定性作用。实际上,集成在机器人上承担真实环境操作任务的机械手和实验室环境的机械手在设计和功能上的...

10130
来自专栏量子位

当一盆植物在MIT成了精,不,它只是成了机器人

这些伶俐的反应,被MIT和Parsons设计学院的研究人员地利用起来,才有了机器人 x 植物这样优雅的存在。

12640
来自专栏华章科技

机器人行走背后的机械原理动画,一文看透

导读:波士顿动力机器人Atlas如今已经能跑能跳,还能躲避障碍。人形机器人一直是AI行业的研发热点,如果想让人形机器人动起来,就得先了解一下动作背后的机械原理。

23430
来自专栏大数据文摘

学界 | 伯克利最新:基于视觉模型强化学习的通用机器人

有时候,只要看一眼,有些天分的人就能进行模仿。用学术一点的话说就是:只需少量的明确监督和反馈,人类就可以通过简单的交互和对世界的生理感知,来学习各种运动技能。

16720
来自专栏量子位

亚马逊自动化仓库事故,机器人失手戳破有毒喷雾,24名工人被送医院

昨晚(12月5日),亚马逊自动化仓库发生机器人事故,造成24名员工直接受伤被送医院,1名员工进重症监护室,50多名员工受影响。

9830
来自专栏钱塘大数据

2018年智能机器人研究报告发布(附PDF)

近二十年来,互联网的发展带动了一系列网络延展科技的发展,给人们的生活带来了翻天覆地的变化。未来互联网将向物联网发展,而在物联网的时代,RT(Robotics T...

24710
来自专栏大数据文摘

快讯 | 日本这家全是机器人的咖啡馆,给残疾人创造了新岗位

机器将大规模抢走人类工作岗位的言论在日常生活中并不少见。所以目前来说,人与机器平等的相处的想法似乎只存在于科幻小说中。毕竟,这个时代,人与自然都不能和谐的相处,...

10730
来自专栏ATYUN订阅号

谷歌教机器人通过与环境的交互来识别物体

谷歌希望使AI系统至少在对象识别和感知方面,能像儿童那样思考。在论文“Grasp2Vec: Learning Object Representations fr...

10620
来自专栏AI研习社

明晚20点大讲堂 | 面向实际应用的欠驱动机械手设计

机械手作为机器人的末端执行器,对机器人实际的操作和抓取性能有着决定性作用。实际上,集成在机器人上承担真实环境操作任务的机械手和实验室环境的机械手在设计和功能上的...

14140

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励