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"/><span style="color: #0000ff"><</span><span style="color: #800000">node </span><span style="color: #ff0000">pkg</span><span style="color: #0000ff">="nodelet"</span><span style="color: #ff0000"> type</span><span style="color: #0000ff">="nodelet"</span><span style="color: #ff0000"> name</span><span style="color: #0000ff">="Plus"</span><span style="color: #ff0000"> args</span><span style="color: #0000ff">="load nodelet_tutorial_math/Plus standalone_nodelet"</span><span style="color: #ff0000"> output</span><span style="color: #0000ff">="screen"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">remap </span><span style="color: #ff0000">from</span><span style="color: #0000ff">="/Plus/out"</span><span style="color: #ff0000"> to</span><span style="color: #0000ff">="Plus2/in"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"></</span><span style="color: #800000">node</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">rosparam </span><span style="color: #ff0000">param</span><span style="color: #0000ff">="Plus2"</span><span style="color: #ff0000"> file</span><span style="color: #0000ff">="$(find nodelet_tutorial_math)/plus_default.yaml"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">node </span><span style="color: #ff0000">pkg</span><span style="color: #0000ff">="nodelet"</span><span style="color: #ff0000"> type</span><span style="color: #0000ff">="nodelet"</span><span style="color: #ff0000"> name</span><span style="color: #0000ff">="Plus2"</span><span style="color: #ff0000"> args</span><span style="color: #0000ff">="load nodelet_tutorial_math/Plus standalone_nodelet"</span><span style="color: #ff0000"> output</span><span style="color: #0000ff">="screen"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">rosparam </span><span style="color: #ff0000">file</span><span style="color: #0000ff">="$(find nodelet_tutorial_math)/plus_default.yaml"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"></</span><span style="color: #800000">node</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">node </span><span style="color: #ff0000">pkg</span><span style="color: #0000ff">="nodelet"</span><span style="color: #ff0000"> type</span><span style="color: #0000ff">="nodelet"</span><span style="color: #ff0000"> name</span><span style="color: #0000ff">="Plus3"</span><span style="color: #ff0000"> args</span><span style="color: #0000ff">="standalone nodelet_tutorial_math/Plus"</span><span style="color: #ff0000"> output</span><span style="color: #0000ff">="screen"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">param </span><span style="color: #ff0000">name</span><span style="color: #0000ff">="value"</span><span style="color: #ff0000"> type</span><span style="color: #0000ff">="double"</span><span style="color: #ff0000"> value</span><span style="color: #0000ff">="2.5"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">remap </span><span style="color: #ff0000">from</span><span style="color: #0000ff">="Plus3/in"</span><span style="color: #ff0000"> to</span><span style="color: #0000ff">="Plus2/out"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"></</span><span style="color: #800000">node</span><span style="color: #0000ff">></span>