自动驾驶系统的配置管理:配置组合、实验复现与运行时分发
研究如何在自动驾驶系统中组织和组合多模块配置、复现实验,并为运行时配置分发选择合适的成熟方案。
- 首次发布
- 最后更新
本文目录
问题与需求
自动驾驶系统由多个相互协作的模块组成,各模块在运行时都需要读取相应配置。这些配置通常以 YAML 文件保存。模块数量较少、运行条件相对固定时,直接维护配置文件简单有效;随着车辆平台、运行模式、测试场景以及需要反复验证的参数增加,配置管理逐渐从单个文件的读写问题演变为大量配置组合的组织问题。
不同场景和参数试验会形成许多相近但不完全相同的配置。如果缺少明确的组合、覆盖和记录机制,这些差异就容易散落在多份文件和临时修改中,最终难以回答几个基本问题:一次运行究竟采用了哪些配置值,这些值由哪些基础配置和试验调整共同形成,它们对应哪组测试条件和结果,以及同一次试验能否再次复现。
因此,需要治理的是配置从组织、组合、选用、调整到运行记录的完整过程,而不只是把 YAML 换成另一种文件格式,也不等同于引入一个远程配置中心。相应的调研可以跨越不同技术层级:配置格式与校验工具、实验管理系统、配置中心和通信基础设施解决的问题并不相同,但都有可能承担其中一部分职责。
目前可以明确的需求包括:
- 配置应按照模块及其适用条件清晰组织,并尽量复用各场景之间的共同部分,避免维护大量内容重复的完整配置;
- 支持按照车辆平台、运行模式和测试场景等条件组合并自动选用配置,同时允许为单次试验明确覆盖待验证参数,而不改变作为基准的配置;
- 能够查看并转储一次运行最终生效的完整配置,不必依靠人工追溯多层文件和临时修改;
- 每次试验使用的最终配置应与相应的测试条件和结果建立明确关联,以便比较参数变化的影响并复现实验;
- 配置文件应尽量便于阅读和修改;
- 提供 GUI 配置界面;如果界面已经完整覆盖日常查看和修改需求,可以适当放宽对源文件直接编辑体验的要求;
- 支持远程分发和更新配置,并为需要在线调整的参数提供运行时动态调节能力;
- 支持配置变更历史,能够追溯某个模块在特定时刻实际采用的配置;
- 优先采用成熟工具覆盖通用能力,控制接入成本和需要自行维护的代码范围。
候选方案
当前框架使用 ROS/ROS 2 作为通信中间件,其parameter server已经能够覆盖一部分需求。不过,框架的长期演进方向是逐步解除与 ROS/ROS 2 的耦合,并最终移除这项依赖,因此该方案从一开始就未被使用。
配置管理并非运动控制框架的核心算法能力,不适合占用过多开发资源。为减少自行开发的工作量,调研范围首先包括 Apollo、Nacos 等现有配置平台。它们本身具备较为完整的能力,但与当前项目的需求和预期使用方式并不完全契合。
随后,调研按照以下顺序进一步评估了三种方案:
- etcd:功能能够覆盖主要需求,但引入和使用成本相对较高,因此没有继续采用。
- NATS:功能与生态都较为成熟,一度接近成为最终选择。不过,在确定方案之前,仍有必要评估是否存在更适合整个系统长期演进的基础设施。
- Zenoh:Zenoh 并不是可以直接使用的配置中心。以它为基础实现配置系统,需要自行补充应用层逻辑,开发成本会高于直接采用 NATS。不过,如果后续在自动驾驶系统的其他功能中继续使用 Zenoh,那么配置能力也可以建立在同一套通信基础设施之上。基于这一点,Zenoh 仍被保留为后续候选方案。
补充背景:Zenoh 与 ROS 2
Zenoh 也是 ROS 2 的非 DDS RMW 实现之一。从 Kilted 开始,
rmw_zenoh_cpp已作为受支持的 RMW 实现随二进制发行版提供,具体用法参见 ROS 2 官方文档。另有一份 ROS 2 RMW 替代方案研究报告 可供参考。
从 YAML 转向 TOML
受早期 ROS 使用习惯影响,框架现有配置文件均采用 YAML。配置系统的调研也重新比较了 YAML 与 TOML:
- TOML 的语法和数据模型更加克制,配置含义通常更明确;
- YAML 历史更久、表达能力更强,同时也允许锚点、别名等更复杂的组织方式。
JSON 拥有成熟的序列化、Schema 校验和工具生态,因此配置数据能否与 JSON 兼容结构清晰地相互转换,是文件格式选型中的一项实际考虑。相较于 YAML,TOML 的数据模型更加克制;只要配置值限定在双方共有的数据类型内,TOML 与 JSON 之间的双向转换通常更加直接。这里不能笼统称为完全无损互转,因为 TOML 原生支持的日期、时间和特殊浮点值在 JSON 中没有直接对应形式;不使用这些特有类型时,则可以在 TOML 与 JSON 兼容结构之间稳定地双向转换,并复用相应的工具生态。
YAML 的锚点、别名等复杂能力也在选型中得到考虑,它们适合在配置文件内部表达复用和组合关系,但并不是当前需求所必需的。相关逻辑可以通过更明确的应用代码或工具实现,没有必要为尚未出现的场景增加配置格式本身的复杂度。因此,TOML 更符合当前系统对清晰数据结构和成熟工具链的需求;这项选择针对的是具体项目,而不是对 YAML 通用价值的否定。
综合这些因素,后续配置系统将采用 TOML 作为基础文件格式。
阶段性实施范围
完整转向新的配置系统并不是一次简单的组件替换。它会同时涉及配置格式、解析接口、运行时更新、远程分发、历史管理和 GUI 等多个方面,不仅任务边界过宽,也会牵动当前系统中的大量模块。如果一次性展开全部改造,系统将在较长时间内处于新旧机制并存、接口持续变化的阶段性不稳定状态,进而影响其他功能的正常开发。
因此,第一阶段只将框架内的配置文件从 YAML 迁移到 TOML,不同时引入运行时文件监听或其他配置管理机制。这项调整虽然范围有限,却具有独立的长期意义:它先确定后续继续沿用的基础文件格式和数据表达方式,也为未来扩展配置解析、校验与分发能力建立稳定起点。
待远程更新、动态调参或其他需求实际出现后,再扩展相应接口,并根据当时的系统条件决定接入文件监听、NATS、Zenoh 或其他合适的基础设施。这样既不提前承担完整配置系统的开发成本,也不会让当前的格式迁移成为一次缺乏后续价值的临时修改。
配置文件格式与完整配置系统由此被划分为两个实施阶段:前者是当前能够确定并独立完成的基础工作,后者则在需求和技术边界进一步明确后再行实施。
后续调研:配置组合与实验管理
本节记录的是基于当前需求和各工具官方资料形成的调研结果,尚未在现有自动驾驶系统中完成接入和运行验证。
最优方案
基于当前场景,最合适的起点是:
Hydra 负责配置组合与参数实验,ClearML 负责实验记录、比较、复现和远程执行。等运行中远程更新成为明确需求后,再增加 Nacos 作为运行时配置发布层。
完整关系是:
模块默认配置+ 车辆配置+ 平台配置+ 运行模式+ 测试场景+ 本次实验参数 ↓Hydra 组合并生成完整配置快照 ↓各个模块读取本次运行的固定配置 ↓ClearML 记录配置、代码版本、运行环境、结果和产物 ↓需要在线发布时,再将经过确认的配置交给 Nacos为什么是 Hydra
Hydra 正好针对“配置差异横跨多个维度”的问题设计。车辆、平台、模式、场景和控制器可以分别成为配置组,每次实验只记录相对于默认配置的选择和差异,不需要复制完整 YAML。官方的“配置实验”模式描述的就是这种情况,并支持直接对多个实验组合执行 sweep。Hydra:Configuring Experiments、Hydra:Multi-run
例如,配置不再按场景复制成大量完整文件,而是拆成彼此独立的维度:
vehicle:车辆尺寸、执行机构参数;platform:实车、仿真、离线回放;mode:不同控制或运行模式;scenario:测试场景;controller:控制器及其默认参数;experiment:本次实验相对于上述配置的少量调整。
最终每次运行必须固化一份完整解析后的配置。各模块只读取这份普通配置,不需要知道 Hydra,也不应各自重新执行配置合并。
为什么搭配 ClearML
Hydra 能生成配置和批量运行,但它本身不足以回答:
- 这次结果究竟使用了哪份最终配置;
- 当时代码是否有未提交修改;
- 哪几个参数不同;
- 不同实验的输出和指标如何比较;
- 如何复制一次实验并修改少量参数重新运行。
ClearML 官方直接支持 Hydra,会自动记录完整 OmegaConf 和运行时覆盖值;Web UI 可以比较源代码、依赖、配置对象、参数、指标和图形,也支持克隆任务、修改配置后交给 Agent 远程执行。ClearML 的 Hydra 集成、实验对比、任务复现
它也支持自托管和离线实验,因此不要求实验车辆或开发环境始终联网。自托管 ClearML Server、Offline Mode
尽管 ClearML 以 MLOps 为主要定位,但其 Task 可以表示测试、应用或任意自定义执行,并不限于神经网络训练。
运行时动态配置应单独处理
当确实需要向正在运行的模块远程发布配置时,Nacos 比直接基于 NATS、Zenoh 或 etcd 自建完整配置系统更合适。
Nacos 目前已经提供:
- 配置查询与监听;
- 历史记录与重新发布;
- 灰度配置;
- 导入、导出和克隆;
- 本地快照与故障恢复。
同时,Nacos 明确把配置内容作为整体存储和分发,并不理解其中业务字段的含义。Nacos 配置管理概览、历史与运维
因此正确边界是:
- Hydra 决定一组配置如何组成;
- ClearML 说明这组配置在哪次实验中产生了什么结果;
- Nacos 只负责把确认后的配置发布给运行中的模块;
- 应用自身负责参数范围、跨字段约束、允许动态修改的字段和安全应用时机。
NATS 与 Zenoh 的调研仍然有价值。它们都能提供 KV、订阅或持久化能力,但如果目的是完整配置管理,GUI、发布流程、Schema、审计和回滚仍需要补充。除非它们已经成为整个系统确定采用的通信基础设施,否则用它们从头构建配置系统不如直接采用 Nacos。
其他成熟方案的位置
| 方案 | 适合的情况 | 不作为首选的原因 |
|---|---|---|
| CUE + ClearML | 配置必须跨 Python、Rust、C++,并强调 Schema 与生成 | 需要引入新的配置语言,参数 sweep 和 ClearML 对接不如 Hydra 直接 |
| Hydra + DVC Experiments | 偏好 Git 原生、无中心服务、需要数据和流水线版本化 | GUI、任务克隆和远程执行不如 ClearML 完整 |
| Dynaconf | 只需要 Python 中的 TOML/YAML 分层、覆盖和校验 | 不负责参数 sweep、实验结果和完整复现 |
| ClearML 单独使用 | 配置结构不复杂,只需记录和远程执行 | 缺少 Hydra 那样清晰的多维配置组合模型 |
| Nacos 单独使用 | 主要问题是运行时发布和热更新 | 不解决大量测试配置的组合与实验结果对应关系 |
CUE 值得作为跨语言备选。它现在可以直接读取、校验、组合并输出 TOML、YAML 和 JSON,不要求运行模块理解 CUE。CUE 的配置组合、CUE 与 TOML
DVC 也已经能够利用 Hydra 组合配置,并对包含任意命令的多阶段流水线运行和保存实验,因此并非只适用于单个 Python 训练脚本。DVC 与 Hydra 集成
对现有文章结论的修正方向
从 YAML 切换到 TOML 可以改善可读性和数据模型,但它不会单独解决配置失控。真正长期有效的机制应当是:
- 不再复制完整场景配置,而是从独立维度组合;
- 每次运行生成并保存不可变的最终配置快照;
- 参数、代码、输入数据、日志和结果使用同一个实验 ID 关联;
- 只有经过确认的配置才进入运行时发布层;
- 在线热更新不承担实验历史管理职责。
因此,目前最值得优先验证的是 Hydra + ClearML。自写边界只应保留两部分:把最终配置交给各模块的薄启动适配层,以及把领域指标和产物登记到 ClearML 的少量代码。配置合并、批量实验、历史数据库、比较界面和远程任务系统都不应自行开发。