ROS学习笔记7:重名解决与名称设置

本文是ROS新手的学习笔记,讲述了在ROS环境中遇到的功能包和节点重名问题,如何通过设置工作空间优先级、命名空间和话题名称重映射来解决,同时介绍了参数名称的设置方法。
摘要由CSDN通过智能技术生成

前言

本人ROS小白,利用寒假时间学习ROS,在此以笔记的方式记录自己每天的学习过程。争取写满15篇(7/15)。
环境:Ubuntu20.04、ROS1:noetic
环境配置:严格按照下方学习链接的教程配置,基本一次成功。
学习链接【Autolabor初级教程】ROS机器人入门
对应链接文档ROS机器人入门课程《ROS理论与实践》
笔记绝大部分代码使用Python语言编写。
本期关键词:功能包重名,节点重名,话题名称设置,参数名称设置

一、功能包重名

  1. 功能包重名指的是在不同工作空间下有相同名称的功能包,比如在demo1_wsdomo2_ws工作空间下都有名为turtlesim的功能包,初次之外,ROS自带的工作空间下也有turtlesim的功能包。
  2. 以上存在三个同名的功能包,我们在运行rosrun指令时,输入turtlesim功能包,运行的是哪一个呢?这个就涉及到~/.bashrc文件中工作空间环境变量的优先级设置。
  3. ~/.bashrc:在ROS中,~/.bashrc 文件是一个shell配置文件,它用于设置用户的bash shell环境。这个文件通常位于用户的主目录下(即用户的home目录),并且每次打开一个新的终端会话时,bash shell都会读取这个文件来执行一些初始化命令。在ROS的上下文中,~/.bashrc 文件可能包含一些特定的命令,这些命令用于配置ROS环境,使得用户能够在终端中方便地使用ROS的命令和工具。
  4. 简单来说,~/.bashrc是一个配置文件,我们之前设置的快捷指令g-pathget-x,待会要设置的工作空间优先级,以及之后要进行的ROS主从机设置,都和~/.bashrc文件配置有关。
  5. 对应的环境变量是功能包运行的前提。大家在学习的过程中可能会有这样的疑问?为什么在运行自定义工作空间的功能包前,需要先加载环境变量(即运行source指令),而运行ROS自带的包(比如乌龟运动控制的包)就不需要先加载环境变量呢?这是因为我们安装ROS的时候,ROS功能包的环境变量路径已经保存在了~/.bashrc文件里,每次我们启动终端,~/.bashrc文件就会帮我们自动加载对应的环境变量,所以才可以直接运行ROS的功能包。
  6. 打开终端,只执行echo echo $ROS_PACKAGE_PATH指令,终端输出的信息为:/opt/ros/noetic/share。这时我们进入工作空间,执行source ./devel/setup.bash后,再执行echo echo $ROS_PACKAGE_PATH,得到的结果为:/home/用户名/XXX_ws/src:/opt/ros/noetic/share
  7. /home/用户名/XXX_ws/src:/opt/ros/noetic/share表示的是前者的工作空间优先级大于后者,如果两个工作空间存在相同的功能包,rosrun指令默认执行前者(高优先级)的功能包。
  8. 综上,如果存在功能包重名的情况,我们可以通过设置工作空间优先级的方法来确定要执行哪个工作空间下的功能包。
  9. ~/.bashrc文件的配置方法:在~/.bashrc文件中source /opt/ros/noetic/setup.bash语句下添加:
source /home/用户/路径/工作空间A/devel/setup.bash
source /home/用户/路径/工作空间B/devel/setup.bash

(语句排位越下,工作空间优先级越高)
10. 我们要尽量避免功能包重名的情况!

二、节点重名

ROS中如果启动重名节点,先启动的节点就会被强制关闭。解决节点重名问题主要有以下三种方法:rosrun命令法、launch文件法、编程法

rosrun命令方法

以我们最熟悉的乌龟运动控制为例。

rosrun设置命名空间
  1. 在三个终端分别运行以下指令:
rosrun turtlesim turtlesim_node
rosrun turtlesim turtlesim_node __ns:=/aaa
rosnode list
  1. 结果为:
/aaa/turtlesim
/rosout
/turtlesim
rosrun名称重映射
  1. 在三个终端中运行以下指令:
rosrun turtlesim turtlesim_node __name:=name1
rosrun turtlesim turtlesim_node __name:=name2
rosnode list
  1. 结果为:
/name1
/name2
/rosout
  1. 这时结果可能还包含刚刚的/aaa/turtlesim/turtlesim,问题不大,执行rosnode cleanup清除一下不可用节点就行。
rosrun设置命名空间+名称重映射
  1. 就是刚刚两个方法的叠加:
rosrun turtlesim turtlesim_node __name:=name1 __ns:=aaa
rosrun turtlesim turtlesim_node __name:=name2 __ns:=bbb
rosnode list
  1. 结果为:
/aaa/name1
/bbb/name2
/rosout
  1. 在上述命令中,经过测试,节点名称前加入的命名空间,指令__ns:=aaa和指令__ns:=/aaa的效果是一样的。(这里注意与下面的话题名称重命名区分。)

launch文件设置

launch文件里的设置比较简单,也是包含命名空间设置和重映射两种。
代码如下:

<launch>

    <node pkg="turtlesim" type="turtlesim_node" name="t1" />
    <node pkg="turtlesim" type="turtlesim_node" name="t2" />
    <node pkg="turtlesim" type="turtlesim_node" name="t1" ns="hello"/>

</launch>

执行rosnode list查看结果:

/hello/t1
/t1
/t2

编码设置

测试代码:

#! usr/bin/env python

import rospy

if __name__=="__main__":
    rospy.init_node("rename1",anonymous=True)
    rospy.loginfo("this is a rename test!")
    rospy.sleep(10.0)# 延时10s,不然程序运行太快,rosnode查看不到节点

执行rosnode list查看,节点名会后缀时间戳,以此避免重名。

三、话题名称设置

rosrun命令方法

rosrun名称重映射语法: rorun 包名 节点名 话题名:=新话题名称
示例1:

# 启动ROS自带键盘控制节点控制乌龟运动
# 将话题/cmd_vel改为/turtle1/cmd_vel
rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
rosrun turtlesim turtlesim_node

示例2:

# 将话题/turtle1/cmd_vel改为/cmd_vel
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel

launch文件设置

launch文件将话题名称重映射要用到remap标签,示例代码如下:

<launch>

    <node pkg="turtlesim" type="turtlesim_node" name="gui" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
    </node>
    <node pkg="turtlesim" type="turtle_teleop_key" name="key" />
    
</launch>

编码设置

以下代码均使用该指令执行:

rosrun helloworld demo_pub_msg.py __ns:=space
  1. 全局名称:以/开头的名称,和节点名称无关。代码示例如下:
#! /usr/bin/env python

import rospy
from helloworld.msg import Person

if __name__ == "__main__":
    rospy.init_node("pub_msg")
    # 以下两种都是将话题名设置为全局名称
    # pub = rospy.Publisher("/msg_test",Person,queue_size=10)# 结果:/msg_test
    pub = rospy.Publisher("/aaa/msg_test",Person,queue_size=10)# 结果:/aaa/msg_test
    
    p=Person()
    p.name="Zhang San"
    p.age=18
    p.height=1.78
    
    rate=rospy.Rate(1)
    while not rospy.is_shutdown():
        pub.publish(p)
        rate.sleep()
        rospy.loginfo("name is: %s, age is: %d, height is: %f", p.name,p.age,p.height)
  1. 相对名称:非/开头的名称,参考命名空间(与节点名称平级)来确定话题名称。
#! /usr/bin/env python

import rospy
from helloworld.msg import Person

if __name__ == "__main__":
    rospy.init_node("pub_msg")
    # 以下两种都是将话题名设置为全局名称
    pub = rospy.Publisher("msg_test",Person,queue_size=10)#结果:/space/msg_test
    # pub = rospy.Publisher("aaa/msg_test",Person,queue_size=10)#结果:/space/aaa/msg_test
    p=Person()
    p.name="Zhang San"
    p.age=18
    p.height=1.78
    
    rate=rospy.Rate(1)
    while not rospy.is_shutdown():
        pub.publish(p)
        rate.sleep()
        rospy.loginfo("name is: %s, age is: %d, height is: %f", p.name,p.age,p.height)
  1. 私有名称:以~开头的名称。
# 将上面代码的话题名称前加个~号即可
pub = rospy.Publisher("~msg_test",Person,queue_size=10)#结果:/space/pub_msg/msg_test
    # pub = rospy.Publisher("~aaa/msg_test",Person,queue_size=10)#结果:/space/pub_msg/aaa/msg_test

四、参数名称设置

因为参数名称设置之前的笔记也提到过,所以这里只给出代码示例啦:

rosrun命令方法

rosrun turtlesim turtlesim_node _A:=100

launch文件设置

<launch>

    <param name="p1" value="100" />
    <node pkg="turtlesim" type="turtlesim_node" name="t1">
        <param name="p2" value="100" />
    </node>

</launch>

编码设置

这里仍然是使用rospy.set_param的方法来设置服务器参数,另外还结合了刚刚提到的“全局”、“相对”、“私有”的概念。

rospy.set_param("/py_A",100)  #全局,和命名空间以及节点名称无关
rospy.set_param("py_B",100)  #相对,参考命名空间
rospy.set_param("~py_C",100)  #私有,参考命名空间与节点名称

往期内容

  1. ROS学习笔记1:基础知识
  2. ROS学习笔记2:话题通信
  3. ROS学习笔记3:服务通信与参数服务器
  4. ROS常用命令记录
  5. ROS学习笔记4:通信机制实操
  6. ROS学习笔记5:常用API和模块导入
  7. ROS学习笔记6:launch文件
  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值