Skip to content

SR2.0 平台化:一套代码 7+ 车型 ​

SR2.0 要同时落在 E38、E28A、F30、H93 等 7 个以上车型上,每块屏的分辨率、FPS、车模都不一样。平台化的答案不是开分支,而是一份 SRPlatform.csv 加一个下拉菜单;配套的 ProtoParser 把多套协议的序列化代码全部自动生成,编辑器内回放工具让台架调试不再依赖实车。

支持车型7+ 一键切换
协议套数行车/泊车/AI代驾/百度LD
压测注入10ms 全信号

背景 ​

SR2.0 是自研的 3D 导航渲染引擎(Unity 2022.3.29f1),运行在车机仪表和中控上。工程本身是模块化的:主工程通过 module-list.json 声明依赖,module-xkernel、module-arts、module-napa5-hmi、module_protocol_xp 等库以软链接形式挂进 Modules 目录,构建过程代码全部复用。

问题在于车型。E38、E38V、F30、H93、E28A、E28AV……每个车型的仪表尺寸、屏幕 FPS、车模资源都不同,而且车型还在增加。同时 SR 要消费的协议不止一套:行车感知、泊车(百度 Apollo 体系)、AI 代驾、百度 LD,各有各的 proto 定义和版本节奏。

问题 ​

问题表现根因
多车型维护每个车型一套工程或一串 if-else,改一处漏三处差异硬编码在代码里
协议代码手写proto 更新后解析代码靠人肉同步,枚举对不上就解错生成代码和 proto 定义没有强一致约束
调试依赖实车问题复现要上车、要路测数据,台架上干等引擎没有数据回放能力
压测靠想象信号洪峰下引擎撑不撑得住,只有上线了才知道没有可控的信号注入手段

方案 ​

配置化平台切换 ​

所有平台差异收敛到配置层,代码只有一份:

mermaid
flowchart TD
    subgraph CFG["配置层 Assets/Document"]
        CSV["SRPlatform.csv<br>分辨率 / FPS / 车模路径"]
        DYN["SRDynamicObj.csv<br>模型资源·全平台共用"]
        CAM["SRVCameraConfig.csv<br>镜头参数·按车型差异化"]
        XML["SystemConfig.xml<br>启动前置加载资源"]
    end
    SW["当前车型下拉菜单<br>E38 / E28A / F30 / H93 ..."]
    RT["SR2.0 运行时<br>同一套代码"]
    CSV --> SW
    CAM --> SW
    DYN --> RT
    XML --> RT
    SW -->|切换 + RefreshGroup| RT
  • SRPlatform.csv 是平台特性的总登记表:平台名、仪表尺寸、仪表 FPS、屏幕尺寸、FPS、车模路径,一行一个车型。切车型就是编辑器里选一下「当前车型」下拉菜单。
  • 差异化隔离:有平台差异的配置(如 SRVCameraConfig.csv 镜头参数)放在对应车型的 Resources 目录下;全平台共用的(如 SRDynamicObj.csv 模型资源)只留一份。
  • 切换后如果车模没刷新,执行 Tools/Asset/RefreshGroup 强制重建资源分组——这是编辑器资源缓存的已知坑,文档里明确写了。

协议代码自动生成 ​

proto 是系统与外部交换数据的契约,生成代码和定义必须严格一致,人肉同步一定会出事:

mermaid
flowchart LR
    P1["行车 proto"] --> PP["ProtoParser<br>protobuf 3.14"]
    P2["泊车 proto"] --> PP
    P3["AI 代驾 proto"] --> PP
    P4["百度 LD proto"] --> PP
    PP --> GEN["协议代码<br>自动生成"]
    GEN --> SIG["信号链路<br>编解码"]
  • 所有 proto 文件集中放在 module_protocol_xp 工程的 Protocol 目录,按体系分目录(BOSCH、BOSCH_HIK、DiDi、XP);非 XPU 定义的协议统一收进 Protocol/XP/customize。
  • 编辑器菜单 Tools/Protocol/[ProtoParser] 一键生成代码,谁更新 proto 谁重新生成,定义和代码不会脱节。

关键实现 ​

编辑器内回放工具。 .record 录制文件丢进 Playback 目录,运行工程、选文件、点播放,引擎按录制时序重放全部信号——台架上就能复现路测现场。工具同时存在两套回放模式:新的「服务下沉」和老的「Unity 自研」(默认),F2 切换 UI 界面、F3 切换回放模式、F1 隐藏界面,两套并存保证老录制文件不失效。

变速与逐帧。 播放速度开放 4 档:x0.5 / x1.0 / x1.5 / x2.0,慢放看时序、快放跑长程;「上一帧 / 下一帧」逐帧步进,进度条可点击可拖拽(拖拽后自动暂停),支持按百分比跳转。轮播模式可以循环过整个 Playback 目录,适合做回归。

10ms 级压测注入。 「压测收集」先把当前录制文件里的所有信号收集起来(100kb 以内会合并),「开始压测」后每 10ms 把收集到的全量信号打一遍——等于把真实路采的信号密度放大成洪峰,在台架上提前压出引擎的吞吐瓶颈,而不是等上线后看事故报告。

显示信息即体检表。 文件状态、播放状态、当前文件、播放进度、录制时间、帧数(信号数)、文件时长全部实时可见,回放文件有没有加载成功、信号量对不对,一眼能判断。

工程与打包配套。 主工程依赖的 XKernel、XTools 等库通过软链接挂进 Modules 目录,新增工程只需在根目录放一份 module-list.json(模块名与 git 仓名保持一致),构建过程代码全复用。打包走 CI 参数化:临时包、daily 包(USERDEBUG)、release 包(USER)共用同一套流水线,版本号统一为 X.Y.Z-buildTime-Branch-PackageType 格式,aar 产物名和 apk 的 dependencies 声明严格对应,谁要打哪个车型的包就是选参数的事。

PC 调试窗口。 编辑器里双 Game 窗口模拟双屏(Display1 2880×1620 对应中控、Display2 1920×720 对应仪表),配合调试菜单窗口里的 AEB 信号、AVM 操作、HUD、OTA 升级、SR 场景模式等开关,大部分联调不用碰实车。

指标 ​

指标改造前改造后
新增车型成本改代码 + 排差异SRPlatform.csv 加一行 + 下拉切换
平台覆盖单车型工程7+ 车型一套代码(E38/E38V/F30/H93/E28A/E28AV 等)
协议代码手写解析,易脱节ProtoParser 自动生成,protobuf 3.14,多套协议并存
问题复现依赖实车路测编辑器内回放,双模式 + 4 档变速 + 逐帧
压力验证上线后被动发现10ms 周期全信号压测注入,台架前置暴露

复盘 ​

  1. 平台化的本质是把差异从代码里赶到配置里。SRPlatform.csv 起作用不是因为 CSV 这个格式,而是因为「分辨率/FPS/车模」被承认是数据而不是逻辑。
  2. 共用与差异要分开存放:SRDynamicObj.csv 全平台一份,SRVCameraConfig.csv 按车型分目录。混在一起的结果就是改 A 车型的镜头把 B 车型搞挂。
  3. 生成代码和 proto 定义的一致性不能靠自觉,ProtoParser 把「更新 proto 必重新生成」变成一次菜单点击,联调期枚举对不上的低级事故直接消失。这套思路和后来 Native-Unity 信号链路 的「一份 proto 两端用」是同一个原则。
  4. 回放工具最值钱的不是播放,是压测注入——把录制信号变成可控洪峰,性能验证从「上线后看运气」前置成「台架上可重复」。回放链路本身的性能问题后来在 回放工具多线程 75 倍提速 里单独治过。
  5. 双模式并存(服务下沉 / Unity 自研)是工具演进的正确姿势:新链路上线不等于老链路当天拆除,老录制文件和旧流程有兜底,切换期的风险才可控。

罗子初 · AI 座舱专家 · 8年端侧研发

Lv.1