巡航设定速度:VCruiseHelper 的 PCM 与非 PCM 两条路径

作者:

在

结论:巡航设定速度(vCruise)是规划与显示的输入,不是车端已执行车速,也不代表系统已使能。源文档把它的产生拆成两条互斥路径:CP.pcmCruise=True 时直接读原车 cruiseState.speed/speedCluster 转 km/h,按键调速由原车系统负责;CP.pcmCruise=False 时由 VCruiseHelper 自己处理按键并步进。两条路径的单位(km/h)、哨兵(255/0/-1)与边界(8–145 km/h)都必须逐车型核对,不能按品牌名称猜测。

一、数据流与单位

Car.state_update() 在车型接口解析车况后,先用当前 sm['carControl'].enabled 调用 update_v_cruise(),在 carControl.enabled 从假变真时再用 CS_prev 调用 initialize_v_cruise()。源文档注释明确这是为了使用 selfdrived 使能那一步的按钮状态,避免按键边沿与 card 的下一次车况更新错位。

随后发布的 CS.vCruise、CS.vCruiseCluster 单位都是 km/h;原始 cruiseState.speed 是 m/s,在 PCM 路径中乘 MS_TO_KPH。LongitudinalPlanner.update() 对 carState.vCruise 上限裁剪到 V_CRUISE_MAX 再转 m/s,并区分 unset;Controls.state_control() 将 CS.vCruise 转 m/s 传给车型 PID 加速度限幅,而 HUD 的设定速度取 vCruiseCluster。两种速度值可能不同,不能把仪表显示值当作规划器原始目标。

二、PCM 与非 PCM 两条路径

条件 update_v_cruise() 行为 影响
原车巡航不可用 设定值及仪表值均为 255;非 PCM 按键计时器不在该分支清零 规划器将其识别为未初始化;不代表车辆实际时速 255 km/h。恢复时旧计时器可能仍在。
CP.pcmCruise=True 直接使用 CS.cruiseState.speed/speedCluster 转 km/h 按键调速由原车系统负责,helper 不自行步进;speed==0 改为 unset,speed==-1 保留 -1 特殊值。
CP.pcmCruise=False 且原车巡航可用 从本地状态处理按钮,然后令仪表设定值等于内部设定值 自管设定速度;只有 enabled=True 时按键会改目标。

PCM 读取路径没有在本 helper 内对正常速度统一裁剪到 145 km/h;下游纵向规划器有自己的上限处理。量产适配需要分别核对原车报文中的 speed 和 speedCluster 含义、无效哨兵和单位,不能把任意 0 或 -1 当作普通速度。

三、非 PCM 按键算法与阈值

_update_v_cruise_non_pcm() 先找增/减速按钮的松开边沿;若找不到,再检查按住计时是否达到 50 帧倍数,将其视作长按重复。执行变更前有两个防重入门:增速键用于从静止巡航恢复时不调高设定值;若按钮按下时尚未 enabled,而松开前才完成使能,也不把同一次按键再次解释为调速。update_button_timers() 在当帧调速判断之后更新计时和按下时的 standstill/enabled 快照,这是边沿语义的一部分。

参数 / 规则 取值 说明
V_CRUISE_UNSET 255 未设定哨兵。
V_CRUISE_MIN 8 km/h 结果下限。
V_CRUISE_MAX 145 km/h 结果上限;上限注释指出模型训练分布外的速度预测可能不可靠。
短按步长 公制 1 km/h;英制 IMPERIAL_INCREMENT=1.6 km/h 英制由 1 mph 转换并取一位小数。
长按倍率 ×5 长按时若当前值不在 5 倍步长网格,增速先向上取整、减速先向下取整,再继续步进。
长按判定 按住 50 帧倍数 最终结果取一位小数并限制在 8–145 km/h。

油门覆盖时按减速键,会把新目标至少抬到当前 vEgo,随后仍受 145 km/h 上限约束。源码条件还写有 setCruise,但该函数的按键选择集合仅含增速/减速,因此当前路径不会选择到 setCruise;不能据该条件宣称 SET 键在此处有同样效果。

四、使能初始化、上游门与测试

initialize_v_cruise() 对 PCM 直接返回;非 PCM 首次使能时默认从当前车速与初始下限中取较大者,普通模式初始下限 40 km/h,实验模式 105 km/h,再限制到 145 km/h。若是增速/恢复按键触发且已有旧设定值,则恢复 v_cruise_kph_last,不是重新用当前车速初始化。这里的 105 km/h 是设定速度的初始下限/上界提示语义,实验模式仍由模型和下游规划裁决实际加速,不能理解为车辆会立即开到该速度。

非 PCM 的按键使能来自 CarState.buttonEnable(基础接口由增/减速键松开边沿产生,车型可覆写),经 CarEvents 转成 buttonEnable 事件,再由状态机决定使能。VCruiseHelper 只管设定值,不负责判断驾驶员监测、车辆故障或 panda 的 controlsAllowed;取消键、刹车与安全事件仍可让系统退出。

源文档的输入清单里还列出 IsMetric 与 ExperimentalMode:前者参与决定短按步长取公制 1 km/h 还是英制 1.6 km/h,后者决定首次使能的初始下限取 40 还是 105 km/h。二者都只影响设定值的产生,不影响车端是否已执行,也不替代使能与安全门。

测试方面,test_cruise_speed.py 覆盖非 PCM 短按松开、使能中按键、静止 resume、油门覆盖和初始化,文件 TODO 明确 PCM 路径尚无对应测试;本工作区的八项原类隔离探针使用假 NumPy 裁剪和假车况,不依赖实际 capnp、CAN 或 UI,也不等于实车按键与执行器测试。

常见问题

设定速度和实际车速是一回事吗?

不是。设定速度是规划/显示输入,不是车端已执行车速,也不代表系统已使能。源文档还强调 vCruise 与 HUD 取的 vCruiseCluster 可能不同,不能把仪表显示值当作规划器原始目标。

PCM 车型的长按调速逻辑由谁负责?

由原车系统负责。CP.pcmCruise=True 时 helper 直接使用 CS.cruiseState.speed/speedCluster 转 km/h,本 helper 不自行步进;因此 50 帧长按、5 倍步进这类算法只存在于非 PCM 路径。

实验模式初始下限 105 km/h,是不是车会立刻加速到 105?

不是。源文档明确 105 km/h 是设定速度的初始下限/上界提示语义,实验模式仍由模型和下游规划裁决实际加速,不能理解为车辆会立即开到该速度。

按增速键从静止恢复会调高设定值吗?

不会。源文档给出的防重入门之一就是:增速键用于从静止巡航恢复时不调高设定值;另一个是若按钮按下时尚未 enabled,而松开前才完成使能,也不把同一次按键再次解释为调速。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/CRUISE_SET_SPEED_DEEP_DIVE.md(取用了数据流与单位、PCM 与非 PCM 路径、非 PCM 按键算法、阈值常量与测试边界)。

说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

更新记录

首次发布 2026-10-11 最近核对:2026-10-11

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注