结论:车型支持文档系统是一条「car_docs → PLATFORMS/EXTRA_PLATFORMS → get_params_for_docs() → 品牌 init_make() + CarDocs.init() → 自然排序 → 两种 Markdown 输出」的生成链,它产出的是展示/采购文档,不是车型识别、上车认证或电气设计规范。三个状态必须分开:车型可展示、线束可购买、车型协议已识别、发布固件允许发送,CarDocs 与 SupportType 都不能直接授予 CAN 写入权。以下为固定提交 c8fb906 的静态阅读与隔离探针分析。
数据与生成顺序
get_all_car_docs() 汇合正常平台与 extra_cars.py 的额外目录,为每个平台调用 get_params_for_docs(),再对每个车型文档项依次执行品牌 init_make()、共同 CarDocs.init(),最后按自然顺序排序。一个平台可包含多个市场车型/年款条目,因而文档行数不等于车型接口数量。
关键是 get_params_for_docs() 的输入:它以空 CAN 指纹、一个占位 CarFw、alpha_long=True、is_release=True、docs=True 调用车型 get_params();额外目录中没有运行时接口的平台使用 MOCK 参数。这样的 CP 是排版/说明输入,既未验证目标车辆固件,也不代表该车能执行控制。
| 阶段 | 入口 | 产出与边界 |
|---|---|---|
| 数据汇合 | car_docs + PLATFORMS + EXTRA_PLATFORMS |
正常平台与额外目录合并,文档行数不等于车型接口数量。 |
| 模拟参数 | get_params_for_docs() |
空指纹、占位 CarFw、alpha_long=True、is_release=True;无接口平台用 MOCK。 |
| 品牌钩子 | 品牌 init_make() |
品牌级展示字段调整为排版输入,非运行时 CP。 |
| 共同派生 | CarDocs.init() |
计算 ACC、最低速度、自动起步、转向星级、支持级别与详情句;展示值可能被文档字段覆写。 |
展示字段与派生逻辑
split_name()、get_year_list() 从名称分离品牌、型号、年款并展开年款范围,依赖名称格式和 20YY 结束年推断,不是 VIN/车型年款校验器。CarDocs.init() 从 CP 和文档覆写计算展示列,其中 min_steer_speed、min_enable_speed 等可由文档字段覆写,展示值未必直接等于运行时 CP。
CarDocs.init() 在 CP.dashcamOnly 且 merged=True 时通常把支持级别降为 DASHCAM,但 CUSTOM 和 REVIEW 是例外;ExtraCarDocs 默认 merged=False、INCOMPATIBLE,社区/安全限制类型由额外目录的子类钩子改写。SupportType 的 UPSTREAM、REVIEW、DASHCAM、COMMUNITY、CUSTOM、INCOMPATIBLE 是文档分类,不是运行时安全模式。
线束清单以 Device.four 及常见附件为基础,品牌/平台可加入特定接头和工具;CarHarness 枚举包含摄像头/网关/OBD 类接头,并有 has_connector 展示标记。CarParts.common() 会加入默认设备并按 remove 列表过滤,但不做去重;递归展开也可能包含共享子件,数量显示在 CarDocs.init() 统计结果中。这些清单列出的是营销/采购名称,不含供电、针脚、隔离、保险丝或失效态参数。
两种 Markdown 输出
| 输出 | 入口 | 范围 |
|---|---|---|
opendbc docs/CARS.md |
opendbc.car.docs.generate_cars_md() |
对传入的全部条目构造简化列,包含不同 SupportType 的支持级别。 |
openpilot docs/CARS.md |
openpilot.selfdrive.car.docs.generate_cars_md() |
只筛 SupportType.UPSTREAM,生成 ACC/ALC/硬件/视频等宽表及脚注。 |
两个生成器都是模板替换,作为 CLI 执行时会覆写各自的输出文件;get_all_car_docs() 和生成函数的注释明确说明它们也被外部网站调用,因此字段语义变化有仓库外消费者。openpilot 生成器的 _build_cars_table() 按 Column 枚举顺序取列,把 Hardware Needed 表头替换为含宽图片的 HTML 片段,前三列左对齐、其余居中。**kwargs 被直接丢弃,是兼容调用签名而非扩展参数。
脚注按 get_all_footnotes() 映射的键迭代顺序重新编号,不使用映射值中的编号;只移除字面量 </br>,不移除 <br>。模板使用严格 Template.substitute(),未定义占位符会抛 KeyError。build_sorted_car_docs_list() 只在文档对象尚无 row 时初始化它;后续对同一内存对象再次生成时,已派生的行不会随新的 CP 或脚注参数自动重算。这是生成过程的状态边界,适合把文档项当一次性构建对象。
对自制硬件与插件化的含义
源文档给出的是一组建议而非现有代码已实现的保障:把「车型可展示」「线束可购买」「车型协议已识别」「发布固件允许发送」定义为四个不同状态,插件目录只展示已验证字段,不用 CarDocs 或 SupportType 直接授予 CAN 写入权;自制硬件物料表应另存电气契约(接头 pinout、线序、额定电流、供电/点火检测、隔离、ESD、保险与断电默认态),并逐车/年款验证,文档 CarParts 只能作高层采购提示;文档生成改为按版本快照纯计算,记录来自哪个 CarParams、DBC、固件数据库和硬件 BOM。
测试与缺口
opendbc 文档测试检查年款重复、命名、部分星级假设和上游线束清单;openpilot 生成器测试主要确认模板能生成。四项原函数隔离探针以临时模板和假 CarDocs 核对上游筛选、列顺序/对齐、调用参数、脚注编号与严格占位符;没有导入完整 opendbc,也未执行真实车型目录生成或覆写归档 CARS.md。这些测试不验证真实线束电气连接、商城库存、车型硬件兼容性或实际发布固件的执行能力。
常见问题
被列为 UPSTREAM 就等于该车型已获安全许可吗?
不等于。SupportType 是文档分类而不是运行时安全模式;文档生成用的是带空 CAN 指纹与占位 CarFw 的模拟参数,不能直接授予 CAN 写入权。
get_params_for_docs() 得到的参数能上车吗?
不能。它以空 CAN 指纹、一个占位 CarFw、alpha_long=True、is_release=True、docs=True 调用车型 get_params(),是排版/说明输入,既未验证目标车辆固件,也不代表该车能执行控制。
线束清单能当电气设计依据吗?
不能。CarParts.all_parts() 列出的是营销/采购名称,不含供电、针脚、隔离、保险丝或失效态参数;自制硬件应另存电气契约并逐车/年款验证。
为什么再次生成文档时行不刷新?
因为 build_sorted_car_docs_list() 只在文档对象尚无 row 时初始化它,已派生的行不会随新的 CP 或脚注参数自动重算,这是生成过程的状态边界。
延伸阅读
- 17 个品牌参数怎么构建:CarParams 冻结只到顶层 —— 文档生成链所用的运行时参数侧契约。
- 车型指纹与固件匹配 —— 「车型协议已识别」这一步真实的判定条件。
- 21 块板卡的去留:A/B/C 分级与阶段门 —— 硬件物料分级的另一种管理视角。
- OBD AI 插件化平台 —— 插件目录与车端执行许可应如何分开审批。
参考资料
- 项目 02 ——
openpilot-research/CAR_DOCS_SUPPORT_HARNESS_DEEP_DIVE.md(生成顺序、展示派生逻辑、两种 Markdown 输出与测试缺口)。 - 项目 02 ——
openpilot-research/同目录平台参数与自制硬件方案专题(作为相邻边界参考)。
说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。
更新记录
首次发布 2026-10-11 最近核对:2026-10-11
发表回复