2. 系统架构设计:整体架构图、模块划分与数据流
好,咱们进入第二章。系统架构设计,说白了就是给整个多屏互动项目搭骨架。我见过不少团队,一上来就写代码,写到一半发现屏幕之间通信乱成一锅粥,最后不得不返工。嗯,咱们别走那条弯路。
我个人习惯,先画一张整体架构图,把大框框定下来。然后再拆模块,最后把数据怎么流、怎么转,一条条理清楚。这样后面写代码的时候,心里才有底。
2.1 整体架构图
先看这张图。它把整个系统分成三层:硬件底层、中间通信层、上层应用。每一层各司其职,层与层之间通过定义好的接口交互。
核心原则:高内聚、低耦合。显示只管显示,通信只管传数据,应用只管业务逻辑。谁也别越界。
这张图我建议你存下来。每次做设计决策时,问自己一句:我这个改动,跨层了吗?如果跨了,八成有问题。
2.2 模块划分
架构图有了,咱们把每个模块拆开看看。我按三层来聊:显示管理、通信中间件、应用层。
2.2.1 显示管理模块
显示管理,管的是屏幕资源。车上有好几块屏,谁该显示什么,谁在前谁在后,分辨率不一样怎么办——这些都是它的事。
我记得有一次,客户说副驾屏显示内容被中控挡住了。查了半天,发现是图层优先级没配好。嗯,从那以后我特别强调图层管理。
| 子模块 | 职责 | 关键技术 |
|---|---|---|
| 窗口合成器 | 管理多个应用的显示窗口,合成最终画面 | Wayland/Weston, SurfaceFlinger |
| 图层管理 | 定义图层优先级、透明度、可见区域 | Z-order, Alpha blending |
| 分辨率适配 | 自动适配不同屏幕的物理分辨率 | DPI scaling, 坐标映射 |
| 触摸事件分发 | 将触摸坐标正确路由到对应应用 | Input dispatcher, 坐标变换 |
| HMI 框架 | 提供 UI 组件和动画能力 | Qt/QML, Flutter |
我的经验:窗口合成器别自己造轮子。直接用 Weston 或 SurfaceFlinger,社区成熟,坑少。你想想看,车规级系统最怕什么?不稳定。用成熟方案能省一半调试时间。
2.2.2 通信中间件模块
通信中间件,是整个系统的血管。应用之间怎么说话?数据怎么传?延迟多少?全看它。
我曾经在一个项目里,用了简单的 Socket 通信。结果车跑起来之后,信号一抖,数据就丢包。后来换成 SOME/IP + DDS 双通道,才把问题解决。
| 子模块 | 职责 | 适用场景 |
|---|---|---|
| SOME/IP | 服务发现、远程过程调用 (RPC) | 控制类消息、服务调用 |
| DDS | 数据分发、发布/订阅模式 | 高频数据流、传感器数据 |
| 共享内存 (SHM) | 进程间高速数据共享 | 视频帧、大块数据 |
| 协议转换网关 | 桥接不同通信协议 | CAN/LIN 与 IP 网络互转 |
避坑指南:别把所有数据都走 DDS。DDS 虽然灵活,但 QoS 配置复杂,搞不好反而增加延迟。我建议:控制类走 SOME/IP,数据流走 DDS,大块数据走共享内存。各取所长。
2.2.3 应用层模块
应用层,就是用户能看到的那些界面和功能。每个应用独立运行,通过中间件互相通信。
这里有个关键点:应用之间不能直接调用。比如仪表盘想显示导航信息,不能直接读导航 app 的内存,必须通过中间件发消息。这样任何一个应用挂了,不会拖垮整个系统。
- 仪表盘应用:车速、转速、油量、报警灯。要求实时性高,刷新率 60fps。
- 中控导航:地图渲染、路线规划、POI 搜索。数据量大,但实时性要求相对低。
- 副驾娱乐:视频播放、音乐、游戏。独立进程,崩溃不影响驾驶。
- 后排影音:类似副驾,但可能有多块屏同时播放不同内容。
- HUD 抬头显示:车速、导航箭头、ADAS 警告。信息精简,延迟要求极高。
2.3 数据流设计
模块分好了,数据怎么流?我画了一张数据流图,把典型场景走一遍。
这个流程里,有几个关键点要注意:
- 发布/订阅解耦:中控只管发,不管谁收。仪表盘和 HUD 只管收,不管谁发。这样新增一个屏幕,不需要改已有代码。
- 数据精简:中控发的是「导航指令」,不是完整地图数据。每个订阅者按需渲染。仪表盘只画一个箭头,HUD 只显示距离文字,没必要传整张图。
- 延迟控制:导航指令从发出到 HUD 显示,延迟不能超过 100ms。我建议用 DDS 的 BEST_EFFORT 策略,牺牲一点可靠性换速度。
数据流设计口诀:谁生产谁发布,谁消费谁订阅。数据最小化,延迟可量化。接口标准化,扩展不用怕。