结论:读一个大型 ADAS 代码库,正确顺序不是从目录名或进程启动顺序开始,而是按职责与信任边界组织:先分清运行底座、输入感知、状态估计、车辆接入、决策执行、旁路验证六大块,再沿「车况从 CAN 进来到控制从 CAN 出去」这条链逐层追。本文给出一条可复用的四步阅读顺序——从进程与消息契约出发,追车况解析、追使能状态机、追候选发送与板端安全钩子——并强调三类不能混同的边界。源代码根提交为 c8fb906,归档缺少模型权重实体,以下为静态分析,不代表构建通过或实车验证。
按职责与信任边界看,而不是按目录名
这个代码库的关键结构不是「哪个目录属于哪个功能」,而是各部分所处的信任层级。可以用一张源码目录地图定位:
| 目录 | 在系统中的位置 | 主要产物或边界 |
|---|---|---|
| 系统与平台目录 | 设备与运行平台 | 进程管理、相机与传感器采集、记录、设备状态与远程服务 |
| 消息契约与传输 | 数据契约与传输 | 日志结构定义、服务频率定义、跨进程消息队列与图像缓冲 |
| 共享运行时 | 共享基础 | 参数持久化、时间与调度、日志、设备抽象与版本信息 |
| 视觉推理目录 | 视觉推理 | 道路与驾驶员模型输入处理与推理输出;模型权重属于缺失的实体 |
| 定位与监控目录 | 状态估计 | 定位、标定、车辆参数学习与驾驶员注意力策略 |
| 车辆 I/O 目录 | 主机侧车辆 I/O | 车况标准化、候选发送帧生成、与安全板通信 |
| 决策与控制目录 | 决策与执行请求 | 雷达融合、纵向规划、控制器与使能告警状态机 |
| 车型协议与安全目录 | 车型协议与独立安全边界 | DBC、车型状态与控制、safety 规则;安全 MCU 执行收发与发送限制 |
| 开发验证目录 | 开发验证 | 回放、仿真、CAN 分析与诊断,不属于车上实时控制路径 |
要特别记住一点:安全板固件、车型协议、跨进程通信与推理运行时分别位于不同的源码归档,不要把它们误认为同一个可热插拔模块。这条边界决定了后面所有替换与移植工作的可行性。
对照这张地图时,一个实用判断是看某模块是否参与了实时控制路径:属于开发验证的部分不应成为车上的必要依赖,而安全相关部分则必须与车型、总线与固件联合版本化。
四步阅读顺序
公开资料给出了一条从函数追到消息的阅读顺序,可以照此执行:
- 从进程配置与进程管理函数找到运行进程,再对照服务频率定义与日志结构定义的主题字段;
- 从车况更新函数追车型接口更新、车型状态与雷达轨迹,再追模型输出、雷达状态、纵向计划的生产者;
- 从事件汇总与状态机更新的函数追使能 / 退出条件,再看控制器如何生成执行请求;
- 从车型编码函数追车型控制器的更新、候选发送帧、主机到板传输与板端安全钩子;任何可替换模块都不能跨越最后一层安全门。
顺序的关键在最后一步:候选发送帧在到达总线之前,必须经过安全 MCU 的独立检查。也就是说,主机侧插件、车型控制器和配置项都不能替代板端规则。
这四步的意义在于把「消息契约」放在第一位:先知道有哪些主题、频率与字段,再去看谁生产它们。否则很容易在某个子目录里困住,却不知道它在闭环中的位置。追控制链时,建议始终回到「车况进来、控制出去」这两条主线上做交叉验证。
运行阶段与消息速查
下表按理解闭环的顺序排列,不是全局同步调用栈。进程各自运行,消息的发布、接收与板端执行发生在不同时间,表内的「输出」也不等于车辆已经执行:
| 阶段 | 主要输入与产出 | 硬件或插件边界 |
|---|---|---|
| 设备与进程 | 板 / 电源 / 温度等状态形成设备启动状态,进程管理据此增减受管进程 | 新平台必须先可靠报告点火、热状态和电源;进程启动不代表传感器健康 |
| 物理采集 | 相机图像进入模型;CAN 经车型解析形成车况与雷达轨迹 | 帧时间、坐标系、CAN 来源总线及采样年龄必须随适配器一起验收 |
| 观测发布 | 分别发布模型输出、相机里程计、车况与雷达轨迹 | 同一发布周期内的多个主题也可能有不同有效条件 |
| 融合与规划 | 雷达轨迹与模型输出形成雷达状态;模型更新触发纵向计划 | 规划插件须声明输入时间轴、有效性和输出期限;计划存在不等于控制获准 |
| 使能与控制 | 事件产生使能状态;控制器综合车况、模型和计划发布控制请求 | 使能、横向、纵向是不同权限;控制请求的 valid 不是最终硬阻断 |
| 车型编码 | 控制请求经车型转换成为候选发送帧 | 主分支检查控制请求存活,不统一检查其有效位 |
| 主机到 MCU | 主机按消息年龄发送候选帧,另维护板状态与心跳 | 消息年龄门和心跳不是逐帧安全授权 |
| 板端安全 | 按安全模式、发送白名单、车型钩子及故障决定是否接受候选帧 | 车型 / DBC / 安全参数 / 固件必须联合版本化 |
建议先用只读 CAN 与图像采集验证前四阶段,再以离线回放验证控制请求,最后独立验证网关与 MCU 的拒帧、超时及故障退化。
三类边界:输入、能力与验证
从源码职责推导,面向自制硬件与插件重构有三条边界,对应四类插件:
| 插件类型 | 可定义的契约 | 不可交给插件自我授权的部分 |
|---|---|---|
| 传感器 / 感知 | 时间戳、坐标系、健康状态和标准消息输出 | 无效或过期输入继续参与控制的许可 |
| 车型适配 | 指纹、DBC、车况与控制帧、受控总线清单 | 安全模式、发送白名单、驾驶员覆盖规则 |
| 规划 / 控制 | 标准模型 / 雷达 / 控制契约及回放等价性 | 无条件接管发送或绕过使能状态机 |
| 记录 / UI / 远程 | 只读订阅、存储和远程诊断能力 | 将远程命令直接转为车辆控制权限 |
第一条边界是物理输入与安全发送:车型、总线、线束、摄像头时间戳以及安全板配置必须版本绑定。第二条是算法与辅助能力:感知、定位、日志和 UI 可以探索可替换接口,但控制相关组件不能仅凭「插件已安装」取得发送权。第三条是验证:先只读采集、进程回放和故障注入,再做台架与受控场地测试;这类文档不是接线图或上车许可。
常见问题
能不能只看目录名理解这套代码?
不建议。应优先按职责与信任边界组织:安全板固件、车型协议、跨进程通信和推理运行时分别位于不同源码归档,按目录名会被误导。可用文中的目录地图定位各部分所处层级。
控制请求发出去了就等于车辆执行了吗?
不等于。候选发送帧在到达总线前还要经过安全 MCU 的独立检查;主机侧的消息年龄门和心跳也不是逐帧安全授权。文中所有表中的「输出」都不等于车辆已经执行。
使能、横向、纵向是同一个开关吗?
不是。公开资料特别指出它们是不同权限,且控制请求的 valid 不是最终硬阻断。判断能否执行应回到使能状态机与板端安全规则,而不是单一布尔值。
这份分析能作为上车依据吗?
不能。归档缺少模型权重实体,本文为静态源码分析,不代表构建通过或实车验证;它不是接线图或上车许可,任何执行能力都需要台架与受控场地另行验证。
延伸阅读
- openpilot 的 100 Hz 控制回路:开源 ADAS 能给车载设备什么 —— 承接控制回路的工程取舍。
- 从使能到车轮:执行链上的八道门,以及它们各自不保证什么 —— 展开「使能到发送」的门控链。
- 车型协议接入实践:从指纹识别到安全固件的最低契约 —— 承接车型适配这条边界。
- UDS 诊断工具为什么不能随手调:只读、会话与写 ECU 的分权设计 —— 承接「远程命令不等于控制权」的边界。
参考资料
- 项目 02 ——
openpilot-research/ARCHITECTURE_GUIDE_CN.md(取用源码目录地图、四步阅读顺序、运行阶段与消息速查、三类边界与插件类型表)。
说明:本文为对固定源码快照(根提交 c8fb906)的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有入口、阶段与边界均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复