3、传感器数据异常排查(上):GPS信号丢失与多路径效应。IMU零偏与温漂问题。轮速计打滑与标价误差。

各位同学,咱们今天聊点实在的。定位漂移,说白了就是车不知道自己到底在哪儿。我做了这么多年自动驾驶,遇到最多的坑,其实不是算法多复杂,而是传感器本身在“撒谎”。

你想想看,GPS、IMU、轮速计,这三个家伙是定位系统的“三驾马车”。任何一个出问题,定位结果就会像喝醉了一样。今天咱们就一个一个来扒皮,看看它们到底是怎么“搞鬼”的。

核心观点: 传感器数据异常是定位漂移的第一大元凶。排查顺序,我建议先看GPS,再看IMU,最后查轮速计。为什么?因为GPS最容易受环境影响,IMU的误差是慢慢累积的,轮速计的问题往往最隐蔽。

传感器数据异常排查(上)知识体系 GPS信号异常 IMU零偏与温漂 轮速计打滑与标定 信号丢失 多路径效应 零偏(Bias) 温漂(Temperature Drift) 打滑(Slip) 标定误差

3.1 GPS信号丢失与多路径效应

GPS这东西,说白了就是靠天上的卫星给你报位置。但卫星信号很脆弱,稍微有点遮挡就完蛋。

信号丢失是最常见的问题。我遇到过最夸张的一次,车在高架桥下面走了不到200米,GPS直接跳了30米。为什么?卫星被桥挡住了,接收机只能抓到一两颗星,定位精度瞬间崩盘。

我的排查习惯: 在ROS2里,我一般会订阅 /gps/fix 话题,重点关注两个字段:status.status 和 position_covariance。如果 status 不是 2(表示固定解),或者协方差矩阵的对角线元素突然变大,那基本可以断定GPS出问题了。

再说多路径效应。这个更隐蔽。信号从卫星发出来,本来应该直线到达接收机。但如果周围有高楼、玻璃幕墙,信号会反射。反射后的信号路径变长了,接收机算出来的位置就会偏。

我记得有一次在市中心测试,定位结果一直在左右摇摆,幅度大概2-3米。查了半天,发现是旁边一栋玻璃大厦搞的鬼。信号反射后,接收机同时收到了直达波和反射波,解算出来的位置就“晃”起来了。

避坑指南: 我曾经在隧道出口吃过亏。车刚出隧道,GPS重新捕获卫星,这时候千万别直接用它的位置。因为接收机需要时间重新收敛,前几秒的数据往往误差很大。我现在的做法是:在ROS2里加一个 gps_validity_check 节点,等协方差稳定了再放行。

3.2 IMU零偏与温漂问题

IMU这东西,说白了就是个“积分器”。它测量加速度和角速度,然后积分出位置和姿态。但积分有个致命问题——误差会累积。

零偏(Bias) 是IMU最头疼的问题。理论上,IMU静止时,输出的加速度应该是0,角速度也应该是0。但实际上,由于制造工艺和电路噪声,它总会输出一个很小的非零值。这个值就是零偏。

你想想看,如果零偏是0.01 m/s²,积分1秒,速度误差是0.01 m/s;积分10秒,速度误差变成0.1 m/s;积分100秒,位置误差就是5米!这就是为什么纯IMU定位撑不了多久。

积分时间 零偏 0.01 m/s² 导致的位置误差
1 秒 0.005 米
10 秒 0.5 米
100 秒 50 米

再看温漂。IMU对温度非常敏感。我做过一个实验:把IMU从25°C的室内拿到40°C的阳光下,零偏直接翻了一倍。为什么?因为MEMS传感器的机械结构会随温度膨胀收缩,导致测量值偏移。

我的做法: 在ROS2里,我会写一个 imu_calibration_node。每次系统启动时,先让IMU预热5分钟,然后采集静态数据,计算零偏并补偿。另外,我会订阅 /imu/temperature 话题,如果温度变化超过5°C,就触发一次在线标定。

# 一个简单的IMU零偏补偿示例(Python)
import rclpy
from sensor_msgs.msg import Imu

class ImuBiasCompensator:
    def __init__(self):
        self.bias_accel = [0.0, 0.0, 0.0]
        self.bias_gyro = [0.0, 0.0, 0.0]
        self.samples = []
        
    def calibrate(self, imu_msg):
        # 采集100个静态样本求平均
        self.samples.append(imu_msg)
        if len(self.samples) >= 100:
            # 计算零偏
            self.bias_accel[0] = sum(s.linear_acceleration.x for s in self.samples) / 100
            # ... 类似计算其他轴
            print("零偏标定完成")
            
    def compensate(self, imu_msg):
        # 补偿后的数据
        imu_msg.linear_acceleration.x -= self.bias_accel[0]
        # ... 类似补偿其他轴
        return imu_msg

3.3 轮速计打滑与标定误差

轮速计,说白了就是靠车轮转了多少圈来算走了多远。听起来很靠谱对吧?但实际用起来,坑也不少。

打滑是最常见的问题。加速时轮胎空转,或者刹车时轮胎抱死,轮速计都会多算或少算里程。我遇到过最离谱的一次,在冰雪路面上,轮速计显示车走了10米,实际上只滑了3米。定位结果直接飞了。

怎么排查?我个人习惯看轮速和GPS速度的对比。如果轮速突然比GPS速度快很多,大概率是打滑了。在ROS2里,我会写一个 wheel_slip_detector 节点,实时计算两者的差值,超过阈值就报警。

再说标定误差。每个车轮的半径其实不完全一样,轮胎气压不同、磨损程度不同,都会导致有效半径变化。如果标定时用的半径是0.3米,实际只有0.29米,那每转一圈就会少算0.0628米。跑个100米,误差就超过2米了。

避坑指南: 我曾经在标定时犯过一个低级错误——用新轮胎的半径去标定,结果跑了两个月后轮胎磨损了,定位越来越不准。后来我改成每个月做一次自动标定,利用GPS数据反推轮速计的比例因子。代码很简单,就是最小二乘法拟合。

# 轮速计比例因子自动标定(伪代码)
def calibrate_wheel_scale(gps_positions, wheel_odom_positions):
    # 用GPS位置作为真值,拟合轮速计的比例因子
    # 模型:gps_pos = scale * wheel_odom_pos + bias
    # 使用最小二乘法
    scale = np.linalg.lstsq(wheel_odom_positions, gps_positions)[0]
    return scale

好了,今天咱们把GPS、IMU、轮速计这三个传感器的常见问题都过了一遍。记住一句话:传感器数据异常,永远是定位漂移排查的第一步。下一章咱们接着聊传感器数据异常排查的下半部分——激光雷达和视觉传感器的那些坑。

课后作业: 打开你的ROS2 bag文件,找到一段包含GPS、IMU、轮速计的数据。分别画出GPS的协方差变化曲线、IMU的零偏随时间的变化、轮速计与GPS速度的差值。看看你能发现什么问题?

可可精品资料库