type
status
date
slug
summary
tags
category
icon
password
move base
是ros navigation导航堆栈的框架名,基于此框架,可以自由定制全局路径规划、局部路径规划、恢复行为以及地图相关的处理。
- ROS 官方对
move base
的介绍:move base - ROS wiki
- move base概述
- 考虑到
move base
其实分为许多个模块,因此下面将基于各个模块讲述 - costmap
- 关于什么是
costmap
这件事,主要在于这个东西它是个map,也就是地图,既然是个地图,那么,不考虑三维的情况下,它肯定是一个二维数组,既然是二维数组,那么数组里面肯定会存某个值,这个是就是所谓的cost。是的,它真的就是一个二维数组,只是在这个二维数组的基础上封装了很多函数方便使用罢了。请务必记住costmap
只是一个数据结构。 - layer
costmap
是layer
的基本组成部分,每一个layer
都是基于costmap
进行处理的,就像手机app上的地图,你会发现有道路图、卫星图等等,这些道路图、卫星图就相当于layer
,这些layer
各有不同的作用。可以在配置文件中自由配置使用哪些layer
,move base
自带的layer
如下图。static_layer
的输入一般来自slam的地图输出,这是整个move base
地图的基石,后续大部分的layer
都将基于static_layer
处理。obstacle_layer
将传感器点云数据作为输入,obstacle_layer
利用这些点云数据为move base
生成避障用的地图。inflation_layer
是基于obstacle_layer
以及static_layer
上的障碍物生成的膨胀层地图。- 当然,我们可以基于上述的几个
layer
定制一个符合需求的地图作为后续路径规划处理的输入。 - GlobalCostMap和LocalCostMap
GlobalCostMap
是提供给全局路径规划使用的地图,LocalCostMap
是提供给局部路径规划使用的地图。所以在配置这两个地图的坐标系时,需要注意将GlobalCostMap
的坐标系设定在世界坐标系下(一般是/map),而LocalCostMap
则将坐标系固定在odom
。- 一般而言,
LocalCostMap
不使用static_layer
,因为局部路径规划不需要知道整个地图的情况,它只需要关注一个很小的范围即可。 - 如下图,
static_layer
只有GlobalCostMap
才使用。不过,如果你的LocalCostMap
自己定制了一层layer
,那么这层layer
基于static_layer
也不是不行。 - 坐标系统(TF)
move base
的坐标系统是十分重要的,各个模块通过坐标系互相连接,完成各自的使命。- 关于什么是tf: ROS中TF(坐标系转换)原理与使用
- 代码参考: kobuki_ros_node
- 一个比较正常的坐标系统如下图,一般而言,在
odom
和base_link
之间也许会多一个base_footprint
的坐标系。 map
坐标系是整个坐标系的基石,以整个地图的原点作为坐标系的原点,在rviz
中一般会将fixed frame
设置在这个坐标系下,绝大多数的ros消息也将发布在这个坐标系下。odom
坐标系是根据小车的odom数据生成的坐标系,这个坐标系的原点为小车启动时的位置作为原点,在slam建图定位一开始时,odom
坐标系将与map
坐标系重合,但是由于odom数据会存在误差,且slam建图定位也不可能百分百准确,所以odom
与map
之间将产生偏差,这个偏差就是map->odom的tf值,move base
将利用这个偏差做一些修正base_link
是以小车当前所在位置为原点的坐标系,随小车运动而实时变化,在这个坐标系下面可以连接更多与传感器有关的坐标系,例如下图中的laser_link
与camera_link
。move base
实际上并不会维护上图中的tf,它只会接收tf中的信息,这意味着上图中所有的tf都需要我们手动配置好。- map->odom:这组tf一般由slam程序发布,有的slam程序也会直接发布map->base_link的tf,这样做也不是不行,但是需要比较熟悉
move base
的配置。 - odom->base_link:一般由底盘数据处理程序发布,只需将odom的记录的数据作为tf的值即可。
- base_link->sensor_link:由base_link到各个传感器的tf一般是静态tf,可以在任何地方发布。



- move base的使用
- 配置文件
- 一组
move base
的典型配置文件结构大抵如下所示,其中launch文件存放move base的启动文件
,每次想要调用move base
时,只需要执行roslaunch kobuki_oa_planner nav_sim.launch
,这个命令将调用nav_sim.launch
中配置的各个node
。而param
文件夹中,则存放了move base
的参数配置文件。至于rviz
文件夹,则存放了rviz
的配置文件,在启动rviz
时,加载这个配置文件,就不用手动去一个个添加ros消息了。 - 具体的参数配置文件内容,请参考:XuanYuan/kobuki_oa_planner
- 各个配置参数的含义,可参考:move base - ROS wiki、costmap2d - ROS wiki、 [[dwa 介绍]]
- 插件使用
move base
的一个特点就是能自由的使用插件替换掉官方的各个模块,包括全局路径规划、局部路径规划以及给globalcostmap
或localcostmap
添加各种layer
。- 要添加插件,首先就需要了解要添加的插件的类型,对于每种插件,
move base
都预留了回调接口,我们只需要实现这个回调接口即可。 - 全局路径规划插件的编写教程与接口: Writing A Global Path Planner As Plugin in ROS
- 局部路径规划插件的编写教程与接口: Writing a local path planner as plugin in ROS
- 至于添加
layer
,参考:layer.h,继承Layer
类,实现相应的函数,在pluginlib
中完成注册即可。一个更加详细的例子可参考:navigation_layers。 - 注意在编写插件时,记得使用宏
PLUGINLIB_EXPORT_CLASS
向pluginlib
注册插件。 - 部署插件
- 为了将插件部署到ros系统中,还需要一些配置文件的辅助,首先需要为你的插件编写一个xml配置文件,例如
bgp_plugin.xml
,内容如下。 在第一行中,你需要向move base
指出你的插件对应的动态链接库路径,这个路径会自动在前面加上ROS_PATH
的路径,同时在后面会自动加上后缀,所以,第一行就是在告诉move base
,你的动态库位于${ROS_PATH}/lib/liboa_planner.so
,这也意味着,你需要将编译出来的插件库放到此路径。 而第二到四行,则是告诉move base
,你的插件属于哪个类,class name
将作为move base
配置文件中加载此插件的索引名,而type
则是指示对应的类类型,base_class_type
则指示对应的类类型的基类,不同种类的插件对应于不同的基类,但是相同种类插件的基类一定相同。 - 除了上述的配置,还需要在
package.xml
中export
出刚刚写好的配置文件,内容大致如下,在export
中,需要指明提供基类的包名nav_core
,也就是告诉move base
,此插件为nav_core
的插件,后面跟着的就是对应的路径,${prefix}
指向的是package.xml
所在目录。 - 编写完上述插件后,将其安装在
${ROS_PATH}/share/${project_name}
下,例如,假如当前项目名为kobuki_oa_planner
,那么则将上述两个配置文件安装在${ROS_PATH}/share/kobuki_oa_planner
目录下。 - 最后,修改
move base
加载的插件名,例如这里的插件是全局路径规划的插件,那么,只需要将参数base_global_planner
修改为刚刚bgp_plugin.xml
中设置的class name
,也就是oa_planner/OAPlanner
。 - 验证插件是否部署成功:
rospack plugins --attrib=plugin nav_core
,我们编写的oa_planner
就是nav_core
的插件,所以这里是查询nav_core
的插件列表,如果查询结果中出现了刚刚编写的插件,则说明部署成功,最后运行move base
即可。 - 参考实例:oa_plugin
- move base如何从点到路径
- 如前所述,在已经拥有了代表地图的
GlobalCostMap
以及LocalCostMap
,代表罗盘的坐标系统(TF)情况下,move base
接收到一个目标点后,会进行如下流程: - 首先,将目标点传递给全局路径规划器
GlobalPlanner
,全局路径规划器根据输入的目标点,生成一条全局路径。 - 得到全局路径后,
move base
会将全局路径传递给局部路径规划器LocalPlanner
,局部路径规划器拿到全局路径后,规划出局部路径以及让小车沿着路径走的一组控制速度的指令,通过消息cmd_vel
传递给小车,从而控制小车沿着局部路径行走。 - 全局和局部路径规划器是一个插件,所以可以通过插件的形式将我们希望的路径通过插件传递给
move base
。
