智能驾驶预测功能服务接口设计规范:从数据契约到工程落地

智能驾驶预测功能服务接口设计规范:从数据契约到工程落地 简介该规范是智能驾驶功能软件平台设计系列的第3部分聚焦预测功能服务接口主要面向主机厂、自动驾驶算法工程师及系统集成商适用于2级及以上智能驾驶系统开发。文件以PDF格式提供共1个文件压缩包大小约909KB。规范覆盖行为预测与轨迹预测两类服务接口明确标准元数据头、行为预测数据、轨迹预测数据、单个交通参与者轨迹预测数据及轨迹点信息等数据结构并附有详细附录便于开发者直接对接决策规划模块。内容源自国汽智联、华为等多家单位联合编制可作为车载计算平台功能软件层接口设计、模块解耦及系统集成的参考依据。目前已有126人学习适合需要标准化预测接口定义或从事相关功能开发的读者。1. 预测功能服务接口卡在哪儿这个设计规范要解决的联调问题一辆车以 80 km/h 行驶在中间车道侧前方目标突然切入规控模块连续三帧拿到的预测结果横向偏差越拉越大决策在跟车与避让之间反复横跳。这类联调事故在智能驾驶项目中反复出现根因往往不在模型而在预测功能服务接口的设计规范没有定死谁声明时间戳、坐标系和有效时间谁在丢帧时兜底都变成了隐式约定。简单说这个标题规定预测模块在功能软件平台里如何对外提供预测数据是连接感知、预测、规控的数据契约。适合架构师、中间件开发、算法工程化和联调测试人员阅读目的是让“预测结果”从算法输出变成稳定可用的平台服务。2. 设计规范先定边界预测功能服务接口在软件平台里的分层位置2.1 预测功能服务接口是横向契约不是一张数据结构表在智能驾驶功能软件平台里“接口”这个词经常被说小。很多人把接口规范等同于目标列表的字段定义等到联调时才发现真正出问题的是发布周期、超时处理、坐标系基准和诊断上报这些“看不见的部分”。预测功能服务接口应当被定义成一组横向契约数据平面约定了发什么行为平面约定了什么时候发、不发怎么办治理平面约定了版本怎么升级、异常怎么暴露。从软件平台的分层看预测服务处在功能软件层内部实现可以是规则、学习模型或者二者的组合但对外呈现必须是稳定服务。平台服务层负责通信、时间同步、日志和诊断接口规范要引用但不重复实现这些能力。分层定位可以概括为下表层次职责与预测服务接口的关系感知接入层提供融合目标、车道线、自车状态等原始输入预测接口的输入来源须约定其发布周期和质量属性功能软件层实现预测、规划、控制等自动驾驶功能预测功能服务接口的定义位置向下依赖平台能力平台服务层提供通信、时间同步、日志、诊断服务承载接口的 QoS、超时监控和数据录制能力应用层HMI、远程监控、数据回传作为预测输出的附加消费者需要订阅和诊断能力这里要特别提一句时间同步。预测接口里所有时间戳必须基于同一个时钟域否则下游计算端到端时延毫无意义。常见做法是平台层统一维护单调时钟和墙上时钟两套时间预测服务在输出时同时携带这两个值接口规范里只说明语义不规定具体实现。2.2 输入侧和输出侧要分开定义避免耦合预测服务接口不能只定义输出。 联调经验里最常见的返工原因就是输入侧没有规范导致预测模块在接入不同感知方案时要改内部代码。设计规范应当明确预测服务的输入对象感知融合后的动态目标列表、自车状态、定位与局部地图、以及下游下发的感兴趣区域ROI。这四类输入信号里感知融合目标列表是主输入自车状态用于运动补偿地图和 ROI 则决定预测的上下文。输出侧要定义目标级预测和场景级预测两类结果。目标级预测是核心包括目标 ID、分类、意图、轨迹点序列和对应置信度场景级预测是自车行为概率或风险场在一些平台里由决策模块直接使用。一个容易被忽略的原则是预测模块每周期必须整帧输出不要按目标逐个推送。规控模块需要看到同一时刻所有目标的相对位置逐目标推送会让下游自己拼帧拼接过程直接引入几毫秒到几十毫秒的随机时延。输入输出分开定义后接口规范还需要说明数据所有权。比如 track_id 由谁生成、生命周期多长、目标消失后 ID 还能不能复用这些规则属于服务契约的一部分不能留给算法内部自行决定。2.3 从服务定义到中间件映射语义、编码与行为三层在 Autosar AP 和 DDS 主导的通信架构下一个预测服务接口会落到三层描述语义层说明“谁在提供、谁在消费”编码层用 IDL 或 proto 定义消息结构行为层定义 QoS 参数、超时策略和异常处理规则。三层缺一不可设计规范至少要用一个独立章节把这三者对应起来。语义层的核心是服务边界。预测服务面向多个消费者规控要预测轨迹HMI 要目标意图展示数据录制模块要完整记录。服务边界决定了接口的访问方式周期性结果用发布订阅模型按需查询用客户端-服务端模型状态跳变用事件模型。这个划分不做好后面很容易出现“查询接口里传了整帧大数组”之类的误用。编码层要做的是冻结字段语义。字段类型、单位、取值范围、枚举值与默认值必须锁定新增字段只能以附加形式引入。行为层则要明确周期、可靠性等级、队列深度和首帧时延指标。实际的工程排错中行为层的缺失比编码层更致命两个模块的数据格式都能对上但一个按 50ms 周期发一个按 100ms 周期读系统就是不稳定。3. 通信模式先于数据预测功能服务接口的 Topic、服务与事件划分3.1 先选语义周期广播、按需查询与异常事件怎么分工设计预测功能服务接口时第一件事不是画数据结构而是回答一个问题这个数据是“每个周期都要给所有人”还是“只有特定调用方发起才需要”。前者用发布订阅Topic后者用服务调用Service。常见做法是预测结果采用发布订阅历史轨迹查询采用服务调用预测降级和感知中断这类跳变用事件上报。三种模式的使用场景和判断方法如下需要周期性推给多个方预测帧、自车状态这类连续流数据使用 Topic。需要按需取一次且请求-应答语义明确如查询某个目标过去 5 秒的预测轨迹使用 Service。只在状态跳变时需要通知如感知中断导致预测批量失效、预测模块主动降级使用 Event。不要把整帧预测数据塞进事件里事件只做触发数据仍通过正常 Topic 链路读取。三种语义分开后接口数量可以控制在 6 到 10 个左右比把所有能力做成一个大 Topic 更易维护。每个接口只承担一种语义角色下游的使用逻辑会清晰很多。3.2 一份可落地的接口清单接口名、方向、周期与载荷下面是一份经过裁剪的预测接口清单适用于典型的高速和城区辅助驾驶场景。接口名采用服务名/语义/版本的命名方式实际命名以整车接口规范为准但结构上建议参考这种分层写法。接口名类型方向周期载荷内容/prediction/input/perception_targets/v1Topic感知到预测20-30 Hz融合目标列表、目标 ID、运动状态/prediction/input/ego_state/v1Topic自车状态到预测50 Hz车速、横摆角速度、加速度、挡位/prediction/output/targets/v1Topic预测到下游20 Hz目标预测轨迹、意图、置信度/prediction/service/history/v1Service下游到预测按需请求目标 ID 和时间窗返回历史轨迹/prediction/event/degraded/v1Event预测到下游跳变降级原因、有效时间、受影响目标范围接口清单里要注意每个接口的周期应当独立声明不能用“尽量”“大概”这类词。Topic 类接口周期由发布方保证Service 接口的超时时间由调用方设定并在接口文档中给出建议值。下面的 IDL 草案展示了预测输出帧的核心结构字段命名和注释遵循接口规范常见的可读性要求// 预测服务输出帧IDL 草案 module prediction_service { struct PathPoint { float x; // 车体坐标系 X单位 m float y; // 车体坐标系 Y单位 m float heading; // 航向角单位 rad float speed; // 速度单位 m/s float acceleration; // 加速度单位 m/s^2 float curvature; // 曲率单位 1/m float relative_time_s; // 相对该帧采集时刻的时间偏移单位 s }; struct PredictedTarget { uint32 track_id; // 目标 ID由预测服务维护 uint8 target_type; // 目标分类枚举 uint8 intention; // 意图枚举 float confidence; // 整条轨迹的置信度0.0-1.0 float existence_prob; // 目标存在概率0.0-1.0 sequencePathPoint path; // 预测轨迹点序列 }; struct PredictionFrame { uint64 frame_id; // 帧序号单调递增 uint64 publish_timestamp_ns; // 发布时间单调时钟 uint64 valid_until_ns; // 数据有效截止时间 sequencePredictedTarget targets; boolean degraded; // 服务是否处于降级状态 uint8 degrade_reason; // 降级原因枚举 }; };这段 IDL 里有几个设计点值得展开。track_id由预测服务维护感知目标 ID 在融合模块中可能随周期变化直接透传会导致下游无法关联历史帧。relative_time_s使用相对时间而不是绝对时间戳是因为轨迹点对应的未来时刻与采集时间有关下游只需要在消费时把它换算到自己的时间轴上。degraded字段很重要它告诉下游这帧数据虽然发了但可信度已经下降没有这个字段时下游只会当成正常预测处理系统行为会变得难以解释。3.3 QoS 参数表可靠性与时效优先级的取舍预测接口的 QoS 设计是工程上最容易被低估的部分。设计规范要给出明确的参数表而不是让每个模块各自调节。下面是一组常见配置适用于 DDS 或类 DDS 通信中间件数据类别可靠性历史策略队列深度周期可容忍丢包感知输入帧BestEffortKeepLast220-30 Hz低依赖插值自车状态ReliableKeepLast550 Hz极低预测输出帧BestEffortKeepLast120 Hz低最新帧优先历史轨迹查询Reliable不适用不适用按需零容忍降级事件ReliableKeepAll16跳变零容忍预测输出帧把可靠性配成 BestEffort队列深度设为 1是一个看起来“反直觉”但实际正确的选择。规控模块只关心最新一帧预测如果使用 Reliable 深队列一次短暂拥堵就会让规控拿到几帧前的旧数据而旧数据的时间戳已经超过有效截止时间规控必须丢弃等于白等一场。至于数据录制和审计可以单独拉一路录制通道用 Reliable 保证完整落盘不要让主控制链路承担重传开销。提示预测输出帧最好在消息头里带上valid_until_ns并把它和发布时间放在同一时钟域。下游判断数据是否可用时只需要比较当前时间和有效截止时间不需要知道发布方内部的处理时延这对多模块级联非常友好。4. 预测功能服务接口的数据模型坐标系、时间戳与无效值约定4.1 目标列表与轨迹字段从 track_id 到路径点的字段设计预测输出数据模型的难点不在“有哪些字段”而在每个字段的语义边界。比如confidence和existence_prob常被混淆前者是模型对这条预测轨迹的置信程度后者是目标本身存在的概率。一个远距离的低置信目标存在概率可能很高但如果预测方只给一个综合置信度下游就无法区分“目标不确定”和“轨迹不确定”两种状态决策模块会做出完全不同的处理。接口设计规范至少要把这两个概率字段分开并且规定它们的取值范围与缺失值表示。轨迹点序列path是另一个需要严格约束的对象。常见做法是约定未来 8 秒、采样间隔 0.1 秒最多 80 个点实际点数允许稀疏但必须按时间递增排列。不要在轨迹末尾补 0 或补 NaN 来凑长度接收方直接以sequence长度为准。速度、加速度、曲率字段的单位也要锁定速度用 m/s加速度用 m/s²曲率用 1/m。单位混乱在仿真和实车环境里会反复触发“看起来参数一样、行为完全不同”的问题。字段级设计还需要规定类型后缀尤其在跨语言环境中。C 侧float和 Python 侧float的精度语义一致但解析int8与uint8时的行为差异会导致负数处理出错。接口规范可以约定所有整数字段显式带符号所有浮点字段在 IDL 里统一为float枚举字段在序列化时使用整数类型并显式编号。这样各语言实现不会自己发挥。4.2 时间戳与坐标系约定让两端在同一根时间轴上计算时间戳和坐标系是预测接口数据模型里最容易吵起来的两个话题。先讲时间戳。预测输出帧中至少要有三个时间输入数据的采集时间、预测帧的发布时间、数据有效截止时间。采集时间用于下游评估链路时延发布时间用于统计周期抖动有效截止时间用于判断数据是否过期。三者不能共用同一个字段。采集时间和发布时间建议用单调时钟一个是uint64纳秒值有效截止时间用相对发布时间加时长来表示示例结构如下struct FrameTimestamp { uint64 capture_monotonic_ns; // 上游感知输入的数据采集时刻 uint64 publish_monotonic_ns; // 当前帧发布时间 uint64 valid_duration_ns; // 从发布时刻起算的有效时长 };坐标系方面预测轨迹点必须声明参考点和轴向。行业里常见约定以自车后轴中心为原点X 轴向前Y 轴向左Z 轴向上航向角以 X 轴为 0、逆时针为正。接口规范要把这个约定写成默认值并允许在帧头中携带坐标系标识而不是让各模块各自实现“车内坐标系”。否则预测输出的轨迹、规控的参考线、感知的目标框可能使用三个不同原点坐标转换误差会在 20Hz 的周期里被不断放大。4.3 枚举与无效值明确“不知道”和“算不出来”无效值的表达直接决定下游代码的复杂度。很多工程代码里用 −1 表示“没有速度”用 0 表示“未知类型”用 999 表示“无效距离”下游就必须对每个字段分别记忆一套魔数。预测功能服务接口规范应当统一约定数值缺失一律用 NaN枚举缺失一律用显式的UNKNOWN服务本身故障用degraded标志而不是返回空列表。这样“没有目标”和“目标结果不可信”在接口上就彻底分开了。目标类型和意图这类枚举必须显式编号并保证新增枚举值时旧编号不变。例如目标类型可定义为UNKNOWN0, CAR1, TRUCK2, BUS3, PEDESTRIAN4, BICYCLE5意图可定义为KEEP_LANE0, LEFT_CHANGE1, RIGHT_CHANGE2, EMERGENCY3, UNKNOWN255。接收方遇到未定义的枚举值时必须跳过该目标而不是中止整帧解析。这一点在多版本混跑的升级窗口期尤其重要老版本消费者遇到新枚举值应该能优雅降级。注意NaN 在 C 里与任何值比较都返回 true直接做value ! value判断时容易写出隐晦逻辑。接口层建议统一封装成IsValid()由序列化库负责把 NaN 识别转换为标准布尔状态避免业务代码到处做浮点特殊值判断。5. 预测功能服务接口的时序预算、版本兼容与验证技巧5.1 时序指标与降级行为首帧、周期和感知中断预测服务必须给自己定一组可测量的时序指标否则联调阶段只能靠“感觉不太稳定”来推进。下面是一组常见指标框架实际取值以整车时延预算为准但结构可以直接复用指标场景建议值或范围说明输出周期正常行驶50 ms20 Hz与规控周期保持一致或为其整数倍周期抖动稳态输出±5 ms 以内超过视为链路拥塞或调度异常首帧时延服务启动到首帧输出小于 100 ms不含模型加载时间输入中断容忍感知丢帧小于 500 ms超过后必须发布降级事件降级输出周期降级期间保持 20 Hz内容允许变稀但不能静默停止感知输入中断超过 500ms 时预测服务应当主动发布降级事件并继续以 20Hz 输出带degradedtrue的空目标列表。这里的关键点是空列表表示“当前没有可预测目标”降级标志表示“预测能力受限”两个信号同时出现下游才知道系统处于异常状态。如果只是发空列表规控会认为环境突然清零可能做出急减速等危险行为。5.2 接口版本兼容策略topic 换名与字段扩展规则预测功能服务接口的升级不能靠“大家约好同一时间切换”。设计规范里锁定下面的兼容规则主版本变更必须换接口名例如/prediction/output/targets/v1升级到/prediction/output/targets/v2次版本变更保持接口名不变但消息体内必须增加minor_version字段并通过类型哈希机制让接收方识别新旧版本。新增字段时所有旧字段的语义和默认值不能改变旧版本消费者遇到新字段应当自动忽略。枚举值扩充也属于次版本变更入口但风险更高。接收方必须对未知枚举值做跳过处理。主版本不兼容的典型情况包括单位变化m 改为 cm、坐标系原点变化、字段类型变化、删除字段等。只要出现其中一种就必须换 topic 名让新老版本在通信层面隔离。接口规范最后还要规定一个过渡窗口期常见做法是主版本接口并行运行至少一个迭代周期直到数据录制和回放链路全部验证通过再废弃旧接口。5.3 用回放与断言脚本验收接口静态检查示例接口验收不能只看“能收到数据”要能自动发现字段级的脏数据。实际操作中我一般会把路采数据按原时间轴回放在预测服务的输入侧重放感知帧和自车状态在输出侧订阅预测结果并运行一段静态断言脚本。把脚本挂到持续集成里可以避免接口字段调整后回归出隐蔽问题。下面是一个适用于录制帧回放链路的检查示例def validate_prediction_frame(frame, prev_ts, period_ms50, max_points80): errors [] if frame.publish_timestamp_ns prev_ts: errors.append(publish_timestamp_ns 不单调) if frame.valid_until_ns frame.publish_timestamp_ns: errors.append(valid_until_ns 晚于 publish_timestamp_ns) for target in frame.targets: if not (0.0 target.confidence 1.0): errors.append(ftrack {target.track_id}: confidence 超出 [0,1]) last_t -0.001 for point in target.path: if point.relative_time_s last_t: errors.append(ftrack {target.track_id}: path 采样时间未严格递增) last_t point.relative_time_s if len(target.path) max_points: errors.append(ftrack {target.track_id}: path 超过 {max_points} 点) if frame.degraded and frame.degrade_reason 0: errors.append(degraded 为真但未填写原因) return errors脚本检查了四个最容易被漏掉的性质时间戳单调性、有效截止时间合法性、轨迹点采样时间的严格单调性、置信度范围。period_ms用来计算相邻两帧的间隔超过周期的 1.2 倍就输出抖动警告而不是直接报错因为路采数据本身可能有微小波动。落地时把这个脚本放在回放工具的后处理阶段每次接口变更后跑一遍全量数据错误数应该保持为零。另一个值得加入的断言是首点时间对齐path中第一个点的relative_time_s应接近 0。若偏差超过 0.1 秒多半是上游感知帧的采集时间被重复使用预测轨迹被整体平移了一段时延。这个检查比任何功能测试都更能暴露链路里的隐性等待。回放验证时把坐标系原点改成当前车体后轴中心再核对首点时间基本就能把预测接口层的时延和坐标问题一次性筛出来。本文还有配套的精品资源点击获取