diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 458312fc8..03ba8b0b6 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,5 +4,8 @@ "ms-vscode.cpptools", "elagil.pre-commit-helper", "charliermarsh.ruff", + "JamiTech.simply-blame", + "k--kato.intellij-idea-keybindings", + "trinm1709.dracula-theme-from-intellij" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index f0731c362..c62cc3df5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,10 +3,25 @@ "editor.insertSpaces": true, "editor.renderWhitespace": "trailing", "files.trimTrailingWhitespace": true, + "terminal.integrated.defaultProfile.linux": "dragonpilot", + "terminal.integrated.profiles.linux": { + "dragonpilot": { + "path": "bash", + "args": ["-c", "distrobox enter dp"] + } + }, "search.exclude": { "**/.git": true, "**/.venv": true, - "**/__pycache__": true + "**/__pycache__": true, + "msgq_repo/": true, + "opendbc/": true, + "rednose/": true, + "rednose_repo/": true, + "openpilot/": true, + "teleoprtc_repo/": true, + "tinygrad/": true, + "tinygrad_repo/": true }, "files.exclude": { "**/.git": true, diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..abeb9f075 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,30 @@ +Copyright (c) 2019, Rick Lan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sublicense, +for non-commercial purposes only, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +- Commercial use (e.g. use in a product, service, or activity intended to + generate revenue) is prohibited without explicit written permission from + the copyright holder. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- +Copyright (c) 2018, Comma.ai, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/common/params_keys.h b/common/params_keys.h index c54600462..3167df8b1 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -28,7 +28,7 @@ inline static std::unordered_map keys = { {"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, {"CurrentBootlog", {PERSISTENT, STRING}}, {"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}}, - {"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"DisableLogging", {PERSISTENT, BOOL, "0"}}, {"DisablePowerDown", {PERSISTENT, BOOL}}, {"DisableUpdates", {PERSISTENT, BOOL}}, {"DisengageOnAccelerator", {PERSISTENT, BOOL, "0"}}, @@ -129,4 +129,6 @@ inline static std::unordered_map keys = { {"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}}, {"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}}, {"Version", {PERSISTENT, STRING}}, + {"dp_device_last_log", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, + {"dp_device_reset_conf", {CLEAR_ON_MANAGER_START, BOOL}}, }; diff --git a/dragonpilot/.gitignore b/dragonpilot/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/dragonpilot/selfdrive/assets/.gitignore b/dragonpilot/selfdrive/assets/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/dragonpilot/selfdrive/assets/dragonpilot.png b/dragonpilot/selfdrive/assets/dragonpilot.png new file mode 100644 index 000000000..1001f1942 Binary files /dev/null and b/dragonpilot/selfdrive/assets/dragonpilot.png differ diff --git a/dragonpilot/selfdrive/assets/icons/icon_empty.svg b/dragonpilot/selfdrive/assets/icons/icon_empty.svg new file mode 100644 index 000000000..2f73de52a --- /dev/null +++ b/dragonpilot/selfdrive/assets/icons/icon_empty.svg @@ -0,0 +1,35 @@ + + + + + diff --git a/dragonpilot/selfdrive/assets/icons/icon_minus.png b/dragonpilot/selfdrive/assets/icons/icon_minus.png new file mode 100644 index 000000000..e5327c0d3 Binary files /dev/null and b/dragonpilot/selfdrive/assets/icons/icon_minus.png differ diff --git a/dragonpilot/selfdrive/assets/icons/icon_plus.png b/dragonpilot/selfdrive/assets/icons/icon_plus.png new file mode 100644 index 000000000..92b448b0b Binary files /dev/null and b/dragonpilot/selfdrive/assets/icons/icon_plus.png differ diff --git a/dragonpilot/selfdrive/assets/images/spinner_comma.png b/dragonpilot/selfdrive/assets/images/spinner_comma.png new file mode 100644 index 000000000..aa90a78c4 Binary files /dev/null and b/dragonpilot/selfdrive/assets/images/spinner_comma.png differ diff --git a/dragonpilot/selfdrive/assets/offroad/icon_plus.png b/dragonpilot/selfdrive/assets/offroad/icon_plus.png new file mode 100644 index 000000000..92b448b0b Binary files /dev/null and b/dragonpilot/selfdrive/assets/offroad/icon_plus.png differ diff --git a/dragonpilot/selfdrive/controls/.gitignore b/dragonpilot/selfdrive/controls/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/dragonpilot/selfdrive/controls/lib/.gitignore b/dragonpilot/selfdrive/controls/lib/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/dragonpilot/selfdrive/ui/.gitignore b/dragonpilot/selfdrive/ui/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/opendbc_repo/opendbc/car/body/interface.py b/opendbc_repo/opendbc/car/body/interface.py index 24e571ee9..daa9dc055 100644 --- a/opendbc_repo/opendbc/car/body/interface.py +++ b/opendbc_repo/opendbc/car/body/interface.py @@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.notCar = True ret.brand = "body" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.body)] diff --git a/opendbc_repo/opendbc/car/car_helpers.py b/opendbc_repo/opendbc/car/car_helpers.py index dfda01552..eaa6a2fc5 100644 --- a/opendbc_repo/opendbc/car/car_helpers.py +++ b/opendbc_repo/opendbc/car/car_helpers.py @@ -149,7 +149,7 @@ def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_mu def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, alpha_long_allowed: bool, - is_release: bool, num_pandas: int = 1, cached_params: CarParamsT | None = None): + is_release: bool, num_pandas: int = 1, dp_params: int = 0, cached_params: CarParamsT | None = None): candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params) if candidate is None: @@ -157,7 +157,7 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip candidate = "MOCK" CarInterface = interfaces[candidate] - CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, docs=False) + CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, dp_params, docs=False) CP.carVin = vin CP.carFw = car_fw CP.fingerprintSource = source diff --git a/opendbc_repo/opendbc/car/chrysler/interface.py b/opendbc_repo/opendbc/car/chrysler/interface.py index 0be2ccacb..d69f192d2 100755 --- a/opendbc_repo/opendbc/car/chrysler/interface.py +++ b/opendbc_repo/opendbc/car/chrysler/interface.py @@ -13,7 +13,7 @@ class CarInterface(CarInterfaceBase): RadarInterface = RadarInterface @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "chrysler" ret.dashcamOnly = candidate in RAM_HD diff --git a/opendbc_repo/opendbc/car/docs.py b/opendbc_repo/opendbc/car/docs.py index 901b889d5..a66a08166 100755 --- a/opendbc_repo/opendbc/car/docs.py +++ b/opendbc_repo/opendbc/car/docs.py @@ -32,7 +32,7 @@ def get_params_for_docs(platform) -> CarParams: cp_platform = platform if platform in interfaces else MOCK.MOCK CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(), car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)], - alpha_long=True, is_release=False, docs=True) + alpha_long=True, is_release=False, dp_params=0, docs=True) return CP diff --git a/opendbc_repo/opendbc/car/ford/interface.py b/opendbc_repo/opendbc/car/ford/interface.py index 97685df58..9d3872e0b 100644 --- a/opendbc_repo/opendbc/car/ford/interface.py +++ b/opendbc_repo/opendbc/car/ford/interface.py @@ -26,7 +26,7 @@ class CarInterface(CarInterfaceBase): return CarControllerParams.ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS) @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "ford" ret.radarUnavailable = Bus.radar not in DBC[candidate] diff --git a/opendbc_repo/opendbc/car/gm/interface.py b/opendbc_repo/opendbc/car/gm/interface.py index 3e731b6b0..5885b8285 100755 --- a/opendbc_repo/opendbc/car/gm/interface.py +++ b/opendbc_repo/opendbc/car/gm/interface.py @@ -82,7 +82,7 @@ class CarInterface(CarInterfaceBase): return self.torque_from_lateral_accel_linear @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "gm" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.gm)] ret.autoResumeSng = False diff --git a/opendbc_repo/opendbc/car/honda/interface.py b/opendbc_repo/opendbc/car/honda/interface.py index 10d52f246..90844cef7 100755 --- a/opendbc_repo/opendbc/car/honda/interface.py +++ b/opendbc_repo/opendbc/car/honda/interface.py @@ -31,7 +31,7 @@ class CarInterface(CarInterfaceBase): return CarControllerParams.NIDEC_ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS) @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "honda" CAN = CanBus(ret, fingerprint) diff --git a/opendbc_repo/opendbc/car/hyundai/interface.py b/opendbc_repo/opendbc/car/hyundai/interface.py index 1e058c4fc..3744450ab 100644 --- a/opendbc_repo/opendbc/car/hyundai/interface.py +++ b/opendbc_repo/opendbc/car/hyundai/interface.py @@ -23,7 +23,7 @@ class CarInterface(CarInterfaceBase): RadarInterface = RadarInterface @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "hyundai" # "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera. diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index b798acaa1..4f3a20c60 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -51,7 +51,7 @@ class TestHyundaiFingerprint: if lka_steering: cam_can = CanBus(None, fingerprint).CAM fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages - CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False) + CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, 0, False) assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering # radar available @@ -59,14 +59,14 @@ class TestHyundaiFingerprint: fingerprint = gen_empty_fingerprint() if radar: fingerprint[1][RADAR_START_ADDR] = 8 - CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False) + CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, 0, False) assert CP.radarUnavailable != radar def test_alternate_limits(self): # Alternate lateral control limits, for high torque cars, verify Panda safety mode flag is set fingerprint = gen_empty_fingerprint() for car_model in CAR: - CP = CarInterface.get_params(car_model, fingerprint, [], False, False, False) + CP = CarInterface.get_params(car_model, fingerprint, [], False, False, 0, False) assert bool(CP.flags & HyundaiFlags.ALT_LIMITS) == bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.ALT_LIMITS) def test_can_features(self): diff --git a/opendbc_repo/opendbc/car/interfaces.py b/opendbc_repo/opendbc/car/interfaces.py index d3bc08134..756aad316 100644 --- a/opendbc_repo/opendbc/car/interfaces.py +++ b/opendbc_repo/opendbc/car/interfaces.py @@ -130,11 +130,11 @@ class CarInterfaceBase(ABC): """ Parameters essential to controlling the car may be incomplete or wrong without FW versions or fingerprints. """ - return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False, False) + return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False, 0, False) @classmethod def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[structs.CarParams.CarFw], - alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams: + alpha_long: bool, is_release: bool, dp_params: int, docs: bool) -> structs.CarParams: ret = CarInterfaceBase.get_std_params(candidate) platform = PLATFORMS[candidate] @@ -147,7 +147,7 @@ class CarInterfaceBase(ABC): ret.tireStiffnessFactor = platform.config.specs.tireStiffnessFactor ret.flags |= int(platform.config.flags) - ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, is_release, docs) + ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) # Vehicle mass is published curb weight plus assumed payload such as a human driver; notCars have no assumed payload if not ret.notCar: @@ -162,7 +162,7 @@ class CarInterfaceBase(ABC): @staticmethod @abstractmethod def _get_params(ret: structs.CarParams, candidate, fingerprint: dict[int, dict[int, int]], - car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams: + car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release: bool, dp_params: int, docs: bool) -> structs.CarParams: raise NotImplementedError @staticmethod diff --git a/opendbc_repo/opendbc/car/mazda/interface.py b/opendbc_repo/opendbc/car/mazda/interface.py index 814846e85..1381e47b1 100755 --- a/opendbc_repo/opendbc/car/mazda/interface.py +++ b/opendbc_repo/opendbc/car/mazda/interface.py @@ -12,7 +12,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "mazda" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.mazda)] ret.radarUnavailable = True diff --git a/opendbc_repo/opendbc/car/mock/interface.py b/opendbc_repo/opendbc/car/mock/interface.py index 3bcc2f8f1..3b6d50159 100755 --- a/opendbc_repo/opendbc/car/mock/interface.py +++ b/opendbc_repo/opendbc/car/mock/interface.py @@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "mock" ret.mass = 1700. ret.wheelbase = 2.70 diff --git a/opendbc_repo/opendbc/car/nissan/interface.py b/opendbc_repo/opendbc/car/nissan/interface.py index bac7b3f1a..f4ca54fa2 100644 --- a/opendbc_repo/opendbc/car/nissan/interface.py +++ b/opendbc_repo/opendbc/car/nissan/interface.py @@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "nissan" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.nissan)] ret.autoResumeSng = False diff --git a/opendbc_repo/opendbc/car/psa/interface.py b/opendbc_repo/opendbc/car/psa/interface.py index f719a3d6a..d644b3406 100644 --- a/opendbc_repo/opendbc/car/psa/interface.py +++ b/opendbc_repo/opendbc/car/psa/interface.py @@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = 'psa' ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.psa)] diff --git a/opendbc_repo/opendbc/car/rivian/interface.py b/opendbc_repo/opendbc/car/rivian/interface.py index f1108e081..2731627f9 100644 --- a/opendbc_repo/opendbc/car/rivian/interface.py +++ b/opendbc_repo/opendbc/car/rivian/interface.py @@ -12,7 +12,7 @@ class CarInterface(CarInterfaceBase): RadarInterface = RadarInterface @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "rivian" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.rivian)] diff --git a/opendbc_repo/opendbc/car/structs.py b/opendbc_repo/opendbc/car/structs.py index a5628c7e0..0959d5c75 100644 --- a/opendbc_repo/opendbc/car/structs.py +++ b/opendbc_repo/opendbc/car/structs.py @@ -18,3 +18,6 @@ CarStateT = capnp.lib.capnp._StructModule RadarDataT = capnp.lib.capnp._StructModule CarControlT = capnp.lib.capnp._StructModule CarParamsT = capnp.lib.capnp._StructModule + +class DPFlags: + pass diff --git a/opendbc_repo/opendbc/car/subaru/interface.py b/opendbc_repo/opendbc/car/subaru/interface.py index b11a987d5..09b9b3a91 100644 --- a/opendbc_repo/opendbc/car/subaru/interface.py +++ b/opendbc_repo/opendbc/car/subaru/interface.py @@ -11,7 +11,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "subaru" ret.radarUnavailable = True # for HYBRID CARS to be upstreamed, we need: diff --git a/opendbc_repo/opendbc/car/tesla/interface.py b/opendbc_repo/opendbc/car/tesla/interface.py index baf159323..2019f7cf4 100644 --- a/opendbc_repo/opendbc/car/tesla/interface.py +++ b/opendbc_repo/opendbc/car/tesla/interface.py @@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "tesla" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.tesla)] diff --git a/opendbc_repo/opendbc/car/tests/test_car_interfaces.py b/opendbc_repo/opendbc/car/tests/test_car_interfaces.py index ae67788de..9b83e7010 100644 --- a/opendbc_repo/opendbc/car/tests/test_car_interfaces.py +++ b/opendbc_repo/opendbc/car/tests/test_car_interfaces.py @@ -64,7 +64,7 @@ class TestCarInterfaces: args = get_fuzzy_car_interface_args(data.draw) car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'], - alpha_long=args['alpha_long'], is_release=False, docs=False) + alpha_long=args['alpha_long'], is_release=False, dp_params=0, docs=False) car_interface = CarInterface(car_params) assert car_params assert car_interface diff --git a/opendbc_repo/opendbc/car/toyota/interface.py b/opendbc_repo/opendbc/car/toyota/interface.py index b8ee8c946..dae5c509b 100644 --- a/opendbc_repo/opendbc/car/toyota/interface.py +++ b/opendbc_repo/opendbc/car/toyota/interface.py @@ -21,7 +21,7 @@ class CarInterface(CarInterfaceBase): return CarControllerParams(CP).ACCEL_MIN, CarControllerParams(CP).ACCEL_MAX @staticmethod - def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "toyota" ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.toyota)] ret.safetyConfigs[0].safetyParam = EPS_SCALE[candidate] diff --git a/opendbc_repo/opendbc/car/volkswagen/interface.py b/opendbc_repo/opendbc/car/volkswagen/interface.py index 4c40f8740..61dd79719 100644 --- a/opendbc_repo/opendbc/car/volkswagen/interface.py +++ b/opendbc_repo/opendbc/car/volkswagen/interface.py @@ -10,7 +10,7 @@ class CarInterface(CarInterfaceBase): CarController = CarController @staticmethod - def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, dp_params, docs) -> structs.CarParams: ret.brand = "volkswagen" ret.radarUnavailable = True diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 27b04ae65..00be61362 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -82,6 +82,8 @@ class Car: is_release = self.params.get_bool("IsReleaseBranch") + dp_params = 0 + if CI is None: # wait for one pandaState and one CAN packet print("Waiting for CAN messages...") @@ -99,7 +101,7 @@ class Car: with car.CarParams.from_bytes(cached_params_raw) as _cached_params: cached_params = _cached_params - self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, cached_params) + self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, dp_params, cached_params) self.RI = interfaces[self.CI.CP.carFingerprint].RadarInterface(self.CI.CP) self.CP = self.CI.CP diff --git a/selfdrive/car/cruise.py b/selfdrive/car/cruise.py index 0d761844b..0474a7a77 100644 --- a/selfdrive/car/cruise.py +++ b/selfdrive/car/cruise.py @@ -12,7 +12,7 @@ V_CRUISE_MIN = 8 V_CRUISE_MAX = 145 V_CRUISE_UNSET = 255 V_CRUISE_INITIAL = 40 -V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 105 +V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 50 IMPERIAL_INCREMENT = round(CV.MPH_TO_KPH, 1) # round here to avoid rounding errors incrementing set speed ButtonEvent = car.CarState.ButtonEvent diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 5c4729ee9..50717ef04 100644 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -39,7 +39,7 @@ class TestCarInterfaces: args = get_fuzzy_car_interface_args(data.draw) car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'], - alpha_long=args['alpha_long'], is_release=False, docs=False) + alpha_long=args['alpha_long'], is_release=False, dp_params=0, docs=False) car_params = car_params.as_reader() car_interface = CarInterface(car_params) assert car_params diff --git a/selfdrive/car/tests/test_models.py b/selfdrive/car/tests/test_models.py index 8996ad646..49532f51b 100644 --- a/selfdrive/car/tests/test_models.py +++ b/selfdrive/car/tests/test_models.py @@ -149,7 +149,7 @@ class TestCarModelBase(unittest.TestCase): cls.openpilot_enabled = cls.car_safety_mode_frame is not None cls.CarInterface = interfaces[cls.platform] - cls.CP = cls.CarInterface.get_params(cls.platform, cls.fingerprint, car_fw, alpha_long, False, docs=False) + cls.CP = cls.CarInterface.get_params(cls.platform, cls.fingerprint, car_fw, alpha_long, False, dp_params=0, docs=False) assert cls.CP assert cls.CP.carFingerprint == cls.platform diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 34fc85f8a..94b63290c 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -26,6 +26,8 @@ MIN_ALLOW_THROTTLE_SPEED = 2.5 _A_TOTAL_MAX_V = [1.7, 3.2] _A_TOTAL_MAX_BP = [20., 40.] +class DPFlags: + pass def get_max_accel(v_ego): return np.interp(v_ego, A_CRUISE_MAX_BP, A_CRUISE_MAX_VALS) @@ -89,7 +91,7 @@ class LongitudinalPlanner: throttle_prob = 1.0 return x, v, a, j, throttle_prob - def update(self, sm): + def update(self, sm, dp_flags = 0): mode = 'blended' if sm['selfdriveState'].experimentalMode else 'acc' if len(sm['carControl'].orientationNED) == 3: diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index bec7eede0..dc3d5d231 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -4,7 +4,7 @@ from openpilot.common.params import Params from openpilot.common.realtime import Priority, config_realtime_process from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.controls.lib.ldw import LaneDepartureWarning -from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner +from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner, DPFlags import cereal.messaging as messaging @@ -22,10 +22,12 @@ def main(): sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState'], poll='modelV2') + dp_flags = 0 + while True: sm.update() if sm.updated['modelV2']: - longitudinal_planner.update(sm) + longitudinal_planner.update(sm, dp_flags) longitudinal_planner.publish(sm, pm) ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl']) diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index cf22040e8..d783b2b67 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -130,7 +130,7 @@ class SelfdriveD: self.ignored_processes = {'loggerd', } # Determine startup event - self.startup_event = EventName.startup if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster + self.startup_event = EventName.startup #if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster if not car_recognized: self.startup_event = EventName.startupNoCar elif car_recognized and self.CP.passive: diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index ba9fa8b7a..751e7a032 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -27,7 +27,7 @@ qt_libs = [widgets, qt_util] + base_libs qt_src = ["main.cc", "ui.cc", "qt/sidebar.cc", "qt/body.cc", "qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc", - "qt/offroad/software_settings.cc", "qt/offroad/developer_panel.cc", "qt/offroad/onboarding.cc", + "qt/offroad/software_settings.cc", "qt/offroad/developer_panel.cc", "qt/offroad/onboarding.cc", "qt/offroad/dp_panel.cc", "qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc", "qt/offroad/firehose.cc", "qt/onroad/onroad_home.cc", "qt/onroad/annotated_camera.cc", "qt/onroad/model.cc", "qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc", "qt/onroad/hud.cc"] diff --git a/selfdrive/ui/qt/offroad/developer_panel.cc b/selfdrive/ui/qt/offroad/developer_panel.cc index a095228da..2f533f16b 100644 --- a/selfdrive/ui/qt/offroad/developer_panel.cc +++ b/selfdrive/ui/qt/offroad/developer_panel.cc @@ -45,6 +45,21 @@ DeveloperPanel::DeveloperPanel(SettingsWindow *parent) : ListWidget(parent) { // Toggles should be not available to change in onroad state QObject::connect(uiState(), &UIState::offroadTransition, this, &DeveloperPanel::updateToggles); + + // error logs + QPushButton* error_log_btn = new QPushButton(QObject::tr("Show Last Errors")); + error_log_btn->setObjectName("error_log_btn"); + + error_log_btn->setStyleSheet(R"( + #error_log_btn { height: 120px; border-radius: 15px; background-color: #393939; } + #error_log_btn:pressed { background-color: #4a4a4a; } + )"); + + addItem(error_log_btn); + + QObject::connect(error_log_btn, &QPushButton::clicked, [=]() { + ConfirmationDialog::rich(QString::fromStdString(params.get("dp_device_last_log")), parent); + }); } void DeveloperPanel::updateToggles(bool _offroad) { diff --git a/selfdrive/ui/qt/offroad/dp_panel.cc b/selfdrive/ui/qt/offroad/dp_panel.cc new file mode 100644 index 000000000..548b02be5 --- /dev/null +++ b/selfdrive/ui/qt/offroad/dp_panel.cc @@ -0,0 +1,295 @@ +#include "selfdrive/ui/qt/offroad/dp_panel.h" + +void DPPanel::add_toyota_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("Toyota / Lexus"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +void DPPanel::add_vag_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("VW / Audi / Skoda"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +void DPPanel::add_mazda_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("Mazda"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +void DPPanel::add_lateral_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("Lateral Ctrl"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +void DPPanel::add_longitudinal_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("Longitudinal Ctrl"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +void DPPanel::add_ui_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("UI"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +void DPPanel::add_device_toggles() { + std::vector> toggle_defs{ + { + "", + QString::fromUtf8("🐉 ") + tr("Device"), + "", + }, + }; + + QWidget *label = nullptr; + bool has_toggle = false; + + for (auto &[param, title, desc] : toggle_defs) { + if (param.isEmpty()) { + label = new LabelControl(title, ""); + addItem(label); + continue; + } + + has_toggle = true; + auto toggle = new ParamControl(param, title, desc, "", this); + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + // If no toggles were added, hide the label + if (!has_toggle && label) { + label->hide(); + } +} + +DPPanel::DPPanel(SettingsWindow *parent) : ListWidget(parent) { + auto cp_bytes = params.get("CarParamsPersistent"); + if (!cp_bytes.empty()) { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + cereal::CarParams::Reader CP = cmsg.getRoot(); + brand = QString::fromStdString(CP.getBrand()); + vehicle_has_long_ctrl = hasLongitudinalControl(CP); + vehicle_has_radar_unavailable = CP.getRadarUnavailable(); + } + + if (brand == "toyota") { + add_toyota_toggles(); + } else if (brand == "volkswagen") { + add_vag_toggles(); + } else if (brand == "mazda") { + add_mazda_toggles(); + } + add_lateral_toggles(); + add_longitudinal_toggles(); + add_ui_toggles(); + add_device_toggles(); + + auto resetBtn = new ButtonControl(tr("Reset dragonpilot settings"), tr("RESET")); + connect(resetBtn, &ButtonControl::clicked, [&]() { + if (ConfirmationDialog::confirm(tr("Are you sure you want to reset all settings?"), tr("Reset"), this)) { + params.putBool("dp_device_reset_conf", true); + } + }); + addItem(resetBtn); + + fs_watch = new ParamWatcher(this); + QObject::connect(fs_watch, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) { + updateStates(); + }); + + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + is_onroad = !offroad; + updateStates(); + }); + + updateStates(); +} + +void DPPanel::showEvent(QShowEvent *event) { + updateStates(); +} + +void DPPanel::updateStates() { + // do fs_watch here + + if (!isVisible()) { + return; + } + + // do state change logic here + +} + +void DPPanel::expandToggleDescription(const QString ¶m) { + toggles[param.toStdString()]->showDescription(); +} diff --git a/selfdrive/ui/qt/offroad/dp_panel.h b/selfdrive/ui/qt/offroad/dp_panel.h new file mode 100644 index 000000000..87095c73b --- /dev/null +++ b/selfdrive/ui/qt/offroad/dp_panel.h @@ -0,0 +1,31 @@ +#pragma once + +#include "selfdrive/ui/qt/offroad/settings.h" + +class DPPanel : public ListWidget { + Q_OBJECT +public: + explicit DPPanel(SettingsWindow *parent); + +public slots: + void expandToggleDescription(const QString ¶m); + +private: + Params params; + ParamWatcher *fs_watch; + std::map toggles; + QString brand; + bool is_onroad = false; + bool vehicle_has_long_ctrl; + bool vehicle_has_radar_unavailable; + + void add_toyota_toggles(); + void add_vag_toggles(); + void add_mazda_toggles(); + void add_lateral_toggles(); + void add_longitudinal_toggles(); + void add_ui_toggles(); + void add_device_toggles(); + void updateStates(); + void showEvent(QShowEvent *event) override; +}; diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 96734d69d..7f37241de 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -15,6 +15,7 @@ #include "selfdrive/ui/qt/widgets/scrollview.h" #include "selfdrive/ui/qt/offroad/developer_panel.h" #include "selfdrive/ui/qt/offroad/firehose.h" +#include "selfdrive/ui/qt/offroad/dp_panel.h" TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { // param, title, desc, icon, restart needed @@ -75,6 +76,20 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { "../assets/icons/metric.png", false, }, + { + "DisableLogging", + tr("Disable Logging"), + "", + "../assets/offroad/icon_empty.svg", + true, + }, + { + "DisableUpdates", + tr("Disable Updates"), + "", + "../assets/offroad/icon_empty.svg", + true, + }, }; @@ -278,13 +293,13 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { QObject::connect(uiState()->prime_state, &PrimeState::changed, [this] (PrimeState::Type type) { pair_device->setVisible(type == PrimeState::PRIME_TYPE_UNPAIRED); }); - QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { - for (auto btn : findChildren()) { - if (btn != pair_device && btn != resetCalibBtn) { - btn->setEnabled(offroad); - } - } - }); + // QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + // for (auto btn : findChildren()) { + // if (btn != pair_device && btn != resetCalibBtn) { + // btn->setEnabled(offroad); + // } + // } + // }); // power buttons QHBoxLayout *power_layout = new QHBoxLayout(); @@ -475,6 +490,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) { {tr("Software"), new SoftwarePanel(this)}, {tr("Firehose"), new FirehosePanel(this)}, {tr("Developer"), new DeveloperPanel(this)}, + {"DP", new DPPanel(this)}, }; nav_btns = new QButtonGroup(this); diff --git a/selfdrive/ui/qt/offroad/software_settings.cc b/selfdrive/ui/qt/offroad/software_settings.cc index 9bc3fad3c..43358ad72 100644 --- a/selfdrive/ui/qt/offroad/software_settings.cc +++ b/selfdrive/ui/qt/offroad/software_settings.cc @@ -50,6 +50,7 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) { addItem(installBtn); // branch selecting + /* targetBranchBtn = new ButtonControl(tr("Target Branch"), tr("SELECT")); connect(targetBranchBtn, &ButtonControl::clicked, [=]() { auto current = params.get("GitBranch"); @@ -73,6 +74,7 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) { if (!params.getBool("IsTestedBranch")) { addItem(targetBranchBtn); } + */ // uninstall button auto uninstallBtn = new ButtonControl(tr("Uninstall %1").arg(getBrand()), tr("UNINSTALL")); @@ -142,7 +144,7 @@ void SoftwarePanel::updateLabels() { } downloadBtn->setEnabled(true); } - targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch"))); +// targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch"))); // current + new versions versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription"))); diff --git a/selfdrive/ui/qt/onroad/buttons.cc b/selfdrive/ui/qt/onroad/buttons.cc index 32e58c9db..b4f9c68b1 100644 --- a/selfdrive/ui/qt/onroad/buttons.cc +++ b/selfdrive/ui/qt/onroad/buttons.cc @@ -19,7 +19,7 @@ void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrus ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(false), engageable(false), QPushButton(parent) { setFixedSize(btn_size, btn_size); - engage_img = loadPixmap("../assets/icons/chffr_wheel.png", {img_size, img_size}); + engage_img = loadPixmap("../../dragonpilot/selfdrive/assets/dragonpilot.png", {img_size, img_size}); experimental_img = loadPixmap("../assets/icons/experimental.svg", {img_size, img_size}); QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode); } diff --git a/selfdrive/ui/qt/sidebar.cc b/selfdrive/ui/qt/sidebar.cc index e9c6a2f7c..d29ac0998 100644 --- a/selfdrive/ui/qt/sidebar.cc +++ b/selfdrive/ui/qt/sidebar.cc @@ -25,7 +25,7 @@ void Sidebar::drawMetric(QPainter &p, const QPair &label, QCol } Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false), mic_indicator_pressed(false) { - home_img = loadPixmap("../assets/images/button_home.png", home_btn.size()); + home_img = loadPixmap("../../dragonpilot/selfdrive/assets/dragonpilot.png", home_btn.size()); flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size()); settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio); mic_img = loadPixmap("../assets/icons/microphone.png", QSize(30, 30)); diff --git a/selfdrive/ui/qt/util.cc b/selfdrive/ui/qt/util.cc index 493c20397..0a55b00f7 100644 --- a/selfdrive/ui/qt/util.cc +++ b/selfdrive/ui/qt/util.cc @@ -27,11 +27,11 @@ QString getVersion() { } QString getBrand() { - return QObject::tr("openpilot"); + return QObject::tr("dragonpilot"); } QString getUserAgent() { - return "openpilot-" + getVersion(); + return "dragonpilot-" + getVersion(); } std::optional getDongleId() { diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h index 3342de532..4158d7d4e 100644 --- a/selfdrive/ui/qt/widgets/controls.h +++ b/selfdrive/ui/qt/widgets/controls.h @@ -88,6 +88,10 @@ public: label.setText(text); label.setAlignment(Qt::AlignRight | Qt::AlignVCenter); hlayout->addWidget(&label); + if (text == "") { + setContentsMargins(0, 50, 0, 0); // 30px top margin, 10px bottom margin + // This will create space above and below the entire header control. + } } void setText(const QString &text) { label.setText(text); } @@ -317,3 +321,136 @@ public: setLayout(l); } }; + +#include +class SpinBoxControl : public AbstractControl { + Q_OBJECT + +public: + SpinBoxControl(const QString &title, const QString &desc = "", const QString &icon = "", const int val = 0, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) { + spinbox.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + spinbox.setAlignment(Qt::AlignCenter); + spinbox.setStyleSheet(R"( + QSpinBox { + width: 300px; + height: 80px; + padding: 0px; + border-radius:40px; + font-size: 36px; + } + QSpinBox::up-button { + subcontrol-origin: margin; + subcontrol-position: center right; + image: url(../../dragonpilot/selfdrive/assets/icons/icon_plus.png); + right: 1px; + height: 80px; + width: 80px; + } + QSpinBox::down-button { + subcontrol-origin: margin; + subcontrol-position: center left; + image: url(../../dragonpilot/selfdrive/assets/icons/icon_minus.png); + left: 1px; + height: 80px; + width: 80px; + } + )"); + + hlayout->addWidget(&spinbox); + QObject::connect(&spinbox, QOverload::of(&QSpinBox::valueChanged), this, &SpinBoxControl::valChanged); + } + +signals: + void valChanged(int val); + +protected: + QSpinBox spinbox; +}; + +class ParamSpinBoxControl : public SpinBoxControl { + Q_OBJECT + +public: + ParamSpinBoxControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, const int minimum = 0, const int maximum = 100, const int step = 1, const QString suffix = "", const QString minText = "", QWidget *parent = nullptr) : SpinBoxControl(title, desc, icon, 0, parent) { + spinbox.setRange(minimum, maximum); + spinbox.setSingleStep(step); + spinbox.setSuffix(suffix); + spinbox.setSpecialValueText(minText); + + std::string str_val = Params().get(param.toStdString().c_str()); + if (str_val != "") { + int val = std::stoi(str_val); + spinbox.setValue(val); + QObject::connect(this, &SpinBoxControl::valChanged, [=](int val) { + Params().put(param.toStdString(), std::to_string(val)); + }); + } + } +}; + +class DoubleSpinBoxControl : public AbstractControl { + Q_OBJECT + +public: + DoubleSpinBoxControl(const QString &title, const QString &desc = "", const QString &icon = "", const double val = 0.0, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) { + spinbox.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + spinbox.setAlignment(Qt::AlignCenter); + spinbox.setStyleSheet(R"( + QDoubleSpinBox { + width: 300px; + height: 80px; + padding: 0px; + border-radius:40px; + font-size: 36px; + } + QDoubleSpinBox::up-button { + subcontrol-origin: margin; + subcontrol-position: center right; + image: url(../../dragonpilot/selfdrive/assets/icons/icon_plus.png); + right: 1px; + height: 80px; + width: 80px; + } + QDoubleSpinBox::down-button { + subcontrol-origin: margin; + subcontrol-position: center left; + image: url(../../dragonpilot/selfdrive/assets/icons/icon_minus.png); + left: 1px; + height: 80px; + width: 80px; + } + )"); + + hlayout->addWidget(&spinbox); + QObject::connect(&spinbox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &DoubleSpinBoxControl::valChanged); + } + +signals: + void valChanged(double val); + +protected: + QDoubleSpinBox spinbox; +}; + +class ParamDoubleSpinBoxControl : public DoubleSpinBoxControl { + Q_OBJECT + +public: + ParamDoubleSpinBoxControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, const double minimum = 0.0, const double maximum = 100.0, const double step = 1.0, const QString suffix = "", const QString minText = "", QWidget *parent = nullptr) : DoubleSpinBoxControl(title, desc, icon, 0.0, parent) { + spinbox.setRange(minimum, maximum); + spinbox.setSingleStep(step); + spinbox.setSuffix(suffix); + spinbox.setSpecialValueText(minText); + + std::string str_val = Params().get(param.toStdString().c_str()); + if (str_val != "") { + double val = std::stod(str_val); + spinbox.setValue(val); + + QObject::connect(this, &DoubleSpinBoxControl::valChanged, [=](double val) { + Params().put(param.toStdString(), std::to_string(val)); + }); + } + } + void setValue(float v) { spinbox.setValue(v); } +}; diff --git a/system/manager/manager.py b/system/manager/manager.py index 36055d863..504cfc9a2 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -171,8 +171,10 @@ def manager_thread() -> None: # Exit main loop when uninstall/shutdown/reboot is needed shutdown = False - for param in ("DoUninstall", "DoShutdown", "DoReboot"): + for param in ("DoUninstall", "DoShutdown", "DoReboot", "dp_device_reset_conf"): if params.get_bool(param): + if param == "dp_device_reset_conf": + os.system("rm -fr /data/params/d/dp_*") shutdown = True params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}") cloudlog.warning(f"Shutting down manager - {param} set") diff --git a/system/manager/process_config.py b/system/manager/process_config.py index 5758512f2..679d4754b 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -19,7 +19,7 @@ def iscar(started: bool, params: Params, CP: car.CarParams) -> bool: return started and not CP.notCar def logging(started: bool, params: Params, CP: car.CarParams) -> bool: - run = (not CP.notCar) or not params.get_bool("DisableLogging") + run = not params.get_bool("DisableLogging") return started and run def ublox_available() -> bool: diff --git a/system/sentry.py b/system/sentry.py index 47d64ba0f..04d52c7c3 100644 --- a/system/sentry.py +++ b/system/sentry.py @@ -12,9 +12,9 @@ from openpilot.system.version import get_build_metadata, get_version class SentryProject(Enum): # python project - SELFDRIVE = "https://6f3c7076c1e14b2aa10f5dde6dda0cc4@o33823.ingest.sentry.io/77924" + SELFDRIVE = "https://980a0cba712a4c3593c33c78a12446e1@o273754.ingest.sentry.io/1488600" # native project - SELFDRIVE_NATIVE = "https://3e4b586ed21a4479ad5d85083b639bc6@o33823.ingest.sentry.io/157615" + SELFDRIVE_NATIVE = "https://980a0cba712a4c3593c33c78a12446e1@o273754.ingest.sentry.io/1488600" def report_tombstone(fn: str, message: str, contents: str) -> None: @@ -26,11 +26,16 @@ def report_tombstone(fn: str, message: str, contents: str) -> None: sentry_sdk.capture_message(message=message) sentry_sdk.flush() +def save_exception(exc_text): + log = "\n".join(exc_text.splitlines()) + "\n" + Params().put("dp_device_last_log", log) def capture_exception(*args, **kwargs) -> None: cloudlog.error("crash", exc_info=kwargs.get('exc_info', 1)) try: + import traceback + save_exception(traceback.format_exc()) sentry_sdk.capture_exception(*args, **kwargs) sentry_sdk.flush() # https://github.com/getsentry/sentry-python/issues/291 except Exception: diff --git a/system/ui/spinner.py b/system/ui/spinner.py index eb33f0834..29a5dba6f 100755 --- a/system/ui/spinner.py +++ b/system/ui/spinner.py @@ -26,7 +26,7 @@ def clamp(value, min_value, max_value): class Spinner(Widget): def __init__(self): super().__init__() - self._comma_texture = gui_app.texture("images/spinner_comma.png", TEXTURE_SIZE, TEXTURE_SIZE) + self._comma_texture = gui_app.texture("../../dragonpilot/selfdrive/assets/images/spinner_comma.png", TEXTURE_SIZE, TEXTURE_SIZE) self._spinner_texture = gui_app.texture("images/spinner_track.png", TEXTURE_SIZE, TEXTURE_SIZE, alpha_premultiply=True) self._rotation = 0.0 self._progress: int | None = None