[具身智能-1146]:激光导航的全流程,包括激光测距,建图,规划,运动,避障等等,一条从光子到车轮的完整数据流水线。
激光导航全流程:从激光测距到机器人运动的完整闭环
激光导航不是一个单一算法,而是一条从光子到车轮的完整数据流水线:激光打出一个光子 → 测出距离 → 拼成点云 → 建成地图 → 算出路径 → 下发速度 → 轮子转动 → 传感器再感知,形成闭环。
下面按数据流动的顺序,逐环节拆解,每个环节讲清楚 "输入是什么、做了什么、输出是什么"。
全流程总览
plaintext
①激光测距 → ②点云预处理 → ③SLAM建图/定位 → ④代价地图 → ⑤路径规划 → ⑥运动控制 → ⑦底盘执行 → 传感器反馈
↑ ↓
└──────────────────────────── 闭环反馈 ────────────────────────────────────────┘
① 激光测距:从光子到一个距离值
输入:FPGA 触发激光二极管发射脉冲 输出:一个方向上的距离值 d
过程(你之前已经深入了解过):
- FPGA 发触发脉冲 → 激光驱动芯片输出大电流 → LD 发出 905nm/1550nm 激光脉冲;
- 同步信号 SYNC 给 TDC 的 START,标记 "发射时刻";
- 激光打到物体反射回来 → APD/SPAD 接收 → TIA 放大 → 比较器整形 → TDC 的 STOP;
- TDC 测飞行时间 t → 距离 d = c × t / 2;
- 扫描机构(旋转电机 / MEMS)让激光扫过不同角度,每个角度得到一个 (d, θ, φ)。
输出:一帧 3D 点云(几万个点,每个点含 X/Y/Z/ 反射强度)。
这一步是硬件层,决定了整个导航系统的 "感知上限"—— 测距不准,后面所有算法都白搭。
② 点云预处理:把原始点云变 "干净"
输入:原始 3D 点云
输出:去畸变、去噪、降采样后的可用点云
原始点云不能直接用,有几个问题必须处理:
2.1 运动畸变补偿
- 激光雷达转一圈需要 50~100ms(10~20Hz),这段时间机器人在运动;
- 一帧点云的开头和结尾,机器人位置已经变了,导致点云 "拖影";
- 用 IMU / 里程计记录每个时刻的位姿,把每个点 "投影回" 同一时刻的坐标系,消除畸变。
2.2 去噪
- 点云里有离群噪点(灰尘、雨滴、激光多径反射产生的假点);
- 统计滤波:每个点看周围邻居数量,邻居太少的判定为噪点删除;
- 半径滤波:指定半径内点数少于阈值就删除。
2.3 降采样(体素滤波)
- 一帧点云几十万点,全处理太慢;
- 把空间分成小立方体(体素,如 5cm×5cm×5cm),每个立方体内只保留一个点(重心);
- 点数减少 5~10 倍,精度损失很小,计算速度大幅提升。
2.4 地面分割
- 地面点占点云的 30~50%,但对避障和建图是 "背景";
- 用 RANSAC 平面拟合或角度特征,把地面点和非地面点分开;
- 地面点用来估计 "可通行区域",非地面点用来检测障碍物。
输出:干净、稀疏、分好类的点云,送给 SLAM 和避障模块。
③ SLAM 建图与定位:我在哪?周围什么样?
SLAM = 同步定位与建图,同时回答两个问题:
- 定位:我现在在什么位置?(x, y, θ)
- 建图:周围环境长什么样?(地图)
3.1 前端:激光里程计(帧间配准)
输入:当前帧点云 + 上一帧点云 / 子地图 输出:两帧之间的机器人位姿变化(Δx, Δy, Δθ)
方法:
- ICP(迭代最近点):找两帧点云中对应的点对,最小化点对距离,解出位姿变换;
- NDT(正态分布变换):把点云分成体素,每个体素用正态分布描述,匹配分布而非点,比 ICP 更鲁棒、更快;
- 特征匹配:提取角点、边线等特征,匹配特征点计算位姿(如 LOAM 系列)。
通俗理解:就像你走路时,靠 "上一秒看到的树和这一秒看到的树位置变化" 来估算自己走了多远、转了多少。
3.2 后端:位姿图优化
输入:前端输出的一连串位姿(有累积误差) 输出:全局优化后的位姿序列
- 前端帧间配准会有误差,走得越远误差累积越大(漂移);
- 后端把所有位姿和约束建成一个 "图",用图优化(g2o、Ceres)全局求解,让整体误差最小;
- 类似把一串有误差的尺子读数,整体拉平到最合理的位置。
3.3 回环检测
输入:当前帧点云 + 历史所有帧 输出:"我回到了以前来过的地方" 的判定
- 机器人转了一圈回到起点,前端累积误差可能显示 "离起点还有 2m";
- 回环检测识别出 "这个地方我来过",添加一个闭环约束;
- 后端根据这个约束,把整条轨迹 "掰正",消除累积漂移。
方法:
- Scan Context:把点云转成环形描述子,快速匹配历史帧;
- 词袋模型:提取特征点,用视觉词袋匹配(适合视觉,激光也有类似方法)。
3.4 地图输出
输入:优化后的位姿序列 + 所有帧点云 输出:
- 2D 占据栅格地图(pgm+yaml):每个格子标记 "占用 / 空闲 / 未知",供导航用;
- 3D 点云地图(pcd):完整三维环境,供 3D 导航 / 数字孪生用;
- OctoMap(.ot):八叉树 3D 地图,高效存储。
建图阶段通常是 "先开着机器人走一圈,把地图建好保存下来";之后导航时不再建图,只用已建好的地图 + 定位。
3.5 定位(AMCL)
输入:已建好的地图 + 当前激光点云 输出:机器人在地图中的精确位姿 (x, y, θ)
- 建图完成后,导航阶段不需要再建图,只需要 "在已知地图中找到自己在哪";
- AMCL(自适应蒙特卡洛定位):用粒子滤波,撒一堆 "可能的位置" 粒子,每个粒子对比 "如果我在这个位置,激光应该看到什么" 和 "实际激光看到了什么",相似度高的粒子保留,低的淘汰,最终收敛到真实位置;
- 通俗理解:就像你在商场里,看一眼周围的店铺,对照商场地图,就知道自己站在哪。
④ 代价地图:把地图变成 "能不能走" 的评分
输入:静态地图 + 实时传感器数据(激光点云) 输出:全局代价地图 + 局部代价地图
光有地图还不够,导航需要知道 "哪里能走、哪里不能走、哪里走起来代价高"。
4.1 全局代价地图
- 基于静态地图,给每个格子打分;
- 障碍物本身:代价最高(不可通行);
- 障碍物附近:膨胀一层(代价较高,避免贴太近);
- 开阔区域:代价低(优先走)。
4.2 局部代价地图
- 以机器人为中心的一个小窗口(如 5m×5m),实时更新;
- 把激光雷达实时看到的动态障碍物(人、车、突然出现的箱子)标记进去;
- 全局地图是 "静态的世界",局部代价地图是 "实时的世界"。
这一步是避障的基础 —— 规划器看着代价地图,就知道 "该绕开哪里"。
⑤ 路径规划:从 A 到 B 怎么走
输入:起点(当前定位)、终点(目标点)、代价地图 输出:一条无碰撞的路径 + 实时速度指令
规划分两层:全局规划(大方向)+ 局部规划(实时避障)。
5.1 全局规划器(Global Planner)
作用:在全局代价地图上,算一条从起点到终点的 "最优路径"。
算法:
- A*:启发式搜索,用 "到终点的估计距离" 引导搜索方向,比 Dijkstra 快;
- Dijkstra:无启发式,保证找到最短路径,但慢;
- 输出:一串路径点(waypoints),类似导航 APP 给的路线。
全局规划只算一次(或目标变了重算),不处理动态障碍物。
5.2 局部规划器(Local Planner)
作用:沿着全局路径走,同时实时避开动态障碍物,输出速度指令。
算法:
- DWA(动态窗口法):在速度空间 (v, ω) 里采样一组可能的速度,模拟未来几秒的轨迹,选一条 "不撞障碍物、离全局路径近、速度快" 的轨迹,输出对应的 /cmd_vel;
- TEB(时间弹性带):把路径当成一条有弹性的带子,在障碍物约束下优化形状和时间,轨迹更平滑,适合差速 / 全向底盘。
输出:/cmd_vel 话题,包含线速度 v(m/s)和角速度 ω(rad/s)。
通俗理解:全局规划是 "导航 APP 给的路线",局部规划是 "你开车时实时打方向盘躲行人"。
⑥ 运动控制:把速度指令变成轮子转动
输入:/cmd_vel(线速度 v, 角速度 ω) 输出:左右轮电机 PWM 信号
6.1 差速底盘运动学解算
对于两轮差速小车(你的 ROSMASTER M1 就是这种):
plaintext
左轮速度 = v - ω × L / 2
右轮速度 = v + ω × L / 2
(L = 左右轮间距)
6.2 PID 速度闭环
- 上面算出的是 "目标轮速",但电机实际转速受负载、电压、地面摩擦影响;
- 编码器反馈实际轮速 → PID 控制器对比目标和实际 → 调整 PWM 占空比;
- P(比例):差多少补多少;I(积分):消除稳态误差;D(微分):抑制超调。
6.3 电机驱动
- MCU 输出 PWM 到电机驱动芯片(TB6612/DRV8833);
- 驱动芯片放大电流,驱动直流电机转动;
- 编码器实时反馈转速,形成闭环。
这一步是 "大脑的指令变成肌肉的动作"。
⑦ 避障:三层防护机制
激光导航的避障不是单一模块,而是三层冗余防护:
表格
| 层级 | 机制 | 作用 | 触发条件 |
|---|---|---|---|
| 第一层 | 局部规划器避障 | 正常绕行动态障碍物 | 激光看到障碍物,局部规划器重新规划轨迹 |
| 第二层 | 代价地图膨胀 | 保持安全距离 | 障碍物进入膨胀区,规划器自动绕开 |
| 第三层 | 紧急制动(安全层) | 急停 | 障碍物进入安全距离内,直接发零速度,不管规划器说什么 |
第三层安全层非常重要 —— 哪怕规划器出 bug,只要激光检测到前方很近有障碍物,直接强制停车,保证安全。
完整闭环数据流(ROS2 视角)
plaintext
激光雷达硬件
↓ /scan 或 /pointcloud2
点云预处理节点
↓
┌─────────────┬──────────────┐
↓ ↓ ↓
SLAM节点 避障节点 定位节点AMCL
(建图时用) (更新代价地图) (导航时用)
↓ ↓ ↓
地图话题 代价地图话题 位姿话题 /tf
└─────────────┴──────────────┘
↓
Nav2规划服务器
(全局规划+局部规划)
↓ /cmd_vel
底盘控制节点(MCU)
↓ PWM
电机驱动 → 轮子转动
↓
编码器反馈 → 里程计 /odom
↓
机器人移动 → 激光看到新环境 → 回到第一步
各环节常用算法 / 工具汇总
表格
| 环节 | 主流算法 / 工具 | ROS2 对应包 |
|---|---|---|
| 激光测距 | TDC+APD/SPAD | 硬件层 |
| 点云预处理 | 体素滤波、统计滤波、RANSAC | PCL、pcl_ros |
| SLAM 前端 | ICP、NDT、LOAM 特征 | slam_toolbox、cartographer |
| SLAM 后端 | 图优化 (g2o/Ceres) | slam_toolbox 内置 |
| 回环检测 | Scan Context、词袋 | slam_toolbox 内置 |
| 定位 | AMCL 粒子滤波 | nav2_amcl |
| 全局规划 | A*、Dijkstra | nav2_planner |
| 局部规划 | DWA、TEB | nav2_controller |
| 代价地图 | 膨胀层、障碍物层 | nav2_costmap_2d |
| 运动控制 | PID、差速运动学 | MCU 固件、diff_drive_controller |
| 避障 | 局部规划 + 安全层 | nav2_obstacle_layer、safety_controller |
一句话总结
激光导航的全流程 = 激光雷达测距 (硬件) → 点云变干净 (预处理) → 边走边建图同时定位 (SLAM) → 把地图变成可走 / 不可走的评分 (代价地图) → 全局算路线 + 局部躲障碍 (规划) → 速度指令换算成轮子转动 (运动控制) → 传感器再感知形成闭环。每一环都有误差,靠闭环反馈不断修正,最终实现 "指哪走哪、不撞东西"。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)