横向目标曲率有三道限幅:jerk 5、加速度 3、曲率 0.2 各拦什么

作者:

在

结论:从目标曲率到车轮,controlsd 要经过「来源仲裁 → 变化率/加速度/绝对曲率三道限幅 → 选定的横向控制器 → 车型编码 → panda 固件」这几层。两个容易被误读的边界是:来源选择只看 lateralManeuverPlan 的消息 valid 位,不看 updated、alive 或消息年龄,因此发布者停发而进程不重启时,最后一条有效计划可能被持续选为目标;另外变化率限幅本身不会置 curvature_limited 标志,不能用它判断「是否发生过裁剪」。以下为固定源码快照 c8fb906 的静态追踪。

两条目标来源与 valid / alive 的差别

正常目标来自 modelV2.action.desiredCurvature;若 controlsd 看到 lateralManeuverPlan 的消息 valid 位为真,则优先采用该计划;横向未激活时两条来源都改用实测曲率,以降低再使能时的阶跃。模型侧 get_action_from_model() 有两条版本兼容路径:没有 action 输出时从预测轨迹的 yaw/yaw rate 估算曲率,有 action 时把输出横向量除以 max(1,vEgo)^2;纵向加速度作 0.3 s 平滑,横向平滑常量为 0,但 vEgo<=0.3 m/s 时保持上一帧曲率。

实验来源 lateral_maneuversd 只有机动 active 且未完成才把计划标为有效,曲率以基线曲率加「目标横向加速度 / max(vEgo,1)^2」形成;进程表只在横向机动条件下管理它,生产运行不应把它当作常驻规划器。

失效语义的核心在消息健康位:SubMaster.update_msgs() 只在收到新消息时更新 valid;alive 按收包时间重新计算;all_checks() 才同时检查存活、频率与有效位。而 controlsd 的来源选择只检查 sm.valid['lateralManeuverPlan'],未检查该主题的 updated、alive 或消息年龄。因此曾收到有效实验计划后,若发布者停发而进程不重启,最后一条计划仍可能被持续选为目标——其后仍经过限幅、latActive、车型与 panda 门,不等于可以任意发送转向。

controlsd 的逐层处理

Controls.__init__() 读取 CarParams,按转向接口类型优先选 angle/curvature,否则按横向调参选 PID/torque;update() 以 selfdriveState 为轮询主题更新异步输入与姿态数据。state_control() 更新车辆模型、活动门、目标曲率与执行器,并对数值字段做有限性检查。VehicleModel.calc_curvature() 把扣除在线角偏置的方向盘角换成实测曲率,考虑转向比、速度与路面横滚;controlsd 在调用前取负号,方向约定需用实车校验。

函数/组件 源码作用 契约或边界
Controls.__init__() 按转向接口类型优先选 angle/curvature,否则按横向调参选 PID/torque。 不同输出单位不能在插件间直接互换。
state_control() 更新车辆模型、活动门、目标曲率与执行器,做有限性检查。 生成的是 CarControl,不是 CAN 或执行许可。
VehicleModel.calc_curvature() 扣除在线角偏置的转角换算实测曲率,考虑转向比/速度/横滚。 调用前取负号,方向约定需实车校验。
clip_curvature() 顺序限制变化率、考虑 roll 的横向加速度范围、绝对曲率。 curvature_limited 只由后两道限幅标记,变化率限幅不置位。
Controls.publish() 发布 controlsState 与 carControl,比较请求与 carOutput。 顶层 valid=CS.canValid,不是 sm.all_checks()。
Car.controls_update() carControl 存活且非被动/已初始化时调用车型 apply() 并发布 sendcan。 仍须通过车型编码与 panda 固件安全约束。

三道限幅与标志位陷阱

clip_curvature() 按顺序做三件事:用至少 1 m/s 的速度计算 5 m/s^3 的近似横向 jerk 限幅;再按 ±3 m/s^2 加 roll 补偿限加速度;最后按 ±0.2 1/m 限绝对曲率。源码明确标注 jerk 公式为近似,这些常量不是可以脱离车型和硬件直接复用的认证约束。

隔离探针给出一个典型陷阱:当变化率单独生效时,输出已从 0.1 改成 0.0005,但 curvature_limited=False。也就是说这个标志不能作为「无裁剪」的诊断依据。探针只验证纯数值函数,不代表 controlsd 消息时序、车型控制器或板端限幅已通过。

限幅 阈值 是否置 curvature_limited
变化率(近似横向 jerk) 5 m/s^3,速度下限 1 m/s 否
横向加速度(含 roll 补偿) ±3 m/s^2 是
绝对曲率 ±0.2 1/m 是

输出单位与有限性清理

控制器输出按 steerControlType 分流:通用第一返回值写 actuators.torque,angle/普通 PID 的第二返回值写 steeringAngleDeg,curvature 型写 actuators.curvature,扭矩控制的第二返回值为零。LatControlAngle 与 LatControlCurvature 都返回 steer=0,有效输出分别是角度与曲率字段;LatControlPID 在施力/低速/安全限幅时冻结积分;LatControlTorque 把目标曲率换横向加速度后返回时会翻转符号,不能把 pid_log.output 与 actuators.torque 直接同号比较。

state_control 对 Actuators 的数值字段逐个检查非有限值并清零,但这只是末端值清理,不是上游模型输入、车辆参数或中间 PID 状态的完整非有限传播防护。publish() 在 selfdriveState.active 时比较本次请求与已收到的 carOutput,把差异留给后续循环的控制器饱和判断,这不是同步的本帧硬件确认。

控制器 有效输出字段 边界
LatControlAngle steeringAngleDeg(steer=0) 曲率反算目标方向盘角并加角偏置。
LatControlCurvature actuators.curvature(steer=0) 曲率误差 PID 或前馈,驾驶员施力时用前馈。
LatControlPID steeringAngleDeg 或扭矩 施力/低速/安全限幅时冻结积分。
LatControlTorque actuators.torque 返回时翻转符号;不能把 pid_log.output 与扭矩直接同号比较。

自制硬件与插件契约

源文档给出的约束是:候选规划插件应输出带来源、时间戳、年龄上限、曲率单位 1/m、车辆坐标/正方向、适用车速范围与显式失效状态的目标;仲裁层独占来源选择与 TTL,失效时回退模型或安全降级。车辆学习参数、转角编码与 carOutput 的实际执行反馈也应按车型/硬件版本记录。

不能让普通插件修改 latActive、车型极限或 panda 固件;CarControl 及其 valid 位也不能替代板级安全门。现有横向饱和测试覆盖部分车型与控制器,扭矩缓冲测试覆盖停用后缓冲清零,但未证明四类控制器全部车型、计划抢占超时、模型丢帧、车况异步或实车符号正确,仍需补齐来源有效→停发/无效切换的回放测试与 NaN/Inf 注入。

常见问题

实验计划停了不发,为什么车还在用它?

因为 controlsd 的来源选择只检查 sm.valid['lateralManeuverPlan'],未检查 updated、alive 或消息年龄。曾收到有效计划后,若发布者停发而进程不重启,最后一条计划仍可能被持续选为目标;但它仍经过限幅、latActive、车型与 panda 门。

curvature_limited=False 就代表没有裁剪吗?

不代表。这个标志只由横向加速度与绝对曲率两道限幅设置;变化率限幅本身不置位。探针显示变化率单独生效时输出已从 0.1 改成 0.0005,但标志仍是 False。

三道限幅的阈值分别是多少?

按顺序是:用至少 1 m/s 计算 5 m/s^3 的近似横向 jerk、±3 m/s^2 的横向加速度(含 roll 补偿)、±0.2 1/m 的绝对曲率。源码标注 jerk 公式为近似,不能直接当认证约束复用。

扭矩控制器的输出符号可以直接对比吗?

不能。LatControlTorque 返回时会翻转符号,不能把 pid_log.output 与 actuators.torque 直接同号比较;angle 与 curvature 两类控制器则返回 steer=0,有效输出在角度或曲率字段。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/LATERAL_TARGET_ACTUATION_DEEP_DIVE.md(两条来源仲裁、controlsd 逐层处理、三道限幅与四类控制器)。
  • 项目 02 —— openpilot-research/ 同目录探针记录:五项 clip_curvature() NumPy 数值契约隔离探针结论。

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

更新记录

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

评论

发表回复

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