3、软件架构设计:实时操作系统(RTOS)选型、中间件(ROS2/DDS/SomeIP)、功能安全软件架构(ISO 26262)

聊到自动驾驶的软件架构,我脑子里第一个蹦出来的词就是「分层解耦」。你想想看,一个系统里既有激光雷达的点云处理,又有控制器的毫秒级响应,还得兼顾功能安全——这要是全揉在一起,调试起来能让人崩溃。

我个人习惯把软件架构拆成三层来看:底层是实时操作系统(RTOS),中间是通信中间件,上层是功能安全逻辑。这三层各司其职,但又有千丝万缕的联系。今天咱们就一个一个掰开聊。

3.1 实时操作系统(RTOS)选型:别让调度器拖了后腿

RTOS 选型,说白了就是选一个「能按时干活」的调度器。自动驾驶里,传感器数据采集、控制指令下发,都有严格的截止时间。我见过不少团队在原型阶段用 Linux + PREEMPT_RT 补丁,结果一上实车就出问题——为什么?因为 Linux 的调度延迟不稳定,偶尔给你来个几十毫秒的抖动,控制环路直接就震荡了。

我个人推荐在量产项目中优先考虑以下 RTOS:

RTOS 适用场景 我的经验
FreeRTOS MCU 端传感器驱动、执行器控制 轻量、生态好,但缺乏内存保护
QNX 域控制器、功能安全关键模块 微内核架构,隔离性好,我量产项目首选
VxWorks 高可靠场景(如线控底盘) 认证齐全,但授权费用高
Zephyr 新兴平台、开源需求 支持 SMP,但生态还在成长

选型时有个坑,我踩过:别只看平均响应时间,要看最差情况响应时间(WCET)。我曾经在一个项目中用了某款 RTOS,平均延迟只有 5μs,但最差情况能到 200μs——这在紧急制动场景下是致命的。所以,一定要做调度分析,用工具(比如 RTAW)跑一下最坏情况。

避坑指南: 我曾经在项目里为了省成本,在 MCU 上用了裸机循环 + 中断的方式代替 RTOS。结果功能安全审核时,认证机构直接打回——因为没有明确的调度策略和优先级反转保护。后来老老实实上了 FreeRTOS + 静态优先级调度,才过了审核。

3.2 中间件选型:ROS2、DDS 还是 SomeIP?

中间件是自动驾驶的「神经系统」。数据从传感器到感知模块,再到规划控制,中间件负责把数据「快递」过去。但不同场景对快递的要求不一样——有的要实时,有的要可靠,有的要跨域通信。

我一般这样选:

  • ROS2:适合原型验证和算法开发。它的发布/订阅模型很直观,社区资源丰富。但说实话,ROS2 的 DDS 实现(比如 Fast DDS)在实时性上还有提升空间,我很少在量产域控上直接用。
  • DDS(Data Distribution Service):这是量产项目的「硬通货」。它支持 QoS 策略,你可以精确控制数据可靠性、时效性、优先级。我在一个项目中用 DDS 做感知结果分发,通过设置 DEADLINE 策略,确保超过 100ms 的旧数据直接被丢弃——这对避免「幽灵刹车」很关键。
  • SomeIP:这是 AUTOSAR 的「亲儿子」,主要用于车载以太网通信。它的服务发现机制(SD)很成熟,适合与传统的 AUTOSAR 模块对接。但 SomeIP 的灵活性不如 DDS,如果你需要动态拓扑或复杂 QoS,建议还是上 DDS。

这里有个经验:不要试图用一个中间件覆盖所有场景。我见过一个团队在感知模块内部用 DDS,结果因为序列化开销太大,导致 CPU 占用率飙升。后来我建议他们在模块内部用共享内存 + 信号量,只在模块间通信用 DDS,问题就解决了。

核心建议: 量产项目中,我倾向于「DDS 为主,SomeIP 为辅」的策略。DDS 负责域内高频数据(如感知结果、控制指令),SomeIP 负责跨域服务调用(如诊断、配置)。ROS2 只用于开发阶段的快速迭代。

3.3 功能安全软件架构:ISO 26262 不是摆设

说到功能安全,很多人第一反应是「文档堆砌」。但我在实际项目中体会到,功能安全是一种设计哲学——它要求你从一开始就考虑「如果这里出错了,系统怎么兜底」。

ISO 26262 把软件架构分为几个关键概念:

  • ASIL 等级:从 A 到 D,等级越高,要求越严。比如转向系统通常是 ASIL D,而信息娱乐系统可能只是 QM。
  • 故障检测与响应:软件要能检测到自身故障(比如内存校验失败),并进入安全状态(比如降级到 L2 功能)。
  • 独立性:不同 ASIL 等级的模块要隔离。你不能让一个 ASIL B 的模块直接访问 ASIL D 模块的内存——这就像把核弹发射按钮放在公共区域一样危险。

我常用的功能安全软件架构模式有两种:

  1. 双通道锁步(Lockstep):两个相同的软件实例并行运行,比较输出结果。如果结果不一致,系统进入安全状态。这种模式在 MCU 上很常见,但代价是硬件资源翻倍。
  2. 监控-执行分离(Supervisor-Executor):一个「监控器」模块独立于主功能模块,专门检查主模块的输出是否合理。比如,规划模块输出一个急转弯指令,监控器发现车速太高,直接否决这个指令。我在一个项目中用这种模式,成功避免了一次因传感器误报导致的「幽灵转向」。
我的小技巧: 在实现功能安全时,别只盯着「故障注入测试」。我建议在架构设计阶段就引入「安全机制清单」,比如:内存保护(MPU/MMU)、程序流监控(WDT)、数据校验(CRC)。每一条都要落实到代码里,而不是只写在文档中。

嗯,这里要注意:功能安全不是「加一层保护」那么简单。我曾经在一个项目中,为了满足 ASIL B 要求,给每个模块都加了双冗余。结果系统复杂度暴增,反而引入了更多 bug。后来我意识到,简化架构本身就是一种安全措施——能用单通道解决的问题,就别硬上双通道。

3.4 三者如何协同?

RTOS、中间件、功能安全,这三者不是孤立的。我一般这样搭:

  • RTOS 提供时间隔离:用 QNX 的微内核,把不同 ASIL 等级的模块放在不同进程里。即使一个进程崩溃,也不会影响其他进程。
  • 中间件提供空间隔离:DDS 的域(Domain)机制可以把不同功能域的数据隔离开。比如,感知域的数据不会误闯到控制域。
  • 功能安全提供逻辑隔离:通过监控器模式,确保即使中间件或 RTOS 出现异常,系统也能安全降级。

举个例子:在一个 L3 量产项目中,我们用了 QNX 作为 RTOS,DDS 作为域内通信,SomeIP 作为跨域服务。功能安全方面,我们在控制模块上实现了「监控-执行分离」——监控器运行在独立的 QNX 进程中,通过 DDS 订阅控制指令,并用一个简单的物理模型验证指令是否合理。如果发现异常,监控器直接通过硬件 GPIO 触发安全继电器,切断执行器电源。

这个架构看起来复杂,但实际运行起来很稳定。我记得第一次实车测试时,工程师们都很紧张,结果跑了一整天,一次安全介入都没有——嗯,这才是我们想要的效果。

总结一句话: RTOS 管时间,中间件管数据,功能安全管异常。三者配合好了,自动驾驶软件架构才算真正「落地」。