2. 环境感知与地图表示:栅格地图、拓扑地图、点云地图、语义地图
各位同学,咱们接着聊。上一节我们把传感器和感知算法过了一遍,现在手里有了原始数据——激光点云、图像、里程计信息。但这些东西,机器人看不懂啊。
它需要一种「地图」——说白了,就是让机器人理解周围环境的数据结构。我这些年做项目,换过好几种地图表示方式,每种都有它的脾气。今天我把四种主流地图掰开揉碎讲给你听。
2.1 栅格地图(Occupancy Grid Map)
这是最直观的一种。想象一下,你把地面切成一个个小方格,每个格子要么是「空闲」,要么是「占用」,要么是「未知」。这就是栅格地图。
我个人习惯用 Bayesian 更新 来处理每个格子的概率。每次激光打回来,我就更新对应格子的置信度。公式不复杂:
P(occupied | z) = P(z | occupied) * P(occupied) / P(z)
嗯,这里要注意:栅格大小很关键。我见过有人把格子设成 5cm,结果地图大得离谱,内存直接爆了。一般室内机器人用 10-20cm 就够了。
优点:
- 实现简单,新手友好
- 适合避障和局部路径规划
- 容易融合多传感器数据
缺点:
- 大场景下内存爆炸
- 没有语义信息,就是一堆格子
我的经验:做扫地机器人时,我用了双层栅格——局部用 5cm 高精度,全局用 20cm 粗粒度。既保证了避障精度,又控制了内存。你可以试试这个思路。
2.2 拓扑地图(Topological Map)
栅格地图太「笨重」了。你想想看,一个 1000 平米的仓库,用 10cm 栅格就是 10 万个格子。机器人真的需要知道每个格子吗?
拓扑地图的思路是:只保留关键节点和连接关系。节点可以是走廊拐角、房间门口、电梯口。边就是路径。
我曾经在一个物流仓库里用拓扑地图做导航。节点数不到 200 个,但覆盖了整个 5000 平米的区域。路径规划用 Dijkstra 算法,毫秒级出结果。
class TopoNode:
def __init__(self, id, position, neighbors):
self.id = id
self.position = position # (x, y)
self.neighbors = neighbors # [(neighbor_id, cost), ...]
class TopoMap:
def __init__(self):
self.nodes = {}
def add_node(self, node):
self.nodes[node.id] = node
def find_path(self, start_id, goal_id):
# 用 Dijkstra 或 A* 搜索
pass
避坑指南:我曾经在动态环境中吃过亏——拓扑地图更新节点连接关系太慢。后来我加了「动态边权重」,根据实时拥堵情况调整 cost。记住:拓扑地图不是静态的,要让它活起来。
2.3 点云地图(Point Cloud Map)
点云地图,说白了就是一堆三维点的集合。每个点有 (x, y, z) 坐标,可能还有强度值或颜色信息。
激光雷达扫一圈,几万到几十万个点就来了。直接存下来就是点云地图。但问题也来了——数据量太大。
我记得第一次做室外无人车,一公里路扫下来,点云文件 2 个 G。后来用了 体素滤波(Voxel Grid Filter),把 5cm 内的点合并成一个,数据量直接降到 1/10。
| 滤波方法 | 效果 | 适用场景 |
|---|---|---|
| 体素滤波 | 均匀降采样 | 通用场景 |
| 统计滤波 | 去除离群点 | 有噪声的传感器 |
| 半径滤波 | 保留密集区域 | 特征提取前 |
点云地图的用途:
- 定位:ICP 匹配,算机器人位姿
- 建图:SLAM 的核心输出
- 障碍物检测:直接做碰撞检测
2.4 语义地图(Semantic Map)
这是目前最「高级」的地图表示。它不光告诉机器人「这里有障碍物」,还告诉它「这是一把椅子」、「这是一扇门」、「这是人行道」。
怎么做?把深度学习的目标检测结果融合到地图里。比如 YOLO 检测到「椅子」,我就把椅子对应的点云或栅格区域标记为「椅子」类别。
我去年做的一个项目,用语义地图实现了「找空椅子」的功能。机器人走到会议室,直接定位到没人坐的椅子位置。这在纯几何地图里根本做不到。
class SemanticCell:
def __init__(self, x, y):
self.x = x
self.y = y
self.occupancy = 0.0 # 占用概率
self.semantic_label = "unknown" # 语义标签
self.confidence = 0.0 # 置信度
# 更新语义信息
def update_semantic(cell, detection):
if detection.confidence > 0.5:
cell.semantic_label = detection.class_name
cell.confidence = detection.confidence
cell.occupancy = 1.0 # 有物体就标记为占用
我的建议:别一上来就搞全语义地图。先从「二分类」开始——只区分「可通行区域」和「障碍物」。等系统稳定了,再慢慢加入「门」、「楼梯」、「电梯」这些关键语义。步子大了容易扯着蛋。
2.5 四种地图怎么选?
你可能会问:那我到底用哪种?
我的经验是:没有银弹。实际项目中往往是混合使用。
- 局部规划:用栅格地图,实时更新,精度高
- 全局导航:用拓扑地图,轻量快速
- 定位:用点云地图,精度高
- 高级交互:用语义地图,理解环境
举个例子,我做的仓储机器人:底层用栅格地图做避障,上层用拓扑地图做路径规划,点云地图用来定位,语义地图用来识别货架和充电桩。四层叠加,各司其职。
最后提醒一句:地图表示不是越复杂越好。如果你的机器人只需要在走廊里跑直线,一个简单的拓扑地图就够了。别为了炫技把系统搞复杂,稳定才是王道。
好,这一节就到这儿。下一节我们讲「全局路径规划算法」,到时候会用到今天讲的地图表示。你先把这四种地图的优缺点记牢,后面用得上。