• ROS学习笔记05、ROS运行管理(元功能包、launch文件、空间覆盖与重名问题、分布式通信)


    前言

    马上开学,目前学校很多实验室都是人工智能这块,大部分都是和机器人相关,然后软件这块就是和cv、ros相关,就打算开始学习一下。

    本章节是虚拟机安装Ubuntu18.04以及安装ROS的环境。

    学习教程:【Autolabor初级教程】ROS机器人入门,博客中一些知识点是来源于赵老师的笔记在线笔记,本博客主要是做归纳总结,如有侵权请联系删除。

    视频中的案例都基本敲了遍,这里给出我自己的源代码文件:

    链接:https://pan.baidu.com/s/13CAzXk0vAWuBsc4oABC-_g 
    提取码:0hws 
    

    所有博客文件目录索引:博客目录索引(持续更新)


    目标解决问题:

    1、如何关联不同的功能包,繁多的ROS节点应该如何启动?

    2、功能包、节点、话题、参数重名时应该如何处理?

    3、不同主机上的节点如何通信?

    一、ROS元功能包

    1.1、认识元功能包

    若是我们编写了多个不同功能的包,那么在提供给用户使用时,难道需要用户一个一个包去下载呢?我们试想是否能够通过一个配置将所需要的包全部直接进行下载引入,将其组织到一起。

    解答:这就设计到元功能包,在ROS中,提供了一种方式可以将不同的功能包打包成一个功能包,当安装某个功能模块时,直接调用打包后的功能包即可,该包又称之为元功能包(metapackage)。。

    概念:MetaPackage是Linux的一个文件管理系统的概念。是ROS中的一个虚包,里面没有实质性的内容,但是它依赖了其他的软件包,通过这种方法可以把其他包组合起来,我们可以认为它是一本书的目录索引,告诉我们这个包集合中有哪些子包,并且该去哪里下载。

    • 例如:sudo apt install ros-noetic-desktop-full 命令安装ros时就使用了元功能包,该元功能包依赖于ROS中的其他一些功能包,安装该包时会一并安装依赖。

    好处:方便用户的安装,我们只需要这一个包就可以把其他相关的软件包组织到一起安装了。

    1.2、自定义一个元功能包

    可参考:ros-wiki-metpackages

    目标:再此之前我们在ROS通信机制中就创建了关于话题通信、服务通信、参数服务器的三个功能包,那么在此我们就可以使用一个元功能包将其进行组织在一起。

    实际案例场景:navigation2

    • image-20220910180224291

    步骤一:创建一个元空间包。

    # 进入工程目录中的src目录下
    cd /home/workspace/roslearn/src
    
    # 创建功能包名为plumbing_my
    catkin_create_pkg --rosdistro melodic plumbing_my
    

    image-20220910175044588

    步骤二:编写package.xml配置,引入相应的功能包

    <exec_depend>plumbing_server_clientexec_depend>
    <exec_depend>plumbing_pub_subexec_depend>
    <exec_depend>plumbing_param_serverexec_depend>
    
    
    <export>
        <metapackage />
    export>
    

    步骤三:修改CMakeLists.txt。

    cmake_minimum_required(VERSION 3.0.2)
    project(plumbing_my)
    find_package(catkin REQUIRED)
    catkin_metapackage()
    
    • 添加最后一行即可。

    最后我们来编译整个项目即可,若是没有报错,说明元功能包配置没有问题。

    image-20220910175759922

    二、ROS节点管理launch文件

    2.1、快速使用launch文件来启动节点

    ros-wiki_roslaunch文档

    # 进入工程目录中的src目录下
    cd /home/workspace/roslearn/src
    
    # 创建功能包名为launch01_basic
    catkin_create_pkg --rosdistro melodic launch01_basic roscpp rospy std_msgs
    

    image-20220911181541153

    01start_turtle.launch:

    <launch>
        <node pkg="turtlesim" type="turtlesim_node"     name="myTurtle" output="screen" />
        <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
    launch>
    

    接着我们来编译整个项目,并进行启动该节点:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 01start_turtle.launch
    

    image-20220911181624837


    2.2、launch文件标签之group节点

    介绍

    标签可以对节点分组,具有 ns 属性,可以让节点归属某个命名空间。

    属性:

    • ns=“名称空间” (可选)

    • clear_params=“true | false” (可选),启动前,是否删除组名称空间的所有参数(慎用…此功能危险)。

    实战示例

    image-20220912095602048

    目的:启动两组相同的服务,看在group下会不会加上对应的namespace前缀。

    分两组启动小乌龟以及键盘控制程序:05demo_group.launch

    <launch>
        <group ns="changlu1">
            <node pkg="turtlesim" type="turtlesim_node"  name="turtle_node" output="screen" />
            <node pkg="turtlesim" type="turtle_teleop_key"  name="turtle_key" output="screen" />
        group>
        <group ns="changlu2">
            <node pkg="turtlesim" type="turtlesim_node"  name="turtle_node" output="screen" />
            <node pkg="turtlesim" type="turtle_teleop_key"  name="turtle_key" output="screen" />
        group>
    launch>
    

    接着去刷新环境变量并进行加载launch文件:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 05demo_group.launch
    

    image-20220912095312737

    对于service、topic都增加上了命名空间:

    image-20220912095424642

    launch文件标签之node节点

    节点的启动时多进程执行的,并非是按照配置文件顺序向下执行。

    属性

    # 节点所属的包
    pkg="包名"
    
    # 节点类型(与之相同名称的可执行文件)
    type="nodeType"
    
    # 节点名称
    name="nodeName"
    
    # 参数传递
    args="xxx xxx xxx" (可选)
    
    # 机器名
    machine="机器名"
    
    # 若是该结点退出,是否自动重启
    respawn="true | false" (可选)
    
    # 一般搭配respawn使用,若是respawn为true,那么延迟 N 秒后启动节点
    respawn_delay=" N" (可选)
    
    # 该节点是否必须,如果为 true,那么如果该节点退出,将杀死整个 roslaunch
    required="true | false" (可选)
    
    # 在指定命名空间 xxx 中启动节点【效果就是在对应发布的话题、服务前缀加上命名空间】
    ns="xxx" (可选)
    
    # 在启动前,删除节点的私有空间的所有参数(慎重使用)
    clear_params="true | false" (可选)
    
    # 日志发送目标,可以设置为 log 日志文件,或 screen 屏幕,默认是 log
    output="log | screen" (可选)
    

    子级标签

    env 环境变量设置
    remap 重映射节点名称
    rosparam 参数设置
    param 参数设置
    

    launch文件标签之remap

    若是我们想要将节点中的话题进行更改,就可以在node节点下新增一个remap节点:

    image-20220911193253594

    <launch>
        <node pkg="turtlesim" type="turtlesim_node"  name="myTurtle" output="screen">
            
            <remap from="/turtle1/cmd_vel" to="/cmd_vel" />
        node>
        <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
    launch>
    

    接着我们启动launch,并查看topic列表看是否有被重命名:

    source ./devel/setup.bash
     
    roslaunch launch01_basic 01start_turtle.launch
    

    image-20220911200428927


    2.3、launch文件标签之include

    include标签用于将另一个 xml 格式的 launch 文件导入到当前文件。

    实战案例:使用include标签来包含之前的启动乌龟案例。

    image-20220911183036296

    02turtle_include.launch:

    <launch>
        
        <include file="$(find launch01_basic)/launch/01start_turtle.launch" />
    launch>
    

    接着去编译执行一下:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 02turtle_include.launch
    

    image-20220911183207369


    2.4、launch文件标签之param

    介绍

    name="命名空间/参数名":参数名称,可以包含命名空间。

    value="xxx" (可选):定义参数值,如果此处省略,必须指定外部文件作为参数源。

    type="str | int | double | bool | yaml" (可选):指定参数类型,如果未指定,roslaunch 会尝试确定参数类型,规则如下:如果包含 ‘.’ 的数字解析未浮点型,否则为整型"true" 和 “false” 是 bool 值(不区分大小写)其他是字符串。

    实战

    创建launch文件:03turtle_parm.launch

    image-20220911212703308

    <launch>
        
        
        <param name="param_a" type="int" value="100" />
        <node pkg="turtlesim" type="turtlesim_node"  name="changlu" output="screen">
            
            <param name="param_b" type="double" value="3.14" />
        node>
        <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
    launch>
    

    编译项目,然后去启动节点:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 03turtle_parm.launch
    

    可以看到下方的param参数第一个是node节点下的,第二个是与node节点平级的:

    rosparam list
    

    image-20220911211922324


    2.5、launch文件标签之rosparam

    介绍

    标签可以从 YAML 文件导入参数,或将参数导出到 YAML 文件,也可以用来删除参数,标签在标签中时被视为私有。

    参数:

    • command=“load | dump | delete” (可选,默认 load)加载、导出或删除参数
    • file="$(find xxxxx)/xxx/yyy…"加载或导出到的 yaml 文件
    • param=“参数名称”
    • ns=“命名空间” (可选)

    实战

    主要介绍load、dump以及delete删除操作。

    image-20220911220020516

    load命令:04demo_rosparam.launch

    <launch>
        
        <rosparam command="load" file="$(find launch01_basic)/launch/params.yaml" />
        <node pkg="turtlesim" type="turtlesim_node"  name="changlu" output="screen">
            <rosparam command="load" file="$(find launch01_basic)/launch/params.yaml" />
        node>
    launch>
    

    params.yaml:

    cl_r: 155
    cl_g: 155
    cl_b: 155
    

    执行命令:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 04demo_rosparam.launch
    

    image-20220911220342028

    dump命令:04demo_dumpparam.launch

    说明:一般dump命令都需要在其他launch文件执行完成之后再执行,若是直接写在launch中不太推荐,因为可能会漏掉一些参数。

    <launch>
        
        <rosparam command="dump" file="$(find launch01_basic)/launch/params_out.yaml" />
    launch>
    

    执行命令:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 04demo_dumpparam.launch
    

    image-20220911220609361

    delete功能:04demo_deleteparam.launch

    <launch>
        <!-- 删除指定param -->
        <rosparam command="delete" param="cl_r" />
    </launch>
    

    执行命令:

    source ./devel/setup.bash
    
    roslaunch launch01_basic 04demo_deleteparam.launch
    

    image-20220911220736810


    实战

    image-20220912101238870

    编写launch文件06demo_arg.launch:根据launch命令添加指定的参数并借助param标签读取arg标签参数值保存到param服务器。

    <launch>
        
        <arg name="param1" default="haha"/>
        
        <param name="param1" value="$(arg param1)" />
    launch>
    

    实际测试:

    source ./devel/setup.bash
     
    # 携带参数
    roslaunch launch01_basic 06demo_arg.launch param1:=12
    
    rosparam get /param1
    

    image-20220912101421126

    roslaunch launch01_basic 06demo_arg.launch
    

    image-20220912101456958


    三、ROS工作空间覆盖

    当我们进行source /home/用户/路径/工作空间A/devel/setup.bash,实际上就会将我们对应工程的src目录添加到ros的包路径,我们可以使用命令来查看:

    echo $ROS_PACKAGE_PATH
    

    image-20220912103036101

    空间覆盖问题:若是我们有两个工程A和B,在两个工程中都有一个相同名称包turtle,那么最后执行source命令的其环境变量优先级更高。

    创建一个新的工程并进行动态刷新配置来查看下效果:

    mkdir -p roslearn2/src
    cd roslearn2
    catkin_make
    source ./devel/setup.bash
    

    image-20220912103410387

    隐藏的一个bug问题

    image-20220912104040100

    若是按照上面的123顺序来进行source加载依赖,那么就会出现问题,注意此时pg2/A的优先级最高,若是在执行pg1的时候,其依赖的是pg3/A,但是在程序代码中引用一般只是A/执行文件,所以此时就会去执行pg2/A,最终造成严重问题!

    解决方案:尽可能不同的工程中不要设置相同的包,以免出现问题。


    四、重名问题

    4.1、ROS节点名称重名(三种方式)

    方式一:rosrun设置命名空间

    # 语法: rosrun 包名 节点名 __ns:=新名称
    rosrun turtlesim turtlesim_node __ns:=/xxx
    

    方式二:launch文件编写时在node标签中添加ns键值对

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

    方式三:代码编写

    //代码1:name_时间戳
    ros::init(argc,argv,"zhangsan",ros::init_options::AnonymousName);
    
    //代码2:传入map的形式
    std::map map;
    map["__ns"] = "xxxx";
    ros::init(map,"wangqiang");
    

    4.2、ROS话题名称设置

    方式一:启动节点命令时进行话题重映射

    # 示例:将话题/cmd_vel重映射为/turtle1/cmd_vel
    rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
    

    方式二:launch文件中ndoe节点下编写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>
    launch>
    

    方式三:代码编写

    //全局名称:与节点名称无关
    ros::Publisher pub = nh.advertise("/chatter",1000);  //结果:/chatter
    
    //相对名称:与命名空间、节点名称连接
    ros::Publisher pub = nh.advertise("chatter",1000); //结果:xx/chatter
    
    //私有名称:节点名称为hello,并且设置了命名空间xx
    ros::NodeHandle nh("~");
    ros::Publisher pub = nh.advertise("chatter",1000);  //结果:/xx/hello/chatter
    
    //使用~,而话题名称有时/开头时,那么话题名称是绝对的(不受影响)
    ros::NodeHandle nh("~");
    ros::Publisher pub = nh.advertise("/chatter/money",1000); //结果依旧是:/chatter/money
    

    4.3、ROS参数名称设置

    方式一:rosrun命令设置参数

    # 设置参数为A=100
    rosrun turtlesim turtlesim_node _A:=100
    

    方式二:launch文件来设置参数,node平级与node节点下

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

    方式三:编码设置参数

    ros::param::set("/set_A",100); //全局,和命名空间以及节点名称无关
    ros::param::set("set_B",100); //相对,参考命名空间
    ros::param::set("~set_C",100); //私有,参考命名空间与节点名称
    

    假设设置的 namespace 为 xxx,节点名称为 yyy,使用 rosparam list 查看:

    /set_A
    /xxx/set_B
    /xxx/yyy/set_C
    

    五、ROS分布式通信

    准备两台机子

    步骤1、确定ip地址以及hostname主机名

    # 获取ip地址
    ifconfig
    
    # 获取主机名
    hostname
    
    主机:192.168.3.41   changlu-VirtualBox
    从机:192.168.3.18   changlu-VirtualBox2
    

    步骤2、配置本地的hostname映射(ip与主机域名)

    打开并编辑/etc/hosts文件

    主机:

    127.0.1.1	changlu-VirtualBox
    192.168.3.41 changlu-VirtualBox2
    

    从机:

    127.0.1.1	changlu-VirtualBox2
    192.168.3.18 changlu-VirtualBox
    

    生效hosts文件命令如下:

    sudo /etc/init.d/networking restart
    

    步骤3、打开/root/.bashrc文件,添加两条参数配置信息

    模板如下:

    export ROS_MASTER_URI=http://主机IP:11311
    export ROS_HOSTNAME=主机IP
    
    export ROS_MASTER_URI=http://主机IP:11311
    export ROS_HOSTNAME=从机IP
    

    主机:

    export ROS_MASTER_URI=http://192.168.3.18:11311
    export ROS_HOSTNAME=192.168.3.18
    
    # 或者
    # export ROS_MASTER_URI=http://changlu-VirtualBox:11311
    # export ROS_HOSTNAME=changlu-VirtualBox
    

    从机(多个从节点同样如此配置Master_URI都填一个):

    export ROS_MASTER_URI=http://192.168.3.18:11311
    export ROS_HOSTNAME=192.168.3.41
    
    # 或者
    export ROS_MASTER_URI=http://changlu-VirtualBox:11311
    export ROS_HOSTNAME=changlu-VirtualBox2
    

    分别令其生效:

    source /root/.bashrc
    

    步骤四:主机从机来进行测试通信

    主机:

    roscore
    
    # 弹出图像化界面
    rosrun turtlesim turtlesim_node
    

    从机:

    # 读取键盘上下左右移动信息控制乌龟行动
    rosrun turtlesim turtle_teleop_key
    

    image-20220912154838385

    其实也可以从机来打开图形化界面,主机来进行键盘控制,不过需要注意的是必须是master启动roscore。

    参考资料

    [1]. Centos Ubuntu 修改hosts文件后,(重启)生效命令

  • 相关阅读:
    基于ubuntu1604的ROS安装
    UNPV2 学习:Posix Message Queues
    实训三:多表查询 - 大学数据库创建与查询实战
    Docker超详细基础教程
    Oracle CPU使用率过高问题处理
    数据类型的定义
    iOS ijkplayer 硬解H265(hevc)4k视频问题解决
    CentOS配网报错:network is unreachable
    中介模式简介
    【MineCraft】-- Mod制作物品与方块
  • 原文地址:https://blog.csdn.net/cl939974883/article/details/126962758