架构与时延:模块边界、时间预算与功能安全
本页关注自动驾驶软件框架的核心骨架:如何拆分模块、管控时延、实现功能安全隔离。
1. 软件分层架构
典型自动驾驶软件栈按职责分为以下层次:
┌──────────────────────────────────────────────────────┐
│ 应用层(Application) │
│ 感知 │ 预测 │ 规划 │ 控制 │ 定位 │ 地图匹配 │
├──────────────────────────────────────────────────────┤
│ 中间件层(Middleware) │
│ 消息传递(Topic/Service) │ 参数服务 │ 生命周期管理 │
├──────────────────────────────────────────────────────┤
│ 运行时层(Runtime) │
│ 调度器 │ 资源管理 │ 时间同步 │ 日志收集 │
├──────────────────────────────────────────────────────┤
│ 硬件抽象层(HAL) │
│ 传感器驱动 │ 执行器接口 │ GNSS/IMU 驱动 │
└──────────────────────────────────────────────────────┘
架构稳定性
模块边界一旦稳定,接口变更代价极高(跨团队协调、回归测试)。在系统早期投入充足时间定义清晰接口,是长期可维护性的关键。
2. 模块边界设计原则
2.1 接口规范要素
每个模块的接口应明确以下内容:
| 要素 | 说明 | 示例 |
|---|---|---|
| 输入消息 | Topic 名称、消息类型、预期频率 | /perception/objects, ObjectList, 20 Hz |
| 输出消息 | Topic 名称、消息类型、保证频率 | /planning/trajectory, Trajectory, 10 Hz |
| 时戳语义 | 消息时戳含义(感知时刻 vs 发布时刻) | 优先使用感知时刻 |
| 失效码 | 模块自我诊断状态的标准编码 | 0=正常,1=降级,2=失效 |
| 版本号 | 消息格式版本,支持兼容性检测 | v1.3.0 |
2.2 主链路与支撑链路
主链路(实时,高优先级):
感知 → 融合 → 预测 → 规划 → 控制
支撑链路(准实时/非实时):
高精地图更新、诊断监控、参数热更新
工具链路(离线/异步):
日志上传、数据统计、模型评估
3. 端到端时延分析
3.1 时延预算分配
自动驾驶闭环时延从传感器曝光到执行器响应:
| 环节 | 预算(城区) | 预算(高速) | 说明 |
|---|---|---|---|
| 传感器曝光与读出 | 30–50 ms | 30–50 ms | 相机帧率决定 |
| 感知推理 | 30–60 ms | 30–60 ms | GPU推理时延 |
| 多传感器融合 | 10–20 ms | 10–20 ms | 时间对齐+融合 |
| 预测 | 10–30 ms | 10–30 ms | Transformer 推理 |
| 规划决策 | 20–50 ms | 20–50 ms | 轨迹优化 |
| 控制计算 | 5–10 ms | 5–10 ms | 高频控制环 |
| 通信与执行器 | 5–15 ms | 5–15 ms | CAN传输+建压 |
| 总计 | ~150 ms | ~170 ms | 高速场景余量更紧 |
长尾时延的危害
控制系统关注的不是平均时延,而是 P99/P99.9。若 P99 超过 300 ms,高速场景下控制环将出现明显不稳定性。必须监控和控制长尾分布。
3.2 关键路径分析
使用有向无环图(DAG)表示任务依赖:
Camera(0ms) ──┐
LiDAR(0ms) ──┤─→ 融合(40ms) ─→ 预测(70ms) ─→ 规划(100ms) ─→ 控制(110ms)
Radar(0ms) ──┘
GNSS/IMU(0ms) ──────────────────────────────────────────────→ 控制(110ms)
关键路径(最长依赖链)决定整体时延下限,优化应优先针对关键路径上的节点。
3.3 时延测量方法
# 在每个模块的入口和出口记录时戳
class ModuleTimer:
def __init__(self, module_name):
self.name = module_name
def on_receive(self, msg):
self.t_recv = now()
self.t_sensor = msg.header.timestamp # 感知时刻
def on_publish(self, msg):
t_pub = now()
latency_proc = t_pub - self.t_recv # 处理时延
latency_e2e = t_pub - self.t_sensor # 端到端时延
publish_metric(f"{self.name}_proc_ms", latency_proc * 1000)
publish_metric(f"{self.name}_e2e_ms", latency_e2e * 1000)
4. 实时调度策略
4.1 POSIX 实时调度
Linux 实时调度策略:
| 策略 | 说明 | 适用 |
|---|---|---|
| SCHED_FIFO | 固定优先级,先进先出 | 感知/控制主线程 |
| SCHED_RR | 固定优先级 + 时间片轮转 | 多传感器并行处理 |
| SCHED_DEADLINE | EDF,指定 deadline 和执行预算 | 精确时间约束任务 |
| SCHED_OTHER | 普通分时调度 | 日志、统计等非实时任务 |
优先级分配建议:
优先级 90:控制执行(最高实时性需求)
优先级 80:感知主链路
优先级 70:规划
优先级 60:定位更新
优先级 20:日志、统计
4.2 CPU 隔离与绑定
通过 CPU affinity 将关键任务绑定到特定核:
# 隔离 CPU 核 2-7(内核启动参数)
isolcpus=2-7 nohz_full=2-7 rcu_nocbs=2-7
# 将进程绑定到核 2
taskset -cp 2 <pid>
4.3 异步流水线与双缓冲
避免阻塞等待:感知输出直接写入下一模块的输入缓冲区,双缓冲(Ping-Pong Buffer)防止读写冲突:
生产者(感知) 消费者(预测)
写入 Buffer_A ─→ 读取 Buffer_B
写入 Buffer_B ─→ 读取 Buffer_A
(交替切换,无锁访问)
5. GPU/NPU 任务调度
5.1 多模型并发推理
CUDA Stream 分配策略:
Stream 0(高优先级):感知主模型(BEV Backbone)
Stream 1:预测模型
Stream 2:辅助感知(车道线/可行驶区域)
Stream 3(低优先级):数据增强/离线推理
多 CUDA Stream 并行可提升 GPU 利用率,但需要注意:
- 共享显存带宽,并发过多反而降低效率
- 不同 Stream 之间的同步开销
- 内存碎片管理
5.2 推理延迟优化
| 技术 | 效果 | 代价 |
|---|---|---|
| TensorRT/NPU 编译优化 | 2–5× 加速 | 需要重新编译,精度可能损失 |
| INT8/FP16 量化 | 1.5–3× 加速 | 精度验证成本 |
| 批处理(Batching) | 提升吞吐,增加时延 | 适合异步推理场景 |
| 动态形状 | 灵活性强 | 编译时间长 |
6. 功能安全架构
6.1 故障检测机制
| 机制 | 检测目标 | 实现方式 |
|---|---|---|
| 心跳超时 | 模块是否存活 | 定期发布心跳消息,超时触发告警 |
| 输出合理性检查 | 输出是否异常 | 速度跳变、坐标跳变、置信度异常 |
| 频率监控 | 发布频率是否正常 | 统计周期内消息数,偏离阈值告警 |
| 看门狗(Watchdog) | 整个进程是否冻结 | 硬件/软件看门狗,超时复位 |
6.2 故障隔离策略
故障等级分类:
L1(轻度):单传感器降级,功能受限但可继续
L2(中度):主链路降级,切换保守策略
L3(重度):规划或控制失效,触发 TOR
L4(严重):无法安全运行,触发 MRC
6.3 安全降级决策树
检测到异常
│
├─ 感知模块失效
│ ├─ 单摄像头失效 → 降低该方向感知权重,限速
│ ├─ LiDAR失效 → 切换视觉主导,限速至 60 km/h
│ └─ 主感知失效 → TOR → MRC
│
├─ 规划模块失效(超时/无解)
│ ├─ 连续 1 帧失效 → 使用上周期轨迹延续
│ ├─ 连续 3 帧失效 → 减速保持车道
│ └─ 连续 5 帧失效 → TOR → MRC
│
└─ 控制模块失效
└─ 立即触发 MRC(最高优先级)
7. 常见工程问题
| 问题 | 根因 | 解决思路 |
|---|---|---|
| 接口频繁变更 | 需求不稳定,接口未冻结 | 建立接口 API Review 流程,变更需版本号递增 |
| 日志粒度不足 | 问题复现困难 | 为每帧数据附加唯一 frame_id,模块间传递 |
| 只看平均时延 | 长尾问题被掩盖 | 监控 P95/P99,建立自动告警 |
| 模块间循环依赖 | 难以独立测试 | 强制分层,低层不依赖高层 |
| 调度抖动导致不稳定 | 非实时任务干扰关键任务 | CPU隔离 + 优先级调整 |
8. 关键指标监控看板
建议监控以下核心指标:
| 指标 | 说明 | 告警阈值示例 |
|---|---|---|
| 感知处理时延 P99 | 感知模块端到端时延 | > 80 ms |
| 规划超时率 | 规划未在预算内完成的比例 | > 0.1% |
| 控制环频率 | 控制指令发布频率 | < 90% 目标频率 |
| 端到端时延 P99 | 全链路时延 | > 200 ms |
| 系统 CPU 利用率 | 整体算力消耗 | > 85% |
| GPU 利用率 | 推理算力使用情况 | > 90%(持续超载) |