nav_msgs::OccupancyGrid数据格式详解

本文详细解析了ROS中nav_msgs::OccupancyGrid数据结构的构成与使用方法,包括Header、MapMetaData及data一维数组的具体含义,并通过实例说明了如何进行地图数据的转换与发布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nav_msgs::OccupancyGrid数据格式详解

可以先查看一下ros官网关于nav_msgs::OccupancyGrid数据格式的解释,我应用的时候,感觉还有一些不清楚的地方,所以我自己做了个实验,大家可以参考一下我对下面参数的理解,如有问题请告知。

主要是涉及实际地图与栅格地图单位的问题,实际地图的单位一般为m,栅格地图单位为一格,有些参数没讲清楚。

以比例尺为0.5,地图栅格大小为20×20,地图实际大小为10m×10m的地图举例说明:
nav_msgs::OccupancyGrid组成包括三个部分:

std_msgs/Header header
nav_msgs/MapMetaData info   
int8[] data      一维数组,数组中的数据为对应栅格的占用概率,范围[1,100],概率越大,
                 说明该点越有可能是障碍点,-1表示位置区域,数组元素的序列号计算为:
                 实际地图中某点坐标为(x,y)[单位m],先转换为栅格右上角为原点的坐标,
                 即mx=(x-map.info.origin.x)/map.info.resolution,my=(y-map.info.origin.y)/map.info.resolution
                 对应栅格地图中坐标为[my*map.info.height+mx]。

下面重点讲一下nav_msgs/MapMetaData info数据格式,包括下面几个部分:

time map_load_time   //地图加载所需时间
float32 resolution   //比例尺,代表一个栅格在实际地图中的大小,比例尺为0.5,说明一个栅格长度为0.5m
uint32 width         //地图宽度,这里指的是栅格数量,不是指实际长度,也就是20,不是10
uint32 height        //同地图宽度
geometry_msgs/Pose origin  //地图原点所在位置,单位m

简单讲一下std_msgs/Header header数据格式:

uint32 seq       //帧序列号,会不断增长
time stamp     //时间戳,做数据融合时会用到
string frame_id  //地图参考的坐标系,比如我代码里参考的坐标系是真实地图下的odom坐标系

geometry_msgs/Pose origin 数据格式也有必要做一下说明,包含两个数据:

geometry_msgs/Point position    //栅格地图原点在真实地图下的坐标,x,y,z,
                                  指栅格点对应的实际位置坐标,单位为m,比如我设置的的
                                  原点为-10,0,则栅格原点在真实地图(-10,0)位置,即栅格
                                  地图整体向x轴负方向移动10m,由于比例尺为0.5,实际移动了20个栅格
geometry_msgs/Quaternion orientation  //坐标轴朝向,四元数表示,这个不讲,真实地图和栅格地图一样。

再说明一下rviz中地图的放置方法,栅格地图中有geometry_msgs/Pose origin数据,代表栅格地图原点在string frame_id (地图参考坐标系)下的坐标和朝向。将地图原点放到参考系对应坐标,地图坐标系/map旋转到对应朝向,其他点按栅格地图的位置关系放置。这里要分清给的坐标是相对与栅格地图/map坐标系下的坐标还是相对于真实地图/odom下的坐标。

下面是我的测试代码:

#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"
#include "nav_msgs/OccupancyGrid.h"

int main(int argc, char * argv[]) {

  ros::init(argc, argv, "gridMap");

  ros::NodeHandle nh;

  ros::Publisher pub = nh.advertise<nav_msgs::OccupancyGrid>("/gridMap1", 1);
  nav_msgs::OccupancyGrid map;

  map.header.frame_id="odom";
  map.header.stamp = ros::Time::now(); 
  map.info.resolution = 0.5;         // float32
  map.info.width      = 20;           // uint32
  map.info.height     = 20;           // uint32
  map.info.origin.position.x = -10.0;
  map.info.origin.position.y = 0.0;
  map.info.origin.position.z = 0.0;
  map.info.origin.orientation.x = 0.0;
  map.info.origin.orientation.y = 0.0;
  map.info.origin.orientation.z = 0.0;
  map.info.origin.orientation.w = 0.0;


  
  int p[map.info.width*map.info.height] = {-1};   // [0,100]
  p[10] = 100;
  std::vector<signed char> a(p, p+400);
  map.data = a;

  while (ros::ok())
  {
      pub.publish(map);
  }

  ros::shutdown();
  return 0;
}


在ROS(Robot Operating System)中,`nav_msgs::OccupancyGrid`是用于表示占用网格地图的消息类型。该消息包含一个二维数组,表示地图上每个单元格的占用概率。如果你需要对`nav_msgs::OccupancyGrid`消息进行转置,即将其行与列互换,你可以在C++中使用标准库中的算法和容器来完成这个任务。 以下是一个简单的例子,展示了如何使用C++和ROS的`nav_msgs::OccupancyGrid`消息类型来转置地图数据: ```cpp #include <nav_msgs/OccupancyGrid.h> #include <algorithm> void transposeOccupancyGrid(nav_msgs::OccupancyGrid& grid) { if(grid.data.empty()) { // 如果网格数据为空,则直接返回 return; } size_t width = grid.info.width; size_t height = grid.info.height; // 计算转置后网格的宽度和高度 grid.info.width = height; grid.info.height = width; // 创建一个新数组来存储转置后的数据 std::vector<int8_t> transposed_data; transposed_data.reserve(width * height); // 对原始数据进行转置处理 for (size_t i = 0; i < width; ++i) { for (size_t j = 0; j < height; ++j) { transposed_data.push_back(grid.data[i * height + j]); } } // 将转置后的数据赋值给原网格对象 grid.data.swap(transposed_data); } // 使用示例 nav_msgs::OccupancyGrid my_map; // 假设my_map已经被填充数据 transposeOccupancyGrid(my_map); ``` 在这个函数中,我们首先检查网格数据是否为空。如果不为空,我们交换`nav_msgs::OccupancyGrid`消息中的`width`和`height`字段,以表示转置后的网格尺寸。然后我们创建一个新的`int8_t`类型的向量来存放转置后的数据,最后将转置后的数据赋值给原始网格对象。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值