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写标定参数,算法工程师自己就能改,不用每次都找软件工程师帮忙。这就是生产力。

我的小技巧: YAML对缩进非常敏感,一定要用空格,不要用Tab。我吃过这个亏——有一次调试了一整天,最后发现是编辑器自动把空格转成了Tab。从那以后,我所有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确实好用。

避坑指南: 我曾经在一个项目里,把三种格式混着用——标定参数用YAML,模块间通信用JSON,系统配置用XML。结果维护成本翻倍。后来我统一成YAML为主,JSON只在需要高性能解析的场景用。记住:一致性比格式本身的优劣更重要。

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_fpscameraFrameRateCAM_FPS。你想想看,这得多混乱。

我建议用蛇形命名法(snake_case),全小写,下划线分隔。比如:

  • lane_detection_confidence_threshold
  • acc_target_distance_m
  • aeb_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

审查时要关注几点:

  • 参数值的变化是否合理
  • 是否有参数被误删
  • 版本号是否更新
  • 变更说明是否清晰
我的习惯: 每次发布新版本配置前,我会用脚本自动对比新旧配置,输出差异报告。这样就不会漏掉任何改动。脚本很简单,就是解析YAML然后做递归对比。有需要的话,后面我可以分享这个脚本。

2.3.3 配置文件的回滚策略

万一新配置出了问题,要能快速回滚。我的做法是:

  1. 每次修改配置文件前,先打tag:git tag config_v2.1.0_before_lane_change
  2. 修改完成后,再打一个tag:git tag config_v2.1.0_after_lane_change
  3. 如果需要回滚,直接切到之前的tag

说白了,就是给配置文件的每次变更都留个快照。这样出了问题,几分钟就能恢复,不用重新调试。

注意: 配置文件回滚后,一定要通知所有相关人员。我曾经回滚了配置,但忘了通知测试团队,结果他们拿着旧配置跑了半天测试,数据全废了。沟通和版本管理同样重要。

好,这一节的内容就到这里。配置文件看起来是小事,但做不好,整个ADAS系统都会受影响。下一节我们聊聊参数化设计,那才是真正让配置活起来的关键。