目录
机器人是一个庞大的系统工程,当机器人运行时,通常要开启很多个node。对于一个复杂的机器人的启动应该怎么做呢?难道对每个节点依次进行rosrun?肯定不是这样的,这样太麻烦了,ROS为我们提供了一个命令能一次性启动master和多个node。该命令是:
roslaunch pkg_name file_name.launch
roslaunch命令首先会自动进行检测系统的roscore有没有运行,也即是确认节点管理器是否在运行状态中,如果master没有启动,那么roslaunch就会首先启动master,然后再按照launch的规则执行。launch文件里已经配置好了启动的规则。 所以 roslaunch 就像是一个启动工具,能够一次性把多个节点按照我们预先的配置启动起来,减少我们在终端中一条条输入指令的麻烦。
接下来,我们来看看launch文件的构成:
<launch>
<node pkg="mrobot_bringup" type="mrobot_bringup" name="mrobot_bringup" output="screen" />
<arg name="urdf_file" default="$(find xacro)/xacro --inorder '$(find mrobot_description)/urdf/mrobot_with_rplidar.urdf.xacro'" />
<param name="robot_description" command="$(arg urdf_file)" />
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="state_publisher">
<param name="publish_frequency" type="double" value="5.0" />
</node>
<node name="base2laser" pkg="tf" type="static_transform_publisher" args="0 0 0 0 0 0 1 /base_link /laser 50"/>
<node pkg="robot_pose_ekf" type="robot_pose_ekf" name="robot_pose_ekf">
<remap from="robot_pose_ekf/odom_combined" to="odom_combined"/>
<param name="freq" value="10.0"/>
<param name="sensor_timeout" value="1.0"/>
<param name="publish_tf" value="true"/>
<param name="odom_used" value="true"/>
<param name="imu_used" value="false"/>
<param name="vo_used" value="false"/>
<param name="output_frame" value="odom"/>
</node>
<include file="$(find mrobot_bringup)/launch/rplidar.launch" />
</launch>
1.launch
XML文件必须要包含一个根元素,launch文件中的根元素采用<launch>标签定义,文件中的其他内容都必须包含在这个标签之中:
<launch>
…
</launch>
2.node
启动文件的核心是启动ROS节点,采用<node>标签定义,包括以下几个参数:
- pkg=”mypackage”: 节点的功能包
- type=”nodetype”: 节点的类型,节点类型是可执行文件(节点)的名称
- name=”nodename”: 节点的名字
- args=”arg1 arg2 arg3”:(可选)传递给节点的参数
- respawn=”true”: (可选)是否自动重启,true 表示如何节点未启动,则自动重启,false 则不重启,默认 false
- ns=”foo”: (可选)在”foo”命名空间启动节点
- output=”log|screen”: (可选)如果选择screen,节点的stdout(标准输出)和stderr(标准错误)信息将显示在终端窗口上;如果选择log,stdout和stderr将发送到一个log文件,stderr也会显示在终端窗口上
下面是一个启动节点的例子:启动gazebo功能包中的gazebo节点,该节点的参数是r2_grap.world文件中的内容,节点的stdout和stderr会显示在终端窗口上。如果gazebo节点停止,不能重新启动。
<node name=”gazebo” pkg=”gazebo” type=”gazebo” args=”$(find r2_gazebo)/gazebo/r2_grap.world”` `output=”screen” respawn=”false”/>
在 node 标签下页可以嵌套使用以下标签:
-
param:为节点设置参数
-
rosparam:为节点加载 rosparam 文件
-
remap:为节点设置重映射参数
-
env:为节点设置环境变量
3. param
parameter是ROS系统运行中的参数,存储在参数服务器中。在launch文件中通过<param>元素加载parameter;launch文件执行后,parameter就加载到ROS的参数服务器上了。每个活跃的节点都可以通过 ros::param::get()接口来获取parameter的值,用户也可以在终端中通过rosparam命令获得parameter的值。param 的参数值可以通过文本文件、二进制文件或命令等属性来设置,另外 param 标签可以嵌入到 node 标签中,以此来作为该 node 的私有参数。
-
name:参数名称
-
type:参数类型 str|int|double|bool
-
value:参数值
-
Textfile=” (findpkg−name)/path/file”(可选)
-
binfile=”(find pkg-name)/path/file” (可选)
-
command=” (find pkg-name)/exe’ $(find pkg-name)/arg.txt’” (可选)exe是可执行文件,arg.txt参数文件
<param name="publish_frequency" type="double" value="10.0">
4.rosparam
rosparam可以帮助我们将一个yaml格式文件中的参数全部加载到ROS参数服务器中,需要设置command属性为“load”,还可以选择设置命名空间“ns”。
# 参数较多使用 yaml 文件
<rosparam command="load" file="$(find rosparam)/example.yaml">
<rosparam command="delete" param="my/param">
# 传递数组
<rosparam param="a_list">[1, 2, 3, 4]</rosparam>
<rosparam>
a: 1
b: 2</rosparam><arg name="whitelist" default="[3, 2]"/>
<rosparam param="whitelist" subt_value="True">$(arg whitelist)
</rosparam>
-
command:load,dump,delete
-
file:参数文件的路径
-
param:参数名称
-
subt_value:是否允许在 YAML 中替换参数
5.remap
remap标签提供了一种节点名称的重映射方法,每个 remap 标签包含一个元素名称和一个新名称,在系统运行后原始名称会被替换为新名称。
From=”original-name”
To=”new-name”
例子:将接受的主题chatter换成hello
<ramap from=”chatter” to=”hello”/>
可以这样理解这个替换标签:你有一个节点订阅了「chatter」主题,但是你只有一个节点发布「hello」主题,而「hello」和「chatter」的类型相同,所以我们可以将「chatter」简单地替换为「hello」,从而实现订阅「hello」主题。
6.env
env 标签可以在启动的节点上设置环境变量,这个标签基本只会使用在 launch、include、node、machine 这 4 个标签内部,当使用在 launch 内部时,env 设置的环境标量会应用到内部定义的节点。
参数
- Name=”environment-variable-name”设置环境变量名字
- Value=” environment-variable-value”设置环境变量的值
<env name="ENV_EXAMPLE" value="some value" />
7.include
include 类似编程语言中的 include 预处理,它可以在当前launch文件中调用另一个launch文件。
<include file=”$(find pr2_controller_manager)/controller_manager.launch”/>
8.machine
machine 标签定义了节点所运行的机器信息,如果只是在本地运行节点则不需要配置这个标签,它主要使用在 SSH 和远程机器,不过也可以用来配置本地机器的相关信息。
<launch>
<machine name="foo" address="foo-address" env-loader="/opt/ros/kinetic/env.sh" user="someone">
<node machine="foo" name="footalker" pkg="test_ros" type="talker.py">
</launch>
-
name:机器名称
-
address:机器的网络地址
-
env-loader:设置机器的环境变量,必须是一个设置了所有要求变量的 shell 脚本
-
user:用户名称
9.arg
arg 标签表示启动参数,该标签允许创建更多可重用和可配置的启动文件,其可以通过命令行、include 标签、定义在高级别的文件这 3 种方式配置值。
arg 标签声明的参数不是全局的,类似于launch文件内部的局部变量,可以当成函数的局部参数来理解,仅限于声明的launch文件中使用,便于launch文件的重构,和ROS节点内部的实现没有关系。
<arg name="arg_name" default="arg_name">
<arg name="arg_name" value="arg_name">
launch文件中需要使用到arg时,可以使用如下方式调用:
<paramname="foo" value="$(argarg-name)" />
<node name="node" pkg="package" type="type "args="$(arg arg-name)" />
注意 arg 和 param 标签的区别:
-
arg:启动时参数,只在启动文件 launch 中有意义
-
param:运行时参数,存储在参数服务器中
10.group
group 标签可以方便的将一组配置应用到组内的所有节点,它也具有命名空间 ns 特点,可以将不同的节点放入不同的 namespace。
常见用法如下:
<group ns="namespace">
<node pkg="pkg_name1" .../>
<node pkg="pkg_name2" .../>
...
</group>
配合 if 和 unless 使用:
-
if=value:value 为 true 则包含内部信息
-
unless=value:value 为 false 则包含内部信息
<group if="$(arg foo1)">
<node pkg="pkg_name1" .../>
</group>
<group unless="$(arg foo2)">
<node pkg="pkg_name2" .../>
</group>
-
当 foo1 == true 时包含其标签内部
-
当 foo2 == false 时包含其标签内部
11. test
test 标签在语法上类似 node 标签,但在功能上只表示当前的节点作为测试节点去运行。
常见用法如下:
<test test-name="test_1" pkg="my_pkg" type="test_1.py" time-limit="10.0" args="--test1">
-
test-name:测试节点名称
-
pkg:测试节点所在的包
-
type:测试节点类型
-
time-limit:超时时间
-
arg:测试节点启动的命令参数