共计 2288 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
自动驾驶系统在复杂城市环境中面临诸多挑战,尤其是在定位精度方面。常见的问题场景包括:

-
隧道环境:GNSS 信号完全丢失,仅能依赖 IMU 进行航位推算,导致误差随时间累积。实测数据显示,在 1 分钟的隧道通行中,仅用 IMU 定位误差可达 5 -10 米。
-
高架桥下:多路径效应导致 GNSS 定位跳动,实测水平误差可达 2 - 3 米,严重影响车道级定位。
-
城市峡谷:高楼遮挡造成卫星信号不稳定,GNSS 定位可能出现间断性失效。
量化研究表明,当定位误差超过 10cm 时,路径规划算法的决策错误率会显著上升。在高速场景下(60km/h),10cm 的横向误差可能导致 50% 的变道决策错误。
技术方案
传感器方案对比
- GNSS-RTK
- 优点:绝对定位,全局一致性
- 缺点:依赖卫星信号,更新频率低(10Hz)
-
典型精度:水平 2cm(开阔环境)
-
视觉 SLAM
- 优点:无需外部信号,丰富语义信息
- 缺点:受光照影响大,累计误差
-
典型精度:0.5%-1% 里程(特征丰富环境)
-
LiDAR 定位
- 优点:高精度,不受光照影响
- 缺点:计算量大,点云匹配耗时
- 典型精度:2-5cm(高精度地图)
Apollo MSF 框架
Apollo 的多传感器融合 (MSF) 框架采用分层设计:
- 数据预处理层
- 时间同步:采用 PTP 协议,实现 μs 级时间对齐
-
空间标定:手眼标定($^{sensor}T_{base}$)解决安装偏差
-
融合算法层
- 运动模型:$\dot{x}=Ax+Bu+w$
- 观测模型:$z=Hx+v$
-
卡尔曼增益:$K=P^-H^T(HP^-H^T+R)^{-1}$
-
输出层
- 发布统一定位结果(/apollo/localization/pose)
- 提供健康状态监测
代码实现
C++ 卡尔曼滤波核心
// Apollo 命名空间规范
namespace apollo {
namespace localization {
namespace msf {void KalmanFilter::Predict(const Eigen::VectorXd& u) {
// 状态预测
x_ = F_ * x_ + B_ * u;
// 协方差更新
P_ = F_ * P_ * F_.transpose() + Q_;}
void KalmanFilter::Update(const Eigen::VectorXd& z) {
// 计算残差
Eigen::VectorXd y = z - H_ * x_;
// 卡尔曼增益
Eigen::MatrixXd K = P_ * H_.transpose() *
(H_ * P_ * H_.transpose() + R_).inverse();
// 状态更新
x_ = x_ + K * y;
// 协方差更新
P_ = (Eigen::MatrixXd::Identity(x_.size(), x_.size()) - K * H_) * P_;
}
} // namespace msf
} // namespace localization
} // namespace apollo
Python 标定工具示例
# Apollo 标定工具使用
from modules.calibration.proto import sensor_calibration_pb2
# 创建标定配置
calib = sensor_calibration_pb2.SensorCalibration()
calib.header.timestamp_sec = time.time()
calib.transform.translation.x = 1.2 # 安装位置 X 偏移(m)
calib.transform.translation.y = 0.3 # Y 偏移
calib.transform.translation.z = 2.1 # Z 高度
# 四元数姿态(车体坐标系到传感器)calib.transform.rotation.qx = 0.0
calib.transform.rotation.qy = 0.0
calib.transform.rotation.qz = 0.707
calib.transform.rotation.qw = 0.707 # 90 度绕 Z 轴旋转
# 保存标定结果
with open('lidar_calib.pb.txt', 'w') as f:
f.write(str(calib))
避坑指南
坐标转换陷阱
-
安装偏差补偿:忽略传感器安装角度会导致融合误差放大。例如激光雷达倾斜 5°时,50m 处会产生 4.36m 的投影误差。
-
时间戳对齐:建议使用 PTP 同步时钟,NTP 同步可能产生 100ms 级偏差,在 60km/ h 下相当于 1.67m 位置误差。
多线程优化
- 数据竞争处理
- 对高频传感器(IMU)使用无锁队列
-
对低频传感器(GNSS)使用读写锁
-
锁粒度控制
- 避免在卡尔曼更新时持有全局锁
- 采用状态快照机制减少临界区
降级策略
- GNSS 失效:启用 LiDAR 定位 +IMU 组合
- LiDAR 失效:切换视觉里程计
- 完全失效:IMU 航位推算 + 电子围栏限制车速
验证方法
DreamView 可视化
-
启动定位模块
cyber_launch start modules/localization/launch/localization.launch -
在 DreamView 中检查:
- 定位轨迹(绿色)与参考线(蓝色)偏差
- 协方差椭球大小
KITTI 评测指标
| 场景 | ATE (m) | RTE (%) |
|---|---|---|
| 城市道路 | 0.12 | 0.3 |
| 高速公路 | 0.08 | 0.2 |
| 地下停车场 | 0.25 | 0.7 |
延伸阅读
- 《概率机器人》第 3 章(卡尔曼滤波)
- Apollo 官方文档:传感器标定指南
- 论文《Robust Vehicle Localization in Urban Environments》
通过这套方案,我们在北京亦庄测试区实现了厘米级定位精度,即使在 GNSS 拒止环境下也能保持 30 秒内误差小于 1 米。关键是要理解各传感器的误差特性,并通过合理的权重分配实现优势互补。
