本章是学习ROS的运行管理
一个完整的ROS系统实现包含:多台主机,每个主机上有多个工作空间,每个工作空间包含多个功能包,每个功能包又包含不同名字的节点,每个节点又可能有不同话题
在一个项目中可能使用多个功能包,将不同的包打包成一个元功能包,在安装时直接调用
他是一个虚包,没有实质性内容,可以类比为一本书的目录索引,告诉我们集合中有哪些子包并该去哪里下载
案例:新建一个元功能包将两个功能包关联
新建一个功能包,依赖不用填写,因为他是虚包
之后的配置针对这俩配置文件
CMake首先删到只剩前三行
cmake_minimum_required(VERSION 3.0.2)
project(xubao)
find_package(catkin REQUIRED)
catkin_metapackage()
CMake唯一写法,不允许有空行,这样就完成了元功能包的创建
Launch基本语法
<launch>
<node pkg="turtlesim" type="turtlesim_node" name="my_gui" output="screen" />
<node pkg="turtlesim" type="turtle_teleop_key" name="my_key" output="screen" />
</launch>
Roslaunch自动启动roscore
<launch deprecated="此文件版本不建议使用">
这样在运行的时候就会报警告
<launch>标签是所有launch文件的根标签
<node>标签我们之前也使用过,用于指定ROS节点,是最常用的标签,注意的是在文档中的声明顺序不等于启动顺序,节点的启动是多进程的
node pkg="turtlesim" type="turtlesim_node" name="my_gui" output="screen" respawn="true"/>
这样子之后乌龟就关不掉了
ns:命名空间
假设一个情景,我们此例的启动乌龟是一种基本功能,在一个新的launch文件中我们要在他的基础上增加功能,通过include标签实现复用
属性有file=“$find(包名)/launch/xx.launch”以及ns=“xxx”
<include file="$(find launch01)/launch/fuyong.launch"/>
remap标签,直接使用rosrun teleop_twist_keyboard teleop_twist_keyboard.py使用的话题是/cmd_vel,与我们乌龟节点使用话题不一样,因此没法实现控制
<remap from="/turtle1/cmd_vel" to="/cmd_vel" />
param标签,用于在参数服务器上设置参数,注意配置完value得配下type,不然会自己解析
在launch下,node外设置可以不带节点名称的前缀
<param name="AA" type="int" value="100"/>
rosparam可以从YAML文件导入参数或者将参数导出到YAML文件,也可以用来删除参数,同样的,如果写在node节点下会被视为私有
属性有command=load|dump|delete加载导出或删除参数,file=用来加载或到处yaml文件,param=参数名称
<rosparam command="load" file="$(find launch01)/launch/1.yaml"/>
在launch文件夹下新建一个yaml文件
一个问题:rosparam在launch里是最优先执行的,所以在导出参数到yaml文件时,很可能发现和预期不一样,很多参数还没来得及定义,解决方法是再定义一个launch文件专门获取环境参数
group标签,ns=名称空间,让节点归属某个命名空间,案例比如启动两对乌龟节点
<launch>
<group ns="11">
<node pkg="turtlesim" type="turtlesim_node" name="my_gui" output="screen" respawn="true"/>
<node pkg="turtlesim" type="turtle_teleop_key" name="my_key" output="screen"/>
</group>
<group ns="22">
<node pkg="turtlesim" type="turtlesim_node" name="my_gui" output="screen" respawn="true"/>
<node pkg="turtlesim" type="turtle_teleop_key" name="my_key" output="screen"/>
</group>
</launch>
这样就可以打开两组乌龟与控制
arg标签,用于动态传参,属性:name=参数名称,default=数值(意思是如果不给他指定值默认值是多少),value=数值,doc=描述
情景:需要设置多个变量,他们使用同一个数值
暴力版
<launch>
<arg name="car_length" default="0.55"/>
<param name="A" value="$(arg car_length)"/>
<param name="B" value="$(arg car_length)"/>
</launch>
这种配置后修改就不用全改,且可以在roslaunch xx.launch 后面跟上car_length=0.6
重名问题
功能包重名(工作空间覆盖)
先在demo01_ws与demo02_ws下新建一个功能包helloworld,为了能在任何终端都调用,在主目录下CTRL+H,打开.bashrc文件,将两个文件的devel文件夹下的setup.bash的地址加到最后
之后调用rosrun helloworld自动补齐发现调用的是demo02下的,因为后刷新的环境变量调用优先级高一些,这样做风险很大
解决思路:设置命名空间(前缀)或者起别名
rosrun时设置ns,注意__ns有两个_
rosrun时设置name,同样__name有两个杠
注意这两种可以叠加__name:-xx __ns:=xx
通过launch文件配置,之前学习过
<node pkg="turtlesim" name="turtle1" type="turtlesim_node" output="screen"/>
<node pkg="turtlesim" name="turtle2" type="turtlesim_node" output="screen"/>
<node pkg="turtlesim" name="turtle1" type="turtlesim_node" output="screen" ns="gui"/>
分别采用别名和命名空间,一下开三龟
最后一种是自定义节点init_node时可以搞anonymous=Ture
话题重名,万一数据载体一样,直接爆炸;或者两个本来想通信的,但名字不一样
案例就是之前键盘控制,ros-noetic-teleop-twist-keyboard话题/cmd_vel与/turtle/cmd_vel不匹配无法控制
直接rosrun里面改 /cmd_vel=/turtle1/cmd_vel
在launch下使用remap修改话题名称
<node pkg="turtlesim" name="turtle1" type="turtlesim_node" output="screen" />
<node pkg="teleop_twist_keyboard" name="keyy" type="teleop_twist_keyboard.py">
<remap from="/cmd_vel" to="/turtle1/cmd_vel"/>
</node>
话题的名称与节点的命名空间以及节点的名称有一定关系
全局(话题参考ROS系统,与节点命名空间平级)
相对(话题参考节点的命名空间,与节点名称平级)
私有(话题参考节点名称,是节点名称的子集)
接下来在python下测试下话题的名称
#全局
pub1=rospy.Publisher("/test",String,queue_size=10)
#相对
pub2=rospy.Publisher("test",String,queue_size=10)
#私有
pub2=rospy.Publisher("~test",String,queue_size=10)
最后是参数重名,参数重名会发生数值覆盖,为了避免这样,采用命名空间的办法,同样是有全局,相对和私有三种类型
rosrun 包名 节点名 _参数名:=参数值;是一种私有的设置方式
<launch>
<param name="r" value="0.2"/>
<node name="t" ns="xx" pkg="turtlesim" type="turtlesim_node">
<param name="r" value="0.2"/>
</node>
</launch>
使用launch来设置参数,在node外是全局的,在node内是私有的
两个r参数名字不同
之后是python设置,跟之前一样/全局,啥都不写相对,~私有
rospy.set_param("/aa",10)
rospy.set_param("aa",10)
rospy.set_param("~aa",10)
这章的最后看一下分布式通信,一个运行中的ROS系统可以包含分布在多台计算机的多个节点,任何节点可能随时需要与任何其他节点通信
需要俩机器,后期再做