跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++AI算法

ROG-Map:一种高效的大场景 LiDAR 机器人中心栅格地图

综述由AI生成ROG-Map 提出了一种基于均匀网格的机器人中心占用栅格地图,通过零拷贝滑动策略解决大场景内存瓶颈。其核心创新包括增量障碍膨胀方法,将计算复杂度降至 O(N),以及概率更新中的对数几率截断策略。该方案在公共数据集上优于现有 SOTA 方法,并已在真实四旋翼无人机中验证了实时避障性能。

忘忧发布于 2026/4/5更新于 2026/4/242 浏览
ROG-Map:一种高效的大场景 LiDAR 机器人中心栅格地图

ROG-Map:基于 LiDAR 的高效机器人中心栅格地图

引言

在自主飞行与移动机器人领域,视觉传感器测量范围有限(通常约 35m),而激光雷达(LiDAR)则能提供精确的远程感知。为了避开小障碍物并实现复杂环境导航,高分辨率的占用栅格地图(OGM)至关重要。然而,传统的 OGM 在大场景中面临两个核心挑战:地图更新和障碍物膨胀的计算负载显著增加。

基于八叉树或哈希表的方法虽然节省内存,但在实时性上往往难以满足要求;而基于均匀网格的方法计算效率高,却因大规模环境下的内存消耗变得不可行。ROG-Map 正是为了解决这些问题而生,它提出了一种以机器人为中心的局部地图策略,配合增量障碍膨胀方法,实现了大场景下的高分辨率与高效率平衡。

核心创新点

  1. 零拷贝地图滑动策略:仅维护机器人周围的局部地图,随机器人移动动态更新,大幅降低大场景任务的内存成本。
  2. 增量障碍膨胀方法:通过状态变化触发邻居更新,将计算复杂度降至 O(N),显著优于传统遍历方法。
  3. 概率更新优化:采用对数几率(Log-odds)截断策略,有效应对动态环境中的障碍物消失问题。

该方案已作为 ROS 包开源,并在基于 LiDAR 的四旋翼无人机上进行了广泛的真实世界测试。

占据栅格地图理论基础

贝叶斯概率更新

当激光雷达扫过环境时,我们需要判断某个栅格是否被占据。这是一个典型的贝叶斯推断问题。假设这是一个马尔可夫过程,我们计算在已知历史测量数据的情况下,栅格 $n$ 被占据的概率 $P_{1:k}(n)$。

经典的二元贝叶斯更新公式涉及连乘运算,经过成千上万次扫描后,浮点数乘法不仅慢,还容易导致数值下溢。因此,引入'对数几率'是工程上的必然选择。

对数几率定义为几率的对数: $$L_{1:k}(n) = \log\frac{P_{1:k}(n)}{1-P_{1:k}(n)}$$

利用对数性质,复杂的连乘转化为简单的加法: $$L_{1:k}(n) = L_{1:k-1}(n) + L_{k}(n)$$

这意味着当前时刻的地图状态等于上一时刻的状态加上本次观测带来的变化。由于对数几率是双射的,地图中只需保存 $L$ 值即可还原概率。

增量计算与截断策略

单次观测的增量由击中(Hit)和未击中(Miss)次数决定: $$L_{k}(n) = n_{hit}\cdot l_{hit} + n_{miss}\cdot l_{miss}$$

其中 $l_{miss}$ 为负值,因为光束穿过意味着该处为空。为了防止动态环境中障碍物移除后概率无法回退,论文采用了截断策略,限制对数几率的上下界: $$L_{1:k}(n) = \max(\min(L_{t}, l_{max}), l_{min})$$

这确保了即使障碍物突然移走,地图也能迅速更新,避免'死锁'。

关键概念解析

在实现过程中,有两个概念对后续膨胀算法至关重要:

  • 上升栅格 (Rising Grid, RG):状态从未知或空闲变为占据的栅格。
  • 下降栅格 (Falling Grid, FG):状态从占据变为空闲或未知的栅格。

系统只需关注这两种状态的栅格,无需遍历全图。

ROG-Map 核心架构

A. 机器人中心局部地图 (Robocentric Local Maps)

解决的核心痛点是:无人机内存有限,但现实世界无限。如果存储全局地图,飞出几公里后内存就会崩溃。

ROG-Map 采用'跑步机'机制:地图核心始终罩在机器人周围,超出范围的旧数据直接丢弃,新探测数据补入。这通过循环缓冲区(Circular Buffer)实现。

坐标转换流程如下:

  1. 全局坐标 -> 全局索引:根据机器人位置 $p_k$ 和分辨率 $r$ 计算。
  2. 全局索引 -> 中间索引:对地图长度取模,利用循环特性。
  3. 中间索引 -> 局部索引:归一化处理,确保数组下标非负。
  4. 局部索引 -> 1D 内存地址:通过展平公式映射到连续内存空间。

最核心的魔法在于Zero-copy(零拷贝)。当机器人移动导致局部地图偏移时,被淘汰的旧内存地址只需清零,随后立即复用为新区域的数据。数据格子在物理层面永远不移动,仅通过数学取模运算确定位置,极大降低了内存搬运开销。

B. 概率更新与增量膨胀

解决了地图如何生成和滑动后,接下来是更新与膨胀。

批量光线投射

传统方法每根激光束穿过一个栅格就更新一次概率,计算量巨大。ROG-Map 使用快速体素遍历算法,并引入缓存队列 $\mathcal{C}$。每一帧内,不管多少条光线穿过同一个空气栅格,该栅格只进行一次概率更新计算。系统先统计每个栅格被 Hit 和 Miss 的次数,最后统一更新。

极速膨胀算法

传统膨胀需遍历所有栅格,耗时极高。ROG-Map 提出了一种时间复杂度恒为 O(N) 的方法(N 为状态改变栅格数)。

核心是一个投票计数器 inflationCounter,初始值为 0,表示周围有几个真正的障碍物栅格。只要计数器 >= 1,该栅格即标记为膨胀占据。

  • 当检测到 RG 时,将其所有邻居的计数器加一。
  • 当检测到 FG 时,将其所有邻居的计数器减一。

这种加减计数器机制让每个栅格的膨胀状态完全独立解耦。操作仅限于极少数发生状态改变的栅格,使得在算力受限的无人机上也能达到 50 Hz 的更新频率(耗时不到 6 毫秒)。

代码实现与架构分析

以下是 ROG-Map 在 ROS 中的核心回调逻辑,展示了其异步处理的设计思想。

// 位姿接收:更新机器人状态,广播 world -> drone 变换
void ROGMap::odomCallback(const nav_msgs::OdometryConstPtr& odom_msg) {
    // 转换格式并广播 TF 变换
    updateRobotState(std::make_pair(
        Vec3f(odom_msg->pose.pose.position.x, odom_msg->pose.pose.position.y, odom_msg->pose.pose.position.z),
        Quatf(odom_msg->pose.pose.orientation.w, odom_msg->pose.pose.orientation.x,
              odom_msg->pose.pose.orientation.y, odom_msg->pose.pose.orientation.z)));
    
    static tf2_ros::TransformBroadcaster br_map_ego;
    geometry_msgs::TransformStamped transformStamped;
    transformStamped.header.stamp = ros::Time::now();
    transformStamped.header.frame_id = "world";
    transformStamped.child_frame_id = "drone";
    transformStamped.transform.translation.x = odom_msg->pose.pose.position.x;
    transformStamped.transform.translation.y = odom_msg->pose.pose.position.y;
    transformStamped.transform.translation.z = odom_msg->pose.pose.position.z;
    transformStamped.transform.rotation.x = odom_msg->pose.pose.orientation.x;
    transformStamped.transform.rotation.y = odom_msg->pose.pose.orientation.y;
    transformStamped.transform.rotation.z = odom_msg->pose.pose.orientation.z;
    transformStamped.transform.rotation.w = odom_msg->pose.pose.orientation.w;
    br_map_ego.sendTransform(transformStamped);
}

// 点云接收:仅缓存,不立即更新
void ROGMap::cloudCallback(const sensor_msgs::PointCloud2ConstPtr& cloud_msg) {
    if (!robot_state_.rcv) return;
    
    double cbk_t = ros::Time::now().toSec();
    if (cbk_t - robot_state_.rcv_time > cfg_.odom_timeout) {
        std::cout << " -- [ROS] Odom timeout, skip cloud callback." << std::endl;
        return;
    }
    
    PointCloud temp_pc;
    pcl::fromROSMsg(*cloud_msg, temp_pc);
    rc_.updete_lock.lock();
    rc_.pc = temp_pc; // 只保留最新一帧
    rc_.pc_pose = std::make_pair(robot_state_.p, robot_state_.q);
    rc_.unfinished_frame_cnt++;
    map_empty_ = false;
    rc_.updete_lock.unlock();
}

// 异步地图更新:定时器线程执行真正计算
void ROGMap::updateCallback(const ros::TimerEvent& event) {
    if (map_empty_ || rc_.unfinished_frame_cnt == 0) return;
    
    if (rc_.unfinished_frame_cnt > 1) {
        std::cout << " -- [ROG WARN] Unfinished frame cnt > 1, the map may not work in real-time" << std::endl;
    }
    
    static PointCloud temp_pc;
    static Pose temp_pose;
    rc_.updete_lock.lock();
    temp_pc = rc_.pc;
    temp_pose = rc_.pc_pose;
    rc_.unfinished_frame_cnt = 0;
    rc_.updete_lock.unlock();
    
    updateProbMap(temp_pc, temp_pose); // 核心更新函数
    writeTimeConsumingToLog(time_log_file_);
}

这段代码体现了三个关键设计原则:

  1. 解耦:里程计和点云回调只负责接收和缓存,不直接参与重计算。
  2. 防阻塞:点云接收和地图更新分离,防止 ROS 回调阻塞主线程。
  3. 实时性优先:只处理最新一帧,若积压超过 1 帧则报警,允许丢帧以保证系统实时响应。

配置参数说明

# Probabilistc update 概率更新与射线投射
raycasting:
  enable: true
  batch_update_size: 1
  local_update_box: [ 50, 50, 5 ] # 局部更新范围 50×50×5 米
  ray_range: [ 0.0, 999 ]        # 射线投射范围
  p_min: 0.12                    # 最小占据概率(下限)
  p_miss: 0.49                   # 射线未命中时的概率
  p_free: 0.499                  # 自由空间的概率阈值
  p_occ: 0.85                    # 占据空间的概率阈值
  p_hit: 0.9                     # 射线命中时的概率
  p_max: 0.98                    # 最大占据概率(上限)

参数 p_min 和 p_max 的作用非常关键,它们防止概率无限接近 0 或 1。例如,一个体素连续多次被看成 free,不会变成绝对 0,只会降到 0.12。这样做的好处是避免一次误测后永远'翻不了身',给后续观测留有修正空间。

数据流与可视化

整体构图流程遵循固定大小局部地图 + 滑动窗口 + 环形内存复用的模式。主要包含四个子地图:

  • ProbMap:主概率栅格,负责射线更新和滑动管理。
  • InfMap:派生的膨胀地图,用于安全碰撞检测。
  • FreeCntMap:前沿提取辅助图。
  • ESDFMap:距离场图,用于距离查询和优化。

在 RViz 中,不同颜色的框代表不同的逻辑范围:

  • 橙色框:Local Map Range,即滑动的局部地图边界。
  • 紫色框:可视化范围,仅用于显示膨胀障碍物,不参与逻辑。
  • 绿色框:本帧实际更新体素覆盖范围,动态调整。
  • 淡蓝色框:A*搜索框,由起点终点确定,不滑动。
  • 深蓝色框:ESDF 图。

通过这种设计,系统能够始终只维护机器人周围最有用的地图信息,既保证了内存稳定,又实现了高效的实时避障规划。

目录

  1. ROG-Map:基于 LiDAR 的高效机器人中心栅格地图
  2. 引言
  3. 核心创新点
  4. 占据栅格地图理论基础
  5. 贝叶斯概率更新
  6. 增量计算与截断策略
  7. 关键概念解析
  8. ROG-Map 核心架构
  9. A. 机器人中心局部地图 (Robocentric Local Maps)
  10. B. 概率更新与增量膨胀
  11. 批量光线投射
  12. 极速膨胀算法
  13. 代码实现与架构分析
  14. 配置参数说明
  15. Probabilistc update 概率更新与射线投射
  16. 数据流与可视化
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AI Agent 架构:基础组成模块深度解析
  • 飞算 JavaAI:Java 智能开发与架构重塑
  • 基于AI工程化文档创建应用前端代码示例
  • openTCS WEB 接口实战:从基础调用到自定义指令开发
  • Office 区域不支持 Copilot 的解决方法
  • 鸿蒙 ArkTS 与 Java 跨平台 TCP 通信实战
  • Midjourney 推出面向动漫领域的图像生成模型:Niji V7
  • Llama-2-7b在昇腾NPU上的六大核心场景性能基准报告
  • Stack-Chan 机器人入门指南:基于 JavaScript 与 M5Stack 构建
  • RTX 4090 本地部署国产 AIGC 视频模型:腾讯混元与通义万相实战
  • 项目分享|LiveKit Agents Playground:快速搭建WebRTC服务端Agent原型的利器
  • Ubuntu 22.04 Realtek 8922AE WiFi 驱动安装指南
  • 大模型时代人形机器人感知:视觉 - 语言模型应用
  • Flood Fill 算法原理及经典题目解析
  • AI 赋能原则 6 解读:深度专业与跨界能力的复合竞争力
  • Java8 ConcurrentHashMap 底层数据结构与核心方法流程
  • 元境智搭:低代码可视化AR远程协助与巡检平台
  • 通义万相 2.1 多模态 AI 生成模型技术解析与应用前景
  • Xilinx PCIe IP 核详解、FPGA 实现及仿真全流程 (Virtex-7 Gen3)
  • uniapp 多用户多仓库进销存管理系统设计与实现

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online