本文主要介绍了导航功能包集的配置和使用。
1 机器人设置
假定我们已经以特定方式设置好了机器人,导航功能包集将使其可以运动。上图概述了这种配置方式。白色的部分是必须且已实现的组件,灰色的部分是可选且已实现的组件,蓝色的部分是必须为每一个机器人平台定制创建的组件。
1.1 ROS
导航功能包集假定你的机器人使用ROS系统。请查阅ROS documentation以了解如何在你的机器人上安装ROS。
1.2 TF变换配置(其他变换)
导航功能包集需要机器人不断使用tf发布有关坐标系之间的关系的信息。详细的配置教程请查阅:Tf配置.
1.3 传感器信息(sensor source)
导航功能包集使用来自传感器的信息实现避开物理环境中的障碍物,并且假定这些传感器在ROS上不断发布sensor_msgs/LaserScan消息或者sensor_msgs/PointCloud消息。有关在ROS上发布这些消息的教程,请查阅在ROS上发布传感器数据流。以下是部分ROS已经支持的传感器以及相关驱动链接:
-
SCIP2.2-compliant Hokuyo Laser Devices as well as the Hokuyo Model 04LX, 30LX -urg_node(英文)
-
SICK LMS2xx Lasers - sicktoolbox_wrapper(英文)
1.4 里程信息(odometry source)
导航功能包集需要使用通过tf和nav_msgs/Odometry消息发布的里程信息。这里有一篇如何发布里程信息的教程:在ROS上发布里程信息. 以下列出部分支持里程计的平台以及可用的驱动:
-
Videre Erratic: erratic_player(英文)
1.5 基座控制器(base controller)
导航功能包集通过在"cmd_vel" topic上发布geometry_msgs/Twist类型的消息,以达到给基座发送速度命令控制基座移动目的。这意味着必须有一个节点订阅"cmd_vel" topic, 该topic上的速度信息为(vx, vy, vtheta)<===>(cmd_vel.linear.x, cmd_vel.linear.y, cmd_vel.angular.z),并能将这些速度信息转换成控制马达的命令发送给移动基座。
以下列出部分支持基座控制器的平台以及可用的驱动:
-
Videre Erratic: erratic_player(英文)
1.6 地图 (map_server)
虽然导航功能包集的配置并不需要操作地图,但考虑到下面使用案例,我们假定你有一张地图。如果没有请查阅教程创建一张地图了解如何在你的系统环境下创建一张地图的细节。
2 导航功能包集设置
本部分将介绍如何配置导航功能包集。假设上述所有需要的环境都已满足。这里特别提醒的是,机器人必须能够使用tf发布坐标帧,能接收来自传感器的sensor_msgs/LaserScan 或者sensor_msgs/PointCloud 消息供导航功能包集使用,能使用tf 和nav_msgs/Odometry 消息发布里程消息,也能接受速度命令并发给基座。如果机器人所需要的这些配置你都没有,请参考上面的机器人配置完成它们。
2.1 创建一个package
首先,我们创建一个package来保存使用导航功能包集所必须配置文件和启动文件。 这个package依赖一些其它的packages用于实现机器人配置小节所述,以及提供了供导航功能包集访问接口的move_base 包。
现在为你的package选好位置,并执行以下命令:
catkin_create_pkg my_robot_name_2dnav move_base my_tf_configuration_dep my_odom_configuration_dep my_sensor_configuration_dep
2.2 创建机器人启动配置文件
现在,我们有了一个存放配置文件和启动文件的工作空间,我们会创建一个roslaunch文件来启动所有的硬件并发布机器人所需的tf。请粘贴如下内容到my_robot_configuration.launch。你可以将 "my_robot" 改成你的机器人的名字。下面你也可以对用到的launch文件做相似的更改。
<launch>
<node pkg="sensor_node_pkg" type="sensor_node_type" name="sensor_node_name" output="screen">
<param name="sensor_param" value="param_value" />
</node>
<node pkg="odom_node_pkg" type="odom_node_type" name="odom_node" output="screen">
<param name="odom_param" value="param_value" />
</node>
<node pkg="transform_configuration_pkg" type="transform_configuration_type" name="transform_configuration_name" output="screen">
<param name="transform_configuration_param" value="param_value" />
</node>
</launch>
好了,现在我们有了一个launch文件模板,但是,我们需要根据自己的机器人去完善它。以下章节,我们会逐步的改变它。
<node pkg="sensor_node_pkg" type="sensor_node_type" name="sensor_node_name" output="screen">
<param name="sensor_param" value="param_value" />
</node>
上面节点会启动机器人运行导航功能包所需的传感器。用你的传感器对应的ROS驱动包替换"sensor_node_pkg",用你的传感器类型替换"sensor_node_type"(通常与节点名一致),用你的传感器节点名替换"sensor_node_name","sensor_param"包含所有必需的参数。注意,如果你有多个传感器,在这里一起定义它们。
<node pkg="odom_node_pkg" type="odom_node_type" name="odom_node" output="screen">
<param name="odom_param" value="param_value" />
</node>
上面我们启动基座(底盘)的里程计。同样,替换相应的pkg, type, name,并根据实际指定相关参数。
<node pkg="transform_configuration_pkg" type="transform_configuration_type" name="transform_configuration_name" output="screen">
<param name="transform_configuration_param" value="param_value" />
</node>
上面我们启动相应的tf变换。同样,替换相应的pkg, type, name,并根据实际指定相关参数。
2.3 配置代价地图 (local_costmap) & (global_costmap)
导航功能包集需要两个代价地图来保存现实世界中的障碍物信息。一张代价地图用于在整个环境中创建长期的规划,另一个用于局部规划与实时避障。有一些参数两个地图都需要,而有一些则各不相同。因此,对于代价地图,有三个配置项: common配置项, global配置项和local配置项。
注意: 接下来的内容只是代价地图的基本配置项。想要查看完整的配置,参看costmap_2d文档.
2.3.1 共同配置(local_costmap) & (global_costmap)
导航功能包集使用代价地图存储障碍物信息。 这里我们需要指出要监听的传感器的话题,以更新数据。
为此我们创建一个名为costmap_common_params.yaml的文件,内容如下:
obstacle_range: 2.5
raytrace_range: 3.0
footprint: [[x0, y0], [x1, y1], ... [xn, yn]]
#robot_radius: ir_of_robot
inflation_radius: 0.55
observation_sources: laser_scan_sensor point_cloud_sensor
laser_scan_sensor: {sensor_frame: frame_name, data_type: LaserScan, topic: topic_name, marking: true, clearing: true}
point_cloud_sensor: {sensor_frame: frame_name, data_type: PointCloud, topic: topic_name, marking: true, clearing: true}
以上代码解释如下:
obstacle_range: 2.5
raytrace_range: 3.0
这些参数设置代价地图的障碍信息的阈值。 “obstacle_range”参数决定了引入障碍物到代价地图的传感器探测的最大范围。 在这里,我们把它设定为2.5米,这意味着机器人只会更新以其底盘为中心半径2.5米内的障碍信息到代价地图。 “raytrace_range”参数用于机器人移动过程中实时清除范围中障碍物以获得自由移动空间。设置为3.0米意味着机器人将基于传感器数据试图清除其前面3.0米远的空间内的障碍物以获得自由空间。
footprint: [[x0, y0], [x1, y1], ... [xn, yn]]
#robot_radius: ir_of_robot
inflation_radius: 0.55
这里我们设置机器人的footprint或机器人半径(如果是圆形的)。 指定的footprint时,机器人的中心被认为是原点(0.0,0.0),顺时针和逆时针规范都支持。 将机器人的几何参数告诉导航功能包集。这样,机器人和障碍物之间就能保持一个合理的距离,也就是说,例如前方有个门,要提前探知机器人是否能穿过这个门。我们还将设置代价地图膨胀半径inflation_radius,给定机器人与障碍物之间必须要保持的最小距离。按照机器人的内切半径对障碍物进行膨胀处理。 例如,膨胀半径设定在0.55米意味着机器人在所有路径与障碍物保持0.55米或更的远离。
observation_sources: laser_scan_sensor point_cloud_sensor
“observation_sources”参数定义了一系列传递空间信息给代价地图的传感器。
laser_scan_sensor: {sensor_frame: frame_name, data_type: LaserScan, topic: topic_name, marking: true, clearing: true}
这一行设置“observation_sources”中提到的传感器。这个例子定义了 laser_scan_sensor。 “frame_name”参数应设置为传感器坐标帧的名称,“data_type”参数应设置为LaserScan或PointCloud,这取决于主题使用的消息,“topic_name”应该设置为发布传感器数据的主题的名称。 “marking”和“clearing”参数确定传感器是否用于向代价地图添加障碍物信息,或从代价地图清除障碍信息,或两者都有。
2.3.2 全局配置(global_costmap)
下面我们将创建一个存储特定的全局代价地图配置选项的文件。新建一个文件:global_costmap_params.yaml并粘贴以下内容:
global_costmap:
global_frame: /map
robot_base_frame: base_link
update_frequency: 5.0
static_map: true
“global_frame”参数定义了代价地图运行所在的坐标系。在这种情况下,我们会选择/map坐标系。 “robot_base_frame”参数定义了代价地图参考的的机器人基座坐标系。global_costmap和robot_base_frame定义机器人和地图之间的坐标变换,建立全局代价地图必须使用这个变换。“update_frequency”参数决定了代价地图更新的频率。 “static_map”参数决定代价地图是否根据map_server提供的地图初始化。如果你不使用现有的地图,设为false。
2.3.3 本地配置(local_costmap)
下面我们将创建一个存储特定的本地代价地图配置的文件。新建一个文件:localal_costmap_params.yaml并粘贴以下内容:
local_costmap:
global_frame: odom
robot_base_frame: base_link
update_frequency: 5.0
publish_frequency: 2.0
static_map: false
rolling_window: true
width: 6.0
height: 6.0
resolution: 0.05
“global_frame”,“robot_base_frame”,“update_frequency”,“static_map”参数与全局配置意义相同。“publish_frequency”参数决定了代价地图发布可视化信息的频率。将“rolling_window”参数设置为true,意味着随着机器人在现实世界里移动,代价地图会保持以机器人为中心,不用滚动窗口。“width”、“height”,“resolution”参数分别设置代价地图的宽度(米、)高度(米)和分辨率(米/单元)。 注意,这里的分辨率和你的静态地图的分辨率可能不同,但我们通常把他们设成一样的。
2.3.4 完整的配置选项
这里是用于启动和运行的最简单的配置,更多的代价地图设置细节请参阅costmap_2d 文档.
2.4 基座局部规划器配置
Base_local_planner负责根据高层规划,计算发送给机器人基座的速度命令。 我们需要根据我们的机器人规格,配置一些选项使其正常启动与运行。
新建一个名为base_local_planner_params.yaml的文件,内容如下:
注意: 本节只涵盖额TrajectoryPlanner的一些基本配置选项。 文档的全部选项,请参阅base_local_planner 文档.
TrajectoryPlannerROS:
max_vel_x: 0.45
min_vel_x: 0.1
max_vel_theta: 1.0
min_in_place_vel_theta: 0.4
acc_lim_theta: 3.2
acc_lim_x: 2.5
acc_lim_y: 2.5
holonomic_robot: true
上面的第一部分参数定义机器人的速度限制。 第二部分定义了机器人的加速度的限制。 holonomic_robot: 如果你的机器人是全向移动机器人那么此值为true,差分型的为false。
2.5 为导航功能包集创建一个启动文件
现在我们已经有了所有的配置文件,我么可以使用前面创建的配置文件为导航功能包集创建一个启动文件,创建一个名为move_base.launch的文件,内容如下:
<launch>
<master auto="start"/>
<!-- Run the map server -->
<node name="map_server" pkg="map_server" type="map_server" args="$(find my_map_package)/my_map.pgm my_map_resolution"/>
<!--- Run AMCL -->
<include file="$(find amcl)/examples/amcl_omni.launch" />
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find my_robot_name_2dnav)/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find my_robot_name_2dnav)/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find my_robot_name_2dnav)/local_costmap_params.yaml" command="load" />
<rosparam file="$(find my_robot_name_2dnav)/global_costmap_params.yaml" command="load" />
<rosparam file="$(find my_robot_name_2dnav)/base_local_planner_params.yaml" command="load" />
</node>
</launch>
唯一需要修改的地方是更改地图服务器指向你的已有的地图,并且如果你有一台差分驱动的机器人,将"amcl_omni.launch"改为"amcl_diff.launch"。
对于如何创建一张地图,请查阅创建一张地图.
2.6 AMCL 配置(amcl)
AMCL有许多配置选项会影响定位的性能。 有关AMCL的更多信息请参阅amcl文档.
利用自适应蒙特卡罗定位(AMCL)算法完成机器人定位,该方法是一种在2D环境下移动机器人的概率统计方法,这种方法在ROS系统中的具体实现是通过在已知地图的基础上使用粒子滤波算法跟踪机器人的位姿。如果你在rviz里不通过2D Pose Estimate 按钮设定初始位姿,则AMCL会假定你的机器人从坐标原点开始运行。这个包默认激光雷达数据,你也可以修改源码,适应如双目之类的传感器。amcl_diff.launch是专用于支持差分驱动机器人平台的。
3 运行导航功能包集
现在配置结束了,我们可以运行导航功能包集了。为此我们需要在机器人上启动两个终端。 在一个终端上,我们将运行有关机器人设置的 my_robot_configuration.launch 文件,在另一个终端上我们将启动我们刚刚创建的用于导航功能的move_base.launch。
终端1:
roslaunch my_robot_configuration.launch
终端2:
roslaunch move_base.launch
关于如何通过图形化界面给导航功能包集发送目标信息,请参阅rviz和导航教程。 如果你想使用代码给导航功能包集发送导航目标,请参阅发送简单导航目标教程。
4 故障排除
关于运行导航功能包集时遇到的常见问题,请参阅导航功能包集故障排除页面。
原文链接:http://wiki.ros.org/cn/navigation/Tutorials/RobotSetup