diff --git a/common/params.cc b/common/params.cc index 3517aa1..f2b3b64 100644 --- a/common/params.cc +++ b/common/params.cc @@ -255,7 +255,10 @@ std::unordered_map keys = { {"DeviceShutdown", PERSISTENT}, {"DisableOnroadUploads", PERSISTENT}, {"DriverCamera", PERSISTENT}, - {"ExperimentalModeViaPress", PERSISTENT}, + {"DriveStats", PERSISTENT}, + {"ExperimentalModeActivation", PERSISTENT}, + {"ExperimentalModeViaLKAS", PERSISTENT}, + {"ExperimentalModeViaScreen", PERSISTENT}, {"EVTable", PERSISTENT}, {"Fahrenheit", PERSISTENT}, {"FireTheBabysitter", PERSISTENT}, @@ -360,6 +363,7 @@ std::unordered_map keys = { {"UpdateSchedule", PERSISTENT}, {"UpdateTime", PERSISTENT}, {"UseSI", PERSISTENT}, + {"UseVienna", PERSISTENT}, {"VisionTurnControl", PERSISTENT}, {"WheelIcon", PERSISTENT}, {"WideCamera", PERSISTENT}, diff --git a/common/params.h b/common/params.h index 78a8ade..9c8af82 100644 --- a/common/params.h +++ b/common/params.h @@ -47,6 +47,10 @@ public: std::string value = get(key, block); return value.empty() ? 0 : std::stoi(value); } + inline float getFloat(const std::string &key, bool block = false) { + std::string value = get(key, block); + return value.empty() ? 0.0 : std::stof(value); + } std::map readAll(); // helpers for writing values @@ -60,6 +64,9 @@ public: inline int putInt(const std::string &key, int val) { return put(key.c_str(), std::to_string(val).c_str(), std::to_string(val).size()); } + inline int putFloat(const std::string &key, float val) { + return put(key.c_str(), std::to_string(val).c_str(), std::to_string(val).size()); + } void putNonBlocking(const std::string &key, const std::string &val); inline void putBoolNonBlocking(const std::string &key, bool val) { putNonBlocking(key, val ? "1" : "0"); @@ -68,6 +75,10 @@ public: inline void putIntNonBlocking(const std::string &key, int val) { putNonBlocking(key, std::to_string(val)); } + void putFloatNonBlocking(const std::string &key, const std::string &val); + inline void putFloatNonBlocking(const std::string &key, float val) { + putNonBlocking(key, std::to_string(val)); + } private: void asyncWriteThread(); diff --git a/common/params_pyx.pyx b/common/params_pyx.pyx index ae6529f..401b064 100644 --- a/common/params_pyx.pyx +++ b/common/params_pyx.pyx @@ -18,13 +18,16 @@ cdef extern from "common/params.h": string get(string, bool) nogil bool getBool(string, bool) nogil int getInt(string, bool) nogil + float getFloat(string, bool) nogil int remove(string) nogil int put(string, string) nogil void putNonBlocking(string, string) nogil void putBoolNonBlocking(string, bool) nogil void putIntNonBlocking(string, int) nogil + void putFloatNonBlocking(string, float) nogil int putBool(string, bool) nogil int putInt(string, int) nogil + int putFloat(string, float) nogil bool checkKey(string) nogil string getParamPath(string) nogil void clearAll(ParamKeyType) @@ -87,6 +90,13 @@ cdef class Params: r = self.p.getInt(k, block) return r + def get_float(self, key, bool block=False): + cdef string k = self.check_key(key) + cdef float r + with nogil: + r = self.p.getFloat(k, block) + return r + def put(self, key, dat): """ Warning: This function blocks until the param is written to disk! @@ -109,6 +119,11 @@ cdef class Params: with nogil: self.p.putInt(k, val) + def put_float(self, key, float val): + cdef string k = self.check_key(key) + with nogil: + self.p.putFloat(k, val) + def put_nonblocking(self, key, dat): cdef string k = self.check_key(key) cdef string dat_bytes = ensure_bytes(dat) @@ -125,6 +140,11 @@ cdef class Params: with nogil: self.p.putIntNonBlocking(k, val) + def put_float_nonblocking(self, key, float val): + cdef string k = self.check_key(key) + with nogil: + self.p.putFloatNonBlocking(k, val) + def remove(self, key): cdef string k = self.check_key(key) with nogil: diff --git a/panda/board/safety/safety_gm.h b/panda/board/safety/safety_gm.h index 131b157..d3d57d7 100644 --- a/panda/board/safety/safety_gm.h +++ b/panda/board/safety/safety_gm.h @@ -226,7 +226,7 @@ static bool gm_tx_hook(CANPacket_t *to_send) { // GAS/REGEN: safety check if (addr == 0x2CB) { bool apply = GET_BIT(to_send, 0U) != 0U; - int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3); + int gas_regen = ((GET_BYTE(to_send, 1) & 0x1U) << 13) + ((GET_BYTE(to_send, 2) & 0xFFU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3); bool violation = false; // Allow apply bit in pre-enabled and overriding states diff --git a/panda/board/safety/safety_toyota.h b/panda/board/safety/safety_toyota.h index 71e516e..d13d446 100644 --- a/panda/board/safety/safety_toyota.h +++ b/panda/board/safety/safety_toyota.h @@ -43,18 +43,28 @@ const LongitudinalLimits TOYOTA_LONG_LIMITS = { const int TOYOTA_GAS_INTERCEPTOR_THRSLD = 805; #define TOYOTA_GET_INTERCEPTOR(msg) (((GET_BYTE((msg), 0) << 8) + GET_BYTE((msg), 1) + (GET_BYTE((msg), 2) << 8) + GET_BYTE((msg), 3)) / 2U) // avg between 2 tracks -#define TOYOTA_COMMON_TX_MSGS \ +// Stock longitudinal +#define TOYOTA_COMMON_TX_MSGS \ + {0x2E4, 0, 5}, {0x191, 0, 8}, {0x412, 0, 8}, {0x343, 0, 8}, {0x1D2, 0, 8}, /* LKAS + LTA + PCM cancel cmds */ \ + +#define TOYOTA_COMMON_LONG_TX_MSGS \ + TOYOTA_COMMON_TX_MSGS \ {0x283, 0, 7}, {0x2E6, 0, 8}, {0x2E7, 0, 8}, {0x33E, 0, 7}, {0x344, 0, 8}, {0x365, 0, 7}, {0x366, 0, 7}, {0x4CB, 0, 8}, /* DSU bus 0 */ \ {0x128, 1, 6}, {0x141, 1, 4}, {0x160, 1, 8}, {0x161, 1, 7}, {0x470, 1, 4}, /* DSU bus 1 */ \ - {0x2E4, 0, 5}, {0x191, 0, 8}, {0x411, 0, 8}, {0x412, 0, 8}, {0x343, 0, 8}, {0x1D2, 0, 8}, /* LKAS + ACC */ \ {0x1D3, 0, 8}, {0x750, 0, 8}, \ + {0x411, 0, 8}, /* PCS_HUD */ \ + {0x750, 0, 8}, /* radar diagnostic address */ \ const CanMsg TOYOTA_TX_MSGS[] = { TOYOTA_COMMON_TX_MSGS }; +const CanMsg TOYOTA_LONG_TX_MSGS[] = { + TOYOTA_COMMON_LONG_TX_MSGS +}; + const CanMsg TOYOTA_INTERCEPTOR_TX_MSGS[] = { - TOYOTA_COMMON_TX_MSGS + TOYOTA_COMMON_LONG_TX_MSGS {0x200, 0, 6}, // gas interceptor }; @@ -214,7 +224,11 @@ static void toyota_rx_hook(CANPacket_t *to_push) { gas_interceptor_prev = gas_interceptor; } - generic_rx_checks((addr == 0x2E4)); + bool stock_ecu_detected = addr == 0x2E4; // STEERING_LKA + if (!toyota_stock_longitudinal) { + stock_ecu_detected = stock_ecu_detected || (addr == 0x343); // ACC_CONTROL + } + generic_rx_checks(stock_ecu_detected); } } @@ -332,6 +346,15 @@ static bool toyota_tx_hook(CANPacket_t *to_send) { } } + // UDS: Only tester present ("\x0F\x02\x3E\x00\x00\x00\x00\x00") allowed on diagnostics address + if (addr == 0x750) { + // this address is sub-addressed. only allow tester present to radar (0xF) + bool invalid_uds_msg = (GET_BYTES(to_send, 0, 4) != 0x003E020FU) || (GET_BYTES(to_send, 4, 4) != 0x0U); + if (invalid_uds_msg) { + tx = 0; + } + } + return tx; } @@ -348,12 +371,19 @@ static safety_config toyota_init(uint16_t param) { } safety_config ret; - if (toyota_lta) { - ret = enable_gas_interceptor ? BUILD_SAFETY_CFG(toyota_lta_interceptor_rx_checks, TOYOTA_INTERCEPTOR_TX_MSGS) : \ - BUILD_SAFETY_CFG(toyota_lta_rx_checks, TOYOTA_TX_MSGS); + if (toyota_stock_longitudinal) { + SET_TX_MSGS(TOYOTA_TX_MSGS, ret); } else { - ret = enable_gas_interceptor ? BUILD_SAFETY_CFG(toyota_lka_interceptor_rx_checks, TOYOTA_INTERCEPTOR_TX_MSGS) : \ - BUILD_SAFETY_CFG(toyota_lka_rx_checks, TOYOTA_TX_MSGS); + enable_gas_interceptor ? SET_TX_MSGS(TOYOTA_INTERCEPTOR_TX_MSGS, ret) : \ + SET_TX_MSGS(TOYOTA_LONG_TX_MSGS, ret); + } + + if (enable_gas_interceptor) { + toyota_lta ? SET_RX_CHECKS(toyota_lta_interceptor_rx_checks, ret) : \ + SET_RX_CHECKS(toyota_lka_interceptor_rx_checks, ret); + } else { + toyota_lta ? SET_RX_CHECKS(toyota_lta_rx_checks, ret) : \ + SET_RX_CHECKS(toyota_lka_rx_checks, ret); } return ret; } diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index 5196397..f16d273 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -213,19 +213,21 @@ def crash_log(candidate): control_keys, vehicle_keys, visual_keys = [ "AdjustablePersonalities", "AlwaysOnLateral", "AlwaysOnLateralMain", "ConditionalExperimental", "CESpeed", "CESpeedLead", "CECurves", "CECurvesLead", "CENavigation", "CESignal", "CESlowerLead", "CEStopLights", "CEStopLightsLead", "CustomPersonalities", "AggressiveFollow", - "AggressiveJerk", "StandardFollow", "StandardJerk", "RelaxedFollow", "RelaxedJerk", "DeviceShutdown", "ExperimentalModeViaPress", - "FireTheBabysitter", "NoLogging", "MuteDM", "MuteDoor", "MuteSeatbelt", "MuteOverheated", "LateralTune", "AverageCurvature", "NNFF", - "LongitudinalTune", "AccelerationProfile", "StoppingDistance", "AggressiveAcceleration", "SmoothBraking", "Model", "MTSCEnabled", - "NudgelessLaneChange", "LaneChangeTime", "LaneDetection", "OneLaneChange", "QOLControls", "HigherBitrate", "PauseLateralOnSignal", "ReverseCruise", - "SetSpeedOffset", "SpeedLimitController", "SLCFallback","SLCOverride", "SLCPriority", "Offset1", "Offset2", "Offset3", "Offset4", "TurnDesires", + "AggressiveJerk", "StandardFollow", "StandardJerk", "RelaxedFollow", "RelaxedJerk", "DeviceShutdown", "ExperimentalModeActivation", + "ExperimentalModeViaLKAS", "ExperimentalModeViaScreen", "FireTheBabysitter", "NoLogging", "MuteDM", "MuteDoor", "MuteSeatbelt", + "MuteOverheated", "LateralTune", "AverageCurvature", "NNFF", "LongitudinalTune", "AccelerationProfile", "StoppingDistance", + "AggressiveAcceleration", "SmoothBraking", "Model", "MTSCEnabled", "MTSCAggressiveness", "NudgelessLaneChange", "LaneChangeTime", + "LaneDetection", "OneLaneChange", "QOLControls", "HigherBitrate", "PauseLateralOnSignal", "ReverseCruise", "SetSpeedOffset", + "SpeedLimitController", "SLCFallback","SLCOverride", "SLCPriority", "Offset1", "Offset2", "Offset3", "Offset4", "TurnDesires", "VisionTurnControl", "CurveSensitivity", "TurnAggressiveness", "DisableOnroadUploads", "OfflineMode" ], [ "EVTable", "GasRegenCmd", "LongPitch", "LowerVolt", "LockDoors", "SNGHack", "TSS2Tune" ], [ - "CustomTheme", "CustomColors", "CustomIcons", "CustomSignals", "CustomSounds", "GoatScream", "CameraView", "Compass", "CustomUI", "LaneLinesWidth", - "RoadEdgesWidth", "PathWidth", "PathEdgeWidth", "AccelerationPath", "AdjacentPath", "BlindSpotPath", "ShowFPS", "LeadInfo", "RoadNameUI", "UnlimitedLength", - "DriverCamera", "GreenLightAlert", "ModelUI", "QOLVisuals", "FullMap", "HideSpeed", "RandomEvents", "RotatingWheel", "ScreenBrightness", "Sidebar", "SilentMode", - "WheelIcon", "NumericalTemp", "Fahrenheit", "ShowCPU", "ShowGPU", "ShowMemoryUsage", "ShowSLCOffset", "ShowStorageLeft", "ShowStorageUsed", "UseSI" + "CustomTheme", "CustomColors", "CustomIcons", "CustomSignals", "CustomSounds", "GoatScream", "CameraView", "Compass", "CustomUI", "AdjacentPath", + "BlindSpotPath", "ShowFPS", "LeadInfo", "RoadNameUI", "UseVienna", "ModelUI", "AccelerationPath", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", + "RoadEdgesWidth", "UnlimitedLength", "DriverCamera", "GreenLightAlert", "QOLVisuals", "UseSI", "DriveStats", "HideSpeed", "RandomEvents", + "RotatingWheel", "ScreenBrightness", "Sidebar", "SilentMode", "WheelIcon", "NumericalTemp", "Fahrenheit", "ShowCPU", "ShowGPU", "ShowMemoryUsage", + "ShowSLCOffset", "ShowStorageLeft", "ShowStorageUsed", "UseSI" ] control_params, vehicle_params, visual_params = map(lambda keys: get_frogpilot_params(params, keys), [control_keys, vehicle_keys, visual_keys]) @@ -258,8 +260,8 @@ def get_car(logcan, sendcan, experimental_long_allowed, num_pandas=1): if get_branch() == "origin/FrogPilot-Development" and dongle_id[:3] != "be6": candidate = "mock" - x = threading.Thread(target=crash_log, args=(candidate,)) - x.start() + setFingerprintLog = threading.Thread(target=crash_log, args=(candidate,)) + setFingerprintLog.start() CarInterface, CarController, CarState = interfaces[candidate] CP = CarInterface.get_params(candidate, fingerprints, car_fw, experimental_long_allowed, docs=False) diff --git a/selfdrive/car/gm/carstate.py b/selfdrive/car/gm/carstate.py index c90aded..7b9973d 100644 --- a/selfdrive/car/gm/carstate.py +++ b/selfdrive/car/gm/carstate.py @@ -44,8 +44,12 @@ class CarState(CarStateBase): self.moving_backward = (pt_cp.vl["EBCMWheelSpdRear"]["MovingBackward"] != 0) and not moving_forward if self.CP.enableBsm: - ret.leftBlindspot = pt_cp.vl["BCMBSM"]["Left_BSM"] == 1 - ret.rightBlindspot = pt_cp.vl["BCMBSM"]["Right_BSM"] == 1 + if self.CP.carFingerprint in SDGM_CAR: + ret.leftBlindspot = cam_cp.vl["BCMBSM"]["Left_BSM"] == 1 + ret.rightBlindspot = cam_cp.vl["BCMBSM"]["Right_BSM"] == 1 + else: + ret.leftBlindspot = pt_cp.vl["BCMBSM"]["Left_BSM"] == 1 + ret.rightBlindspot = pt_cp.vl["BCMBSM"]["Right_BSM"] == 1 # Variables used for avoiding LKAS faults self.loopback_lka_steering_cmd_updated = len(loopback_cp.vl_all["ASCMLKASteeringCmd"]["RollingCounter"]) > 0 @@ -195,7 +199,7 @@ class CarState(CarStateBase): self.previous_personality_profile = self.personality_profile # Toggle Experimental Mode from steering wheel function - if self.experimental_mode_via_press and ret.cruiseState.available: + if self.experimental_mode_via_lkas and ret.cruiseState.available: if self.CP.carFingerprint in SDGM_CAR: lkas_pressed = cam_cp.vl["ASCMSteeringButton"]["LKAButton"] else: @@ -228,6 +232,8 @@ class CarState(CarStateBase): ("BCMGeneralPlatformStatus", 10), ("ASCMSteeringButton", 33), ] + if CP.enableBsm: + messages.append(("BCMBSM", 10)) else: messages += [ ("AEBCmd", 10), @@ -251,10 +257,6 @@ class CarState(CarStateBase): ("ECMAcceleratorPos", 80), ] - # BSM does not send a signal until the first instance of it lighting up - messages.append(("left_blindspot", 0)) - messages.append(("right_blindspot", 0)) - if CP.carFingerprint in SDGM_CAR: messages += [ ("ECMPRDNL2", 40), @@ -271,6 +273,8 @@ class CarState(CarStateBase): ("BCMGeneralPlatformStatus", 10), ("ASCMSteeringButton", 33), ] + if CP.enableBsm: + messages.append(("BCMBSM", 10)) # Used to read back last counter sent to PT by camera if CP.networkLocation == NetworkLocation.fwdCamera: diff --git a/selfdrive/car/gm/gmcan.py b/selfdrive/car/gm/gmcan.py index c4ea34d..790b37f 100644 --- a/selfdrive/car/gm/gmcan.py +++ b/selfdrive/car/gm/gmcan.py @@ -65,7 +65,6 @@ def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop): "GasRegenFullStopActive": at_full_stop, "GasRegenAlwaysOne": 1, "GasRegenAlwaysOne2": 1, - "GasRegenAlwaysOne3": 1, } dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[2] diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index ad1d66f..d44eaac 100644 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -81,7 +81,7 @@ class CarInterface(CarInterfaceBase): @staticmethod def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): # FrogPilot variables - params = params() + params = Params() useGasRegenCmd = params.get_bool("GasRegenCmd") ret.carName = "gm" diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py index 7854b76..abd13f9 100644 --- a/selfdrive/car/honda/carcontroller.py +++ b/selfdrive/car/honda/carcontroller.py @@ -253,7 +253,7 @@ class CarController: if self.frame % 10 == 0: hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_control.leadVisible, CS.personality_profile + 1, hud_control.lanesVisible, fcw_display, acc_alert, steer_required) - can_sends.extend(hondacan.create_ui_commands(self.packer, self.CP, CC.enabled, pcm_speed, hud, CS.is_metric, CS.acc_hud, CS.lkas_hud)) + can_sends.extend(hondacan.create_ui_commands(self.packer, self.CP, CC.enabled, pcm_speed, hud, CS.is_metric, CS.acc_hud, CS.lkas_hud, CC.latActive)) if self.CP.openpilotLongitudinalControl and self.CP.carFingerprint not in HONDA_BOSCH: self.speed = pcm_speed diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index 0a1884b..424a04d 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -288,7 +288,7 @@ class CarState(CarStateBase): self.previous_personality_profile = self.personality_profile # Toggle Experimental Mode from steering wheel function - if self.experimental_mode_via_press and ret.cruiseState.available: + if self.experimental_mode_via_lkas and ret.cruiseState.available: lkas_pressed = self.cruise_setting == 1 if lkas_pressed and not self.lkas_previously_pressed: if self.conditional_experimental_mode: diff --git a/selfdrive/car/honda/hondacan.py b/selfdrive/car/honda/hondacan.py index 11c995c..df57cbc 100644 --- a/selfdrive/car/honda/hondacan.py +++ b/selfdrive/car/honda/hondacan.py @@ -122,7 +122,7 @@ def create_bosch_supplemental_1(packer, car_fingerprint): return packer.make_can_msg("BOSCH_SUPPLEMENTAL_1", bus, values) -def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, acc_hud, lkas_hud): +def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, acc_hud, lkas_hud, lat_active): commands = [] bus_pt = get_pt_bus(CP.carFingerprint) radar_disabled = CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and CP.openpilotLongitudinalControl @@ -155,7 +155,7 @@ def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, acc_hud, lkas_hud_values = { 'SET_ME_X41': 0x41, 'STEERING_REQUIRED': hud.steer_required, - 'SOLID_LANES': hud.lanes_visible, + 'SOLID_LANES': lat_active, 'BEEP': 0, } diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py index 85c030d..20bc0ef 100644 --- a/selfdrive/car/hyundai/carstate.py +++ b/selfdrive/car/hyundai/carstate.py @@ -184,7 +184,7 @@ class CarState(CarStateBase): self.previous_personality_profile = self.personality_profile # Toggle Experimental Mode from steering wheel function - if self.experimental_mode_via_press and ret.cruiseState.available: + if self.experimental_mode_via_lkas and ret.cruiseState.available: lkas_pressed = cp.vl["BCM_PO_11"]["LFA_Pressed"] if lkas_pressed and not self.lkas_previously_pressed: if self.conditional_experimental_mode: @@ -300,7 +300,7 @@ class CarState(CarStateBase): self.previous_personality_profile = self.personality_profile # Toggle Experimental Mode from steering wheel function - if self.experimental_mode_via_press and ret.cruiseState.available: + if self.experimental_mode_via_lkas and ret.cruiseState.available: lkas_pressed = cp.vl[self.cruise_btns_msg_canfd]["LKAS_BTN"] if lkas_pressed and not self.lkas_previously_pressed: if self.conditional_experimental_mode: diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 2fc014e..4b6b09b 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -596,7 +596,7 @@ class CarStateBase(ABC): def update_frogpilot_params(self, params): self.conditional_experimental_mode = params.get_bool("ConditionalExperimental") - self.experimental_mode_via_press = params.get_bool("ExperimentalModeViaPress") + self.experimental_mode_via_lkas = params.get_bool("ExperimentalModeViaLKAS") and params.get_bool("ExperimentalModeActivation"); self.personalities_via_wheel = params.get_int("AdjustablePersonalities") in {1, 3} INTERFACE_ATTR_FILE = { diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 25d4a38..45e3918 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -208,7 +208,7 @@ class CarState(CarStateBase): self.previous_personality_profile = self.personality_profile # Toggle Experimental Mode from steering wheel function - if self.experimental_mode_via_press and ret.cruiseState.available and self.CP.carFingerprint != CAR.PRIUS_V: + if self.experimental_mode_via_lkas and ret.cruiseState.available and self.CP.carFingerprint != CAR.PRIUS_V: message_keys = ["LDA_ON_MESSAGE", "SET_ME_X02"] lkas_pressed = any(self.lkas_hud.get(key) == 1 for key in message_keys) if lkas_pressed and not self.lkas_previously_pressed: diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 9fc9680..af7980b 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -236,11 +236,11 @@ class CarInterface(CarInterfaceBase): # since we don't yet parse radar on TSS2/TSS-P radar-based ACC cars, gate longitudinal behind experimental toggle use_sdsu = bool(ret.flags & ToyotaFlags.SMART_DSU) if candidate in (RADAR_ACC_CAR | NO_DSU_CAR): - ret.experimentalLongitudinalAvailable = use_sdsu + ret.experimentalLongitudinalAvailable = use_sdsu or candidate in RADAR_ACC_CAR if not use_sdsu: # Disabling radar is only supported on TSS2 radar-ACC cars - if experimental_long and candidate in RADAR_ACC_CAR and False: # TODO: disabling radar isn't supported yet + if experimental_long and candidate in RADAR_ACC_CAR: ret.flags |= ToyotaFlags.DISABLE_RADAR.value else: use_sdsu = use_sdsu and experimental_long diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 22699bb..de6b35a 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -988,7 +988,8 @@ class Controls: # Update FrogPilot parameters if self.params_memory.get_bool("FrogPilotTogglesUpdated"): - self.update_frogpilot_params() + updateFrogPilotParams = threading.Thread(target=self.update_frogpilot_params) + updateFrogPilotParams.start() except SystemExit: e.set() @@ -1010,7 +1011,7 @@ class Controls: self.green_light_alert = self.params.get_bool("GreenLightAlert") lateral_tune = self.params.get_bool("LateralTune") - self.steer_ratio = self.params.get_int("SteerRatio") / 100 if lateral_tune else self.params.get_int("SteerRatioStock") / 100 + self.steer_ratio = self.params.get_float("SteerRatio") if lateral_tune else self.params.get_float("SteerRatioStock") longitudinal_tune = self.params.get_bool("LongitudinalTune") self.sport_plus = self.params.get_int("AccelerationProfile") == 3 and longitudinal_tune diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py index 4efc8a1..102936e 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @@ -56,7 +56,7 @@ T_DIFFS = np.diff(T_IDXS, prepend=[0.]) COMFORT_BRAKE = 2.5 STOP_DISTANCE = 6.0 -def get_jerk_factor(custom_personalities, aggressive_jerk, standard_jerk, relaxed_jerk, personality=log.LongitudinalPersonality.standard): +def get_jerk_factor(custom_personalities=False, aggressive_jerk=0.5, standard_jerk=1.0, relaxed_jerk=1.0, personality=log.LongitudinalPersonality.standard): if custom_personalities: if personality==log.LongitudinalPersonality.relaxed: return relaxed_jerk @@ -241,6 +241,13 @@ def gen_long_ocp(): class LongitudinalMpc: def __init__(self, mode='acc'): + # FrogPilot variables + self.safe_obstacle_distance = 0 + self.safe_obstacle_distance_stock = 0 + self.stopped_equivalence_factor = 0 + self.t_follow = 0 + self.t_follow_offset = 1 + self.mode = mode self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N) self.reset() @@ -292,8 +299,9 @@ class LongitudinalMpc: for i in range(N): self.solver.cost_set(i, 'Zl', Zl) - def set_weights(self, custom_personalities, aggressive_jerk, standard_jerk, relaxed_jerk, prev_accel_constraint=True, personality=log.LongitudinalPersonality.standard): + def set_weights(self, prev_accel_constraint=True, custom_personalities=False, aggressive_jerk=0.5, standard_jerk=1.0, relaxed_jerk=1.0, personality=log.LongitudinalPersonality.standard): jerk_factor = get_jerk_factor(custom_personalities, aggressive_jerk, standard_jerk, relaxed_jerk, personality) + jerk_factor /= np.mean(self.t_follow_offset) if self.mode == 'acc': a_change_cost = A_CHANGE_COST if prev_accel_constraint else 0 cost_weights = [X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, jerk_factor * a_change_cost, jerk_factor * J_EGO_COST] @@ -351,7 +359,7 @@ class LongitudinalMpc: self.cruise_min_a = min_a self.max_a = max_a - def update(self, radarstate, v_cruise, x, v, a, j, aggressive_acceleration, smoother_braking, custom_personalities, aggressive_follow, standard_follow, relaxed_follow, increased_stopping_distance, personality=log.LongitudinalPersonality.standard): + def update(self, radarstate, v_cruise, x, v, a, j, aggressive_acceleration, increased_stopping_distance, smoother_braking, custom_personalities, aggressive_follow, standard_follow, relaxed_follow, personality=log.LongitudinalPersonality.standard): t_follow = get_T_FOLLOW(custom_personalities, aggressive_follow, standard_follow, relaxed_follow, personality) self.t_follow = t_follow v_ego = self.x0[1] @@ -363,8 +371,9 @@ class LongitudinalMpc: # Offset by FrogAi for FrogPilot for a more natural takeoff with a lead if aggressive_acceleration: distance_factor = np.maximum(1, lead_xv_0[:,0] - (lead_xv_0[:,1] * t_follow)) - t_follow_offset = np.clip((lead_xv_0[:,1] - v_ego) + (STOP_DISTANCE + increased_stopping_distance - v_ego), 1, distance_factor) - t_follow = t_follow / t_follow_offset + standstill_offset = max(STOP_DISTANCE + increased_stopping_distance - (v_ego**COMFORT_BRAKE), 0) + self.t_follow_offset = np.clip((lead_xv_0[:,1] - v_ego) + standstill_offset, 1, distance_factor) + t_follow = t_follow / self.t_follow_offset # Offset by FrogAi for FrogPilot for a more natural approach to a slower lead if smoother_braking: diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 2da1018..6f32e1e 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -135,7 +135,7 @@ class LongitudinalPlanner: accel_limits_turns[0] = min(accel_limits_turns[0], self.a_desired + 0.05) accel_limits_turns[1] = max(accel_limits_turns[1], self.a_desired - 0.05) - self.mpc.set_weights(frogpilot_planner.custom_personalities, frogpilot_planner.aggressive_jerk, frogpilot_planner.standard_jerk, frogpilot_planner.relaxed_jerk, prev_accel_constraint, personality=self.personality) + self.mpc.set_weights(prev_accel_constraint, frogpilot_planner.custom_personalities, frogpilot_planner.aggressive_jerk, frogpilot_planner.standard_jerk, frogpilot_planner.relaxed_jerk, personality=self.personality) self.mpc.set_accel_limits(accel_limits_turns[0], accel_limits_turns[1]) self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) x, v, a, j = self.parse_model(sm['modelV2'], self.v_model_error) diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index d433fe8..fe81589 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os import numpy as np +import threading from cereal import car from openpilot.common.params import Params from openpilot.common.realtime import Priority, config_realtime_process @@ -41,7 +42,7 @@ def plannerd_thread(): debug_mode = bool(int(os.getenv("DEBUG", "0"))) - frogpilot_planner = FrogPilotPlanner(params) + frogpilot_planner = FrogPilotPlanner(params, params_memory) longitudinal_planner = LongitudinalPlanner(CP) lateral_planner = LateralPlanner(CP, debug=debug_mode) @@ -60,7 +61,8 @@ def plannerd_thread(): publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner) if params_memory.get_bool("FrogPilotTogglesUpdated"): - frogpilot_planner.update_frogpilot_params(params) + updateFrogPilotToggles = threading.Thread(target=frogpilot_planner.update_frogpilot_params, args=(params, params_memory)) + updateFrogPilotToggles.start() def main(): plannerd_thread() diff --git a/selfdrive/frogpilot/functions/conditional_experimental_mode.py b/selfdrive/frogpilot/functions/conditional_experimental_mode.py index 285b75c..47b1dfa 100644 --- a/selfdrive/frogpilot/functions/conditional_experimental_mode.py +++ b/selfdrive/frogpilot/functions/conditional_experimental_mode.py @@ -200,7 +200,7 @@ class ConditionalExperimentalMode: def update_frogpilot_params(self, is_metric, params): self.curves = params.get_bool("CECurves") self.curves_lead = params.get_bool("CECurvesLead") - self.experimental_mode_via_press = params.get_bool("ExperimentalModeViaPress") + self.experimental_mode_via_press = params.get_bool("ExperimentalModeActivation") self.limit = params.get_int("CESpeed") * (CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS) self.limit_lead = params.get_int("CESpeedLead") * (CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS) self.navigation = params.get_bool("CENavigation") diff --git a/selfdrive/frogpilot/functions/frogpilot_planner.py b/selfdrive/frogpilot/functions/frogpilot_planner.py index 10ae8b2..67654ff 100644 --- a/selfdrive/frogpilot/functions/frogpilot_planner.py +++ b/selfdrive/frogpilot/functions/frogpilot_planner.py @@ -55,7 +55,7 @@ def calculate_lane_width(lane, current_lane, road_edge): class FrogPilotPlanner: - def __init__(self, params): + def __init__(self, params, params_memory): self.cem = ConditionalExperimentalMode() self.mtsc = MapTurnSpeedController() @@ -69,7 +69,7 @@ class FrogPilotPlanner: self.x_desired_trajectory = np.zeros(CONTROL_N) - self.update_frogpilot_params(params) + self.update_frogpilot_params(params, params_memory) def update(self, sm, mpc): carState, controlsState, modelData = sm['carState'], sm['controlsState'], sm['modelV2'] @@ -203,7 +203,7 @@ class FrogPilotPlanner: pm.send('frogpilotLongitudinalPlan', frogpilot_longitudinal_plan_send) - def update_frogpilot_params(self, params): + def update_frogpilot_params(self, params, params_memory): self.is_metric = params.get_bool("IsMetric") self.blindspot_path = params.get_bool("CustomUI") and params.get_bool("BlindSpotPath") diff --git a/selfdrive/frogpilot/ui/control_settings.cc b/selfdrive/frogpilot/ui/control_settings.cc index 5d9ce55..fbb93a1 100644 --- a/selfdrive/frogpilot/ui/control_settings.cc +++ b/selfdrive/frogpilot/ui/control_settings.cc @@ -15,7 +15,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil {"CustomPersonalities", "Custom Driving Personalities", "Customize the driving personality profiles to your driving style.", "../frogpilot/assets/toggle_icons/icon_custom.png"}, {"DeviceShutdown", "Device Shutdown Timer", "Configure the timer for automatic device shutdown when offroad conserving energy and preventing battery drain.", "../frogpilot/assets/toggle_icons/icon_time.png"}, - {"ExperimentalModeViaPress", "Experimental Mode Via 'LKAS' Button / Screen", "Toggle Experimental Mode by double-clicking the 'Lane Departure'/'LKAS' button or double tapping screen.\n\nOverrides 'Conditional Experimental Mode'.", "../assets/img_experimental_white.svg"}, + {"ExperimentalModeActivation", "Experimental Mode Via", "Toggle Experimental Mode by double-clicking the 'Lane Departure'/'LKAS' button or double tapping screen.\n\nOverrides 'Conditional Experimental Mode'.", "../assets/img_experimental_white.svg"}, {"FireTheBabysitter", "Fire the Babysitter", "Deactivate some of openpilot's 'Babysitter' protocols for more user autonomy.", "../frogpilot/assets/toggle_icons/icon_babysitter.png"}, {"NoLogging", "Disable All Logging", "Turn off all data tracking to enhance privacy or reduce thermal load.\n\nWARNING: This action will prevent drive recording and data cannot be recovered!", ""}, @@ -23,11 +23,12 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil {"MuteDM", "Mute Driver Monitoring", "Disable driver monitoring.", ""}, {"MuteOverheated", "Mute Overheated System Alert", "Disable alerts for the device being overheated.", ""}, {"MuteSeatbelt", "Mute Seatbelt Unlatched Alert", "Disable alerts for unlatched seatbelts.", ""}, + {"OfflineMode", "Offline Mode", "Allow the device to be offline indefinitely.", ""}, {"LateralTune", "Lateral Tuning", "Modify openpilot's steering behavior.", "../frogpilot/assets/toggle_icons/icon_lateral_tune.png"}, {"AverageCurvature", "Average Desired Curvature", "Use Pfeiferj's distance-based curvature adjustment for improved curve handling.", ""}, {"NNFF", "NNFF - Neural Network Feedforward", "Use Twilsonco's Neural Network Feedforward for enhanced precision in lateral control.", ""}, - {"SteerRatio", steerRatioStock != 0 ? QString("Steer Ratio (Default: " + QString::number(steerRatioStock / 100.0) + ")") : "Steer Ratio", "Set a custom steer ratio for your vehicle controls.", ""}, + {"SteerRatio", steerRatioStock != 0 ? QString("Steer Ratio (Default: %1)").arg(steerRatioStock, 0, 'f', 2) : "Steer Ratio", "Set a custom steer ratio for your vehicle controls.", ""}, {"LongitudinalTune", "Longitudinal Tuning", "Modify openpilot's acceleration and braking behavior.", "../frogpilot/assets/toggle_icons/icon_longitudinal_tune.png"}, {"AccelerationProfile", "Acceleration Profile", "Change the acceleration rate to be either sporty or eco-friendly.", ""}, @@ -36,6 +37,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil {"SmoothBraking", "Smoother Braking Behind Lead", "Smoothen out the braking behavior when approaching slower vehicles.", ""}, {"Model", "Model Selector", "Choose your preferred openpilot model.", "../assets/offroad/icon_calibration.png"}, + {"MTSCEnabled", "Map Turn Speed Control", "Slow down for anticipated curves detected by your downloaded maps.", "../frogpilot/assets/toggle_icons/icon_speed_map.png"}, {"NudgelessLaneChange", "Nudgeless Lane Change", "Enable lane changes without manual steering input.", "../frogpilot/assets/toggle_icons/icon_lane.png"}, @@ -44,6 +46,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil {"OneLaneChange", "One Lane Change Per Signal", "Limit to one nudgeless lane change per turn signal activation.", ""}, {"QOLControls", "Quality of Life", "Miscellaneous quality of life changes to improve your overall openpilot experience.", "../frogpilot/assets/toggle_icons/quality_of_life.png"}, + {"DisableOnroadUploads", "Disable Onroad Uploads", "Prevent large data uploads when onroad.", ""}, {"HigherBitrate", "Higher Bitrate Recording", "Increases the quality of the footage uploaded to comma connect.", ""}, {"PauseLateralOnSignal", "Pause Lateral On Turn Signal Below", "Temporarily disable lateral control during turn signal use below the set speed.", ""}, {"ReverseCruise", "Reverse Cruise Increase", "Reverses the 'long press' functionality when increasing the max set speed. Useful to increase the max speed quickly.", ""}, @@ -72,7 +75,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 3, {{0, "None"}, {1, "Steering Wheel"}, {2, "Onroad UI Button"}, {3, "Wheel + Button"}}, this, true); } else if (param == "AlwaysOnLateral") { - std::vector aolToggles{tr("AlwaysOnLateralMain")}; + std::vector aolToggles{"AlwaysOnLateralMain"}; std::vector aolToggleNames{tr("Enable On Cruise Main")}; toggle = new FrogPilotParamToggleControl(param, title, desc, icon, aolToggles, aolToggleNames); @@ -112,11 +115,11 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil conditionalSpeedsMetric = new FrogPilotDualParamControl(CESpeedMetric, CESpeedLeadMetric, this); addItem(conditionalSpeedsMetric); - std::vector curveToggles{tr("CECurvesLead")}; + std::vector curveToggles{"CECurvesLead"}; std::vector curveToggleNames{tr("With Lead")}; toggle = new FrogPilotParamToggleControl(param, title, desc, icon, curveToggles, curveToggleNames); } else if (param == "CEStopLights") { - std::vector stopLightToggles{tr("CEStopLightsLead")}; + std::vector stopLightToggles{"CEStopLightsLead"}; std::vector stopLightToggleNames{tr("With Lead")}; toggle = new FrogPilotParamToggleControl(param, title, desc, icon, stopLightToggles, stopLightToggleNames); @@ -167,6 +170,11 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil } toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 33, shutdownLabels, this, false); + } else if (param == "ExperimentalModeActivation") { + std::vector experimentalModeToggles{"ExperimentalModeViaLKAS", "ExperimentalModeViaScreen"}; + std::vector experimentalModeNames{tr("LKAS Button"), tr("Screen")}; + toggle = new FrogPilotParamToggleControl(param, title, desc, icon, experimentalModeToggles, experimentalModeNames); + } else if (param == "FireTheBabysitter") { FrogPilotParamManageControl *fireTheBabysitterToggle = new FrogPilotParamManageControl(param, title, desc, icon, this); QObject::connect(fireTheBabysitterToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() { @@ -187,7 +195,7 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil }); toggle = lateralTuneToggle; } else if (param == "SteerRatio") { - toggle = new FrogPilotParamValueControl(param, title, desc, icon, steerRatioStock * 0.75, steerRatioStock * 1.25, std::map(), this, false, "", 100); + toggle = new FrogPilotParamValueControlFloat(param, title, desc, icon, steerRatioStock * 0.75, steerRatioStock * 1.25, std::map(), this, false, "", 10.0); } else if (param == "LongitudinalTune") { FrogPilotParamManageControl *longitudinalTuneToggle = new FrogPilotParamManageControl(param, title, desc, icon, this); @@ -395,11 +403,12 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil } conditionalExperimentalKeys = {"CECurves", "CECurvesLead", "CESlowerLead", "CENavigation", "CEStopLights", "CESignal"}; - fireTheBabysitterKeys = {"NoLogging", "MuteDM", "MuteDoor", "MuteOverheated", "MuteSeatbelt"}; + fireTheBabysitterKeys = {"NoLogging", "MuteDM", "MuteDoor", "MuteOverheated", "MuteSeatbelt", "OfflineMode"}; laneChangeKeys = {"LaneChangeTime", "LaneDetection", "OneLaneChange"}; lateralTuneKeys = {"AverageCurvature", "NNFF", "SteerRatio"}; longitudinalTuneKeys = {"AccelerationProfile", "AggressiveAcceleration", "SmoothBraking", "StoppingDistance"}; - qolKeys = {"HigherBitrate", "PauseLateralOnSignal", "ReverseCruise", "SetSpeedOffset"}; + mtscKeys = {"MTSCAggressiveness"}; + qolKeys = {"DisableOnroadUploads", "HigherBitrate", "PauseLateralOnSignal", "ReverseCruise", "SetSpeedOffset"}; speedLimitControllerKeys = {"Offset1", "Offset2", "Offset3", "Offset4", "SLCFallback", "SLCOverride", "SLCPriority"}; visionTurnControlKeys = {"CurveSensitivity", "TurnAggressiveness"}; @@ -418,10 +427,10 @@ FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPil } void FrogPilotControlsPanel::updateCarToggles() { - FrogPilotParamValueControl *steerRatioToggle = static_cast(toggles["SteerRatio"]); - steerRatioStock = params.getInt("SteerRatioStock"); - steerRatioToggle->setTitle(steerRatioStock != 0 ? QString("Steer Ratio (Default: " + QString::number(steerRatioStock / 100.0) + ")") : QString("Steer Ratio")); - steerRatioToggle->updateControl(steerRatioStock * 0.75, steerRatioStock * 1.25, "", 100); + FrogPilotParamValueControlFloat *steerRatioToggle = static_cast(toggles["SteerRatio"]); + steerRatioStock = params.getFloat("SteerRatioStock"); + steerRatioToggle->setTitle(steerRatioStock != 0 ? QString("Steer Ratio (Default: %1)").arg(steerRatioStock, 0, 'f', 2) : QString("Steer Ratio")); + steerRatioToggle->updateControl(steerRatioStock * 0.75, steerRatioStock * 1.25, "", 10.0); steerRatioToggle->refresh(); } @@ -535,6 +544,7 @@ void FrogPilotControlsPanel::hideSubToggles() { laneChangeKeys.find(key.c_str()) != laneChangeKeys.end() || lateralTuneKeys.find(key.c_str()) != lateralTuneKeys.end() || longitudinalTuneKeys.find(key.c_str()) != longitudinalTuneKeys.end() || + mtscKeys.find(key.c_str()) != mtscKeys.end() || qolKeys.find(key.c_str()) != qolKeys.end() || speedLimitControllerKeys.find(key.c_str()) != speedLimitControllerKeys.end() || visionTurnControlKeys.find(key.c_str()) != visionTurnControlKeys.end(); diff --git a/selfdrive/frogpilot/ui/control_settings.h b/selfdrive/frogpilot/ui/control_settings.h index 1520c11..b029249 100644 --- a/selfdrive/frogpilot/ui/control_settings.h +++ b/selfdrive/frogpilot/ui/control_settings.h @@ -38,6 +38,7 @@ private: std::set laneChangeKeys; std::set lateralTuneKeys; std::set longitudinalTuneKeys; + std::set mtscKeys; std::set qolKeys; std::set speedLimitControllerKeys; std::set visionTurnControlKeys; @@ -48,5 +49,5 @@ private: Params paramsMemory{"/dev/shm/params"}; bool isMetric = params.getBool("IsMetric"); - int steerRatioStock = params.getInt("SteerRatioStock"); + float steerRatioStock = params.getFloat("SteerRatioStock"); }; diff --git a/selfdrive/frogpilot/ui/frogpilot_functions.cc b/selfdrive/frogpilot/ui/frogpilot_functions.cc index 496989a..503cdd6 100644 --- a/selfdrive/frogpilot/ui/frogpilot_functions.cc +++ b/selfdrive/frogpilot/ui/frogpilot_functions.cc @@ -79,8 +79,11 @@ void setDefaultParams() { {"CustomUI", "1"}, {"DeviceShutdown", "9"}, {"DriverCamera", "0"}, + {"DriveStats", "1"}, {"EVTable", FrogsGoMoo ? "0" : "1"}, - {"ExperimentalModeViaPress", "1"}, + {"ExperimentalModeActivation", "1"}, + {"ExperimentalModeViaLKAS", "1"}, + {"ExperimentalModeViaScreen", FrogsGoMoo ? "0" : "1"}, {"Fahrenheit", "0"}, {"FireTheBabysitter", FrogsGoMoo ? "1" : "0"}, {"FullMap", "0"}, @@ -149,6 +152,7 @@ void setDefaultParams() { {"TurnDesires", "1"}, {"UnlimitedLength", "1"}, {"UseSI", FrogsGoMoo ? "1" : "0"}, + {"UseVienna", "0"}, {"VisionTurnControl", "1"}, {"WheelIcon", FrogsGoMoo ? "1" : "0"} }; diff --git a/selfdrive/frogpilot/ui/frogpilot_functions.h b/selfdrive/frogpilot/ui/frogpilot_functions.h index ac5469c..ffa4134 100644 --- a/selfdrive/frogpilot/ui/frogpilot_functions.h +++ b/selfdrive/frogpilot/ui/frogpilot_functions.h @@ -363,6 +363,120 @@ private: } }; +class FrogPilotParamValueControlFloat : public ParamControl { + Q_OBJECT + +public: + FrogPilotParamValueControlFloat(const QString ¶m, const QString &title, const QString &desc, const QString &icon, + const float &minValue, const float &maxValue, const std::map &valueLabels, + QWidget *parent = nullptr, const bool &loop = true, const QString &label = "", const float &division = 1.0f) + : ParamControl(param, title, desc, icon, parent), + minValue(minValue), maxValue(maxValue), valueLabelMappings(valueLabels), loop(loop), labelText(label), division(division) { + key = param.toStdString(); + + valueLabel = new QLabel(this); + hlayout->addWidget(valueLabel); + + QPushButton *decrementButton = createButton("-", this); + QPushButton *incrementButton = createButton("+", this); + + hlayout->addWidget(decrementButton); + hlayout->addWidget(incrementButton); + + connect(decrementButton, &QPushButton::clicked, this, [=]() { + updateValue(-1.0f); + }); + + connect(incrementButton, &QPushButton::clicked, this, [=]() { + updateValue(1.0f); + }); + + toggle.hide(); + } + + void updateValue(float increment) { + value += increment * 0.1f; + + if (loop) { + if (value < minValue) value = maxValue; + else if (value > maxValue) value = minValue; + } else { + value = std::max(minValue, std::min(maxValue, value)); + } + + params.putFloat(key, value); + refresh(); + emit buttonPressed(); + emit valueChanged(value); + } + + void refresh() { + value = params.getFloat(key); + + QString text; + auto it = valueLabelMappings.find(value); + if (division > 0.1f) { + text = QString::number(value, 'f', 1); + } else { + text = it != valueLabelMappings.end() ? it->second : QString::number(value, 'f', 1); + } + if (!labelText.isEmpty()) { + text += labelText; + } + valueLabel->setText(text); + valueLabel->setStyleSheet("QLabel { color: #E0E879; }"); + } + + void updateControl(float newMinValue, float newMaxValue, const QString &newLabel, float newDivision = 1.0f) { + minValue = newMinValue; + maxValue = newMaxValue; + labelText = newLabel; + division = newDivision; + } + + void showEvent(QShowEvent *event) override { + refresh(); + } + +signals: + void buttonPressed(); + void valueChanged(float value); + +private: + bool loop; + float division; + float maxValue; + float minValue; + float value; + QLabel *valueLabel; + QString labelText; + std::map valueLabelMappings; + std::string key; + Params params; + + QPushButton *createButton(const QString &text, QWidget *parent) { + QPushButton *button = new QPushButton(text, parent); + button->setFixedSize(150, 100); + button->setAutoRepeat(true); + button->setAutoRepeatInterval(150); + button->setStyleSheet(R"( + QPushButton { + border-radius: 50px; + font-size: 50px; + font-weight: 500; + height: 100px; + padding: 0 25 0 25; + color: #E4E4E4; + background-color: #393939; + } + QPushButton:pressed { + background-color: #4a4a4a; + } + )"); + return button; + } +}; + class FrogPilotDualParamControl : public QFrame { Q_OBJECT diff --git a/selfdrive/frogpilot/ui/vehicle_settings.cc b/selfdrive/frogpilot/ui/vehicle_settings.cc index 5f1f76a..b658218 100644 --- a/selfdrive/frogpilot/ui/vehicle_settings.cc +++ b/selfdrive/frogpilot/ui/vehicle_settings.cc @@ -121,10 +121,10 @@ FrogPilotVehiclesPanel::FrogPilotVehiclesPanel(SettingsWindow *parent) : FrogPil }); } - gmKeys = {"EVTable", "GasRegenCmd", "LongPitch"}; - toyotaKeys = {}; + gmKeys = {"EVTable", "GasRegenCmd", "LongPitch", "LowerVolt"}; + toyotaKeys = {"LockDoors", "SNGHack", "TSS2Tune"}; - std::set rebootKeys = {"LowerVolt", "TSS2Tune"}; + std::set rebootKeys = {"EVTable", "GasRegenCmd", "LongPitch", "LowerVolt", "TSS2Tune"}; for (const std::string &key : rebootKeys) { QObject::connect(toggles[key], &ToggleControl::toggleFlipped, [this]() { if (FrogPilotConfirmationDialog::toggle("Reboot required to take effect.", "Reboot Now", this)) { diff --git a/selfdrive/frogpilot/ui/visual_settings.cc b/selfdrive/frogpilot/ui/visual_settings.cc index b825287..3bad476 100644 --- a/selfdrive/frogpilot/ui/visual_settings.cc +++ b/selfdrive/frogpilot/ui/visual_settings.cc @@ -18,6 +18,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"ShowFPS", "FPS Counter", "Display the Frames Per Second (FPS) of your onroad UI for monitoring system performance.", ""}, {"LeadInfo", "Lead Info and Logics", "Get detailed information about the vehicle ahead, including speed and distance, and the logic behind your following distance.", ""}, {"RoadNameUI", "Road Name", "See the name of the road you're on at the bottom of your screen. Sourced from OpenStreetMap.", ""}, + {"UseVienna", "Use Vienna Speed Limit Signs", "Use the Vienna (EU) speed limit style signs as opposed to MUTCD (US).", ""}, {"DriverCamera", "Driver Camera On Reverse", "Show the driver's camera feed when you shift to reverse.", "../assets/img_driver_face_static.png"}, {"GreenLightAlert", "Green Light Alert", "Get an alert when a traffic light changes from red to green.", "../frogpilot/assets/toggle_icons/icon_green_light.png"}, @@ -152,7 +153,16 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot }); } - customOnroadUIKeys = {"AdjacentPath", "BlindSpotPath", "ShowFPS", "LeadInfo", "RoadNameUI"}; + std::set rebootKeys = {"DriveStats"}; + for (const std::string &key : rebootKeys) { + QObject::connect(toggles[key], &ToggleControl::toggleFlipped, [this]() { + if (FrogPilotConfirmationDialog::toggle("Reboot required to take effect.", "Reboot Now", this)) { + Hardware::reboot(); + } + }); + } + + customOnroadUIKeys = {"AdjacentPath", "BlindSpotPath", "ShowFPS", "LeadInfo", "RoadNameUI", "UseVienna"}; customThemeKeys = {"CustomColors", "CustomIcons", "CustomSignals", "CustomSounds"}; modelUIKeys = {"AccelerationPath", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", "RoadEdgesWidth", "UnlimitedLength"}; qolKeys = {"DriveStats", "HideSpeed", "ShowSLCOffset"}; diff --git a/selfdrive/locationd/paramsd.py b/selfdrive/locationd/paramsd.py index fcf231f..cf7f8d1 100755 --- a/selfdrive/locationd/paramsd.py +++ b/selfdrive/locationd/paramsd.py @@ -134,10 +134,13 @@ def main(): CP = msg cloudlog.info("paramsd got CarParams") - steer_ratio_stock = params_reader.get_int("SteerRatioStock") - if steer_ratio_stock != CP.steerRatio * 100: - params_reader.put_int("SteerRatio", CP.steerRatio * 100) - params_reader.put_int("SteerRatioStock", CP.steerRatio * 100) + steer_ratio = params_reader.get_float("SteerRatio") + steer_ratio_stock = params_reader.get_float("SteerRatioStock") + + if steer_ratio_stock != CP.steerRatio or steer_ratio >= steer_ratio_stock * 2: + params_reader.put_float("SteerRatio", CP.steerRatio) + params_reader.put_float("SteerRatioStock", CP.steerRatio) + params_reader.put_bool("DoReboot", True) min_sr, max_sr = 0.5 * CP.steerRatio, 2.0 * CP.steerRatio diff --git a/selfdrive/navd/navd.py b/selfdrive/navd/navd.py index 61396f7..fe99365 100755 --- a/selfdrive/navd/navd.py +++ b/selfdrive/navd/navd.py @@ -77,7 +77,8 @@ class RouteEngine: def update(self): # Update FrogPilot parameters if self.params_memory.get_bool("FrogPilotTogglesUpdated"): - self.update_frogpilot_params() + updateFrogPilotParams = threading.Thread(target=self.update_frogpilot_params) + updateFrogPilotParams.start() self.sm.update(0) diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index d3abf66..15863ed 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -309,7 +309,7 @@ def thermald_thread(end_event, hw_queue) -> None: startup_conditions["time_valid"] = now > MIN_DATE set_offroad_alert_if_changed("Offroad_InvalidTime", (not startup_conditions["time_valid"]) and peripheral_panda_present) - startup_conditions["up_to_date"] = params.get("OfflineMode") or params.get("Offroad_ConnectivityNeeded") is None or params.get_bool("DisableUpdates") or params.get_bool("SnoozeUpdate") + startup_conditions["up_to_date"] = (params.get("OfflineMode") and params.get("FireTheBabysitter")) or params.get("Offroad_ConnectivityNeeded") is None or params.get_bool("DisableUpdates") or params.get_bool("SnoozeUpdate") startup_conditions["not_uninstalling"] = not params.get_bool("DoUninstall") startup_conditions["accepted_terms"] = params.get("HasAcceptedTerms") == terms_version diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 8957551..3dae154 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -160,7 +160,7 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { left_widget->addWidget(new DriveStats); left_widget->setStyleSheet("border-radius: 10px;"); - left_widget->setCurrentIndex(uiState()->hasPrime() ? 0 : true ? 2 : 1); + left_widget->setCurrentIndex(params.getBool("DriveStats") ? 2 : uiState()->hasPrime() ? 0 : 1); connect(uiState(), &UIState::primeChanged, [=](bool prime) { left_widget->setCurrentIndex(prime ? 0 : 1); }); diff --git a/selfdrive/ui/qt/network/networking.cc b/selfdrive/ui/qt/network/networking.cc index 80c481b..a14e74b 100644 --- a/selfdrive/ui/qt/network/networking.cc +++ b/selfdrive/ui/qt/network/networking.cc @@ -205,14 +205,6 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid }); list->addItem(hiddenNetworkButton); - // Disable onroad uploads toggle - const bool disableOnroadUploads = params.getBool("DisableOnroadUploads"); - disableOnroadUploadsToggle = new ToggleControl(tr("Disable Onroad Uploads"), tr("Prevent large data uploads when onroad."), "", disableOnroadUploads); - QObject::connect(disableOnroadUploadsToggle, &ToggleControl::toggleFlipped, [=](bool state) { - params.putBool("DisableOnroadUploads", state); - }); - list->addItem(disableOnroadUploadsToggle); - // Set initial config wifi->updateGsmSettings(roamingEnabled, QString::fromStdString(params.get("GsmApn")), metered); diff --git a/selfdrive/ui/qt/network/networking.h b/selfdrive/ui/qt/network/networking.h index 3a4dff9..9b6af00 100644 --- a/selfdrive/ui/qt/network/networking.h +++ b/selfdrive/ui/qt/network/networking.h @@ -67,9 +67,6 @@ private: WifiManager* wifi = nullptr; Params params; - // FrogPilot variables - ToggleControl *disableOnroadUploadsToggle; - signals: void backPress(); void requestWifiScreen(); diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 64bccf3..bab606e 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -136,29 +136,29 @@ void OnroadWindow::mousePressEvent(QMouseEvent* e) { if (isMaxSpeedClicked || isSpeedClicked || isSpeedLimitClicked) { // Check if the click was within the max speed area if (isMaxSpeedClicked) { - reverseCruise = !params.getBool("ReverseCruise"); - params.putBoolNonBlocking("ReverseCruise", reverseCruise); + bool currentReverseCruise = !params.getBool("ReverseCruise"); + params.putBoolNonBlocking("ReverseCruise", currentReverseCruise); if (!params.getBool("QOLControls")) { params.putBoolNonBlocking("QOLControls", true); } - paramsMemory.putBoolNonBlocking("FrogPilotTogglesUpdated", true); // Check if the click was within the speed text area } else if (isSpeedClicked) { - hideSpeed = !params.getBool("HideSpeed"); - params.putBoolNonBlocking("HideSpeed", hideSpeed); + bool currentHideSpeed = !params.getBool("HideSpeed"); + params.putBoolNonBlocking("HideSpeed", currentHideSpeed); if (!params.getBool("QOLVisuals")) { params.putBoolNonBlocking("QOLVisuals", true); } } else { - showSLCOffset = !params.getBool("ShowSLCOffset"); - params.putBoolNonBlocking("ShowSLCOffset", showSLCOffset); + bool currentShowSLCOffset = !params.getBool("ShowSLCOffset"); + params.putBoolNonBlocking("ShowSLCOffset", currentShowSLCOffset); if (!params.getBool("QOLVisuals")) { params.putBoolNonBlocking("QOLVisuals", true); } } widgetClicked = true; + paramsMemory.putBoolNonBlocking("FrogPilotTogglesUpdated", true); // If the click wasn't for anything specific, change the value of "ExperimentalMode" - } else if (scene.experimental_mode_via_press && e->pos() != timeoutPoint) { + } else if (scene.experimental_mode_via_screen && e->pos() != timeoutPoint) { if (clickTimer.isActive()) { clickTimer.stop(); if (scene.conditional_experimental) { @@ -179,7 +179,7 @@ void OnroadWindow::mousePressEvent(QMouseEvent* e) { // Switch between map and sidebar when using navigate on openpilot bool sidebarVisible = geometry().x() > 0; bool show_map = uiState()->scene.navigate_on_openpilot ? sidebarVisible : !sidebarVisible; - if (!scene.experimental_mode_via_press || map->isVisible()) { + if (!scene.experimental_mode_via_screen || map->isVisible()) { map->setVisible(show_map && !map->isVisible()); } } @@ -385,7 +385,7 @@ void ExperimentalButton::changeMode() { Params paramsMemory = Params("/dev/shm/params"); const auto cp = (*uiState()->sm)["carParams"].getCarParams(); - bool can_change = hasLongitudinalControl(cp) && (params.getBool("ExperimentalModeConfirmed") || scene.experimental_mode_via_press); + bool can_change = hasLongitudinalControl(cp) && (params.getBool("ExperimentalModeConfirmed") || scene.experimental_mode_via_screen); if (can_change) { if (scene.conditional_experimental) { int override_value = (scene.conditional_status >= 1 && scene.conditional_status <= 4) ? 0 : scene.conditional_status >= 5 ? 3 : 4; @@ -432,11 +432,11 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { QPixmap img = wheelIcon ? engage_img : (experimental_mode ? experimental_img : engage_img); QColor background_color = wheelIcon && !isDown() && engageable ? + (scene.always_on_lateral_active ? QColor(10, 186, 181, 255) : (scene.conditional_status == 1 ? QColor(255, 246, 0, 255) : (experimental_mode ? QColor(218, 111, 37, 241) : - (scene.navigate_on_openpilot ? QColor(49, 161, 238, 255) : QColor(0, 0, 0, 166)))) : - (scene.always_on_lateral_active ? QColor(10, 186, 181, 255) : - QColor(0, 0, 0, 166)); + (scene.navigate_on_openpilot ? QColor(49, 161, 238, 255) : QColor(0, 0, 0, 166))))) : + QColor(0, 0, 0, 166); if (!scene.show_driver_camera) { if (rotatingWheel || firefoxRandomEventTriggered) { @@ -524,8 +524,8 @@ void AnnotatedCameraWidget::updateState(const UIState &s) { speedLimit = speedLimit - (showSLCOffset ? slcSpeedLimitOffset : 0); } - has_us_speed_limit = (nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::MUTCD) || slcSpeedLimit; - has_eu_speed_limit = (nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::VIENNA); + has_us_speed_limit = (nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::MUTCD) || (slcSpeedLimit && !useViennaSLCSign); + has_eu_speed_limit = (nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::VIENNA) || (slcSpeedLimit && useViennaSLCSign); is_metric = s.scene.is_metric; speedUnit = s.scene.is_metric ? tr("km/h") : tr("mph"); hideBottomIcons = (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE || customSignals && (turnSignalLeft || turnSignalRight)) || showDriverCamera; @@ -581,7 +581,8 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) { QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size); if (is_cruise_set && cruiseAdjustment) { float transition = qBound(0.0f, 4.0f * (cruiseAdjustment / setSpeed), 1.0f); - QColor min = whiteColor(75), max = redColor(75); + QColor min = whiteColor(75); + QColor max = redColor(75); p.setPen(QPen(QColor::fromRgbF( min.redF() + transition * (max.redF() - min.redF()), @@ -1122,7 +1123,8 @@ void AnnotatedCameraWidget::paintEvent(QPaintEvent *event) { void AnnotatedCameraWidget::showEvent(QShowEvent *event) { CameraWidget::showEvent(event); - ui_update_params(uiState()); + std::thread updateFrogPilotParams(ui_update_params, uiState()); + updateFrogPilotParams.detach(); prev_draw_t = millis_since_boot(); } @@ -1146,15 +1148,6 @@ void AnnotatedCameraWidget::initializeFrogPilotWidgets() { main_layout->addLayout(bottom_layout); - if (params.getBool("QOLControls")) { - reverseCruise = params.getBool("ReverseCruise"); - } - - if (params.getBool("QOLVisuals")) { - hideSpeed = params.getBool("HideSpeed"); - showSLCOffset = params.getBool("ShowSLCOffset"); - } - // Custom themes configuration themeConfiguration = { {1, {QString("frog_theme"), {QColor(23, 134, 68, 242), {{0.0, QBrush(QColor::fromHslF(144 / 360., 0.71, 0.31, 0.9))}, @@ -1200,6 +1193,7 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) { customColors = scene.custom_colors; desiredFollow = scene.desired_follow; experimentalMode = scene.experimental_mode; + hideSpeed = scene.hide_speed; laneWidthLeft = scene.lane_width_left; laneWidthRight = scene.lane_width_right; leadInfo = scene.lead_info; @@ -1208,8 +1202,10 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) { obstacleDistance = scene.obstacle_distance; obstacleDistanceStock = scene.obstacle_distance_stock; onroadAdjustableProfiles = scene.personalities_via_screen; + reverseCruise = scene.reverse_cruise; roadNameUI = scene.road_name_ui; showDriverCamera = scene.show_driver_camera; + showSLCOffset = scene.show_slc_offset; slcOverridden = scene.speed_limit_overridden; slcOverriddenSpeed = scene.speed_limit_overridden_speed; slcSpeedLimit = scene.speed_limit; @@ -1218,6 +1214,7 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) { turnSignalLeft = scene.turn_signal_left; turnSignalRight = scene.turn_signal_right; useSI = scene.use_si; + useViennaSLCSign = scene.use_vienna_slc_sign; if (!showDriverCamera) { if (leadInfo) { diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index a5a4cc6..07c1c3f 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -17,9 +17,6 @@ const int btn_size = 192; const int img_size = (btn_size / 4) * 3; // FrogPilot global variables -static bool hideSpeed; -static bool reverseCruise; -static bool showSLCOffset; static double fps; // ***** onroad widgets ***** @@ -191,16 +188,20 @@ private: bool compass; bool conditionalExperimental; bool experimentalMode; + bool hideSpeed; bool leadInfo; bool mapOpen; bool muteDM; bool onroadAdjustableProfiles; + bool reverseCruise; bool roadNameUI; bool showDriverCamera; + bool showSLCOffset; bool slcOverridden; bool turnSignalLeft; bool turnSignalRight; bool useSI; + bool useViennaSLCSign; double maxAcceleration; float cruiseAdjustment; float laneWidthLeft; @@ -223,6 +224,8 @@ private: QTimer *animationTimer; size_t animationFrameIndex; + inline QColor greenColor(int alpha = 242) { return QColor(23, 134, 68, alpha); } + std::unordered_map>>> themeConfiguration; std::vector signalImgVector; diff --git a/selfdrive/ui/qt/sidebar.cc b/selfdrive/ui/qt/sidebar.cc index f76af4b..16b890c 100644 --- a/selfdrive/ui/qt/sidebar.cc +++ b/selfdrive/ui/qt/sidebar.cc @@ -24,7 +24,7 @@ void Sidebar::drawMetric(QPainter &p, const QPair &label, QCol p.drawText(rect.adjusted(22, 0, 0, 0), Qt::AlignCenter, label.first + "\n" + label.second); } -Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false) { +Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false), scene(uiState()->scene) { home_img = loadPixmap("../assets/images/button_home.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); @@ -36,7 +36,6 @@ Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed( setFixedWidth(300); QObject::connect(uiState(), &UIState::uiUpdate, this, &Sidebar::updateState); - QObject::connect(uiState(), &UIState::uiUpdateFrogPilotParams, this, &Sidebar::updateFrogPilotParams); pm = std::make_unique>({"userFlag"}); @@ -68,7 +67,11 @@ Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed( settings_imgs[key] = loadPixmap(paths[2], settings_btn.size(), Qt::IgnoreAspectRatio); } - updateFrogPilotParams(); + home_img = home_imgs[scene.custom_icons]; + flag_img = flag_imgs[scene.custom_icons]; + settings_img = settings_imgs[scene.custom_icons]; + + currentColors = themeConfiguration[scene.custom_colors].second; } void Sidebar::mousePressEvent(QMouseEvent *event) { @@ -144,6 +147,12 @@ void Sidebar::updateState(const UIState &s) { setProperty("netStrength", strength > 0 ? strength + 1 : 0); // FrogPilot properties + home_img = home_imgs[scene.custom_icons]; + flag_img = flag_imgs[scene.custom_icons]; + settings_img = settings_imgs[scene.custom_icons]; + + currentColors = themeConfiguration[scene.custom_colors].second; + auto frogpilotDeviceState = sm["frogpilotDeviceState"].getFrogpilotDeviceState(); int maxTempC = deviceState.getMaxTempC(); @@ -227,19 +236,6 @@ void Sidebar::updateState(const UIState &s) { setProperty("pandaStatus", QVariant::fromValue(pandaStatus)); } -void Sidebar::updateFrogPilotParams() { - // Update FrogPilot parameters upon toggle change - isCustomTheme = params.getBool("CustomTheme"); - customColors = isCustomTheme ? params.getInt("CustomColors") : 0; - customIcons = isCustomTheme ? params.getInt("CustomIcons") : 0; - - home_img = home_imgs[customIcons]; - flag_img = flag_imgs[customIcons]; - settings_img = settings_imgs[customIcons]; - - currentColors = themeConfiguration[customColors].second; -} - void Sidebar::paintEvent(QPaintEvent *event) { QPainter p(this); p.setPen(Qt::NoPen); diff --git a/selfdrive/ui/qt/sidebar.h b/selfdrive/ui/qt/sidebar.h index c807b0f..e3a4d55 100644 --- a/selfdrive/ui/qt/sidebar.h +++ b/selfdrive/ui/qt/sidebar.h @@ -34,9 +34,6 @@ public slots: void offroadTransition(bool offroad); void updateState(const UIState &s); - // FrogPilot slots - void updateFrogPilotParams(); - protected: void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *event) override; @@ -70,6 +67,7 @@ private: // FrogPilot variables Params params; + UIScene &scene; ItemStatus cpu_status, memory_status, storage_status; @@ -80,13 +78,10 @@ private: std::vector currentColors; bool isCPU; - bool isCustomTheme; bool isFahrenheit; bool isGPU; bool isMemoryUsage; bool isNumericalTemp; bool isStorageLeft; bool isStorageUsed; - int customColors; - int customIcons; }; diff --git a/selfdrive/ui/qt/widgets/offroad_alerts.cc b/selfdrive/ui/qt/widgets/offroad_alerts.cc index b5140cd..f9db008 100644 --- a/selfdrive/ui/qt/widgets/offroad_alerts.cc +++ b/selfdrive/ui/qt/widgets/offroad_alerts.cc @@ -37,7 +37,12 @@ AbstractAlert::AbstractAlert(bool hasRebootBtn, QWidget *parent) : QFrame(parent disable_check_btn->setFixedSize(625, 125); footer_layout->addWidget(disable_check_btn, 1, Qt::AlignBottom | Qt::AlignCenter); QObject::connect(disable_check_btn, &QPushButton::clicked, [=]() { - params.putBool("OfflineMode", true); + if (!params.getBool("FireTheBabysitter")) { + params.putBool("FireTheBabysitter", true); + } + if (!params.getBool("OfflineMode")) { + params.putBool("OfflineMode", true); + } Hardware::reboot(); }); QObject::connect(disable_check_btn, &QPushButton::clicked, this, &AbstractAlert::dismiss); diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 5b6451b..8e17de7 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -1,6 +1,7 @@ import math import numpy as np import time +import threading import wave from typing import Dict, Optional, Tuple @@ -167,7 +168,8 @@ class Soundd: # Update FrogPilot parameters if self.params_memory.get_bool("FrogPilotTogglesUpdated"): - self.update_frogpilot_params() + updateFrogPilotParams = threading.Thread(target=self.update_frogpilot_params) + updateFrogPilotParams.start() def update_frogpilot_params(self): self.silent_mode = self.params.get_bool("SilentMode") diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 4597f75..687acd0 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -309,9 +309,11 @@ void ui_update_params(UIState *s) { scene.road_name_ui = params.getBool("RoadNameUI") && scene.custom_onroad_ui; scene.show_fps = params.getBool("ShowFPS") && scene.custom_onroad_ui; scene.use_si = params.getBool("UseSI") && scene.custom_onroad_ui; + scene.use_vienna_slc_sign = params.getBool("UseVienna") && scene.custom_onroad_ui; scene.custom_theme = params.getBool("CustomTheme"); scene.custom_colors = scene.custom_theme ? params.getInt("CustomColors") : 0; + scene.custom_icons = scene.custom_theme ? params.getInt("CustomIcons") : 0; scene.custom_signals = scene.custom_theme ? params.getInt("CustomSignals") : 0; scene.model_ui = params.getBool("ModelUI"); @@ -323,12 +325,17 @@ void ui_update_params(UIState *s) { scene.unlimited_road_ui_length = params.getBool("UnlimitedLength") && scene.model_ui; scene.driver_camera = params.getBool("DriverCamera"); - scene.experimental_mode_via_press = params.getBool("ExperimentalModeViaPress"); + scene.experimental_mode_via_screen = params.getBool("ExperimentalModeViaScreen") && params.getBool("ExperimentalModeActivation"); scene.mute_dm = params.getBool("MuteDM") && params.getBool("FireTheBabysitter"); scene.personalities_via_screen = (params.getInt("AdjustablePersonalities") == 2 || params.getInt("AdjustablePersonalities") == 3); + scene.quality_of_life_controls = params.getBool("QOLControls"); + scene.reverse_cruise = params.getBool("ReverseCruise") && scene.quality_of_life_controls; + scene.quality_of_life_visuals = params.getBool("QOLVisuals"); - scene.full_map = params.getBool("QOLVisuals") && scene.quality_of_life_visuals; + scene.full_map = params.getBool("FullMap") && scene.quality_of_life_visuals; + scene.hide_speed = params.getBool("HideSpeed") && scene.quality_of_life_visuals; + scene.show_slc_offset = params.getBool("ShowSLCOffset") && scene.quality_of_life_visuals; scene.random_events = params.getBool("RandomEvents"); scene.rotating_wheel = params.getBool("RotatingWheel"); @@ -385,8 +392,7 @@ UIState::UIState(QObject *parent) : QObject(parent) { wifi = new WifiManager(this); - scene.screen_brightness = params.getInt("ScreenBrightness"); - + ui_update_params(this); setDefaultParams(); } @@ -403,8 +409,8 @@ void UIState::update() { // Update FrogPilot variables when they are changed Params paramsMemory{"/dev/shm/params"}; if (paramsMemory.getBool("FrogPilotTogglesUpdated")) { - ui_update_params(this); - emit uiUpdateFrogPilotParams(); + std::thread updateFrogPilotParams(ui_update_params, this); + updateFrogPilotParams.detach(); } // FrogPilot live variables that need to be constantly checked diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index bedf45b..91346ea 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -184,18 +184,22 @@ typedef struct UIScene { bool driver_camera; bool enabled; bool experimental_mode; - bool experimental_mode_via_press; + bool experimental_mode_via_screen; bool full_map; + bool hide_speed; bool lead_info; bool map_open; bool model_ui; bool mute_dm; bool personalities_via_screen; + bool quality_of_life_controls; bool quality_of_life_visuals; bool random_events; + bool reverse_cruise; bool road_name_ui; bool rotating_wheel; bool show_driver_camera; + bool show_slc_offset; bool show_fps; bool speed_limit_controller; bool speed_limit_overridden; @@ -204,6 +208,7 @@ typedef struct UIScene { bool turn_signal_right; bool unlimited_road_ui_length; bool use_si; + bool use_vienna_slc_sign; float adjusted_cruise; float lane_line_width; float lane_width_left; @@ -221,6 +226,7 @@ typedef struct UIScene { int conditional_status; int current_random_event; int custom_colors; + int custom_icons; int custom_signals; int desired_follow; int obstacle_distance; @@ -265,9 +271,6 @@ signals: void primeChanged(bool prime); void primeTypeChanged(PrimeType prime_type); - // FrogPilot signals - void uiUpdateFrogPilotParams(); - private slots: void update(); diff --git a/selfdrive/updated.py b/selfdrive/updated.py index 2796690..0bba9eb 100644 --- a/selfdrive/updated.py +++ b/selfdrive/updated.py @@ -194,7 +194,6 @@ def finalize_update() -> None: # FrogPilot update functions params = Params() params.put("Updated", datetime.datetime.now().astimezone(ZoneInfo('America/Phoenix')).strftime("%B %d, %Y - %I:%M%p")) - params.remove("OfflineMode") # Reset the param since the user has internet connection again def handle_agnos_update() -> None: from openpilot.system.hardware.tici.agnos import flash_agnos_update, get_target_slot_number @@ -227,7 +226,7 @@ class Updater: self._has_internet: bool = False # FrogPilot variables - self.disable_internet_check = self.params.get_bool("OfflineMode") + self.disable_internet_check = self.params.get_bool("OfflineMode") and self.params.get_bool("FireTheBabysitter") @property def has_internet(self) -> bool: