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
使用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_()
{} 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", );
sub = private_nh.subscribe("in", , &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>
参考:
ROS nodelet的使用的更多相关文章
- ros nodelet 使用
ros nodelet能够加快高吞吐量程序运行速度比如点云 基本入门程序可以看 http://wiki.ros.org/nodelet/Tutorials/Porting%20nodes%20to%2 ...
- ROS nodelet 理解记录
发现网上许多的例子都是基于官网的例子,还需要做进一步的说明. 1. NODELET_DEBUG 是无法打印的信息的,需要使用NODELET_INFO NODELET_DEBUG("Addin ...
- 使用yocs_cmd_vel_mux进行机器人速度控制切换
cmd_vel_mux包从名字就可以推测出它的用途,即进行速度的选择(In electronics, a multiplexer or mux is a device that selects one ...
- ubuntu14.04 and ros indigo install kinect driver--16
摘要: 原创博客:转载请表明出处:http://www.cnblogs.com/zxouxuewei/ 今日多次测设ros indigo install kinect driver ,提示各种失败,然 ...
- ROS Node/Topic/Message/Service的一些问题
1.Node http://blog.exbot.net/archives/1412 (摘自老王说ros) node干的什么活?callback queue里的活.这个callback queue里的 ...
- ZED 相机 && ORB-SLAM2安装环境配置与ROS下的调试
注:1. 对某些地方进行了更新(红色标注),以方便进行配置. 2. ZED ROS Wrapper官方github已经更新,根据描述新的Wrapper可能已经不适用与Ros Indigo了,如果大家想 ...
- (一)ROS系统入门 Getting Started with ROS 以Kinetic为主更新 附课件PPT
ROS机器人程序设计(原书第2版)补充资料 教案1 ROS Kinetic系统入门 ROS Kinetic在Ubuntu 16.04.01 安装可参考:http://blog.csdn.net/zha ...
- 奥比中光Orbbec Astra Pro RGBD 3D视觉传感器在ROS(indigo和kinetic)使用说明 rgb depth同时显示
Orbbec Astra Pro传感器在ROS(indigo和kinetic)使用说明 rgb depth同时显示 这款摄像头使用uvc输入彩色信息,需要libuvc和libuvc_ros这样才能在R ...
- ROS机器人程序设计(原书第2版)补充资料 (贰) 第二章 ROS系统架构及概念
ROS机器人程序设计(原书第2版)补充资料 (贰) 第二章 ROS系统架构及概念 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 由于工作事 ...
随机推荐
- POJ 3280 Cheapest Palindrome【DP】
题意:对一个字符串进行插入删除等操作使其变成一个回文串,但是对于每个字符的操作消耗是不同的.求最小消耗. 思路: 我们定义dp [ i ] [ j ] 为区间 i 到 j 变成回文的最小代价.那么对于 ...
- python学习之集合
集合(set)是一个无序的不重复元素序列. 可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典. 创建格 ...
- Python debug 调试;
F9:执行跳到下一个断点 F8:执行下一步 F7:进入函数
- Linux salt
引用自:https://blog.csdn.net/langsim/article/details/43939295 Saltstack介绍 Saltstack是一个新的基础设施管理工具.目前处于快速 ...
- 010 处理模型数据(ModelAndView,Map Model,@SessionAttributes)
1.处理数据模型 SpringMVC提供了几种途径出书模型数据 二:ModelAndView 1.介绍 2.index <%@ page language="java" co ...
- 关于Jar包 和 war
Jar包: 别人写好的java类打包,将这些jar包引入你的项目中,然后就可以直接使用这些jar包中的类和属性以及方法,一般都会放在lib目录下 war 是web项目
- moodle3.15+,mysql完全的Unicode支持配置
https://docs.moodle.org/dev/Releases,moodle个版本升级的主要内容和改动 在windows是mysql.ini linux 下是mysql.cnf 因为MyS ...
- python爬虫学习(一):BeautifulSoup库基础及一般元素提取方法
最近在看爬虫相关的东西,一方面是兴趣,另一方面也是借学习爬虫练习python的使用,推荐一个很好的入门教程:中国大学MOOC的<python网络爬虫与信息提取>,是由北京理工的副教授嵩天老 ...
- Flutter中打造多行列列表GridView组件的使用
GridView组件.一个可滚动的二维空间数组. 在使用无限加载滚动列表的时候,最先使用的还是ListView组件.但若是要一行显示2列或者更多列的滚动列表,GridView组件更为方便.如下 在向服 ...
- Metasploit AFP信息获取模块afp_server_info
Metasploit AFP信息获取模块afp_server_info AFP服务默认端口为548或者427.通过扫描该端口信息,afp_server_info模块可以获取AFP服务相关信息.这些 ...