首先了解到导航所用的栅格地图的消息类型
经查阅资料可知为nav_msgs/OccupancyGrid。
$ rosmsg show nav_msgs/OccupancyGrid
std_msgs/Header header # 数据的消息头
uint32 seq # 数据的序号
time stamp # 数据的时间戳
string frame_id # 地图的坐标系
nav_msgs/MapMetaData info # 地图的一些信息
time map_load_time # 加载地图的时间
float32 resolution # 地图的分辨率,一个格子代表着多少米,一般为0.05,[m/cell]
uint32 width # 地图的宽度,像素的个数, [cells]
uint32 height # 地图的高度,像素的个数, [cells]
geometry_msgs/Pose origin # 地图左下角的格子对应的物理世界的坐标,[m, m, rad]
geometry_msgs/Point position
float64 x
float64 y
float64 z
geometry_msgs/Quaternion orientation
float64 x
float64 y
float64 z
float64 w
# 地图数据,优先累加行,从(0,0)开始。占用值的范围为[0,100],未知为-1。起点冲左下角开始,即左下角那个栅格是第一个。
int8[] data
可以看到,消息可以分为3个部分,消息头header,地图信息info,地图数据data.
地图信息info储存了地图相关的信息,包括 加载地图的时间,地图的分辨率,地图的宽度与高度,以及地图左下角栅格对应的物理坐标.
地图本身是只有像素坐标的,其像素坐标系为坐下角为(0, 0) 的坐标系.通过左下角栅格对应的物理坐标 origin 以及 分辨率,再通过 像素 * 分辨率 + origin , 将像素坐标转成物理世界的坐标,从而确定了整个地图的物理坐标.
地图数据data是一维的,我们在赋值之前要首先对这个一维数组进行初始化,数据的大小就是所有像素的个数.
遍历的时候要注意方向,这个数据是以行为主要递增方向的.也就是说遍历的时候要先遍历第一行的所有数据,然后再遍历第二行的所有数据.
关于栅格图
ros里导航用到的地图会有个.yaml文件,其内容如下:
这个origin坐标代表地图左下角点在物理地图下的坐标。
如上图,该地图设置的初始x_min和y_min都为-50.0,即origin的坐标.我订阅了/map话题得到的数据中origin:[-50.0,-50.0,0.0],即地图左下角在物理坐标系下的坐标为-50.0,-50.0.这里我使用了ros里的visualization_msgs::Marker来标记了左下角的这个坐标为(-50,-50)的点,标记的红正方形是将给的坐标作为该正方形的中心去标记的,比如我这上图标记的点的坐标为-50,-50。那么该正方形的中心对应的坐标为-50,-50.