
1. 可通行区域检测到底在解决什么问题第一次接触可通行区域检测这个概念是在一个移动机器人项目里。当时的需求很朴素让一台小车在室内环境中自己找到能走的路不要撞墙、不要卡在桌子腿中间、不要一脚踩进台阶下面。听起来简单但真正动手做的时候才发现这件事远比想象中复杂。可通行区域检测英文通常叫 Traversable Area Detection 或者 Free Space Detection本质上是从传感器采集到的原始数据中判断出哪些区域是可以通过的哪些区域是障碍物、边界或者不可进入的区域。它是移动机器人、自动驾驶、无人机避障等系统的第一道感知环节。没有这一步后面的路径规划、运动控制全都是空中楼阁。为什么说它是第一道环节因为路径规划算法需要一个明确的地图表示告诉你哪里能走、哪里不能走。如果你给规划器的地图是错的把障碍物标成了可通行区域那规划出来的路径再优美也没用车直接撞上去。反过来如果把可通行区域误标成了障碍物车就会变得畏手畏脚明明能过的地方不敢过任务效率大打折扣。这个方向适合谁来参考如果你正在做移动机器人、AGV、自动驾驶感知、扫地机导航、无人机避障等相关项目可通行区域检测是你绕不开的基础模块。不管你是刚入门的学生还是已经工作几年想系统梳理感知链路的工程师理解这个模块的理论基础和工程实现细节都会对你后续的开发和调试有直接帮助。我写这部分内容主要是想把可通行区域检测的理论框架讲清楚。所谓理论部分不是说只讲公式推导而是把整个问题的定义、常见的技术路线、每种路线背后的假设和适用场景、以及实际落地时容易踩的坑都摊开来聊一遍。你把这部分吃透了再去看具体的代码实现或者论文会顺畅很多。2. 核心思路与技术路线拆解2.1 从传感器数据到可通行区域的映射逻辑可通行区域检测的核心任务可以形式化地描述为给定传感器在某一时刻的观测数据输出一个关于周围空间的二值或多值分类结果标记每个位置是否可通行。不同传感器给出的数据形式完全不同。激光雷达给出的是距离测量点云深度相机给出的是深度图单目相机给出的是RGB图像超声波给出的是几个离散的距离值。所以可通行区域检测的第一步永远是把传感器数据转换到一个统一的空间表示中。最常见的空间表示有两种栅格地图和图像空间。栅格地图的思路是把地面划分成一个个小格子每个格子标记为可通行、障碍物或未知。这种表示的好处是直观、易于路径规划算法直接使用缺点是分辨率受限于格子大小而且三维信息被压扁到二维丢失了高度信息。图像空间的思路是直接在相机的像素平面上做判断每个像素标记为可通行或不可通行。这种表示保留了完整的视觉信息适合用深度学习方法来做但缺点是缺乏真实世界的尺度信息需要额外的投影变换才能用于规划。我个人的经验是如果你用的是激光雷达或者深度相机栅格地图是更自然的选择如果你用的是单目相机图像空间更直接。当然两者可以互相转换但每次转换都会引入误差所以尽量在原始数据所在的空间里做判断。2.2 基于几何的方法与基于学习的方法怎么选可通行区域检测的方法大致可以分成两大阵营基于几何的方法和基于学习的方法。基于几何的方法核心思想是利用传感器数据的几何特性来判断可通行性。比如激光雷达点云你可以通过分析地面的平整度、坡度、高度变化来判断某个区域是否可通行。地面是平的点云应该在一个平面上如果某个区域点云突然升高那大概率是障碍物如果点云突然降低那可能是坑或者台阶。这类方法的优点是可解释性强、不需要训练数据、计算量相对可控。缺点是对环境假设比较强比如假设地面是平的遇到斜坡、草地、地毯边缘就容易出问题。而且几何方法很难处理语义层面的可通行性比如一扇关着的玻璃门几何上看起来是障碍物但实际上是可以打开的。基于学习的方法核心思想是用数据驱动的方式让模型自己学会判断哪里能走。早期的方法用SVM、随机森林等传统机器学习算法提取特征后分类。近几年深度学习成为主流语义分割网络、深度估计网络、占用网络等各种架构层出不穷。这类方法的优点是适应性强、能处理复杂场景、可以融入语义信息。缺点是需要大量标注数据、训练成本高、模型泛化能力依赖训练集分布、推理时的计算资源需求也更高。那到底怎么选我的建议是看你的应用场景和资源约束。如果你做的是结构化环境下的AGV地面平整、障碍物类型固定几何方法完全够用而且更稳定、更容易调试。如果你做的是开放环境下的自动驾驶或者服务机器人场景复杂多变那学习方法是更好的选择但要做好数据闭环和模型迭代的准备。实际项目中几何方法和学习方法混合使用是很常见的策略。比如用几何方法快速筛出候选可通行区域再用学习模型做精细分类或者用学习模型做语义分割再用几何约束做后处理。这种混合方案能兼顾实时性、鲁棒性和准确性。2.3 不同传感器配置下的方案差异传感器配置直接决定了可通行区域检测的方案设计。单目相机方案成本最低但难度最大。单目图像没有直接的深度信息需要通过单应性变换、消失点检测、深度估计等方法来推断地面和障碍物。单目方案的可通行区域检测通常依赖语义分割把道路、人行道、地板等类别分割出来作为可通行区域。难点在于尺度不确定性和光照变化。双目相机方案通过视差计算深度可以得到稠密的深度图。有了深度信息可通行区域检测就变成了在深度图上找地面平面或者找高度突变。双目方案的难点在于标定精度、纹理缺失区域的匹配失败、以及计算量。激光雷达方案直接给出三维点云几何信息最准确。可通行区域检测通常通过地面分割、坡度分析、高度阈值等方法实现。激光雷达的难点在于点云稀疏性、反射率影响、以及雨雪雾等天气条件下的性能下降。深度相机方案介于双目和激光雷达之间给出稠密深度图但测量范围和精度受限于红外结构光或ToF原理。室内场景表现好室外强光下容易失效。多传感器融合方案把相机、激光雷达、IMU、轮速计等数据融合起来取长补短。这是目前最主流的方案但也是最复杂的涉及时间同步、外参标定、数据关联等一系列工程问题。我踩过的一个坑是一开始觉得激光雷达点云最准就只用激光雷达做可通行区域检测。结果在一条长廊里激光雷达扫到两面墙地面点云因为入射角太斜反射回来的点很少导致地面分割失败可通行区域出现大片空洞。后来加了相机做视觉补充才解决了这个问题。所以传感器配置不是越贵越好而是要跟你的场景匹配。3. 核心细节解析与实操要点3.1 地面分割可通行区域检测的基石地面分割是可通行区域检测中最基础也最关键的一步。不管你用什么传感器最终都需要把地面从其他物体中分离出来因为地面通常就是可通行区域的主要组成部分。地面分割的经典方法是RANSAC平面拟合。假设地面是一个平面随机采样三个点确定一个平面然后计算其他点到这个平面的距离距离小于阈值的点认为是地面点。重复多次选择内点最多的平面作为地面。RANSAC的优点是简单、快速、不需要先验知识。缺点是只能拟合平面遇到斜坡或者不平整的地面就失效了。而且当场景中有一个很大的平面障碍物比如一面墙时RANSAC可能会把墙误认为是地面。改进的方法包括基于法向量的方法计算每个点的法向量地面点的法向量应该大致朝上基于高度直方图的方法统计点云的高度分布地面通常对应高度最低的那个峰值基于区域生长的方法从种子点开始逐步扩展地面区域直到遇到高度突变或者法向量突变。在实际操作中我通常会把多种方法结合起来。先用RANSAC快速找到一个粗略的地面平面然后用高度阈值和法向量约束做精细筛选最后用区域生长填补空洞。这套组合拳在大多数室内外场景下都能得到不错的地面分割效果。注意地面分割的阈值设置非常关键。阈值太小地面点会被漏掉可通行区域出现空洞阈值太大低矮障碍物会被误判为地面导致可通行区域错误扩张。我的经验是阈值应该根据传感器精度和地面平整度来定通常取传感器测量误差的2到3倍。3.2 障碍物检测与可通行区域边界确定地面分割完成后剩下的点云就是非地面点也就是潜在的障碍物。但并不是所有非地面点都是障碍物比如树叶、雨滴、灰尘等噪声点需要过滤掉。障碍物检测的核心是聚类。把非地面点云分成一个个独立的簇每个簇代表一个障碍物。常用的聚类算法是DBSCAN它基于密度不需要预先指定簇的数量能发现任意形状的簇还能识别噪声点。DBSCAN有两个关键参数邻域半径eps和最小点数minPts。eps决定了多大的距离内的点被认为是邻居minPts决定了形成一个簇所需的最少点数。这两个参数需要根据点云密度和障碍物尺寸来调。点云稀疏时eps要调大障碍物较小时minPts要调小。聚类完成后每个簇就是一个障碍物。障碍物的边界可以通过计算簇的凸包或者包围盒来得到。可通行区域就是地面区域减去障碍物区域。但这里有一个容易忽略的问题障碍物的膨胀。因为传感器有测量误差障碍物的实际边界可能比测量到的边界稍微大一点。如果规划器贴着障碍物边界走就可能发生碰撞。所以通常会把障碍物向外膨胀一个安全距离这个距离取决于机器人的尺寸和控制精度。提示障碍物膨胀的距离不是越大越好。膨胀太大可通行区域会被过度压缩机器人可能找不到路。我的经验是膨胀距离取机器人半径加上一个小的安全余量通常5到10厘米就够了。3.3 可通行区域的表示与后处理可通行区域检测的输出通常是一个栅格地图或者一个多边形区域。不管哪种表示都需要做后处理来提升质量。形态学操作是最常用的后处理手段。开运算先腐蚀后膨胀可以去除小的噪声区域闭运算先膨胀后腐蚀可以填补小的空洞。这两个操作结合起来可以让可通行区域的边界更平滑、更完整。连通域分析也很重要。可通行区域应该是连通的如果出现了孤立的可通行小区域那大概率是误检应该去掉。只保留与机器人当前位置连通的那个区域作为最终的可通行区域。距离变换可以计算每个可通行栅格到最近障碍物的距离这个距离场对于后续的路径规划非常有用。规划器可以倾向于选择距离障碍物较远的路径提高安全性。还有一个容易被忽视的后处理步骤是时间一致性滤波。单帧检测结果可能有抖动如果直接送给规划器会导致机器人运动不流畅。可以用卡尔曼滤波或者简单的滑动窗口平均把多帧结果融合起来得到更稳定的可通行区域。我在一个项目中遇到过这样的问题机器人静止时可通行区域检测结果很稳定但机器人一运动由于传感器运动畸变和帧间配准误差可通行区域边界就开始抖动导致规划器频繁重新规划路径机器人走起来一顿一顿的。后来加了时间一致性滤波问题就解决了。4. 实操过程与核心环节实现4.1 数据预处理与坐标变换可通行区域检测的第一步是数据预处理。不管你用什么传感器原始数据都不能直接拿来用需要经过一系列清洗和变换。对于激光雷达点云预处理包括去畸变因为激光雷达在旋转过程中机器人也在运动每个点的采集时刻不同需要根据运动信息校正、降采样减少点云数量提高后续处理速度、离群点去除去掉明显的噪声点。去畸变的方法通常是利用IMU或者轮速计提供的运动信息对每个点做运动补偿。降采样常用体素栅格滤波把三维空间划分成小立方体每个立方体只保留一个点。离群点去除可以用统计滤波计算每个点到其邻居的平均距离距离过大的点认为是离群点。坐标变换是把传感器坐标系下的数据转换到机器人坐标系或者世界坐标系。这一步需要精确的外参标定包括传感器到机器人中心的平移和旋转。外参标定不准后续所有的检测都会有问题。注意外参标定是可通行区域检测中最容易被低估的环节。我见过很多项目算法本身没问题但就是因为外参标定有偏差导致可通行区域整体偏移机器人老是往一边偏。标定的时候一定要用标准的标定板或者标定场地不要凭感觉估。4.2 地面分割与障碍物聚类的参数调优地面分割和障碍物聚类的参数调优是可通行区域检测中最耗时的环节。参数没有一套通用的值必须根据你的传感器、场景和机器人平台来调。我通常的调优流程是这样的第一步采集一组代表性数据覆盖你的应用场景中的各种情况包括平坦地面、斜坡、不同高度的障碍物、不同光照条件等。第二步可视化地面分割结果手动调整RANSAC的距离阈值直到地面点被正确分割出来同时低矮障碍物没有被误判为地面。第三步可视化障碍物聚类结果调整DBSCAN的eps和minPts直到不同障碍物被正确分开同一个障碍物的点没有被拆散。第四步把可通行区域检测结果叠加到原始数据上检查是否有漏检和误检根据检查结果微调参数。这个过程可能需要反复迭代很多次。我的经验是先保证召回率再优化准确率。也就是说宁可把一些可通行区域误判为障碍物也不要让障碍物被误判为可通行区域。因为前者导致机器人保守后者导致机器人碰撞后者的代价大得多。4.3 可通行区域检测的完整流程与代码框架下面给出一个基于激光雷达的可通行区域检测的完整流程框架。这个框架是伪代码级别的你可以根据自己使用的语言和库来填充具体实现。# 伪代码框架基于激光雷达的可通行区域检测 def traversable_area_detection(point_cloud, robot_pose): # 1. 数据预处理 cloud remove_outliers(point_cloud) cloud voxel_downsample(cloud, voxel_size0.05) cloud motion_compensate(cloud, robot_pose) # 2. 坐标变换到机器人坐标系 cloud_robot transform_to_robot_frame(cloud, extrinsic_params) # 3. 地面分割 ground_plane ransac_plane_fit(cloud_robot, distance_threshold0.1, max_iterations100) ground_points, obstacle_points split_by_plane(cloud_robot, ground_plane, threshold0.1) # 4. 地面点精细筛选 ground_points filter_by_normal(ground_points, max_angle30) ground_points filter_by_height(ground_points, min_height-0.2, max_height0.2) # 5. 障碍物聚类 clusters dbscan_cluster(obstacle_points, eps0.3, min_pts10) # 6. 障碍物膨胀 inflated_clusters inflate_clusters(clusters, inflation_radius0.3) # 7. 生成可通行区域栅格 grid create_grid(cloud_robot, resolution0.1) grid mark_ground(grid, ground_points) grid mark_obstacles(grid, inflated_clusters) # 8. 后处理 grid morphological_close(grid, kernel_size3) grid keep_largest_connected_component(grid) grid temporal_filter(grid, history_buffer) return grid这个框架涵盖了可通行区域检测的主要步骤。实际实现时每个步骤都有很多细节需要处理。比如RANSAC平面拟合你需要决定是全局拟合还是分区域拟合DBSCAN聚类你需要决定是在三维空间聚类还是投影到二维后再聚类栅格地图的分辨率你需要权衡精度和计算量。4.4 性能优化与实时性保障可通行区域检测通常是感知链路中的一环需要满足实时性要求。如果检测一帧要几百毫秒那整个系统的控制周期就会很长机器人运动就会不流畅。性能优化的手段主要有几个方向算法层面选择计算复杂度低的算法避免不必要的全局搜索。比如地面分割如果场景中地面占主导可以用高度直方图快速定位地面而不是用RANSAC做全局搜索。数据结构层面使用KD树或者八叉树来加速最近邻搜索。DBSCAN聚类中邻域查询是最耗时的操作用KD树可以把复杂度从O(n²)降到O(n log n)。并行计算层面点云预处理、聚类、栅格化等步骤都可以并行化。如果平台支持CUDA或者OpenCL可以把这些步骤放到GPU上跑速度提升非常明显。降采样层面在不影响检测精度的前提下尽量降低点云密度。体素栅格滤波的体素大小从0.05米调到0.1米点云数量能减少到原来的八分之一速度提升非常可观。我在一个项目中通过把体素大小从0.05调到0.08同时把DBSCAN的邻域查询换成KD树实现单帧处理时间从120毫秒降到了35毫秒满足了10赫兹的实时性要求。提示性能优化不要过早进行。先把功能做对再考虑做快。很多优化手段会引入额外的参数和复杂度如果功能还没稳定就做优化调试起来会非常痛苦。5. 常见问题与排查技巧实录5.1 地面分割失败的各种原因与对策地面分割失败是可通行区域检测中最常见的问题。表现是地面点被漏掉可通行区域出现大片空洞或者地面点被误判为障碍物可通行区域被过度压缩。原因一地面不是平面。斜坡、起伏地面、地毯边缘等都会导致RANSAC平面拟合失败。对策是改用基于法向量或者基于区域生长的方法或者把场景分成多个小区域每个区域单独拟合平面。原因二地面点云太稀疏。激光雷达在远处或者大入射角时地面点云会变得很稀疏RANSAC可能找不到足够的内点。对策是增大RANSAC的距离阈值或者用多帧累积来增加点云密度。原因三地面被遮挡。比如桌子下面的地面被桌子挡住激光雷达扫不到。对策是接受这部分区域为未知区域不要强行标记为可通行或障碍物。规划器应该能够处理未知区域。原因四地面反射率太低。黑色地面、镜面地面等激光雷达可能收不到回波。对策是融合其他传感器比如相机或者深度相机来补充地面信息。5.2 障碍物漏检与误检的排查思路障碍物漏检的后果是机器人可能撞上障碍物这是最危险的情况。障碍物误检的后果是机器人过于保守影响任务效率。漏检的常见原因障碍物太小点云太少DBSCAN的minPts设得太大导致小障碍物被当成噪声过滤掉。对策是降低minPts或者对近距离区域使用更小的minPts。漏检的另一个原因障碍物被地面分割误判为地面。比如低矮的台阶高度只有几厘米如果地面分割的高度阈值设得太大台阶就会被当成地面。对策是降低高度阈值或者增加基于法向量的约束。误检的常见原因地面上的噪声点被聚类成障碍物。比如雨滴、灰尘、地面纹理等。对策是加强预处理阶段的离群点去除或者在聚类后根据障碍物的尺寸和形状做过滤。误检的另一个原因动态障碍物。比如行人、其他机器人等。这些障碍物在单帧中看起来是障碍物但下一帧可能就移走了。对策是引入跟踪算法区分静态障碍物和动态障碍物对动态障碍物做特殊处理。5.3 可通行区域抖动与时间一致性问题可通行区域抖动是指相邻帧的检测结果不一致边界位置跳变。这个问题在机器人运动时尤其明显。抖动的来源传感器噪声、运动畸变、帧间配准误差、算法参数敏感等。排查方法先固定机器人看静止时是否有抖动。如果静止时也抖动那是传感器噪声或者算法参数问题。如果静止时不抖运动时抖那是运动畸变或者配准问题。解决思路对于传感器噪声可以用滤波或者多帧平均。对于运动畸变需要做运动补偿。对于配准误差需要提高配准精度或者降低对配准的依赖。时间一致性滤波是我常用的手段。维护一个可通行区域的历史缓冲区每帧的新结果和缓冲区中的历史结果做加权平均。权重可以根据机器人的运动速度来调运动快时权重偏向新结果运动慢时权重偏向历史结果。5.4 常见问题速查表问题现象可能原因排查方法解决思路可通行区域大片空洞地面分割失败可视化地面点云调整地面分割参数或换算法可通行区域边界抖动传感器噪声或运动畸变静止对比运动时间滤波或运动补偿小障碍物漏检聚类参数过严检查小障碍物点云降低minPts或分区域调参地面噪声误检为障碍物预处理不足检查离群点加强离群点去除可通行区域整体偏移外参标定不准检查标定参数重新标定外参远处可通行区域缺失点云稀疏检查远处点云密度多帧累积或降低分辨率动态障碍物导致可通行区域跳变未区分动静障碍物检查障碍物跟踪引入跟踪算法处理时间过长算法复杂或点云过多计时各步骤降采样或并行化这张表是我在实际项目中总结出来的基本上覆盖了80%以上的常见问题。遇到问题的时候先对照这张表排查能省不少时间。注意排查问题时一定要可视化中间结果。不要只看最终的可通行区域要把地面分割结果、障碍物聚类结果、栅格地图都可视化出来逐级排查。很多问题在中间步骤就能看出来直接看最终结果反而找不到原因。6. 从理论到落地的几个关键认知6.1 没有万能的算法只有匹配场景的方案我刚开始做可通行区域检测的时候总想找一个通用的算法能适应所有场景。后来发现这是不可能的。室内和室外、结构化道路和非结构化地形、低速机器人和高速车辆对可通行区域检测的要求完全不同。室内扫地机器人地面平整障碍物主要是家具和墙壁几何方法加简单的语义分割就够了。室外自动驾驶地面起伏障碍物种类繁多需要多传感器融合加深度学习。工业AGV环境固定可以用预先建好的地图做定位可通行区域检测只需要处理动态障碍物。所以不要盲目追求算法的先进性要根据你的场景选择最合适的方案。有时候一个简单的阈值方法比复杂的深度学习模型更稳定、更可靠。6.2 数据质量比算法复杂度更重要我见过很多项目算法选得很高级但效果不好。排查到最后发现是数据质量问题。传感器标定不准、时间同步没做好、点云去畸变没做、外参有偏差这些问题不解决再好的算法也白搭。数据质量包括几个方面传感器精度、标定精度、时间同步精度、数据预处理质量。这四个方面任何一个出问题都会直接影响可通行区域检测的效果。我的建议是在算法开发之前先花时间把数据质量做好。标定要精确时间同步要严格预处理要到位。这些基础工作做好了后面算法调优会顺利很多。6.3 可通行区域检测不是孤立的模块可通行区域检测是感知链路中的一环它的输入来自传感器输出送给规划器。所以它的设计必须考虑上下游的需求。上游方面你需要知道传感器的特性比如激光雷达的扫描模式、深度相机的测量范围、相机的视场角。这些特性决定了你能检测到什么样的可通行区域。下游方面你需要知道规划器需要什么样的表示。有的规划器需要栅格地图有的需要多边形有的需要距离场。输出格式不匹配规划器就用不了。我在一个项目中可通行区域检测输出的是栅格地图但规划器需要的是多边形边界。中间加了一个栅格转多边形的步骤结果多边形边界锯齿严重规划出来的路径也不平滑。后来改成直接输出多边形问题就解决了。所以可通行区域检测的设计一定要从系统层面考虑不要只盯着自己的模块。6.4 持续迭代比一次做完美更现实可通行区域检测很难一次做到完美。场景在变传感器在老化需求在演进。所以要建立持续迭代的机制。迭代的基础是数据闭环。把实际运行中遇到的问题数据收集起来标注后加入训练集或者测试集不断优化算法。同时建立评测体系用客观指标来衡量算法的改进效果。评测指标通常包括准确率、召回率、IoU、处理时间等。对于可通行区域检测召回率比准确率更重要因为漏检可通行区域的代价是机器人保守而漏检障碍物的代价是碰撞。我个人的习惯是每做一个改进都要在固定的测试集上跑一遍对比改进前后的指标。如果指标没有提升或者提升很小但引入了额外的复杂度那就不要这个改进。保持算法的简洁性对长期维护非常重要。可通行区域检测这个方向理论部分看起来不复杂但真正落地的时候细节非常多。每一个参数、每一个步骤、每一个假设都可能影响最终效果。希望这部分内容能帮你建立一个完整的理论框架在实际项目中少走一些弯路。后面如果有机会再聊聊具体的代码实现和工程优化细节。