本章将掌握三种基本计算图源和一种其他的计算图源的来历,查看方式以及优缺点对比等。
介绍
前文给节点命名(“hello_ros”和"publish_velocity")以及给话题命名(“turtle1/cmd_vel”和“turtle1/pose”)等的都是计算图源名称的例子。
接下来一起看看不同的计算图源名称。
不同的计算图源
node、topic、service、参数等统称计算图源。而每个计算图源由一个叫计算图源名称(graph resource name)的短字符串标识。
事实上,计算图源名称在 ROS 命令行和代码中是广泛存在的,前面我们已经多次接触它们。例如,前面学习的 rosnode info 命令行工具和 ros::init 函数都将节点名作为其参数,rostopic echo 命令行工具和 ros::Publisher 构造函数则都要求提供话题名作为参数,这些都是计算图源名称的具体实例
全局名称
例如我们已经遇到过的:
/teleop_turtle
/turtlesim
/turtle1/cmd_vel
/turtle1/pose
/run_id
/count_and_log/set_logger_level
- “/”表示全局名称。
- 每个斜杠代表以及命名空间
- 描述资源本身的基本名称(base name)。上述的cmd_vel、pose等都是。
- 它在任何地方都可以使用(包括但不限于代码、命令行工具、图形界面)。
- 有明确的含义,不存在二义性。
优缺点
- 为了指明一个计算图源,需要列出完整的所属空间,尤其是命名空间层很多。
- 除去使人更容易追踪变量外,几乎没有优点,相对名称和私有名称似乎更好用。
相对名称
让ROS为计算图源提供一个默认命名空间,替代中间命名空间层过多的全局名称的做法。具有此特征的名称称为相对名称。例子如下:
teleop_turtle
turtlesim
cmd_vel
turtle1/pose
run_id
count_and_log/set_logger_level
- 可以明显看到前边少了/,知道ROS解析某个计算图源时候的默认命名空间,相对名称就可以和特定计算图源匹配。
解析相对名称
- 将当前默认的命名空间的名称加载相对名称的前边,就可以解析为全局名称。
- 比如在默认命名空间为/turtle1的地方使用相对名称,可以解析到全局名称如下:
/turtle1 + cmd_vel => /turtle1/cmd_vel
默认命名空间 相对名称 全局名称
- 此时只用cmd_vel(相对名称)ROS即可自动解析
设置默认命名空间
默认命名空间单独为每个节点设置的。如果不设置命名空间,ROS会将全局命名空间作为默认命名空间(ns属性)。
- 1.命令行参数设置
_ _ns:=default-namespace
- 2.利用环境变量设置
Export ROS_NAMESPACE=default-namespace
- 请注意1的优先级高于2.
相对名称的意义
- 它使得在小系统基础上实现复杂系统变得更加容易
- 如果所有节点都是相对名称,则移植(用户能方便的将此节点和话题移植到其他命名空间)简单。高效资源结合。
私有名称
以一个波浪字符开始(~),解析方式同相对名称一样。唯一不同是私有名称以它们的节点名作为默认命名空间。
例如:
/sim1/pubvel + ~max_vel => /sim1/pubvel/max_vel
节点命名空间 相对名称 全局名称
- 每个节点内部都有只与本节点有关的资源,不会与其他节点打交道。
- 私有名称通常用roslaunch的专门功能设置私有名称可以访问的参数。
- 私有名称也用于一个节点的运算服务。
私有名称的关键字“private”仅仅表示其他节点不会使用它们所在的命名空间,也就是仅在命名空间层面上有意义。对于其他节点来讲,只要知道私有名称解析后的全局名称,都可以通过其全局名称访问这些计算图源。它不等于C++中的私有变量。
匿名名称
之前介绍的三种是基本变量类型。ROS 还提供了另一种被称为匿名名称的命名机制,匿名并不是指没有名字,而是指非用户指定而又没有语义信息的名字
使用处理器时间生成匿名名称
示例程序
// This program starts with an anonymous name, which
// allows multiple copies to execute at the same time ,
// without needing to manually create distinct names
// for each of them.
#include <ros/ros.h>
int main ( int argc, char **argv )
{
ros::init ( argc, argv, "anon",
ros::init_options::AnonymousName );
ros::NodeHandle nh ;
ros::Rate rate (1) ;
while (ros::ok( ))
{
ROS_INFO_STREAM( "This␣ message␣ is␣ from␣ "
<< ros::this_node::getName ( ));
rate.sleep( );
}
}
即便是多次启动也不会导致命名冲突。因为会得到唯一性名称。
结束
下一章roslaunch工具。🤣