diff --git a/opendbc_repo/opendbc/car/volkswagen/interface.py b/opendbc_repo/opendbc/car/volkswagen/interface.py index d4772a70a..0fedacf7f 100644 --- a/opendbc_repo/opendbc/car/volkswagen/interface.py +++ b/opendbc_repo/opendbc/car/volkswagen/interface.py @@ -3,7 +3,20 @@ from opendbc.car.interfaces import CarInterfaceBase from opendbc.car.volkswagen.carcontroller import CarController from opendbc.car.volkswagen.carstate import CarState from opendbc.car.volkswagen.radar_interface import RadarInterface -from opendbc.car.volkswagen.values import CanBus, CAR, DBC, NetworkLocation, TransmissionType, VolkswagenFlags, VolkswagenSafetyFlags +from opendbc.car.volkswagen.values import CanBus, CAR, DBC, NetworkLocation, TransmissionType, VolkswagenFlags, VolkswagenSafetyFlags, resolve_network_location + + +def _network_location_override() -> int | None: + try: + from openpilot.common.params import Params + value = Params().get("VagNetworkLocation") + except Exception: + return None + try: + return None if value is None else int(value) + except (TypeError, ValueError): + return None + class CarInterface(CarInterfaceBase): CarState = CarState @@ -17,6 +30,7 @@ class CarInterface(CarInterfaceBase): def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: ret.brand = "volkswagen" ret.radarUnavailable = Bus.radar not in DBC[candidate] + network_location_override = _network_location_override() if ret.flags & VolkswagenFlags.PQ: # Set global PQ35/PQ46/NMS parameters @@ -33,6 +47,7 @@ class CarInterface(CarInterfaceBase): ret.networkLocation = NetworkLocation.gateway else: ret.networkLocation = NetworkLocation.fwdCamera + ret.networkLocation = resolve_network_location(ret.networkLocation, network_location_override) ret.dashcamOnly = is_release # Release support needs HCA timeout fix, safety validation @@ -41,7 +56,7 @@ class CarInterface(CarInterfaceBase): safety_configs = [get_safety_config(structs.CarParams.SafetyModel.volkswagenMlb)] if 0x30F in fingerprint[0]: # SWA_01 ret.flags |= VolkswagenFlags.HAS_BSM.value - ret.networkLocation = NetworkLocation.gateway + ret.networkLocation = resolve_network_location(NetworkLocation.gateway, network_location_override) ret.dashcamOnly = is_release # Release support needs HCA timeout fix, safety validation, revised J533 harness elif ret.flags & VolkswagenFlags.MEB: @@ -65,7 +80,8 @@ class CarInterface(CarInterfaceBase): ret.networkLocation = NetworkLocation.gateway else: ret.networkLocation = NetworkLocation.fwdCamera - ret.radarUnavailable = True + ret.networkLocation = resolve_network_location(ret.networkLocation, network_location_override) + ret.radarUnavailable = ret.networkLocation == NetworkLocation.fwdCamera or Bus.radar not in DBC[candidate] if 0x24C in fingerprint[0]: # MEB_Side_Assist_01 ret.flags |= VolkswagenFlags.HAS_BSM.value @@ -95,6 +111,7 @@ class CarInterface(CarInterfaceBase): ret.networkLocation = NetworkLocation.gateway else: ret.networkLocation = NetworkLocation.fwdCamera + ret.networkLocation = resolve_network_location(ret.networkLocation, network_location_override) if 0x126 in fingerprint[2]: # HCA_01 ret.flags |= VolkswagenFlags.STOCK_HCA_PRESENT.value diff --git a/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py b/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py index 45293ad39..8d5cb0829 100644 --- a/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py +++ b/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py @@ -5,7 +5,7 @@ import unittest from opendbc.car import DT_CTRL from opendbc.car.structs import CarParams from opendbc.car.volkswagen.carcontroller import HCAMitigation -from opendbc.car.volkswagen.values import CAR, CarControllerParams as CCP, FW_QUERY_CONFIG, WMI +from opendbc.car.volkswagen.values import CAR, CarControllerParams as CCP, FW_QUERY_CONFIG, NetworkLocation, WMI, resolve_network_location from opendbc.car.volkswagen.fingerprints import FW_VERSIONS Ecu = CarParams.Ecu @@ -29,6 +29,20 @@ class TestVolkswagenHCAMitigation(unittest.TestCase): expected_torque = actuator_value - (1, -1)[actuator_value < 0] if should_nudge else actuator_value assert hca_mitigation.update(actuator_value, actuator_value) == expected_torque, f"{frame=}" +class TestVolkswagenNetworkLocationOverride(unittest.TestCase): + def test_override(self): + assert resolve_network_location(NetworkLocation.gateway, 0) == NetworkLocation.gateway + assert resolve_network_location(NetworkLocation.gateway, 1) == NetworkLocation.fwdCamera + assert resolve_network_location(NetworkLocation.fwdCamera, 0) == NetworkLocation.gateway + assert resolve_network_location(NetworkLocation.fwdCamera, 1) == NetworkLocation.fwdCamera + + def test_auto_and_invalid_values_preserve_detection(self): + assert resolve_network_location(NetworkLocation.gateway, None) == NetworkLocation.gateway + assert resolve_network_location(NetworkLocation.fwdCamera, None) == NetworkLocation.fwdCamera + assert resolve_network_location(NetworkLocation.gateway, 2) == NetworkLocation.gateway + assert resolve_network_location(NetworkLocation.fwdCamera, -1) == NetworkLocation.fwdCamera + + class TestVolkswagenPlatformConfigs(unittest.TestCase): def test_spare_part_fw_pattern(self): # Relied on for determining if a FW is likely VW diff --git a/opendbc_repo/opendbc/car/volkswagen/values.py b/opendbc_repo/opendbc/car/volkswagen/values.py index 38ab0cdf5..525e11176 100644 --- a/opendbc_repo/opendbc/car/volkswagen/values.py +++ b/opendbc_repo/opendbc/car/volkswagen/values.py @@ -13,6 +13,19 @@ from opendbc.car.vin import Vin Ecu = structs.CarParams.Ecu NetworkLocation = structs.CarParams.NetworkLocation TransmissionType = structs.CarParams.TransmissionType + +VAG_NETWORK_LOCATION_GATEWAY = 0 +VAG_NETWORK_LOCATION_CAMERA = 1 + + +def resolve_network_location(default: NetworkLocation, override: int | None) -> NetworkLocation: + if override == VAG_NETWORK_LOCATION_GATEWAY: + return NetworkLocation.gateway + if override == VAG_NETWORK_LOCATION_CAMERA: + return NetworkLocation.fwdCamera + return default + + GearShifter = structs.CarState.GearShifter Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values']) diff --git a/openpilot/common/libparams_c.so b/openpilot/common/libparams_c.so index d48723050..18fc01036 100755 Binary files a/openpilot/common/libparams_c.so and b/openpilot/common/libparams_c.so differ diff --git a/openpilot/common/params_keys.h b/openpilot/common/params_keys.h index 302d83472..dcba232b7 100644 --- a/openpilot/common/params_keys.h +++ b/openpilot/common/params_keys.h @@ -236,6 +236,7 @@ inline static std::unordered_map keys = { {"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}}, {"ToyotaAftermarketBsm", {PERSISTENT | BACKUP, BOOL, "0"}}, {"VagAvoidEPSLockout", {PERSISTENT | BACKUP, BOOL, "0"}}, + {"VagNetworkLocation", {PERSISTENT | BACKUP, INT, "0"}}, {"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}}, diff --git a/openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py b/openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py index 21a38fbbf..123d87bdd 100644 --- a/openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +++ b/openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py @@ -7,13 +7,16 @@ 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 +from openpilot.system.ui.sunnypilot.widgets.list_view import multiple_button_item_sp, toggle_item_sp DESCRIPTIONS = { 'avoid_eps_lockout': tr_noop( 'Scale steering torque down at low speeds to avoid EPS lockout.' - ) + ), + 'network_location': tr_noop( + 'Choose whether the J533 harness is connected at the vehicle gateway or front camera. Changing this restarts the car interface.' + ), } @@ -29,7 +32,16 @@ class VolkswagenSettings(BrandSettings): enabled=lambda: not ui_state.engaged, ) + self.network_location = multiple_button_item_sp( + lambda: tr("Volkswagen Connection"), + lambda: tr(DESCRIPTIONS["network_location"]), + [lambda: tr("Gateway"), lambda: tr("Camera")], + callback=self._on_network_location_changed, + inline=False, + ) + self.items = [ + self.network_location, self.avoid_eps_lockout, ] @@ -37,5 +49,17 @@ class VolkswagenSettings(BrandSettings): ui_state.params.put_bool("VagAvoidEPSLockout", state, block=True) ui_state.params.put_bool("OnroadCycleRequested", True) + def _on_network_location_changed(self, index: int): + if index not in (0, 1): + return + ui_state.params.put("VagNetworkLocation", index, block=True) + ui_state.params.put_bool("OnroadCycleRequested", True) + def update_settings(self): - pass + value = ui_state.params.get("VagNetworkLocation") + try: + index = 0 if value is None else int(value) + except (TypeError, ValueError): + index = 0 + self.network_location.action_item.set_selected_button(index if index in (0, 1) else 0) + self.network_location.action_item.set_enabled(ui_state.is_offroad()) diff --git a/openpilot/selfdrive/ui/translations/app.pot b/openpilot/selfdrive/ui/translations/app.pot index 7f2ed0931..b97ca5354 100644 --- a/openpilot/selfdrive/ui/translations/app.pot +++ b/openpilot/selfdrive/ui/translations/app.pot @@ -665,6 +665,7 @@ msgid "Reset Calibration" msgstr "" #: openpilot/selfdrive/ui/layouts/settings/device.py +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py msgid "RESET" msgstr "" @@ -935,6 +936,10 @@ msgstr "" msgid "Enable Always Offroad" msgstr "" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py +msgid "Reset Settings" +msgstr "" + #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/platform_selector.py msgid "Confirm" @@ -966,11 +971,6 @@ msgstr "" msgid "Training Guide" msgstr "" - -#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py -msgid "Reset Settings" -msgstr "" - #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py msgid "Are you sure you want to reset all sunnypilot settings to default? Once the settings are reset, there is no going back." msgstr "" @@ -1521,8 +1521,6 @@ msgstr "" msgid "Show Advanced Controls" msgstr "" - - #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/developer.py msgid "copyparty Service" msgstr "" @@ -2025,10 +2023,26 @@ msgstr "" msgid "Scale steering torque down at low speeds to avoid EPS lockout." msgstr "" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Choose whether the J533 harness is connected at the vehicle gateway or front camera. Changing this restarts the car interface." +msgstr "" + #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py msgid "Avoid EPS Lockout" msgstr "" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Volkswagen Connection" +msgstr "" + +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Gateway" +msgstr "" + +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Camera" +msgstr "" + #: openpilot/selfdrive/ui/sunnypilot/onroad/speed_limit.py msgid "Near" msgstr "" diff --git a/openpilot/selfdrive/ui/translations/app_en.po b/openpilot/selfdrive/ui/translations/app_en.po index 9e8a5031f..ae3e34692 100644 --- a/openpilot/selfdrive/ui/translations/app_en.po +++ b/openpilot/selfdrive/ui/translations/app_en.po @@ -328,6 +328,10 @@ msgstr "" msgid "Calibration in Progress" msgstr "" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Camera" +msgstr "Camera" + #: openpilot/selfdrive/selfdrived/events.py msgid "Camera Frame Rate Low" msgstr "" @@ -413,6 +417,10 @@ msgstr "" msgid "Choose how Automatic Lane Centering (ALC) behaves after the brake pedal is manually pressed in sunnypilot." msgstr "" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Choose whether the J533 harness is connected at the vehicle gateway or front camera. Changing this restarts the car interface." +msgstr "Choose whether the J533 harness is connected at the vehicle gateway or front camera. Changing this restarts the car interface." + #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/models.py msgid "Clear Cache" msgstr "" @@ -804,7 +812,6 @@ msgstr "" msgid "Enable your car's LKAS to engage" msgstr "" - #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/toyota.py msgid "Enforce Factory Longitudinal Control" msgstr "" @@ -932,6 +939,10 @@ msgstr "" msgid "GOOD" msgstr "GOOD" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Gateway" +msgstr "Gateway" + #: openpilot/selfdrive/selfdrived/events.py msgid "Gear not D" msgstr "" @@ -940,7 +951,6 @@ msgstr "" msgid "Getting the big model ready." msgstr "" - #: openpilot/selfdrive/ui/widgets/pairing_dialog.py msgid "Go to https://connect.comma.ai on your phone" msgstr "Go to https://connect.comma.ai on your phone" @@ -1295,7 +1305,6 @@ msgstr "" msgid "Onroad Brightness Delay" msgstr "" - #: openpilot/selfdrive/ui/widgets/setup.py msgid "Open" msgstr "Open" @@ -1468,6 +1477,7 @@ msgid "REMOVE" msgstr "REMOVE" #: openpilot/selfdrive/ui/layouts/settings/device.py +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py msgid "RESET" msgstr "RESET" @@ -2134,6 +2144,10 @@ msgstr "" msgid "Visuals" msgstr "" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Volkswagen Connection" +msgstr "Volkswagen Connection" + #: openpilot/selfdrive/selfdrived/events.py msgid "WARNING: This branch is not tested" msgstr "" diff --git a/openpilot/selfdrive/ui/translations/app_zh-CHS.po b/openpilot/selfdrive/ui/translations/app_zh-CHS.po index 02b6ca36c..7d16f50d6 100644 --- a/openpilot/selfdrive/ui/translations/app_zh-CHS.po +++ b/openpilot/selfdrive/ui/translations/app_zh-CHS.po @@ -328,6 +328,10 @@ msgstr "标定无效:请重新安装设备并重新标定" msgid "Calibration in Progress" msgstr "标定进行中" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Camera" +msgstr "相机接入" + #: openpilot/selfdrive/selfdrived/events.py msgid "Camera Frame Rate Low" msgstr "摄像头帧率过低" @@ -413,6 +417,10 @@ msgstr "如果车辆已通电,更改此设置将重启 sunnypilot。" msgid "Choose how Automatic Lane Centering (ALC) behaves after the brake pedal is manually pressed in sunnypilot." msgstr "选择在 sunnypilot 中手动踩下刹车踏板后自动车道居中(ALC)的行为。" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Choose whether the J533 harness is connected at the vehicle gateway or front camera. Changing this restarts the car interface." +msgstr "选择 J533 线束连接在车辆网关还是前视相机。切换后会重启车辆接口。" + #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/models.py msgid "Clear Cache" msgstr "清除缓存" @@ -806,7 +814,6 @@ msgstr "启用此项以强制 sunnypilot 使用扭矩横向控制转向。" msgid "Enable your car's LKAS to engage" msgstr "请开启车辆的 LKAS 以启用" - #: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/toyota.py msgid "Enforce Factory Longitudinal Control" msgstr "强制使用原厂纵向控制" @@ -934,6 +941,10 @@ msgstr "摩擦" msgid "GOOD" msgstr "良好" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Gateway" +msgstr "网关接入" + #: openpilot/selfdrive/selfdrived/events.py msgid "Gear not D" msgstr "挡位不在 D 挡" @@ -942,7 +953,6 @@ msgstr "挡位不在 D 挡" msgid "Getting the big model ready." msgstr "正在准备大模型。" - #: openpilot/selfdrive/ui/widgets/pairing_dialog.py msgid "Go to https://connect.comma.ai on your phone" msgstr "在手机上前往 https://connect.comma.ai" @@ -1297,7 +1307,6 @@ msgstr "行车亮度" msgid "Onroad Brightness Delay" msgstr "行车亮度延迟" - #: openpilot/selfdrive/ui/widgets/setup.py msgid "Open" msgstr "打开" @@ -1470,6 +1479,7 @@ msgid "REMOVE" msgstr "移除" #: openpilot/selfdrive/ui/layouts/settings/device.py +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/device.py msgid "RESET" msgstr "重置" @@ -2139,6 +2149,10 @@ msgstr "虚拟移动摄像头视角,将模型中心向左(+值)或向右 msgid "Visuals" msgstr "视觉" +#: openpilot/selfdrive/ui/sunnypilot/layouts/settings/vehicle/brands/volkswagen.py +msgid "Volkswagen Connection" +msgstr "大众接入方式" + #: openpilot/selfdrive/selfdrived/events.py msgid "WARNING: This branch is not tested" msgstr "警告:此分支未经测试"