ROS launch文件学习了一天,觉得网站上的文章都太不负责了,于是就写了这个,欢迎关注公众号"小秋SLAM笔记"!
官方文档:http://wiki.ros.org/roslaunch/XML
launch文件中的根元素采用标签定义,文件中的其他内容都必须包含在这个标签中。
标签语法格式
<launch>
</launch>
启动文件的核心是启动ROS节点,采用
标签定义。
标签语法格式
<node pkg="package-name" type="executable-name" name="node-name"/>
pkg:节点所在功能包名称
type: 节点可执行文件名称
这两个属性等同于在终端中使用rosrun命令执行节点
name:节点运行时的名称,将覆盖节点init()赋予节点的名称
args=“arg1 arg2 arg3”(optional) 节点需要的输入参数。
machine=“machine-name”(optional, see ) launch文件中运行的每个节点可以指定该节点运行的machine,
respawn=“true”(optional, default: False) 复位属性,该节点停止时,会自动重启,默认为false。
respawn_delay=“30” (optional, default 0) 尝试重新启动之前检测到节点故障后等待时间。
required=“true”(optional) 必要节点,当该节点停止时,launch文件中的其他节点也会被终止。
ns=“foo”(optional) 命名空间,为节点内的相对名称添加命名空间前缀
clear_params=“true|false”(optional) 在启动前删除节点的私有命名空间中的所有参数。
output=“log|screen”(optional) 将节点的标准输出打印到终端屏幕,默认输出为日志文档
cwd=“ROS_HOME|node”(optional) 如果为“node”,则节点的工作目录将设置为与节点的可执行文件相同的目录。
launch-prefix=“prefix arguments”(optional) 用于预先添加到节点的启动参数的命令/参数
标签调用样例
<node name="listener1" pkg="rospy_tutorials" type="listener.py" args="--test" respawn="true" />
<node name="bar1" pkg="foo_pkg" type="bar" args="$(find baz_pkg)/resources/map.pgm" />
<arg name="rtabmapviz" default="true"/>
name是参数的名称
Value是参数的值
default设定预设值
命令行方式可以覆盖default的值,但是不能覆盖 value 。
$(arg arg-name)
如何获取数值
roslaunch package-name launch-file-name arg-name:=arg-value
命令行使用方式
给出一个节点原来的名字和新的名字, 中间用:=分开
<remap from="left/image_rect" to="/camera/infra1/image_rect_raw"/>
在launch文件中,我们现在把数据的话题left/image_rect名称改为:/camera/infra1/image_rect_raw。
<include file="path-to-launch-file">
<arg name="arg-name" value="arg-value"/>
</include>
在 include 元素中插入 arg 元素作为 include 元素的子类(children),递给 include 元素里包含的子launch文件使用。
<arg name="arg-name" value="$(arg arg-name)" />
被包含(included)的launch文件和本launch文件会有共同的参数
在这两个地方使用相同的argument name (参数名)。
复杂系统有很多launch文件,它们之间存在依赖关系,可以复用已经有的launch文件。
包含其他文件这个file属性期望我们添加想要包含的文件的完整路径。
大多数时候,include 使用find命令来搜索程序包,代替一个明确的完整路径:
<include file="$(find package-name)/launch-file-name" />
include 也支持 ns 属性,可以让这个文件里的内容推送到一个命名空间里面:
<include file=". . . " ns="namespace" />
example:
<include file="$(find realsense2_camera)/launch/rs_camera.launch">
<arg name="align_depth" value="true"/>
<arg name="unite_imu_method" value="linear_interpolation"/>
</include>
补充资料:
https://durant35.github.io/2017/07/14/ROS_%3Carg%3E %3Cparam%3E %3Crosparam%3E/
http://www.guyuehome.com/2195
<param name="output_frame" value="odom"/>
运行launch文件后。output_frame这个parameter的值就设置为odom,并接加载到ROS参数服务器上了。用户也可以通过rosparam命令获得parameter的值。
rosrun param_test param_test output_frame:=odom
命令行使用方式
重映射机制,提高代码的复用率,
标签语法格式
<remap from="publishes topic" to="subscribes topic" />
在启动一个节点的时候,有两种方法创建重映射:
在终端命令行中启动一个节点时,要重新给这个节点命名:给出一个节点原来的名字和新的名字, 中间用:=分开。 original-name:=new-name
例如,在运行turtlesim实例时,我们现在想把发布姿态数据的话题/turtle1/pose名称改 为:/tim,那么命令就是这样的:$ rosrun turtlesim turtlesim_node turtle1/pose:=tim
在launch文件中重新命名:使用 remap 元素:
<remap from="original-name" to="new-name" />
节点发布的话题,节点接收的话题。
如果这个 remap 是 launch 元素的一个child(子类),与 node 元素同一层级,
并在launch元素内的最顶层。 那么这个 remapping 将会作用于后续所有的节点。
这个remap元素也可以作为 node 元素的一个child(子类)出现。下面这个就是使用模板:
<node node-attributes >
<remap from="original-name" to="new-name" />
. . .
</node>
例如:上面命令行命令如果在launch文件中,就是下面这个样子的:
<node pkg="turtlesim" type="turtlesim_node"
name="turtlesim" >
<remap from="turtle1/pose" to="tim" />
</node>
标签调用样例
<remap from="/image_raw" to="/camera/image_raw"/>
所有ROS节点内的资源名称都可以在节点启动时进行重映射。
命名重映射语法格式
name:=new_name
节点发布的话题,节点接收的话题。
命名重映射调用样例
rosbag play ros.bag /image_raw:=/camera/image_raw
rosrun rospy_tutorials talker chatter:=/new/chatter
标签定义命名空间
标签语法格式
<group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<group ns="turtlesim2">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
在这里我们创建了两个节点分组并以’命名空间(namespace)’标签来区分,
其中一个名为turtulesim1,另一个名为turtlesim2,
两个组里面都使用相同的turtlesim节点并命名为’sim’。
这样可以让我们同时启动两个turtlesim模拟器而不会产生命名冲突。
(当然如果直接用不同的命名也是可以的,比如一个叫sim_1,一个叫sim_2,这样也可以同时多次启动同一节点).
<group if="0-or-1" />
. . .
</group>
如果 if 属性的值是 1 , 标签内封闭的元素(elements)会被包含。
如果 if 属性 值是 0 ,则 标签内包含的元素会被忽略。
unless 属性的工作方式类似 if 属性,但是含义颠倒:
<group unless="1-or-0" />
. . .
</group>
第一种情况,当if属性的值为0的时候将会忽略掉之间的标签。
第二种恰好相反,当if属性的值为1的时候将会忽略掉之间的标签。
但是我们通常不会直接用1或0来定义if标签。因为这样不够灵活。
通常会搭配$(arg arg_name)来使用。
讲完原理来讲一下实际的例子吧!
我的系统是 ubuntu 16.04 ROS版本是kinetic
下面我们用检查ROS是否成功安装的小乌龟例子讲解
打开三个终端 运行下面三条命令
rosrun 后面接的是功能包里面的可执行文件名字,这个可执行文件就是节点的名字。
roslaunch 后面接的是launch启动文件,同时启动多个可执行文件,也就是节点。
rostopic list 终端输入这个命令后可以显示活动的话题目录
/rosout
/rosout_agg
/statistics
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
终端输入rqt_graph
显示如下图所示:
我们再来看第二个例子
终端运行:roslaunch turtle_tf turtle_tf_demo.launch
gedit /opt/ros/kinetic/share/turtle_tf/launch/turtle_tf_demo.launch
<launch>
<!-- Turtlesim Node-->
<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
<!-- Axes -->
<param name="scale_linear" value="2" type="double"/>
<param name="scale_angular" value="2" type="double"/>
<node name="turtle1_tf_broadcaster" pkg="turtle_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
<param name="turtle" type="string" value="turtle1" />
</node>
<node name="turtle2_tf_broadcaster" pkg="turtle_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
<param name="turtle" type="string" value="turtle2" />
</node>
<node name="turtle_pointer" pkg="turtle_tf" type="turtle_tf_listener.py" respawn="false" output="screen" >
</node>
</launch>
终端运行:rostopic list
/rosout
/rosout_agg
/tf
/tf_static
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
/turtle2/cmd_vel
/turtle2/color_sensor
/turtle2/pose
终端运行 rosrun rqt_graph rqt_graph
椭圆代表的是节点,方框代表的是负责节点间通信的话题。
<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
pkg="turtlesim"
节点所在功能包的名字
type="turtlesim_node" 节点的名字 也就是可执行文件或者py程序的名字
name="sim"
定义节点的名称,将覆盖节点init()赋予节点的名称
每个活跃的节点都可以通过rosparam来获取parameter的值
Commands:
rosparam set set parameter
rosparam get get parameter
rosparam load load parameters from file
rosparam dump dump parameters to file
rosparam delete delete parameter
rosparam list list parameter names
<param name="scale_linear" value="2" type="double"/>
<param name="scale_angular" value="2" type="double"/>
<param name="turtle" type="string" value="turtle1" />
<param name="turtle" type="string" value="turtle2" />
终端输入:rosparam get scale_angular
输出:2.0