ROS中launch文件的编写
launch文件介绍
ROS系统里的组成单位是节点(node),在启动ROS时需要启动所有的node,如果手动一一启动会是一项十分繁琐的事情,因此ROS通过launch文件可以同时启动多个node,而且launch文件会默认启动ROSMaster,不需要使用roscore来启动。
launch文件使用的XML文件格式,不清楚的同学可以戳这里XML文件基本格式。
我的感觉这个格式像C语言中的结构体,如果“结构体”中的变量没有嵌套“结构体”,可以用下面这种形式书写:
<class param1="value1" param2="value2" param3="value3" />
如果“结构体”中的变量有嵌套“结构体”,可以用下面这种形式书写:
<calss>
<class1>
<class1_param1="value1" />
</class1>
<class2>
<class2_param2="value2" />
</class2>
</class>
使用launch文件
launch文件不需要编译,启动launch文件之前需要先设置环境变量,在工作空间目录下使用命令行设置。
source devel/setup.bash
启动launch文件有两种启动方式。
#1.利用功能包启动
roslaunch pkg_name launchfile_name.launch
#2.利用绝对路径启动
roslaunch path_to_launchfile
两种启动方式launch文件后面都可以添加参数,常见的参数有:
--screen
:可以将node里的信息输出到屏幕上,生成log日志文件。arg:=value
: launch 文件中有待赋值的变量,可以通过这种方式赋值,例如:
roslaunch pkg_name file_name.launch model:=urdf/myfile.urdf #file_name.launch 中有参数 “model” 需要赋值
roslaunch pkg_name file_name.launch model:='$(find urdf_pkg)/urdf/myfile.urdf' # 用 find 命令提供路径
launch文件的标签
< launch >
launch文件的根标签必须是:
<launch>
...
....
...
</launch>
< include >
将一个launch文件嵌入另一个launch文件。具有两种格式:
<!--绝对路径-->
<include file="path_of_launch_file" />
<!--功能包-->
<include file="$(find package_name)/launch_file_name" />
有时,另一个 launch 引入的 node 可能需要统一命名,或者具有类似特征的 node 名字,比如 /vehicle1/gps, /vehicle1/lidar, /vehicle1/imu,即 node 具有统一的前缀,方便查找。这可以通过设置 ns (namespace)属性来实现,命令如下:
<include file="$(find package-name)/launch-file-name " ns="namespace_name" />
< node >
< node >就是launch文件启动节点的指令。其有许多配置参数:
pkg
:node所在的功能包名。type
:node代码生成的可执行文件的名字,(CMakeLists中的add_executable中可以修改)。name
:node的名字,在ros::init()中定义。respawn
:复位功能,node关闭可以重新启动。required
:必要节点,该节点关闭,其他节点也将终止。launch-prefix
:重新开一个窗口执行。output
:输出打印到终端屏幕,生成log日志。args
:节点需要输入的参数。ns
:命名空间,为节点内的相对名称添加命名空间前缀。
<launch>
<node
pkg="my_pkg"
type="my_node"
name="my_node"
respawn="true"
required="true"
launch-prefix="xterm -e"
args="value"
output="screen"
ns="some_namespace"
/>
</launch>
< remap >
重映射功能,将node中的话题名称进行重映射。这里需要清楚节点是发布者还是订阅者。
<!--节点是发布者将自身的origin_topic映射成new_topic发布出去 -->
<node pkg="my_pkg" type="my_node" name="my_node">
<remap from="origin_topic" to="new_topic" />
<!--节点是订阅者订阅first_topic映射成订阅second_topic -->
<node pkg="my_pkg" type="my_node" name="my_node">
<remap from="first_topic" to="second_topic" />
< arg >
相当于launch文件里的局部变量,只在launch文件中生效,可以从命令行输入,或是launch文件中定义,可以替换重复值,三种赋值方法:
<arg name="foo">
:声明一个 arg,但不赋值。稍后可以通过命令行赋值,或者通过 < include > tag 赋值。<arg name="foo" default="1">
:赋默认值。这个值可以被命令行和< include > tag 重写。<arg name="foo" value="1">
: 赋固定值,这个值不可以被改写。
<!--命令行赋值-->
roslaunch pkg_name file_name.launch arg1:=val1 arg2:=val2
<!--在文件中充当一个局部变量-->
<arg name="x" default="true"/>
<param name="use_x" value="$(arg x)"/>
< param >
param是ROS系统运行中的参数,存储在参数服务器中,因此param参数是共享的、全局的,与arg有区别,而且param的参数不仅仅是value,还可以是文件,命令行。
<param name="param_name" type="type1" value="val"/> # type可以省略,系统自动判断
<param name="param_name" textfile="$(find pkg)/path/file"/> # 读取 file 存成 string
<param name="param_name" command="$(find pkg)/exe '$(find pkg)/arg.txt'"/>
实例:
<param name="param" type="yaml" command="cat '$(find pkg)/*.yaml'"/> # command 的结果存在 param 中
param 可以是在 global scope 中,它的 name 就是原本的 name,也可以在某个更小的 scope 中,比如 node,那么它在全局的名字就是 node/param 形式。
<param name="publish_frequency" type="double" value="10.0" />
<node name="node1" pkg="pkg1" type="exe1">
<param name="param1" value="False"/>
</node>
如果用 rosparam list
列出server 中的 param,则有:
/publish_frequency
/node1/param1 # 自动加上了 namespace 前缀
注意:虽然 param 名字前加了 namespace,但是依然 global viewable。
< rosparam >
可以对param进行批量操作。
< group >
如果要对多个 node 进行同样的设置,比如都在同一个特定的 namespace,remap 相同的topic 等,可以用 tag。在 group 中可以使用所有常见的 tag 进行设置,例如:
<group ns="wg2">
<remap from="chatter" to="talker"/> # 对该 group 中后续所有 node 都有效
<node ... />
<node ... >
<remap from="chatter" to="talker1"/> # 各个 node 中可以重新设置 remap
</node>
</group>
本文参考博主链接:
https://www.jianshu.com/p/e55850b87c7d
如有侵权请告知