Note: 本教程假定你很熟悉ROS及其使用。请先阅读ROS Documentation。另外,软件包2dnav_erratic是一个使用本教程创建的基于Videre Erratic平台的软件包.
(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

在机器人上配置并使用导航功能包集

Description: 本教程一步步介绍如何在机器人上运行导航功能包集。包括:使用tf发送变换,发布里程计信息,发布来自激光的传感器信息,基本的导航功能包集的配置。

Tutorial Level: INTERMEDIATE

机器人配置

attachment:overview_tf.png假定我们已经以特定方式配置机器人,导航功能包集将使其可以运动。上图概述了这种配置方式。白色的部分是必须且已实现的组件,灰色的部分是可选且已实现的组件,蓝色的部分是必须为每一个机器人平台创建的组件。以下章节将介绍使用导航功能包集的先决条件以及如何满足不同平台。

ROS

导航功能包集假定机器人使用ROS系统。请查阅ROS documentation以了解如何在你的机器人上安装ROS。

TF变换配置(其他变换)

导航功能包集需要机器人不断使用tf发布有关坐标系之间的关系的信息。详细的配置教程请查阅:Tf配置.

传感器信息(sensor source)

导航功能包集使用来自传感器的信息避开现实环境中的障碍物,它假定这些传感器在ROS上不断发布sensor_msgs/LaserScan消息或者sensor_msgs/PointCloud消息。有关在ROS上发布这些消息的教程,请查阅在ROS上发布传感器数据流。此外,一些已经有了ROS上的驱动的传感器亦满足这一教程。一下是部分ROS支持的传感器以及相关驱动链接:

里程信息(odometry source)

导航功能包集需要使用tfnav_msgs/Odometry消息发布的里程信息。这里有一篇发布里程信息的教程:在ROS上发布里程信息. 以下列出部分支持里程计的平台以及可用的驱动:

基座控制器(base controller)

导航功能包集假定它可以通过话题"cmd_vel"发布geometry_msgs/Twist类型的消息,这个消息基于机器人的基座坐标系,它传递的是运动命令。这意味着必须有一个节点订阅"cmd_vel"话题, 将该话题上的速度命令(vx, vy, vtheta转换为电机命令(cmd_vel.linear.x, cmd_vel.linear.y, cmd_vel.angular.z)发送给移动基座。以下列出部分支持基座控制器的平台以及可用的驱动:

地图 (map_server)

导航功能包集的配置并不需要有一张地图以供操作,但基于本教程的目的,我们假定你有一张地图。请查阅教程创建一张地图了解在你的系统环境下创建一张地图的细节。

导航功能包集配置

本节介绍如何配置导航功能包集。假设上述所有需要的环境都已满足。特别的,这意味着,机器人必须使用tf发布坐标帧,并从所有的传感器接收 sensor_msgs/LaserScan 或者 sensor_msgs/PointCloud 消息用于导航,同时需要使用 tfnav_msgs/Odometry 消息发布导航消息,消息会以命令的形式下发给机器人底座。如果所需要的配置你都没有,请参见机器人配置

创建一个软件包

首先,我们创建一个软件包,用来保存我们所有的配置文件和启动文件。这个软件包需要包含所有用于实现 机器人配置小节所述依赖,就如其以依赖导航功能包集高级接口 move_base 软件包一样。因此, 为你的软件包选好位置,执行以下命令:

catkin_create_pkg my_robot_name_2dnav move_base my_tf_configuration_dep my_odom_configuration_dep my_sensor_configuration_dep

这个指令会创建一个包含运行导航功能包集所需依赖的软件包。

创建机器人启动配置文件

现在,我们有了一个存放所有配置文件和启动文件的工作空间,我们会创建一个ROS launch文件来启动所有的硬件以及发布机器人所需的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,并根据实际指定相关参数。

配置代价地图 (local_costmap) & (global_costmap)

导航功能包集需要两个代价地图来保存世界中的障碍物信息。一张代价地图用于路径规划,在整个环境中创建长期的路径规划,另一个用于局部路径规划与避障。有一些参数两个地图都需要,而有一些则各不相同。因此,对于代价地图,有三个配置项: common配置项, global配置项和local配置项。

注意: 接下来的内容只是代价地图的基本配置项。想要查看完整的配置,参看costmap_2d文档.

共同配置(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),顺时针和逆时针规范都支持。 我们还将设置代价地图膨胀半径。膨胀半径应该设置为障碍物产生代价的最大距离。 例如,膨胀半径设定在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”参数确定传感器是否用于向代价地图添加障碍物信息,或从代价地图清除障碍信息,或两者都有。

全局配置(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”参数定义了代价地图参考的的机器底盘的坐标帧。“update_frequency”参数决定了代价地图更新的频率。 “static_map”参数决定代价地图是否根据map_server提供的地图初始化。如果你不使用现有的地图,设为false。

本地配置(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”参数分别设置局部代价地图的宽度(米)、高度(米)和分辨率(米/单元)。 注意,这里的分辨率和你的静态地图的分辨率可能不同,但我们通常把他们设成一样的。

完整的配置选项

这里是用于启动和运行的最简单的配置,更多的细节请参阅costmap_2d 文档.

Base Local Planner 配置

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

上面的第一部分参数定义机器人的速度限制。 第二部分定义了机器人的加速度的限制。

为导航功能包创建一个Launch启动文件

现在我们已经有了所有的配置文件,我们需要在一个启动文件中一起启动他们,创建一个名为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"。对于如何创建一张地图,请查阅 创建一张地图.

AMCL 配置(amcl)

AMCL有许多配置选项将影响定位的性能。 有关AMCL的更多信息请参阅amcl文档.

运行导航功能包集

现在我们配置结束,我们可以运行导航功能包了。为此我们需要在机器人上启动两个终端。 在一个终端上,我们将启动 my_robot_configuration.launch 文件,在另一个终端上我们将启动我们刚刚创建的move_base.launch

终端1:

roslaunch my_robot_configuration.launch

终端2:

roslaunch move_base.launch

祝贺你,导航功能包集现在应该运行了。关于如何通过图形化界面给导航功能包集发送一个目标信息,请参阅rviz和导航教程。 如果你想使用代码给导航功能包集发送导航目标,请参阅发送简单导航目标教程。

故障排除

关于运行导航功能包集时遇到的常见问题,请参阅导航功能包集故障排除页面。

#keywords 移动平台配置,机器人配置,设置机器人,getting started with mobile robot

Wiki: cn/navigation/Tutorials/RobotSetup (last edited 2017-03-13 02:26:23 by SawYer)