3.4 节点重名
问题描述
在 ROS2 中不同的节点可以有相同的节点名称,比如可以启动多个 turtlesim_node 节点,这些节点的名称都是 turtlesim。节点重名虽然是被允许的,但是开发者应该主动避免这种情况,因为节点重名时可能会导致操作上的混淆,仍以启动了多个 turtlesim_node 节点为例,当使用计算图(rqt_graph)查看节点运行状态时,由于他们的节点名称一致,那么虽然实际有多个节点,但是在计算图上显示一个。并且节点名称也会和话题名称、服务名称、动作名称、参数等产生关联,届时也可能会导致通信逻辑上的混乱。
那么在 ROS2 中如何避免节点重名呢?
解决思路
避免重名问题,一般有两种策略:
名称重映射,也即为节点起别名;
命名空间,是为节点名称添加前缀,可以有多级,格式:/xxx/yyy/zzz。
这也是在 ROS2 中解决重名问题的常用策略。
解决方案
上述两种策略的实现途径主要有如下三种:
ros2 run 命令实现;
launch 文件实现;
编码实现。
本节将逐一演示上述三种方案的实现语法。
3.4.1 ros2 run设置节点名称
1.ros2 run设置命名空间
1.1设置命名空间演示
语法:ros2 run 包名 节点名 --ros-args --remap __ns:=命名空间
示例:
ros2 run turtlesim turtlesim_node --ros-args --remap __ns:=/t1
1.2运行结果
使用ros2 node list
查看节点信息,显示结果:
/t1/turtlesim
2.ros2 run名称重映射
2.1为节点起别名
语法: ros2 run 包名 节点名 --ros-args --remap __name:=新名称
或
ros2 run 包名 节点名 --ros-args --remap __node:=新名称
示例:
ros2 run turtlesim turtlesim_node --ros-args --remap __name:=turtle1
2.2运行结果
使用ros2 node list
查看节点信息,显示结果:
/turtle1
3.ros2 run命名空间与名称重映射叠加
3.1设置命名空间同时名称重映射
语法: ros2 run 包名 节点名 --ros-args --remap __ns:=新名称 --remap __name:=新名称
ros2 run turtlesim turtlesim_node --ros-args --remap __ns:=/t1 --remap __name:=turtle1
3.2运行结果
使用ros2 node list
查看节点信息,显示结果:
/t1/turtle1
3.4.2 launch设置节点名称
在ROS2中launch文件可以由Python、XML或YAML三种语言编写(关于launch文件的基本使用可以参考4.1 启动文件launch简介),每种实现方式都可以设置节点的命名空间或为节点起别名。
1.Python方式实现的launch文件设置命名空间与名称重映射
在 Python 方式实现的 launch 文件中,可以通过类 launch_ros.actions.Node
来创建被启动的节点对象,在对象的构造函数中提供了 name 和 namespace 参数来设置节点的名称与命名空间,使用示例如下:

2.XML方式实现的launch文件设置命名空间与名称重映射
在 XML 方式实现的 launch 文件中,可以通过 node 标签中 name 和 namespace 属性来设置节点的名称与命名空间,使用示例如下:

3.YAML方式实现的launch文件设置命名空间与名称重映射
在 YAML 方式实现的 launch 文件中,可以通过 node 属性中 name 和 namespace 属性来设置节点的名称与命名空间,使用示例如下:

4.测试
上述三种方式在设置命名空间与名称重映射时虽然语法不同,但是实现功能类似,都是启动了三个 turtlesim_node 节点,第一个节点设置了节点名称,第二个节点设置了命名空间,第三个节点既设置了命名空间又设置了节点名称,分别执行三个launch文件,然后使用ros2 node list
查看节点信息,显示结果都如下所示:

3.4.3 编码设置节点名称
在 rclcpp 和 rclpy 中,节点类的构造函数中,都分别提供了设置节点名称与命名空间的参数。
1.rclcpp中的相关API
rclcpp中节点类的构造函数如下:
Node (const std::string &node_name, const NodeOptions &options=NodeOptions())
Node (const std::string &node_name, const std::string &namespace_, const NodeOptions &options=NodeOptions())
构造函数1中可以直接通过node_name设置节点名称,构造函数2既可以通过node_name设置节点名称也可以通过namespace_设置命名空间。
2.rclpy中的相关API
rclpy中节点类的构造函数如下:

构造函数中可以使用node_name设置节点名称,namespace设置命名空间。

B站有完整的ros系列教程视频,可以观看完整内容ros课程ROS2理论与实践
更多内容将在猛狮知识星球社区更新最新课程,后续将推出更多优质内容——详情可关注猛狮集训营公众号和猛狮集训营官方网站。