volkswagen: add Avoid EPS Lockout toggle (port from dragonpilot)

Adds a VW-brand toggle that scales steering torque down at low speeds
(vEgo 0.4 -> 80%, 3.5 -> 95%, >=4.0 -> 100% of STEER_MAX) to avoid EPS
lockout. Ported from dragonpilot (dp_vag_avoid_eps_lockout) following the
sunnypilot brand-params pattern: VagAvoidEPSLockout param -> VolkswagenFlagsSP
-> VW carcontroller. Default off; requires an onroad cycle to take effect.
This commit is contained in:
Comma Device
2026-08-25 12:06:59 +08:00
parent b061d88cfa
commit aa1716d404
8 changed files with 67 additions and 1 deletions
@@ -6,6 +6,7 @@ from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.interfaces import CarControllerBase
from opendbc.car.volkswagen import mebcan, mlbcan, mqbcan, pqcan
from opendbc.car.volkswagen.values import CanBus, CarControllerParams, VolkswagenFlags
from opendbc.sunnypilot.car.volkswagen.values import VolkswagenFlagsSP
VisualAlert = structs.CarControl.HUDControl.VisualAlert
LongCtrlState = structs.CarControl.Actuators.LongControlState
@@ -40,6 +41,7 @@ class CarController(CarControllerBase):
self.CAN = CanBus(CP)
self.packer_pt = CANPacker(dbc_names[Bus.pt])
self.aeb_available = not CP.flags & VolkswagenFlags.PQ
self.dp_avoid_eps_lockout = bool(self.CP_SP.flags & VolkswagenFlagsSP.AVOID_EPS_LOCKOUT)
if CP.flags & VolkswagenFlags.MEB:
self.meb_long_state = mebcan.MebLongStateMachine(self.CP, self.CCP)
@@ -105,7 +107,13 @@ class CarController(CarControllerBase):
else:
if CC.latActive:
new_torque = int(round(actuators.torque * self.CCP.STEER_MAX))
if self.dp_avoid_eps_lockout:
# Scale steering torque down at low speeds to avoid EPS lockout
torque_scale = np.interp(CS.out.vEgo, [0.4, 3.5, 4.0], [0.8, 0.95, 1.0])
scaled_steer_max = self.CCP.STEER_MAX * torque_scale
new_torque = int(round(actuators.torque * scaled_steer_max))
else:
new_torque = int(round(actuators.torque * self.CCP.STEER_MAX))
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.CCP)
apply_torque = self.hca_mitigation.update(apply_torque, self.apply_torque_last)
@@ -21,6 +21,7 @@ from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP
from opendbc.sunnypilot.car.subaru.values_ext import SubaruFlagsSP, SubaruSafetyFlagsSP
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP, TeslaSafetyFlagsSP
from opendbc.sunnypilot.car.toyota.values import ToyotaFlagsSP
from opendbc.sunnypilot.car.volkswagen.values import VolkswagenFlagsSP
class LatControlInputs(NamedTuple):
@@ -90,6 +91,7 @@ def setup_interfaces(CI, CP: structs.CarParams, CP_SP: structs.CarParamsSP,
_initialize_radar_tracks(CP, CP_SP, can_recv, can_send)
_initialize_stop_and_go(CP, CP_SP, params_dict)
_initialize_toyota(CP, CP_SP, params_dict)
_initialize_volkswagen(CP, CP_SP, params_dict)
def _initialize_custom_longitudinal_tuning(CI, CP: structs.CarParams, CP_SP: structs.CarParamsSP,
@@ -166,3 +168,10 @@ def _initialize_toyota(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params
if toyota_stop_and_go_hack and CP.openpilotLongitudinalControl:
CP_SP.flags |= ToyotaFlagsSP.STOP_AND_GO_HACK.value
def _initialize_volkswagen(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params_dict: dict[str, str]) -> None:
if CP.brand == 'volkswagen':
avoid_eps_lockout = int(params_dict.get("VagAvoidEPSLockout", 0)) == 1
if avoid_eps_lockout:
CP_SP.flags |= VolkswagenFlagsSP.AVOID_EPS_LOCKOUT.value
@@ -0,0 +1,11 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from enum import IntFlag
class VolkswagenFlagsSP(IntFlag):
AVOID_EPS_LOCKOUT = 1
Binary file not shown.
+1
View File
@@ -231,6 +231,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaAftermarketBsm", {PERSISTENT | BACKUP, BOOL, "0"}},
{"VagAvoidEPSLockout", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
@@ -5,11 +5,37 @@ This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.vehicle.brands.base import BrandSettings
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.multilang import tr, tr_noop
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp
DESCRIPTIONS = {
'avoid_eps_lockout': tr_noop(
'Scale steering torque down at low speeds to avoid EPS lockout.'
)
}
class VolkswagenSettings(BrandSettings):
def __init__(self):
super().__init__()
self.avoid_eps_lockout = toggle_item_sp(
lambda: tr("Avoid EPS Lockout"),
description=lambda: tr(DESCRIPTIONS["avoid_eps_lockout"]),
initial_state=ui_state.params.get_bool("VagAvoidEPSLockout"),
callback=self._on_enable_avoid_eps_lockout,
enabled=lambda: not ui_state.engaged,
)
self.items = [
self.avoid_eps_lockout,
]
def _on_enable_avoid_eps_lockout(self, state: bool):
ui_state.params.put_bool("VagAvoidEPSLockout", state, block=True)
ui_state.params.put_bool("OnroadCycleRequested", True)
def update_settings(self):
pass
@@ -2816,3 +2816,9 @@ msgstr[1] "到目前为止,您有 {} 段驾驶数据被用于训练数据集
msgid "✓ SUBSCRIBED"
msgstr "✓ 已订阅"
msgid "Avoid EPS Lockout"
msgstr "避免EPS锁定"
msgid "Scale steering torque down at low speeds to avoid EPS lockout."
msgstr "低速时按速度降低转向扭矩,避免EPS锁定。"
@@ -138,4 +138,9 @@ def initialize_params(params) -> list[dict[str, Any]]:
"ToyotaStopAndGoHack",
])
# volkswagen
keys.extend([
"VagAvoidEPSLockout",
])
return [{k: params.get(k, return_default=True)} for k in keys]