当前位置: 首页 > 工具软件 > 重名修改 > 使用案例 >

十七、ROS功能包重名和节点名重名解决办法

郎思远
2023-12-01

1、ROS不同工作空间功能包重名

1.定义

所谓工作空间覆盖,是指在不同的工作空间中,存在重名的功能包的情形。在ROS开发中,在同一工作空间中,功能包不会重名。但是,不同的工作空间中,可能会出现功能包重名的现象。

2.功能包重名时的调用规则

    1. 在根目录下的.bashrc文件中添加ROS功能包检索路径:
    source /opt/ros/noetic/setup.bash
    source /media/d102/EPAN/Desktop/code_study_ubuntu/rosdemo_05/devel/setup.bash
    source /media/d102/EPAN/Desktop/code_study_ubuntu/rosdemo_04/devel/setup.bash
    
    1. 更新检索路径
      在根目录下:
    source .bashrc
    
    1. 打印ROS功能包检索路径
    • 命令:echo $ROS_PACKAGE_PATH
echo $ROS_PACKAGE_PATH 
/media/d102/EPAN/Desktop/code_study_ubuntu/rosdemo_04/src:/media/d102/EPAN/Desktop/code_study_ubuntu/rosdemo_05/src:/opt/ros/noetic/share

可见,路径越靠后,优先级越高,功能包重名时,会按照优先级进行查找,优先级高的先被执行

    1. roscd 功能包
      会进入含有相应功能包的工作空间,通过查看该工作空间路径,就可以知道调用的是哪个工作空间的功能包

3.安全隐患

当含有重名功能包时,可能会出现执行异常的情况。比如,C功能包执行时,依赖A中的turtle功能包,但却执行了B中的turtle功能包,由于两个功能包重名,功能有差别,从而导致执行异常

4.BUG说明

在根目录下的.bashrc文件中,同时source多个文件时,可能会出现在ROS_PACKAGE_PATH中只包含两个工作空间的bug,解决办法如下:(这个BUG很玄学,目前没有找到100%有效的方法,下面方法可供参考)

删除工作空间下的build和devel文件夹重新编译,然后重新载入.bashrc文件
  • 注意:
    重新编译时,可能会出现如下BUG:
    -- Using PYTHON_EXECUTABLE: /home/matthew/anaconda3/envs/torch/bin/python3
    -- Using Debian Python package layout
    -- Could NOT find PY_em (missing: PY_EM) 
    CMake Error at /opt/ros/noetic/share/catkin/cmake/empy.cmake:30 (message):
    Unable to find either executable 'empy' or Python module 'em'...  try
    installing the package 'python3-empy'
    Call Stack (most recent call first):
    /opt/ros/noetic/share/catkin/cmake/all.cmake:164 (include)
    /opt/ros/noetic/share/catkin/cmake/catkinConfig.cmake:20 (include)
    CMakeLists.txt:58 (find_package)
    

这是因为catkin找的的python版本为anaconda下面的版本,所以需要改为指定采用下面的命令:

catkin_make -DPYTHON_EXECUTABLE=/usr/bin/python3

2. ROS节点名称重名

2.1 背景

有时,需要启动相同的节点,如果直接启动,由于节点名相同,先启动的节点就会由于重名被关闭,为了解决这一问题,可以采用如下三种方法:

2.2 解决办法

2.2.1 rosrun设置命名空间和重映射

2.2.1.1 rosrun设置命名空间

  • 格式:rosrun package_name node_name __ns:=ns_name
  • 代码实现:
    # bash1
    rosrun turtlesim turtlesim_node __ns:=ns1
    # bash2
    rosrun turtlesim turtlesim_node __ns:=ns2
    
  • 运行结果:
    rosnode list
    /ns1/turtlesim
    /ns2/turtlesim
    /rosout
    /turtlesim
    

2.2.1.2 rosrun名称重映射

  • 格式:rosrun package_name node_name __name:=new_name(不适用于Python)
  • 代码实现:
    # bash1
    rosrun turtlesim turtlesim_node __name:=t1
    # bash2
    rosrun turtlesim turtlesim_node __name:=t2
    
  • 运行结果:
    rosnode list
    /t1
    /t2
    /turtlesim
    

2.2.1.3 rosrun命名空间和名称重映射的叠加

  • 格式1:rosrun package_name node_name __ns:=ns_name __name:=new_name
  • 格式2:rosrun package_name node_name __name:=new_name __ns:=ns_name
  • 代码实现:
    # bash1
    rosrun turtlesim turtlesim_node __ns:=ns1 __name:=t1
    # bash2
    rosrun turtlesim turtlesim_node __name:=t2 __ns:=ns2
    
  • 运行结果:
    /ns1/t1
    /ns2/t2
    

2.2.1.4 设置环境变量也可以设置命名空间

  • 格式:export ROS_NAMESPACE=ns_name
  • 代码实现:
    # bash1
    d102@d102-W65KJ1-KK1:~$ export ROS_NAMESPACE=ns3
    d102@d102-W65KJ1-KK1:~$ rosrun turtlesim turtlesim_node  
    # bash2
    d102@d102-W65KJ1-KK1:~$ export ROS_NAMESPACE=ns4
    d102@d102-W65KJ1-KK1:~$ rosrun turtlesim turtlesim_node 
    
  • 运行结果:
    /ns3/turtlesim
    /ns4/turtlesim
    

2.2.2 launch文件设置命名空间和重映射

  • 代码实现:
    <launch>
        <!-- 参考节点 -->
        <node pkg="turtlesim" type="turtlesim_node" name="turtlesim" />
        <!-- 名称重映射 -->
        <node pkg="turtlesim" type="turtlesim_node" name="turtlesim_01" />
        <!-- 命名空间 -->
        <node pkg="turtlesim" type="turtlesim_node" name="turtlesim" ns="ns_01"/>
        <!-- 命名空间+名称重映射 -->
        <node pkg="turtlesim" type="turtlesim_node" name="turtlesim_02" ns="ns_02"/>
    </launch>
    
  • 运行结果:
    rosnode list
    /ns3/ns_01/turtlesim
    /ns3/ns_02/turtlesim_02
    /ns3/turtlesim_01
    /turtlesim
    

2.2.3 编码设置命名空间和重映射

2.2.3.1 C++实现重映射

  • 代码实现:
    ros::init(argc,argv,"server",ros::init_options::AnonymousName);//在节点后面加上时间戳
    
  • 运行结果:
    # bash1
    rosrun server_client server
    # bash2
    rosnode list 
    /server_1656775703891563446
    

2.2.3.2 C++实现命名空间

  • 代码实现:
    std::map<std::string, std::string> map;
    map["__ns"] = "namespace_01";
    ros::init(map,"server",ros::init_options::AnonymousName);//server为节点名
    
  • 运行结果:
    # bash1 
    rosrun server_client server
    # bash2
    rosnode list 
    /namespace_01/server_1656776071871347181
    

2.2.3.3 Python实现重映射(无法实现命名空间)

  • 代码实现:
    rospy.init_node("server_p",anonymous=True) #会在节点后加入时间戳
    
  • 运行结果:
    # bash1
    rosrun server_client server_p.py 
    # bash2
    rosnode list
    /server_p_188947_1656776369182
    
 类似资料: