From d37a75047142da2aae4006f656eb89ad601e0873 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 21 Mar 2025 23:45:09 -0500 Subject: [PATCH 1/6] feat: Show alert on user flag event --- cereal/log.capnp | 1 + selfdrive/selfdrived/events.py | 10 +++++++++- selfdrive/selfdrived/selfdrived.py | 10 +++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cereal/log.capnp b/cereal/log.capnp index 7b6076311f..c2d64c16ec 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -126,6 +126,7 @@ struct OnroadEvent @0xc4fa6047f024e718 { espActive @90; personalityChanged @91; aeb @92; + userFlag @94; soundsUnavailableDEPRECATED @47; } diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index ee2c418b6e..18471c5dca 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -889,7 +889,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # causing the connection to the panda to be lost EventName.usbError: { ET.SOFT_DISABLE: soft_disable_alert("USB Error: Reboot Your Device"), - ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device", ""), + ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device"), ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"), }, @@ -977,6 +977,14 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { ET.WARNING: personality_changed_alert, }, + EventName.userFlag: { + ET.PERMANENT: Alert( + "Bookmark Saved", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 1. + ), + }, } diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index c7320f9350..b452fec054 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -69,7 +69,7 @@ class SelfdriveD: # TODO: de-couple selfdrived with card/conflate on carState without introducing controls mismatches self.car_state_sock = messaging.sub_sock('carState', timeout=20) - ignore = self.sensor_packets + self.gps_packets + ['alertDebug'] + ignore = self.sensor_packets + self.gps_packets + ['alertDebug', 'userFlag'] if SIMULATION: ignore += ['driverCameraState', 'managerState'] if REPLAY: @@ -78,7 +78,7 @@ class SelfdriveD: self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration', 'carOutput', 'driverMonitoringState', 'longitudinalPlan', 'livePose', 'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters', - 'controlsState', 'carControl', 'driverAssistance', 'alertDebug'] + \ + 'controlsState', 'carControl', 'driverAssistance', 'alertDebug', 'userFlag'] + \ self.camera_packets + self.sensor_packets + self.gps_packets, ignore_alive=ignore, ignore_avg_freq=ignore, ignore_valid=ignore, frequency=int(1/DT_CTRL)) @@ -361,13 +361,17 @@ class SelfdriveD: if self.sm['modelV2'].frameDropPerc > 20: self.events.add(EventName.modeldLagging) - # decrement personality on distance button press + # Decrement personality on distance button press if self.CP.openpilotLongitudinalControl: if any(not be.pressed and be.type == ButtonType.gapAdjustCruise for be in CS.buttonEvents): self.personality = (self.personality - 1) % 3 self.params.put_nonblocking('LongitudinalPersonality', str(self.personality)) self.events.add(EventName.personalityChanged) + # Check for user flag (bookmark) press + if self.sm.updated['userFlag']: + self.events.add(EventName.userFlag) + def data_sample(self): car_state = messaging.recv_one(self.car_state_sock) CS = car_state.carState if car_state else self.CS_prev From f1da6a4f5f555d4db50b47fb68ce74ae7737b8af Mon Sep 17 00:00:00 2001 From: David Date: Fri, 21 Mar 2025 23:45:58 -0500 Subject: [PATCH 2/6] feat: Temporarily update border status on user flag to match connect timeline --- selfdrive/ui/ui.cc | 30 ++++++++++++++++++++++-------- selfdrive/ui/ui.h | 3 +++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index ec3d40961d..5dde3e0c90 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -68,13 +68,27 @@ void ui_update_params(UIState *s) { } void UIState::updateStatus() { - if (scene.started && sm->updated("selfdriveState")) { - auto ss = (*sm)["selfdriveState"].getSelfdriveState(); - auto state = ss.getState(); - if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) { - status = STATUS_OVERRIDE; - } else { - status = ss.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; + if (scene.started) { + // Check for user flag events + if (sm->updated("userFlag")) { + user_flag_active_frame = sm->frame; + } + + // Show user flag status for 1 second after event is received + if (user_flag_active_frame > 0 && (sm->frame - user_flag_active_frame) < (1 * UI_FREQ)) { + status = STATUS_USER_FLAG; + return; // Skip rest of status checks for this frame + } + + // Check for selfdrive state status + if (sm->updated("selfdriveState")) { + auto ss = (*sm)["selfdriveState"].getSelfdriveState(); + auto state = ss.getState(); + if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) { + status = STATUS_OVERRIDE; + } else { + status = ss.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; + } } } @@ -93,7 +107,7 @@ UIState::UIState(QObject *parent) : QObject(parent) { sm = std::make_unique(std::vector{ "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", - "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", + "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", "userFlag" }); prime_state = new PrimeState(this); language = QString::fromStdString(Params().get("LanguageSetting")); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 6ff67cacde..706d3acc24 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -42,12 +42,14 @@ typedef enum UIStatus { STATUS_DISENGAGED, STATUS_OVERRIDE, STATUS_ENGAGED, + STATUS_USER_FLAG, } UIStatus; const QColor bg_colors [] = { [STATUS_DISENGAGED] = QColor(0x17, 0x33, 0x49, 0xc8), [STATUS_OVERRIDE] = QColor(0x91, 0x9b, 0x95, 0xf1), [STATUS_ENGAGED] = QColor(0x17, 0x86, 0x44, 0xf1), + [STATUS_USER_FLAG] = QColor(0xff, 0xff, 0x00, 0xf1), }; typedef struct UIScene { @@ -77,6 +79,7 @@ public: UIScene scene = {}; QString language; PrimeState *prime_state; + uint64_t user_flag_active_frame = 0; // frame when user flag was received signals: void uiUpdate(const UIState &s); From 1777be866a5f15f2e3280a9872896c3b65ea19c1 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 26 Mar 2025 15:15:12 -0500 Subject: [PATCH 3/6] Revert "feat: Temporarily update border status on user flag to match connect timeline" This reverts commit f1da6a4f5f555d4db50b47fb68ce74ae7737b8af. --- selfdrive/ui/ui.cc | 30 ++++++++---------------------- selfdrive/ui/ui.h | 3 --- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 5dde3e0c90..ec3d40961d 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -68,27 +68,13 @@ void ui_update_params(UIState *s) { } void UIState::updateStatus() { - if (scene.started) { - // Check for user flag events - if (sm->updated("userFlag")) { - user_flag_active_frame = sm->frame; - } - - // Show user flag status for 1 second after event is received - if (user_flag_active_frame > 0 && (sm->frame - user_flag_active_frame) < (1 * UI_FREQ)) { - status = STATUS_USER_FLAG; - return; // Skip rest of status checks for this frame - } - - // Check for selfdrive state status - if (sm->updated("selfdriveState")) { - auto ss = (*sm)["selfdriveState"].getSelfdriveState(); - auto state = ss.getState(); - if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) { - status = STATUS_OVERRIDE; - } else { - status = ss.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; - } + if (scene.started && sm->updated("selfdriveState")) { + auto ss = (*sm)["selfdriveState"].getSelfdriveState(); + auto state = ss.getState(); + if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) { + status = STATUS_OVERRIDE; + } else { + status = ss.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; } } @@ -107,7 +93,7 @@ UIState::UIState(QObject *parent) : QObject(parent) { sm = std::make_unique(std::vector{ "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", - "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", "userFlag" + "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", }); prime_state = new PrimeState(this); language = QString::fromStdString(Params().get("LanguageSetting")); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 706d3acc24..6ff67cacde 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -42,14 +42,12 @@ typedef enum UIStatus { STATUS_DISENGAGED, STATUS_OVERRIDE, STATUS_ENGAGED, - STATUS_USER_FLAG, } UIStatus; const QColor bg_colors [] = { [STATUS_DISENGAGED] = QColor(0x17, 0x33, 0x49, 0xc8), [STATUS_OVERRIDE] = QColor(0x91, 0x9b, 0x95, 0xf1), [STATUS_ENGAGED] = QColor(0x17, 0x86, 0x44, 0xf1), - [STATUS_USER_FLAG] = QColor(0xff, 0xff, 0x00, 0xf1), }; typedef struct UIScene { @@ -79,7 +77,6 @@ public: UIScene scene = {}; QString language; PrimeState *prime_state; - uint64_t user_flag_active_frame = 0; // frame when user flag was received signals: void uiUpdate(const UIState &s); From d28851933a8cffc952f9ad690fbd7e3bb37d814a Mon Sep 17 00:00:00 2001 From: David Date: Wed, 26 Mar 2025 16:38:56 -0500 Subject: [PATCH 4/6] feat: Increase alert duration to 1.5 seconds --- selfdrive/selfdrived/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index 18471c5dca..fb80128416 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -982,7 +982,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { "Bookmark Saved", "", AlertStatus.normal, AlertSize.small, - Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 1. + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 1.5 ), }, } From 9baf21ee3a44b35a7981b7beabc7ca768c7bc0fd Mon Sep 17 00:00:00 2001 From: David Date: Mon, 14 Apr 2025 21:20:24 -0500 Subject: [PATCH 5/6] remove audible alert for bookmark event --- selfdrive/selfdrived/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index fb80128416..699aced8c1 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -982,7 +982,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { "Bookmark Saved", "", AlertStatus.normal, AlertSize.small, - Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 1.5 + Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.5 ), }, } From f8f33e58c3b299737b10802a87d973f16bf60540 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 15 Apr 2025 10:53:47 -0500 Subject: [PATCH 6/6] refactor: Use NormalPermamentAlert for user flag alert --- selfdrive/selfdrived/events.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index 699aced8c1..a8762857b5 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -978,12 +978,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { }, EventName.userFlag: { - ET.PERMANENT: Alert( - "Bookmark Saved", - "", - AlertStatus.normal, AlertSize.small, - Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.5 - ), + ET.PERMANENT: NormalPermanentAlert("Bookmark Saved", duration=1.5), }, }