2. 配置文件基础:配置文件格式(YAML/JSON/XML)、数据结构设计原则、版本控制基础
好,咱们正式开始聊配置文件。说实话,我入行那会儿,ADAS系统的配置还都是硬编码在C代码里的。改个参数?重新编译、烧录、上车测试,一天就过去了。后来我们开始用配置文件,效率才真正提上来。
这一节,我带你看看ADAS系统里最常用的三种配置文件格式——YAML、JSON、XML。我会结合我踩过的坑,讲讲它们各自适合什么场景。然后聊聊数据结构设计原则,最后说说版本控制。嗯,这些都是基本功,但基本功往往最容易被忽视。
2.1 三种配置文件格式:YAML、JSON、XML
你想想看,ADAS系统里有多少参数需要配置?摄像头内参、雷达安装位置、控制器的PID系数、功能使能开关、标定阈值……少说几百个。没有一套好的配置文件管理方式,项目根本跑不起来。
我个人习惯,把配置文件格式分成三类:
| 特性 | YAML | JSON | XML |
|---|---|---|---|
| 可读性 | ★★★★★ | ★★★★ | ★★★ |
| 数据密度 | 高 | 中 | 低(标签冗余) |
| 注释支持 | 支持(#) | 不支持 | 支持() |
| 解析速度 | 中等 | 快 | 慢 |
| 工具链成熟度 | 高 | 极高 | 高 |
| ADAS适用场景 | 标定参数、功能配置 | 数据交换、API接口 | 遗留系统、复杂文档 |
2.1.1 YAML——我最推荐的ADAS配置格式
YAML是我在ADAS项目里用得最多的格式。为什么?因为它太适合人类阅读了。你看下面这个例子:
# 前向摄像头配置
camera:
model: "OV10640"
resolution:
width: 1920
height: 1080
fps: 30
intrinsics:
fx: 1280.5
fy: 1280.5
cx: 960.0
cy: 540.0
distortion:
model: "radial-tangential"
k1: -0.283
k2: 0.082
p1: 0.0001
p2: -0.0002
# 车道线检测参数
lane_detection:
enabled: true
min_lane_width_m: 0.1
max_lane_width_m: 0.5
confidence_threshold: 0.75
看到没?缩进结构一目了然。我在项目中遇到过,用YAML写标定参数,算法工程师自己就能改,不用每次都找软件工程师帮忙。这就是生产力。
# 注意:请使用空格缩进。
2.1.2 JSON——数据交换的首选
JSON在ADAS系统里,更多用于模块间的数据交换。比如感知模块输出给规划模块的目标列表,用JSON就很合适。它解析快,几乎所有语言都有原生支持。
{
"timestamp": 1623456789.123,
"objects": [
{
"id": 1,
"type": "vehicle",
"position": {"x": 10.5, "y": 2.3, "z": 0.0},
"velocity": {"x": 15.0, "y": 0.0, "z": 0.0},
"confidence": 0.95
},
{
"id": 2,
"type": "pedestrian",
"position": {"x": 25.0, "y": -1.5, "z": 0.0},
"velocity": {"x": 1.2, "y": 0.0, "z": 0.0},
"confidence": 0.87
}
]
}
但JSON有个硬伤——不支持注释。你想想看,一个标定参数文件几百行,没有注释,后来的人怎么知道这个参数为什么设成这个值?所以我一般只用JSON做运行时数据交换,不做长期维护的配置文件。
2.1.3 XML——老项目里的常客
XML现在用得少了,但如果你接手的是五年前甚至更早的ADAS项目,大概率会遇到。它最大的优点是自带Schema校验,可以严格约束数据结构。
<?xml version="1.0" encoding="UTF-8"?>
<adas_config>
<sensor name="front_camera">
<param name="model">OV10640</param>
<param name="fps">30</param>
<calibration>
<matrix name="intrinsic">
<row>1280.5 0.0 960.0</row>
<row>0.0 1280.5 540.0</row>
<row>0.0 0.0 1.0</row>
</matrix>
</calibration>
</sensor>
</adas_config>
说实话,XML写起来太啰嗦了。同样的数据,YAML可能10行,XML要30行。但如果你需要严格的文档结构校验,XML的XSD Schema确实好用。
2.2 数据结构设计原则
配置文件格式选好了,接下来就是怎么组织数据。我总结了几条原则,都是血泪教训换来的。
2.2.1 扁平化优先,嵌套适度
很多人喜欢把配置写成很深的多层嵌套。比如:
# 不推荐:嵌套太深
system:
modules:
perception:
camera:
front:
intrinsics:
fx: 1280.5
# 推荐:适当扁平化
camera_front_intrinsics_fx: 1280.5
当然,也不是越扁平越好。完全扁平的话,参数名会变得很长。我的经验是:嵌套不超过3层。超过3层,代码里访问起来也麻烦,可读性也差。
2.2.2 命名规范要统一
这个看起来简单,但做起来真不容易。我见过一个项目里,同一个参数有三种命名方式:camera_fps、cameraFrameRate、CAM_FPS。你想想看,这得多混乱。
我建议用蛇形命名法(snake_case),全小写,下划线分隔。比如:
lane_detection_confidence_thresholdacc_target_distance_maeb_braking_force_percent
单位也要统一写在参数名里。带单位的参数,一定要在名字里标明单位,比如_m、_kmh、_deg。这样看名字就知道值是什么意思,不用去查文档。
2.2.3 版本号必须内置
这一点特别重要。配置文件一定要有版本号字段:
config_version: "2.1.0"
last_modified: "2024-03-15"
author: "zhang_san"
为什么?因为ADAS系统是迭代开发的。今天你加了一个参数,明天他改了一个阈值。没有版本号,你根本不知道车上跑的是哪一版配置。我在项目里遇到过,同一辆车,上午和下午的配置不一样,查了一周才发现是配置文件版本没对齐。
- 嵌套不超过3层
- 命名用蛇形,带单位
- 版本号必须内置
- 每个参数都要有默认值
- 布尔值用true/false,不要用1/0
2.3 版本控制基础
配置文件也是代码,必须纳入版本控制。这个道理我一开始也不懂,觉得配置文件嘛,改改就行了。直到有一次,我把一个标定参数改错了,导致整个车队的功能异常……嗯,从那以后,我再也不敢不管理配置文件的版本了。
2.3.1 Git管理配置文件的要点
Git是标配。但配置文件有它的特殊性:
- 不要提交敏感信息:比如相机内参、车辆VIN号等,可以用环境变量或占位符替代
- 区分模板和实例:
config_template.yaml是通用模板,config_vehicle_001.yaml是具体车辆的配置 - 每次修改都要写commit message:说明为什么改这个参数,改了之后有什么影响
我习惯在项目里建一个configs/目录,结构如下:
configs/
├── templates/
│ ├── camera_config_template.yaml
│ ├── radar_config_template.yaml
│ └── system_config_template.yaml
├── vehicles/
│ ├── vehicle_001.yaml
│ ├── vehicle_002.yaml
│ └── vehicle_003.yaml
├── changelog.md
└── README.md
2.3.2 配置文件的diff审查
代码审查大家都会做,但配置文件的diff审查往往被忽略。我建议每次配置文件变更,都要做diff审查:
# 查看配置文件的变更
git diff configs/vehicles/vehicle_001.yaml
审查时要关注几点:
- 参数值的变化是否合理
- 是否有参数被误删
- 版本号是否更新
- 变更说明是否清晰
2.3.3 配置文件的回滚策略
万一新配置出了问题,要能快速回滚。我的做法是:
- 每次修改配置文件前,先打tag:
git tag config_v2.1.0_before_lane_change - 修改完成后,再打一个tag:
git tag config_v2.1.0_after_lane_change - 如果需要回滚,直接切到之前的tag
说白了,就是给配置文件的每次变更都留个快照。这样出了问题,几分钟就能恢复,不用重新调试。
好,这一节的内容就到这里。配置文件看起来是小事,但做不好,整个ADAS系统都会受影响。下一节我们聊聊参数化设计,那才是真正让配置活起来的关键。