当前位置:   article > 正文

ROS之命名空间_ros命名空间

ros命名空间

转载自:https://blog.csdn.net/u014587147/article/details/75647002

ROS之命名空间

小菜虎 2017-07-21 17:02:24 7143 收藏 47

分类专栏: ROS 文章标签: ros 命名空间 参数 重映射

最后发布:2017-07-21 17:02:24首次发布:2017-07-21 17:02:24

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/u014587147/article/details/75647002

版权

已经学ROS快两个月了,一开始对ROS 命名空间,参数,参数服务器,重映射没认真看,后来发现很重要,它是学习ROS代码的基础。我们都知道ros以topic通信,但是只靠topic通信是远远不够的,于是使用客服端服务器、actionlib、参数服务器来补充,这几种都是通信的机制。但还不够,为了方便又加入了命名空间,重映射。只有清楚了这些,其实才算对ros有了初步了解,下面的几个文章我将分别介绍。

在介绍之前,我先抱怨一下,对于只学过C语言的我,没有写过什么项目,然后自己学习ROS,简直痛苦。想找几个资料,英文的根本看不懂,四级都没过,找中文的基本都是直译过来的,而且大多数人的理解,或多或少的都有点错误,当然,我的理解应该有点错误的,希望明白之人能指出,感激不尽。

在C++中的命名空间,using namespace std,std就是名空间,这里的命名空间跟它差不多,但是比它更多,一层嵌套一层,用的特别灵活。先举个简单的例子,然后细说。

我们先运行一个小乌龟:

 

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话题。

接下来我们看看节点句柄的构造函数,也可以跳过:

 

  1. namespace ros
  2. {
  3. class NodeHandleBackingCollection;
  4. /**
  5. * \brief roscpp's interface for creating subscribers, publishers, etc.
  6. *
  7. * This class is used for writing nodes. It provides a RAII interface
  8. * to this process' node, in that when the first NodeHandle is
  9. * created, it instantiates everything necessary for this node, and
  10. * when the last NodeHandle goes out of scope it shuts down the node.
  11. *
  12. * NodeHandle uses reference counting internally, and copying a
  13. * NodeHandle is very lightweight.
  14. *
  15. * You must call one of the ros::init functions prior to instantiating
  16. * this class.
  17. *
  18. * The most widely used methods are:
  19. * - Setup:
  20. * - ros::init()
  21. * - Publish / subscribe messaging:
  22. * - advertise()
  23. * - subscribe()
  24. * - RPC services:
  25. * - advertiseService()
  26. * - serviceClient()
  27. * - ros::service::call()
  28. * - Parameters:
  29. * - getParam()
  30. * - setParam()
  31. */
  32. class ROSCPP_DECL NodeHandle
  33. {
  34. public:
  35. /**
  36. * \brief Constructor
  37. *
  38. * When a NodeHandle is constructed, it checks to see if the global
  39. * node state has already been started. If so, it increments a
  40. * global reference count. If not, it starts the node with
  41. * ros::start() and sets the reference count to 1.
  42. *
  43. * \param ns Namespace for this NodeHandle. This acts in addition to any namespace assigned to this ROS node.
  44. * eg. If the node's namespace is "/a" and the namespace passed in here is "b", all
  45. * topics/services/parameters will be prefixed with "/a/b/"
  46. * \param remappings Remappings for this NodeHandle.
  47. * \throws InvalidNameException if the namespace is not a valid graph resource name
  48. */
  49. NodeHandle(const std::string& ns = std::string(), const M_string& remappings = M_string());
  50. NodeHandle(const NodeHandle& rhs);
  51. NodeHandle(const NodeHandle& parent, const std::string& ns);
  52. NodeHandle(const NodeHandle& parent, const std::string& ns, const M_string& remappings);
  53. ~NodeHandle();
  54. }


是不是发现他有多个构造函数,

 

 

ros::init(argc, argv, "my_node_name");
ros::NodeHandle nh("/my_node_handle_namespace");

我们创建节点句柄nh时,指明了它的命名空间,所以nh的命名空间为/my_node_handle_namespace,

 

所以这个节点里的所有的参数,话题前面都应该有/my_node_handle_namespace

最后一种命名空间是私有命名空间,私有名称,以一个波浪字符(~)开始。和相对名称一样,私有名称并不能完全确定它们自身所在的命名空间,而是需要ROS 客户端库将这个名称解析为一个全局名称。与相对名称的主要差别在于,私有名称不是用当前默认命名空间,而是用的它们节点名称作为命名空间。

 

ros::init(argc, argv, "my_node_name");
ros::NodeHandle nh1("~");
ros::NodeHandle nh2("~foo");
 ros::Subscriber sub1 = nh1.subscribe("my_private_topic", ...);
 ros::Subscriber sub2 = nh2.subscribe("my_private_topic", ...);

sub1订阅的话题是my_node_name/my_private_topic

 

sub2订阅的话题是my_node_name/foo/my_private_topic

到这里,我相信大家对命名空间似懂非懂,这个东西到底是干什么的。如果你懂上面说的东西,接下来,看看参数的使用,似乎就懂命名空间到底是干什么的了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/999816
推荐阅读
相关标签
  

闽ICP备14008679号