• 【ROS进阶篇】第四讲 ROS中的重名问题(节点、话题与参数)


    【ROS进阶篇】第四讲 ROS中的重名问题(节点、话题与参数)

    在这里插入图片描述

    前言

    在上一篇博客中,我们对于ROS的文件管理系统进行了层次分析,并研究了工作空间覆盖以及不同主机之间的通信问题,本节内容主要转换方向,来考虑ROS系统中的存在的诸多重名问题,例如节点重名、话题重名、参数重名等。
    在这里插入图片描述

    一、节点重名

    1. 问题介绍

    • 概念:在ROS系统中节点是最为基本的概念,在创建节点时,例如使用C++语言进行初始化,需要通过指定API定义节点名称,而如果存在重名节点,那么在调用时就会出现问题;
    • 实际情况:在ROS中重名节点启动时,会直接关闭之前已经存在的节点,提示如下:
    [ WARN] [1578812836.351049332]: Shutdown request received.
    [ WARN] [1578812836.351207362]: Reason given for shutdown: [new node registered with same name]
    
    • 1
    • 2
    • 解决策略:
    1. 使用命名空间:添加前缀
    2. 名称重映射:重新起名

    对于上述两种策略,实现途径有三种方法:rosrun命令、launch文件与编程实现,本文将一一进行分析介绍

    2. 解决方法

    1)rosrun

    • 设置命名空间:rosrun 功能包名 节点名 __ns:=/新节点名
      示例如下:
    rosrun turtlesim turtlesim_node __ns:=/xxx
    rosrun turtlesim turtlesim_node __ns:=/yyy
    
    • 1
    • 2
    • 名称重映射:rosrun 功能包名 节点名 __name:=新节点名
      示例如下:
    rosrun turtlesim  turtlesim_node __name:=t1 |  rosrun turtlesim   turtlesim_node /turtlesim:=t1
    rosrun turtlesim  turtlesim_node __name:=t2 |  rosrun turtlesim   turtlesim_node /turtlesim:=t2
    
    • 1
    • 2

    2)launch

    • 在先前的launch文件解析教程中,我们提到了node标签的两个属性,name和ns,通过设置这两个属性就可以轻松实现上述两种策略;
    <launch>
    
        <node pkg="turtlesim" type="turtlesim_node" name="t1" />
        <node pkg="turtlesim" type="turtlesim_node" name="t1" ns="xxx"/>
    
    </launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3)c++

    • 设置命名空间:
    std::map<std::string, std::string> map;
    map["__ns"] = "xxxx";
    ros::init(map,"test_node");
    
    • 1
    • 2
    • 3
    • 名称重映射:给原本的节点名后添加时间戳
    ros::init(argc,argv,"test_node",ros::init_options::AnonymousName);
    
    • 1

    二、话题重名

    1. 问题介绍

    • 相比于节点,ROS中的话题当然也存在重名问题,但是会更加复杂一些,因为在实际的应用中 ,话题名的设置相对灵活,需要灵活修改。
    • 解决策略:与节点重名相同,基本的策略仍旧是重映射和前缀两种方法,区别在于这里的前缀种类很多,可以分为以下三种:
    1. 全局前缀:参考ROS系统,与命名空间平级
    2. 相对前缀:参考命名空间,与节点名称平级
    3. 私有前缀:参考节点名称,位于节点名称之下
    • 实例研究:在解决方法的测试中,假定场景如下:
      使用键盘控制功能包,用于控制海龟运动,指令如下:
    sudo apt install ros-noetic-teleop-twist-keyboard
    rosrun teleop_twist_keyboard teleop_twist_keyboard.py
    rosrun turtlesim turtlesim_node
    
    • 1
    • 2
    • 3
    • 问题:前者(控制节点)话题为cmd_vel,后者(显示节点)是/turtle1/cmd_vel

    2. 解决方法

    1)rosrun

    • 主要使用名称重映射方法,通过如下指令实现便捷修改话题名
      rosrun 功能包名 节点名 话题名:=新话题名

    示例如下:

    rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
    rosrun turtlesim turtlesim_node
    // 或者相反
    rosrun teleop_twist_keyboard teleop_twist_keyboard.py
    rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)launch

    • 同样,通过launch文件中node中的remap可以实现话题重映射
    <launch>
    
        <node pkg="turtlesim" type="turtlesim_node" name="t1" />
        <node pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py" name="key">
            <remap from="/cmd_vel" to="/turtle1/cmd_vel" />
        </node>
        
    	<-- 注释:相反的解决办法 -->
    
        <node pkg="turtlesim" type="turtlesim_node" name="t1">
            <remap from="/turtle1/cmd_vel" to="/cmd_vel" />
        </node>
        <node pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py" name="key" />
    
    </launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3)c++

    • 对于C++的解决办法,主要采用添加前缀的办法,而不同的名称,添加的前缀不同:
    1. 前提:设置节点名称为tsnode,启动节点时添加空间前缀:xxx
    2. 全局名称:
    //以/开头的名称,与节点名称无关
    ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    //结果:/chatter
    
    • 1
    • 2
    • 3
    1. 相对名称:
    //非/开头的名称,参考工作空间确定话题名
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
    //结果:xxx/chatter
    
    • 1
    • 2
    • 3
    1. 私有名称:
    //以~开头的名称,添加工作空间和节点名前缀
    ros::NodeHandle nh("~");
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
    //结果:/xxx/tsnode/chatter
    
    • 1
    • 2
    • 3
    • 4

    三、参数重名

    1. 问题介绍

    • 概念:与先前不同,参数名称也会出现重名覆盖问题,但是解决办法大多只有添加前缀的办法;
    • 解决办法:在参数生成时,本质上都会带有一定的前缀,前缀种类同话题的三种,本文将会一一介绍;

    2. 解决方法

    1)rosrun

    • 采用rosrun启动节点,可以通过如下指令设置:
    rosrun 功能包名 节点名 _参数名:=参数值
    
    • 1
    • 实例:自动添加节点前缀(私有模式)
    rosrun turtlesim turtlesim_node _A:=100
    // 查看对应参数信息
    /turtlesim/A
    
    • 1
    • 2
    • 3

    2)launch

    • 两种方法:
    1. node标签外设置参数:全局性质
    <launch>
    
        <param name="p1" value="100" />
        <-- 结果:/p1 -->
    
    </launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. node标签内设置参数:私有性质
    <launch>
    
        <node pkg="turtlesim" type="turtlesim_node" name="t1">
            <param name="p2" value="100" />
        </node>
         <-- 结果:/t1/p2 -->
    
    </launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3)c++

    • 对于C++编程来说,通过API:param::set或者NodeHandle实现:

    • paramset:

    ros::param::set("/set_A",100); //全局,和命名空间以及节点名称无关
    
    ros::param::set("set_B",100); //相对,参考命名空间
    
    ros::param::set("~set_C",100); //私有,参考命名空间与节点名称
    
    //结果
    /set_A
    /xxx/set_B
    /xxx/yyy/set_C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • NodeHandle:
    ros::NodeHandle nh;
    nh.setParam("/nh_A",100); //全局,和命名空间以及节点名称无关
    
    nh.setParam("nh_B",100); //相对,参考命名空间
    
    ros::NodeHandle nh_private("~");
    nh_private.setParam("nh_C",100);//私有,参考命名空间与节点名称
    
    //结果
    /nh_A
    /xxx/nh_B
    /xxx/yyy/nh_C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    总结

    • 声明:本节博客部分参考了CSDN用户赵虚左的ROS教程,从下篇博客起ROS进阶篇的教程将会步入功能组件的学习上,我们首先从TF变换工具包重新出发。

    在这里插入图片描述

  • 相关阅读:
    【财务系统】报告如何转换下载为word?这个方法值得借鉴
    C++ 漫谈哈夫曼树
    springboot打war包
    双馈风电机组备用容量控制策略研究
    ROS基础-ROS msg发布订阅:嵌套自定义类型 数组
    SpringCloud:使用Nacos作为配置中心
    逐鹿澳洲市场 宁德时代储能全场景解决方案亮相澳大利亚全能源展
    面试官:IoC 和 DI 有什么区别?
    windows 的一些常见命令
    自制一款远程控制软件——VeryControl
  • 原文地址:https://blog.csdn.net/lc1852109/article/details/125503945