我是靠谱客的博主 香蕉吐司,最近开发中收集的这篇文章主要介绍ROS学习之name(三),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

仅作学习笔记,参考《ROS机器人编程》
一、ROS学习之name(名称)
ROS有一个称为图(graph)的抽象数据类型作为其基本概念。这显示了每个节点的连接关系以及通过箭头表达发送和接收消息(数据)的关系。为此,服务中使用的节点、话题、消息以及ROS中使用的参数都具有唯一的名称(name)。话题名称分为相对的方法、全局方法和私有方法。
以下代码显示了常用的话题的声明。在这里,我们通过修改话题名称来理解名称的用法。

int main(int argc, char **argv) // 节点主函数
{
ros::init(argc, argv, "node1"); // 初始化节点
ros::NodeHandle nh; // 声明节点句柄
// 声明发布者,话题名 = bar
ros::Publisher node1_pub = nh.advertise<std_msg::Int32>("bar", 10);

这里的节点名称是/node1。如果您用一个没有任何字符的相对形式的bar来声明一个发布者,这个话题将和/bar具有相同的名字。如果以如下所示使用斜杠(/)字符用作全局形式,话题名也是/bar。

ros::Publisher node1_pub = nh.advertise<std_msg::Int32>(/bar”, 10);

但是,如果使用波浪号(~)字符将其声明为私有,则话题名称将变为/node1/bar。

ros::Publisher node1_pub = nh.advertise<std_msg::Int32>(~bar”, 10);

如果要运行两个摄像头应该如何做? 简单地两次执行相关节点将导致之前执行的节点因ROS的性质而终止,因为ROS必须具有唯一的名称。用户可以在运行时更改节点的名称,而不需要运行额外的程序或更改源代码。方法包括命名空间(namespace)和重新映射(remapping)。

为了帮助理解,假设有一个虚拟的camera_package。假设执行camera_package功能包的camera_node会运行camera节点,此时的运行方法如下。

$rosrun camera_package camera_node

当该节点将相机的图像值发送给image话题时,可以通过rqt_image_view传送该image话题,如下所示。

$rosrun rqt_imgae_view rqt_imgae_view

现在让我们通过重新映射来修改这些节点的话题值。如果执行如下命令,只有话题名称将被改为/front/image。其中,image是camera_node的话题名,而这些命令是在运行两个节点的同时,顺便修改名称的例子。

$ rosrun camera_package camera_node image:=front/image
$ rosrun rqt_imgae_view rqt_imgae_view image:=front/image

例如,当有前、左、右,三个摄像头,且当多次执行同名的节点时,由于节点名重复,该节点将被重复执行,因此节点会被停止。为了避免这种情况,可以采取用同一个名称运行多个不同的节点的方法。下面的命令示例中,name选项使用了两个下划线(__)。附加地说明,选项__ns、__name、__log、__ip、__hostname和__master是运行节点时使用的特殊选项。我们在话题名称选项中使用了一个下划线(_),如果它是private名称,则在现有名称前加上一个下划线。

$ rosrun camera_package camera_node __name:=front _device:=/dev/video0
$ rosrun camera_package camera_node __name:=left _device:=/dev/video1
$ rosrun camera_package camera_node __name:=right _device:=/dev/video2
$ rosrun rqt_imgae_view rqt_imgae_view

如果想绑定到单一的命名空间,可以如下操作。这样会将指定的节点和话题都绑定到一个命名空间,因此会改变所有的名称。

$ rosrun camera_package camera_node __ns:=back
$ rosrun rqt_imgae_view rqt_imgae_view __ns:=back

上面讲到了名称的多种用法。名称使得整个ROS系统的灵活运转。在本节中,我们通过节点运行命令rosrun了解了修改名称值的方法。同样,可以使用roslaunch,用一次执行来指定它们的选项.
二、关于命名空间:
学过C++或者其他语言应该知道命名空间这个概念(熟悉的std),在ROS里面也有这个概念。一开始接触ROS我只知道不能同时运行两个同名的节点,如果运行同名节点,前一个会被终止。了解了ROS命名空间之后我在知道应该是在同一个命名空间下不能运行两个同名的节点,除非给节点进行一个名字的重映射或者命名空间。
先以小乌龟为例

rosrun turtlesim turtlesim_node 

turtlesim是一个包名,turtlesim_node是执行文件名,可以与节点名相同,也不可以不同。这里的节点名是 /turtlesim。说明可能初始化的时候是这样的,为什么是可能,因为重映射可以改变:

ros::init(argc, argv, "turtlesim");

节点名前面加个“/”,这意味这个节点是全局空间的。另外说下,节点是有类型的,节点的类型就是节点所在包名和可执行文件名的加。一般的定义节点句柄:

ros::NodeHandle n;

NodeHandle是一个类,然后我们实例化的一个对象n.这种情况默认n这个节点是全局命名空间下的。你可以认为"/"这个斜杠就是全局名空间。现在我们来改变这个节点的名空间,通过重映射。
你会发现,这个节点的名变为/my/turtlesim,此时,节点所在的空间发生了变化,我们把这个节点从全局名空间放进了一个/my的名空间下。于是节点内的所有参数,服务,话题也都放在了/my的命名空间下。
你会发现,它所发布的和订阅的话题,服务都在这个名空间,这意味着它现在只会订阅和发布这个名空间下的话题。
这个时候运行rosrun turtlesim turtle_teleop_key ,是不会控制小乌龟的,因为它只会发布/turtel1/cmd_vel话题,不会发布/my/turtel1/cmd_vel。
节点,话题,服务,包括参数都是有名空间的,这个名空间约束着是它们的范围。这个时候你可能会想,那不在一个名空间节点是不是就无法通信了,显然这种想法是错误的,这违背了我们通信的初衷,我们通过重映射和参数服务器,很容易让不同命名空间的节点都能通信。
重映射不仅可以把命名空间改变,还可以将发布的话题给改变(还可改变参数的空间),这样/my空间下的乌龟就可以移动了。当然你也可以直接将这个节点的名空间改为/my,这样他们在同一个命名空间,当然可以直接通信了。

上面说的是全局命名空间,还有一个相对命名空间,/turtle1/cmd_vel就是相对命名空间,它在/my的命名空间下,发布/turtle1/cmd_vel话题,解析器会把它解析成/my/turtle1/cmd_vel话题。发布的/turtle1/cmd_vel话题相对/my空间下是/turtle1/cmd_vel话题,对于全局它是/my/turtle1/cmd_vel话题。第二点参考:https://blog.csdn.net/u014587147/article/details/75647002

最后

以上就是香蕉吐司为你收集整理的ROS学习之name(三)的全部内容,希望文章能够帮你解决ROS学习之name(三)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部