Occupancy Grid Mapping

**占据栅格地图(occupancy grid)**将空间离散化为若干单元(2D 中为方格,3D 中为体素),并为每个单元 mim_i 存储其被障碍物占据的概率 p(mi)p(m_i)。给定已知的机器人位姿(来自 SLAM)和测距测量值(LiDAR、声呐、深度相机),占据栅格地图将对每个单元的大量含噪观测融合为稳定的空闲/占据/未知分类结果——这正是路径规划器实际使用的地图格式。

逐单元的二值贝叶斯滤波

关键的建模假设是:每个单元是一个二值、静态的随机变量(占据或空闲,不随时间变化),并且各单元之间相互独立。在这些假设下,整幅地图的后验分布可以分解为逐单元的后验分布,每当测量值 z1:t\mathbf{z}_{1:t} 到来时,都用一个二值贝叶斯滤波器进行更新。

直接处理概率需要在每次更新时重新归一化。标准的技巧是使用**对数几率(log-odds)**表示:

l=logp1p,p=111+exp(l)l = \log\frac{p}{1 - p}, \qquad p = 1 - \frac{1}{1 + \exp(l)}

对数几率将 p(0,1)p \in (0,1) 映射到 l(,)l \in (-\infty, \infty)l=0l = 0 表示未知(p=0.5p = 0.5),正值表示可能被占据,负值表示可能空闲。在对数几率形式下,贝叶斯更新变成了简单的加法

lt(mi)=lt1(mi)+logp(mizt)1p(mizt)l0l_t(m_i) = l_{t-1}(m_i) + \log\frac{p(m_i \mid \mathbf{z}_t)}{1 - p(m_i \mid \mathbf{z}_t)} - l_0

其中:

无需重新归一化,也无需做乘积——每次观测只是加上一个常量增量。这就是为什么占据栅格建图足够廉价,可以在嵌入式机器人上运行。

逆传感器模型与光线投射

对于测距传感器,每一条测量光束都通过在栅格中对测量射线进行**光线投射(ray casting)**来处理(例如使用 Bresenham 直线遍历算法):

反复一致的观测会不断累加,因此一个被二十次未命中和一次偶发命中触及的单元,仍然清楚地读作空闲;一个移动的人会留下一条临时的痕迹,之后的未命中会将其擦除。实现中通常会将对数几率**限幅(clamp)**在某个最小/最大范围内,以使单元始终可更新(这种有界置信度限幅正是 OctoMap 所做的事),并对概率 pp 设定阈值(例如 0.50.5)以对单元进行分类,供规划使用。

2D 栅格、八叉树与体素

平面 2D 栅格是室内移动机器人的经典表示方式(ROS 中的 nav_msgs/OccupancyGrid)。在 3D 中,稠密栅格的内存开销为 O(r3)O(r^3),因此实际系统会使用分层或稀疏结构:OctoMap 将概率占据信息存储在八叉树中,只在存在几何结构的地方进行细分,并能够裁剪均匀区域;而基于哈希的体素地图则用哈希代替层级结构,以换取 O(1) 的访问速度。在所有这些结构中,逐单元的对数几率计算方式都是相同的。

对SLAM的意义

SLAM 能给你一条轨迹和一份地图点/特征点地图——但一个稀疏的点云无法回答”这块空间能否安全通行?“这个问题,因为它完全没有说明空闲空间的信息。占据栅格地图明确地表示了空闲、占据和未知的体积区域,这正是碰撞检测、基于边界(frontier)的探索和路径规划所需要的。在实践中,SLAM 系统提供位姿,而占据栅格建图模块将带位姿的扫描数据转化为导航栈实际运行所依赖的代价地图(costmap);对数几率滤波器还天然地对动态物体和传感器噪声具有鲁棒性,这是原始几何地图所不具备的。

动手实践

相关条目