下图为ROS中导航系统的框架。
运行导航的move_base节点需要提供以下几个话题:
话题 | 作用 | 格式 |
---|---|---|
\tf | 提供机器人与地图等的坐标关系 | tf/Messege |
\map | 提供地图数据 | nav/msgs/GetMap |
sensor topics | 提供传感器数据 | sensor_msgs/LaserScan、sensor_msgs/PointCloud |
odom | 提供里程计数据 | nav_msgs/Odometry |
move_base_simple/goal | 提供目标航点 | geometry_msgs/PoseStamped |
该节点发布的话题就是速度控制信息\cmd_vel
在move_base节点中,
下图是官方提供的机器人在进行导航时的预期恢复行为,即当机器人无法正确规划导航路线时,采取一系列动作恢复导航行为。
全局规划器
全局规划器有两种,分别为广度优先算法和深度优先算法,广度优先算法包括:Dijkstra算法、Flood Fill算法。深度优先算法包括:A*算法、回溯算法、随机深度优先搜索
ROS中,有三种全局规划器: |全局规划器名称|说明|变量名称| |—|—|—| |Navfn|屎山且默认|navfn/NavfnROS| |Global_planner||global_planner/GlobalPlanner| |Carrot_planner|用于二次开发|carrot_planner/CarrotPlanner|
前两个功能一样,但第一个是屎山,第二个是重新写的,都包含了dijkstra和A*算法,第三个就是简单的规划一个从起点到终点的路径,因此二次开发可能用到。
参数设置
全局规划器的参数设置在
<param name="base_global_planner" value="global_planner/GlobalPlanner" />
要指定使用dijkstra还是A*算法,就还需要添加一对参数:
<param name="GlobalPlanner/use_djikstra" value="false" />
<param name="GlobalPlanner/use_grid_path" value="true" />
AMCL 定位算法
中文翻译过来就是:自适应蒙特拉洛定位算法。
这个节点订阅的话题:
- scan:激光雷达扫描数据(sensor_msgs/LaserScan)
- tf:订阅的包括里程计发布的base_link到odom的坐标转换和传感器数据到base_link的转换(tf/tfMessage)
- initialpose:没有则初始化为(0,0,0)(geometry_msgs/PoseWithCovarianceStamped)
- map:地图数据(nav_msgs/OccupancyGrid)
发布的话题:
- acml_pose:机器人的计算位置(geometry_msgs/PoseWithCovarianceStamped)
- particlecloud:粒子云(geometry_msgs/PoseArray)
- tf:发布odom到map的坐标转换(tf/tfMessage)
该算法参数很多,ros index直接搜amcl。
amcl负责输出从map到odom的tf,里程计负责输出odom到base_footprint的tf,
算法原理
就是在一段移动步长之间,在机器人附近生成一堆粒子(含方向),然后假设当机器人处在这个粒子的时候,比对当前传感器获得的数据和推算数据的相似度,从而判断该粒子位置的可信度,从中选取出一个最可信的粒子。
局部规划器
局部规划器是在全局规划器规定的轨迹基础上进行小范围的轨迹规划,主要用于避障。主流的局部规划器有DWA和TEB,还有Trajetory、Eband,还可自定义规划器
Trajetory与DWA规划器就是有规律的生成一些路线(窗口),然后根据一些条件挑选最优的一条进行运动。挑选的参考标准包括:
- 运动轨迹与全局导航路线的贴合程度(过程)
- 轨迹末端和目标点的距离(目标)
- 轨迹路线和障碍物之间的距离(风险)
两者的区别在于轨迹的生成方式,WDA的是采样一组速度和加速度,更加动态,而Trahetory的轨迹采样通常是圆弧或直线
Eband与TEB规划器是在机器人当前位置和局部目标点之间拉一个弹力带(作为局部路径),障碍物对该弹力带具有排斥作用,全局路径对其具有吸引作用。区别是TEB在此基础上引入了时间信息。
特性 | TrajectoryPlanner | Eband | DWA | TEB |
---|---|---|---|---|
路径生成方式 | 轨迹采样 | 弹性带优化 | 动态窗口采样 | 时间弹性带优化 |
路径平滑性 | 一般 | 较好 | 一般 非常好 | |
动态避障能力 | 较弱 | 较强 | 强 | 强 |
计算效率 | 高 | 中 | 高 | 中 |
实时性 | 好 | 较好 | 非常好 | 较好 |
适用场景 | 简单环境 | 复杂环境 | 动态环境 | 复杂、动态环境 |
动力学约束 | 简单 | 中等 | 中等 | 强 |
参数设置
<param name="base_local_planner" value="base_local_planner/TrajetoryPlannerROS" />
<param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
<param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" />
<param name="base_local_planner" value="eband_local_planner/EBandPlannerROS" />
修改以上参数,move_base节点就会自动调用对应的规划器
TEB规划器的参数很多,为实现动态调参,可以用以下工具:
rosrun rqt_reconfigure rqt_reconfigure
恢复行为
当导航的动作被围困时,机器人会采用恢复行为来恢复正常导航。
首先进行保守重置,如仍不能脱困,则采用旋转清除,如仍不能脱困,则采用激进重置,如还不能脱困,则再采取旋转清除,若依然无法脱困,则最终放弃任务。
- 保守重置:清除代价地图上一部分的障碍物信息,清除范围是以机器人为中心,(通常是3米)以外的地图区域
- 旋转清除:旋转底盘,刷新地图上的障碍物信息
- 激进重置:更加激进的清除代价地图上的障碍物信息(清除范围比保守重置更大)
- 旋转清楚:旋转底盘,刷新地图上的障碍物信息
如果不满意官方的恢复行为设计方法,可以自定义恢复行为在yaml文件中。
在recover_behavior行为列表中,可以逐条添加恢复行为的动作,然后为每个动作配置参数。如下是一个示例:
recovery_behaviors:
- name: 'conservative_reset' # (保守)重置
type: 'clear_costmap_recovery/ClearCostmapRecovery'
- name: 'rotate_recovery' # 旋转清除
type: 'rotate_recovery/RotateRecovery'
- name: 'aggressive_reset' # (激进)重置
type: 'clear_costmap_recovery/ClearCostmapRecovery'
conservative_reset:
reset_distance: 2.0
layer_names: ["obstacle_layer"] # 需要将重置地图层的名称保持一致
aggressive_reset:
reset_distance: 0.0
layer_names: ["obstacle_layer"] # 需要将重置地图层的名称保持一致
重置行为的代码对应的类型为 clear_costmap_recovery/ClearCostmapRecovery