0
点赞
收藏
分享

微信扫一扫

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

七千22 2022-10-24 阅读 62


文章目录

  • ​​前言​​
  • ​​一、ROS元功能包​​
  • ​​1.1、认识元功能包​​
  • ​​1.2、自定义一个元功能包​​
  • ​​二、ROS节点管理launch文件​​
  • ​​2.1、快速使用launch文件来启动节点​​
  • ​​2.2、launch文件标签之group节点​​
  • ​​launch文件标签之node节点​​
  • ​​launch文件标签之remap​​
  • ​​2.3、launch文件标签之include​​
  • ​​2.4、launch文件标签之param​​
  • ​​2.5、launch文件标签之rosparam​​
  • ​​三、ROS工作空间覆盖​​
  • ​​四、重名问题​​
  • ​​4.1、ROS节点名称重名(三种方式)​​
  • ​​4.2、ROS话题名称设置​​
  • ​​4.3、ROS参数名称设置​​
  • ​​五、ROS分布式通信​​
  • ​​参考资料​​

前言

马上开学,目前学校很多实验室都是人工智能这块,大部分都是和机器人相关,然后软件这块就是和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​​

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

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

# 进入工程目录中的src目录下
cd /home/workspace/roslearn/src

# 创建功能包名为plumbing_my

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

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

<exec_depend>plumbing_server_client</exec_depend>
<exec_depend>plumbing_pub_sub</exec_depend>
<exec_depend>plumbing_param_server</exec_depend>

<!-- 新增一个<metapackage />标签 -->
<export>
<metapackage />
</export>

步骤三:修改CMakeLists.txt。

cmake_minimum_required(VERSION 3.0.2)
project(plumbing_my)
find_package(catkin REQUIRED)
catkin_metapackage()

  • 添加最后一行即可。

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

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

二、ROS节点管理launch文件

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

​​ros-wiki_roslaunch文档​​

# 进入工程目录中的src目录下
cd /home/workspace/roslearn/src

# 创建功能包名为launch01_basic

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

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

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

2.2、launch文件标签之group节点

介绍

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

属性:

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

实战示例

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

目的:启动两组相同的服务,看在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

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

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

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

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节点:

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

<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

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

2.3、launch文件标签之include

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

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

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

02turtle_include.launch:

<launch>
<!-- include表示直接包含某个launch文件,来直接启动 -->
<include file="$(find launch01_basic)/launch/01start_turtle.launch" />
</launch>

接着去编译执行一下:

source

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

2.4、launch文件标签之param

介绍

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

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

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

实战

创建launch文件:​​03turtle_parm.launch​

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

<launch>
<!-- param标签:向param服务器添加键值对参数 -->
<!-- 方式一:设置在与node节点同级 -->
<param name="param_a" type="int" value="100" />
<node pkg="turtlesim" type="turtlesim_node" name="changlu" output="screen">
<!-- 方式二:在node节点下添加param(这里在node节点对应的parm参数名称前要对应命名空间) -->
<param name="param_b" type="double" value="3.14" />
</node>
<node pkg="turtlesim" type="turtle_teleop_key" name="myTurtleContro" output="screen" />
</launch>

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

source

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

rosparam list

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

2.5、launch文件标签之rosparam

介绍

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

参数:

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

实战

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

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

load命令:04demo_rosparam.launch

<launch>
<!--
rosparam位置:node节点平级、node的子节点
commond="load",表示导入
-->
<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

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

dump命令:04demo_dumpparam.launch

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

<launch>
<!-- dump所有param -->
<rosparam command="dump" file="$(find launch01_basic)/launch/params_out.yaml" />
</launch>

执行命令:

source

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

delete功能:04demo_deleteparam.launch

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

执行命令:

source

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

实战

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

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

<launch>
<!--
default表示默认值,在命令行启动launch时可以不用传参也不会报错。
name表示参数名称
-->
<arg name="param1" default="haha"/>
<!-- 想要获取到arg标签中的参数需要使用表达式:$(arg xxx) -->
<param name="param1" value="$(arg param1)" />
</launch>

实际测试:

source ./devel/setup.bash

# 携带参数
roslaunch launch01_basic 06demo_arg.launch param1:=12

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

roslaunch launch01_basic 06demo_arg.launch

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

三、ROS工作空间覆盖

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

echo $ROS_PACKAGE_PATH

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

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

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

mkdir -p roslearn2/src
cd roslearn2
catkin_make
source

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

隐藏的一个bug问题

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

若是按照上面的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>
<!-- ns表示命名空间 -->
<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<std::string, std::string> 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<std_msgs::String>("/chatter",1000); //结果:/chatter

//相对名称:与命名空间、节点名称连接
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000); //结果:xx/chatter

//私有名称:节点名称为hello,并且设置了命名空间xx
ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000); //结果:/xx/hello/chatter

//使用~,而话题名称有时/开头时,那么话题名称是绝对的(不受影响)
ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise<std_msgs::String>("/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

步骤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

步骤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

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

主机:

roscore

# 弹出图像化界面

从机:

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

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

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

举报

相关推荐

0 条评论