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

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
    
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ROS中,C++节点通常是由多个单词组成的,每个单词以小写字母开头,单词之间用下划线连接。例如,一个为“my_node”的节点可能属于一个为“my_package”的,因此它的完整称将是“my_package/my_node”。 创建一个C++节点的步骤如下: 1. 创建一个ROS软件,使用catkin_create_pkg或者手动创建。 2. 在的src目录下创建一个.cpp源文件,并在CMakeLists.txt中添加对该文件的编译。 3. 在.cpp文件中编写节点的代码,节点的初始化、回调函数和主循环等。 4. 在CMakeLists.txt中添加节点的编译和链接信息。 5. 在package.xml中添加节点的描述信息,节点称、作者、版本号等。 6. 使用catkin_make编译整个软件,生成可执行文件。 7. 运行节点,使用rosrun命令或者在launch文件中启动。 下面是一个示例的C++节点代码: ```cpp #include <ros/ros.h> #include <std_msgs/String.h> void callback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("I heard: [%s]", msg->data.c_str()); } int main(int argc, char** argv) { ros::init(argc, argv, "my_node"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe("my_topic", 10, callback); ros::spin(); return 0; } ``` 在这个例子中,节点称为“my_node”,订阅了一个为“my_topic”的主题,并在收到消息时调用回调函数“callback”。要编译这个节点,需要在CMakeLists.txt中添加以下内容: ```cmake add_executable(my_node src/my_node.cpp) target_link_libraries(my_node ${catkin_LIBRARIES}) ``` 然后使用catkin_make命令来编译整个软件
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值