4. 传感器仿真:激光雷达(LiDAR)仿真、IMU仿真、相机仿真、传感器噪声建模
传感器仿真,说白了就是给虚拟机器人装上一双“眼睛”和“耳朵”。你想想看,算法在真机上跑之前,总得有个地方先验证一下吧?直接上真车真机器人,撞坏了谁赔?所以,仿真环境里的传感器数据,就是我们算法工程师的“练兵场”。
我个人习惯把传感器仿真分成两派:一派是物理渲染派,追求极致的真实感,适合做感知算法验证;另一派是抽象数据派,只关心数据格式和频率,适合做规划控制算法的快速迭代。今天咱们重点聊前者,因为后者太简单,没什么好讲的。
4.1 激光雷达(LiDAR)仿真
LiDAR 仿真,我遇到过最坑的事就是——仿真里点云干干净净,一上实车全是噪点,算法直接崩了。所以,LiDAR 仿真不能只做“射线投射”,还得把物理特性模拟出来。
常见的做法是使用 射线投射(Ray Casting) 算法。从 LiDAR 原点发射出一圈射线,碰到物体就返回距离。但这里有个细节:
- 光束发散: 真实激光是有角度的,不是一条理想的线。仿真里如果不加这个发散角,点云会过于锐利。
- 多次回波: 比如透过树叶打到树干。仿真里要支持返回多个 hit 点。
- 最大探测距离: 超过 100 米就截断,别让射线无限延伸。
下面是一个简单的 LiDAR 仿真参数配置表,我一般这么设:
| 参数名 | 典型值 | 说明 |
|---|---|---|
| 水平视场角 | 360° | 机械式 LiDAR 常见 |
| 垂直视场角 | 30° | 16线/32线/64线 |
| 角分辨率 | 0.2° | 越高点云越密 |
| 最大距离 | 100 m | 超过此值返回 inf |
| 噪声标准差 | 0.02 m | 高斯噪声,模拟测距误差 |
4.2 IMU 仿真
IMU 仿真,说白了就是“加速度计 + 陀螺仪”的数学模型。这东西在仿真里特别容易“飘”,因为真实 IMU 有零偏、有噪声、有温漂。如果你在仿真里给一个完美的 IMU,那你的状态估计器永远学不会处理真实数据。
我建议至少模拟以下三个误差源:
- 零偏(Bias): 静态时输出不为 0。仿真里可以加一个随机游走模型。
- 白噪声: 高频抖动。用高斯分布采样即可。
- 尺度因子误差: 输出值比真实值大或小一个比例。
代码实现上,我习惯这样写:
// 伪代码:IMU 仿真模型
float simulate_imu_accel(float true_accel) {
static float bias = 0.05; // 零偏
float noise = gaussian_random(0, 0.01); // 白噪声
float scale = 1.02; // 尺度因子
return true_accel * scale + bias + noise;
}
4.3 相机仿真
相机仿真,这是最吃算力的部分。你要渲染出逼真的图像,还得考虑畸变、曝光、运动模糊。我个人习惯用 光线追踪 或者 光栅化 两种方式。光栅化快,但效果差一点;光线追踪慢,但真实感强。
对于自动驾驶仿真,我建议至少模拟以下效果:
- 镜头畸变: 径向畸变和切向畸变。用 OpenCV 的畸变模型直接套。
- 自动曝光: 从暗处到亮处,图像亮度会自适应变化。仿真里不做这个,算法会过度依赖固定亮度。
- 运动模糊: 车辆高速运动时,图像会拖影。这个对目标检测影响很大。
相机内参矩阵是必须的,我一般这样配:
| 参数 | 值 | 含义 |
|---|---|---|
| fx | 600.0 | x 方向焦距 |
| fy | 600.0 | y 方向焦距 |
| cx | 320.0 | 光心 x 坐标 |
| cy | 240.0 | 光心 y 坐标 |
| k1, k2 | -0.2, 0.1 | 径向畸变系数 |
4.4 传感器噪声建模
这是传感器仿真的灵魂。没有噪声的仿真,就是“温室里的花朵”。我见过太多团队,仿真里跑得完美无缺,一上路就翻车。原因只有一个:噪声模型太简单。
我常用的噪声模型有这几种:
- 高斯噪声: 最基础,适用于测距误差、像素亮度误差。
- 泊松噪声: 适用于光子计数场景,比如弱光下的相机。
- 量化噪声: 模拟 ADC 转换时的精度损失。
- 时间戳抖动: 传感器数据到达的时间不是完全均匀的。这个对多传感器融合影响极大。
下面这张图是我自己总结的传感器噪声注入流程:
嗯,这里要注意一个细节:噪声参数不是随便设的。我一般会先录一段真实传感器的数据,然后统计它的噪声分布,再把统计结果用到仿真里。这叫“数据驱动噪声建模”。
4.5 多传感器时间同步仿真
最后聊一个容易被忽略的点——时间同步。仿真里虽然所有传感器都在同一台机器上,但它们的“虚拟时钟”可能不同步。比如 LiDAR 是 10Hz,相机是 20Hz,IMU 是 100Hz。如果你不做时间同步,融合算法会拿到错位的数据。
我常用的做法是:
- 所有传感器共享一个 全局虚拟时钟。
- 每个传感器发布数据时,带上时间戳。
- 在仿真调度器里,按时间戳顺序依次发布数据。
这样,你的算法在仿真里就能直接复用真机上的时间同步逻辑,省去很多麻烦。