From 85d2653fdac1145a31173131844509012d700bfd Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 17:50:35 -0400 Subject: [PATCH 1/5] Speed Limit Assist: No Easter Eggs --- .../controls/lib/speed_limit/speed_limit_assist.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py index bb03a9eb1c..5d798949a9 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py @@ -54,7 +54,6 @@ class SpeedLimitAssist: self.frame = -1 self.long_engaged_timer = 0 self.pre_active_timer = 0 - self.speed_limit_changed_timer = 0 self.is_metric = self.params.get_bool("IsMetric") self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist self.long_enabled = False @@ -288,7 +287,6 @@ class SpeedLimitAssist: def update_state_machine_non_pcm_long(self): self.long_engaged_timer = max(0, self.long_engaged_timer - 1) self.pre_active_timer = max(0, self.pre_active_timer - 1) - self.speed_limit_changed_timer = max(0, self.speed_limit_changed_timer - 1) # ACTIVE, ADAPTING, PENDING, PRE_ACTIVE, INACTIVE if self.state != SpeedLimitAssistState.disabled: @@ -302,8 +300,6 @@ class SpeedLimitAssist: self.state = SpeedLimitAssistState.inactive elif self.speed_limit_changed and self.apply_confirm_speed_threshold: - self.speed_limit_changed_timer = int(SPEED_LIMIT_CHANGED_HOLD_PERIOD / DT_MDL) - elif self.speed_limit_changed_timer <= 0: self.state = SpeedLimitAssistState.preActive self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) @@ -318,8 +314,6 @@ class SpeedLimitAssist: # INACTIVE elif self.state == SpeedLimitAssistState.inactive: if self.speed_limit_changed: - self.speed_limit_changed_timer = int(SPEED_LIMIT_CHANGED_HOLD_PERIOD / DT_MDL) - elif self.speed_limit_changed_timer <= 0: self.state = SpeedLimitAssistState.preActive self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) elif self._update_non_pcm_long_confirmed_state(): From ae901d15624b0b5849e8b09a3a67180a5b611b5b Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 20:17:53 -0400 Subject: [PATCH 2/5] ui: add Display settings panel (#1301) * init * onroad brightness control * new icon * update touch handlling * don't touch me * now i feel every touch * resolve review comments * tired of this shit * ugh * just panel for now * more --------- Co-authored-by: nayan --- selfdrive/ui/sunnypilot/SConscript | 1 + .../qt/offroad/settings/display_panel.cc | 29 +++++++++++++++++++ .../qt/offroad/settings/display_panel.h | 26 +++++++++++++++++ .../qt/offroad/settings/settings.cc | 2 ++ .../selfdrive/assets/offroad/icon_display.png | 3 ++ 5 files changed, 61 insertions(+) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h create mode 100644 sunnypilot/selfdrive/assets/offroad/icon_display.png diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 5c2680b299..a3c03ee03f 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -24,6 +24,7 @@ qt_src = [ "sunnypilot/qt/offroad/offroad_home.cc", "sunnypilot/qt/offroad/settings/developer_panel.cc", "sunnypilot/qt/offroad/settings/device_panel.cc", + "sunnypilot/qt/offroad/settings/display_panel.cc", "sunnypilot/qt/offroad/settings/lateral_panel.cc", "sunnypilot/qt/offroad/settings/longitudinal_panel.cc", "sunnypilot/qt/offroad/settings/max_time_offroad.cc", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc new file mode 100644 index 0000000000..e980840a8c --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h" + +DisplayPanel::DisplayPanel(QWidget *parent) : QWidget(parent) { + main_layout = new QStackedLayout(this); + ListWidgetSP *list = new ListWidgetSP(this, false); + + sunnypilotScreen = new QWidget(this); + QVBoxLayout* vlayout = new QVBoxLayout(sunnypilotScreen); + vlayout->setContentsMargins(50, 20, 50, 20); + + sunnypilotScroller = new ScrollViewSP(list, this); + vlayout->addWidget(sunnypilotScroller); + main_layout->addWidget(sunnypilotScreen); +} + +void DisplayPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + refresh(); +} + +void DisplayPanel::refresh() { +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h new file mode 100644 index 0000000000..22e7303465 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +class DisplayPanel : public QWidget { + Q_OBJECT + +public: + explicit DisplayPanel(QWidget *parent = nullptr); + void showEvent(QShowEvent *event) override; + void refresh(); + +private: + QStackedLayout* main_layout = nullptr; + QWidget* sunnypilotScreen = nullptr; + ScrollViewSP *sunnypilotScroller = nullptr; + Params params; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc index 5415e75ea9..c712442df3 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc @@ -13,6 +13,7 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/software_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/sunnylink_panel.h" @@ -87,6 +88,7 @@ SettingsWindowSP::SettingsWindowSP(QWidget *parent) : SettingsWindow(parent) { PanelInfo(" " + tr("Steering"), new LateralPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_lateral.png"), PanelInfo(" " + tr("Cruise"), new LongitudinalPanel(this), "../assets/icons/speed_limit.png"), PanelInfo(" " + tr("Visuals"), new VisualsPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_visuals.png"), + PanelInfo(" " + tr("Display"), new DisplayPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_display.png"), PanelInfo(" " + tr("OSM"), new OsmPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_map.png"), PanelInfo(" " + tr("Trips"), new TripsPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_trips.png"), PanelInfo(" " + tr("Vehicle"), new VehiclePanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_vehicle.png"), diff --git a/sunnypilot/selfdrive/assets/offroad/icon_display.png b/sunnypilot/selfdrive/assets/offroad/icon_display.png new file mode 100644 index 0000000000..547977f522 --- /dev/null +++ b/sunnypilot/selfdrive/assets/offroad/icon_display.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:614767308d435d165a9ab78e3eac22ee15697d94066df8200ef32afb33ef8d60 +size 5698 From 49e58a253220cc32d503ba06824201e6990456ef Mon Sep 17 00:00:00 2001 From: Nayan Date: Tue, 30 Sep 2025 21:06:11 -0400 Subject: [PATCH 3/5] Device: Driving Screen Off (#1252) * init * onroad brightness control * new icon * update touch handlling * don't touch me * now i feel every touch * resolve review comments * tired of this shit * ugh * translate * duplicate * fix * adjust * update param in the same function * flip * format * reorder --------- Co-authored-by: Jason Wen --- common/params_keys.h | 3 + selfdrive/ui/sunnypilot/SConscript | 6 +- .../display/onroad_screen_brightness.cc | 63 +++++++++++++++++++ .../display/onroad_screen_brightness.h | 42 +++++++++++++ .../qt/offroad/settings/display_panel.cc | 11 ++++ .../qt/offroad/settings/display_panel.h | 2 + .../ui/sunnypilot/qt/onroad/onroad_home.cc | 2 + selfdrive/ui/sunnypilot/ui.cc | 24 +++++++ selfdrive/ui/sunnypilot/ui.h | 1 + selfdrive/ui/sunnypilot/ui_scene.h | 3 + selfdrive/ui/ui.cc | 7 +++ 11 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h diff --git a/common/params_keys.h b/common/params_keys.h index 5ba6b53108..1056a3903e 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -157,6 +157,9 @@ inline static std::unordered_map keys = { {"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}}, {"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}}, {"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}}, + {"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "100"}}, + {"OnroadScreenOffControl", {PERSISTENT | BACKUP, BOOL}}, + {"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "0"}}, {"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}}, {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}}, diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index a3c03ee03f..3f0e013d34 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -91,9 +91,13 @@ brand_settings_qt_src = [ "sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.cc", ] +display_panel_qt_src = [ + "sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc", +] sp_widgets_src = widgets_src + network_src -sp_qt_src = qt_src + lateral_panel_qt_src + vehicle_panel_qt_src + brand_settings_qt_src + longitudinal_panel_qt_src + osm_panel_qt_src +sp_qt_src = qt_src + lateral_panel_qt_src + vehicle_panel_qt_src + brand_settings_qt_src + \ + longitudinal_panel_qt_src + osm_panel_qt_src + display_panel_qt_src sp_qt_util = qt_util Export('sp_widgets_src', 'sp_qt_src', "sp_qt_util") diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc new file mode 100644 index 0000000000..3e9dc427bf --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h" + +OnroadScreenBrightnessControl::OnroadScreenBrightnessControl(const QString ¶m, const QString &title, + const QString &description, const QString &icon, + QWidget *parent) + : ExpandableToggleRow(param, title, description, icon, parent) { + auto *mainFrame = new QFrame(this); + auto *mainFrameLayout = new QGridLayout(); + mainFrame->setLayout(mainFrameLayout); + mainFrameLayout->setSpacing(0); + + onroadScreenOffTimer = new OptionControlSP( + "OnroadScreenOffTimer", + "", + "", + "", + {0, 11}, 1, true, &onroadScreenOffTimerOptions); + + onroadScreenBrightness = new OptionControlSP( + "OnroadScreenOffBrightness", + "", + "", + "", + {0, 100}, 10, true, nullptr, false); + + connect(onroadScreenOffTimer, &OptionControlSP::updateLabels, this, &OnroadScreenBrightnessControl::refresh); + connect(onroadScreenBrightness, &OptionControlSP::updateLabels, this, &OnroadScreenBrightnessControl::refresh); + onroadScreenOffTimer->setFixedWidth(280); + onroadScreenBrightness->setFixedWidth(280); + mainFrameLayout->addWidget(onroadScreenOffTimer, 0, 0, Qt::AlignLeft); + mainFrameLayout->addWidget(onroadScreenBrightness, 0, 1, Qt::AlignRight); + + addItem(mainFrame); + + refresh(); +} + +void OnroadScreenBrightnessControl::refresh() { + // Driving Screen Off Timer + int valTimer = std::atoi(params.get("OnroadScreenOffTimer").c_str()); + std::string labelTimer = ""; + labelTimer += "Delay"; + labelTimer += "
"; + labelTimer += (valTimer < 60 ? std::to_string(valTimer) + "s" : std::to_string(valTimer / 60) + "m"); + labelTimer += "
"; + onroadScreenOffTimer->setLabel(QString::fromStdString(labelTimer)); + + // Driving Screen Off Brightness + std::string valBrightness = params.get("OnroadScreenOffBrightness"); + std::string labelBrightness = ""; + labelBrightness += "Brightness"; + labelBrightness += "
"; + labelBrightness += (valBrightness == "0" ? " Screen Off" : valBrightness + "%"); + labelBrightness += "
"; + onroadScreenBrightness->setLabel(QString::fromStdString(labelBrightness)); +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h new file mode 100644 index 0000000000..02335d1ce6 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/expandable_row.h" + +static const QMap onroadScreenOffTimerOptions = { + {"0", "15"}, + {"1", "30"}, + {"2", "60"}, + {"3", "120"}, + {"4", "180"}, + {"5", "240"}, + {"6", "300"}, + {"7", "360"}, + {"8", "420"}, + {"9", "480"}, + {"10", "540"}, + {"11", "600"} +}; + +class OnroadScreenBrightnessControl : public ExpandableToggleRow { + Q_OBJECT + +public: + OnroadScreenBrightnessControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, + QWidget *parent = nullptr); + void refresh(); + +private: + Params params; + OptionControlSP *onroadScreenOffTimer; + OptionControlSP *onroadScreenBrightness; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc index e980840a8c..b441021ff3 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc @@ -15,6 +15,16 @@ DisplayPanel::DisplayPanel(QWidget *parent) : QWidget(parent) { QVBoxLayout* vlayout = new QVBoxLayout(sunnypilotScreen); vlayout->setContentsMargins(50, 20, 50, 20); + // Onroad Screen Off/Brightness + onroadScreenBrightnessControl = new OnroadScreenBrightnessControl( + "OnroadScreenOffControl", + tr("Driving Screen Off: Non-Critical Events"), + tr("Turn off device screen or reduce brightness after driving starts. " + "It automatically brightens again when screen is touched or a critical event occurs."), + "", + this); + list->addItem(onroadScreenBrightnessControl); + sunnypilotScroller = new ScrollViewSP(list, this); vlayout->addWidget(sunnypilotScroller); main_layout->addWidget(sunnypilotScreen); @@ -26,4 +36,5 @@ void DisplayPanel::showEvent(QShowEvent *event) { } void DisplayPanel::refresh() { + onroadScreenBrightnessControl->refresh(); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h index 22e7303465..1714c8a436 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h @@ -7,6 +7,7 @@ #pragma once +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" @@ -23,4 +24,5 @@ private: QWidget* sunnypilotScreen = nullptr; ScrollViewSP *sunnypilotScroller = nullptr; Params params; + OnroadScreenBrightnessControl *onroadScreenBrightnessControl = nullptr; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc b/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc index b26d1b828a..3f853e3363 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc @@ -25,8 +25,10 @@ void OnroadWindowSP::updateState(const UIStateSP &s) { void OnroadWindowSP::mousePressEvent(QMouseEvent *e) { OnroadWindow::mousePressEvent(e); + uiStateSP()->reset_onroad_sleep_timer(); } void OnroadWindowSP::offroadTransition(bool offroad) { OnroadWindow::offroadTransition(offroad); + uiStateSP()->reset_onroad_sleep_timer(); } diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index fd7365821c..6cbdeadf58 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -11,6 +11,16 @@ void UIStateSP::updateStatus() { UIState::updateStatus(); + + if (scene.started && scene.onroadScreenOffControl) { + auto selfdriveState = (*sm)["selfdriveState"].getSelfdriveState(); + if (selfdriveState.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE && + selfdriveState.getAlertStatus() != cereal::SelfdriveState::AlertStatus::NORMAL) { + reset_onroad_sleep_timer(); + } else if (scene.onroadScreenOffTimer > 0) { + scene.onroadScreenOffTimer--; + } + } } UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { @@ -55,6 +65,20 @@ void ui_update_params_sp(UIStateSP *s) { s->scene.standstill_timer = params.getBool("StandstillTimer"); s->scene.speed_limit_mode = std::atoi(params.get("SpeedLimitMode").c_str()); s->scene.road_name = params.getBool("RoadNameToggle"); + + // Onroad Screen Brightness + s->scene.onroadScreenOffBrightness = std::atoi(params.get("OnroadScreenOffBrightness").c_str()); + s->scene.onroadScreenOffControl = params.getBool("OnroadScreenOffControl"); + s->scene.onroadScreenOffTimerParam = std::atoi(params.get("OnroadScreenOffTimer").c_str()); + s->reset_onroad_sleep_timer(); +} + +void UIStateSP::reset_onroad_sleep_timer() { + if (scene.onroadScreenOffTimerParam >= 0 and scene.onroadScreenOffControl) { + scene.onroadScreenOffTimer = scene.onroadScreenOffTimerParam * UI_FREQ; + } else { + scene.onroadScreenOffTimer = -1; + } } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { diff --git a/selfdrive/ui/sunnypilot/ui.h b/selfdrive/ui/sunnypilot/ui.h index 393f997cbd..55dd43ad52 100644 --- a/selfdrive/ui/sunnypilot/ui.h +++ b/selfdrive/ui/sunnypilot/ui.h @@ -61,6 +61,7 @@ public: return user.user_id.toLower() != "unregisteredsponsor" && user.user_id.toLower() != "temporarysponsor"; }); } + void reset_onroad_sleep_timer(); signals: void sunnylinkRoleChanged(bool subscriber); diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h index 768cc5d7a1..7cfabb15c3 100644 --- a/selfdrive/ui/sunnypilot/ui_scene.h +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -12,4 +12,7 @@ typedef struct UISceneSP : UIScene { bool standstill_timer = false; int speed_limit_mode = 0; bool road_name = false; + int onroadScreenOffBrightness, onroadScreenOffTimer = 0; + bool onroadScreenOffControl; + int onroadScreenOffTimerParam; } UISceneSP; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 4cad883f7d..6bca2b7f7f 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -204,6 +204,13 @@ void Device::updateBrightness(const UIState &s) { brightness = 0; } + // Onroad Brightness Control +#ifdef SUNNYPILOT + if (awake && s.scene.started && s.scene.onroadScreenOffControl && s.scene.onroadScreenOffTimer == 0) { + brightness = s.scene.onroadScreenOffBrightness * 0.01 * brightness; + } +#endif + if (brightness != last_brightness) { if (!brightness_future.isRunning()) { brightness_future = QtConcurrent::run(Hardware::set_brightness, brightness); From f3ed57787050c330ca74c566dad2d7812753e7ba Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 22:37:13 -0400 Subject: [PATCH 4/5] Longitudinal: reimplement Gas Interceptor (comma Pedal) support (#1290) * init * bump * bump * bump * recheck openpilot long availability * bump * bump * bump * bump * bump * just base for now * bump * bump * bump * bump * flipped * apparently it's yucky, reverting most * bump * need to add for toyota * should've been remove * flipped * bump * no way * fix * test sdsu distance * final tuning for pedal * bump --- cereal/custom.capnp | 1 + opendbc_repo | 2 +- selfdrive/car/tests/test_car_interfaces.py | 2 +- selfdrive/controls/controlsd.py | 2 +- selfdrive/controls/lib/longcontrol.py | 10 +++++--- selfdrive/controls/tests/test_longcontrol.py | 27 +++++++++++--------- selfdrive/selfdrived/selfdrived.py | 2 +- sunnypilot/selfdrive/car/car_specific.py | 10 ++++++-- 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index c87ac0d2e0..674f109fc7 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -299,6 +299,7 @@ struct CarParamsSP @0x80ae746ee2596b11 { safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags pcmCruiseSpeed @3 :Bool; intelligentCruiseButtonManagementAvailable @4 :Bool; + enableGasInterceptor @5 :Bool; neuralNetworkLateralControl @2 :NeuralNetworkLateralControl; diff --git a/opendbc_repo b/opendbc_repo index 52d50f9841..dfcfacb667 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 52d50f984191d63cf6a79398b21df2d2e3b9236e +Subproject commit dfcfacb667c6ff131d0e620c36e118f14a84dc4a diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 7c7a563003..821767ee46 100644 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -60,7 +60,7 @@ class TestCarInterfaces: # Test controller initialization # TODO: wait until card refactor is merged to run controller a few times, # hypothesis also slows down significantly with just one more message draw - LongControl(car_params) + LongControl(car_params, car_params_sp) if car_params.steerControlType == CarParams.SteerControlType.angle: LatControlAngle(car_params, car_params_sp, car_interface) elif car_params.lateralTuning.which() == 'pid': diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 3751efc87a..3601ae310e 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -58,7 +58,7 @@ class Controls(ControlsExt, ModelStateBase): self.pose_calibrator = PoseCalibrator() self.calibrated_pose: Pose | None = None - self.LoC = LongControl(self.CP) + self.LoC = LongControl(self.CP, self.CP_SP) self.VM = VehicleModel(self.CP) self.LaC: LatControl if self.CP.steerControlType == car.CarParams.SteerControlType.angle: diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py index 6d4f922461..b8b00e2fb9 100644 --- a/selfdrive/controls/lib/longcontrol.py +++ b/selfdrive/controls/lib/longcontrol.py @@ -10,8 +10,11 @@ CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] LongCtrlState = car.CarControl.Actuators.LongControlState -def long_control_state_trans(CP, active, long_control_state, v_ego, +def long_control_state_trans(CP, CP_SP, active, long_control_state, v_ego, should_stop, brake_pressed, cruise_standstill): + # Gas Interceptor + cruise_standstill = cruise_standstill and not CP_SP.enableGasInterceptor + stopping_condition = should_stop starting_condition = (not should_stop and not cruise_standstill and @@ -45,8 +48,9 @@ def long_control_state_trans(CP, active, long_control_state, v_ego, return long_control_state class LongControl: - def __init__(self, CP): + def __init__(self, CP, CP_SP): self.CP = CP + self.CP_SP = CP_SP self.long_control_state = LongCtrlState.off self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), (CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV), @@ -61,7 +65,7 @@ class LongControl: self.pid.neg_limit = accel_limits[0] self.pid.pos_limit = accel_limits[1] - self.long_control_state = long_control_state_trans(self.CP, active, self.long_control_state, CS.vEgo, + self.long_control_state = long_control_state_trans(self.CP, self.CP_SP, active, self.long_control_state, CS.vEgo, should_stop, CS.brakePressed, CS.cruiseState.standstill) if self.long_control_state == LongCtrlState.off: diff --git a/selfdrive/controls/tests/test_longcontrol.py b/selfdrive/controls/tests/test_longcontrol.py index ab50810d89..cf0ab24e0b 100644 --- a/selfdrive/controls/tests/test_longcontrol.py +++ b/selfdrive/controls/tests/test_longcontrol.py @@ -1,4 +1,4 @@ -from cereal import car +from cereal import car, custom from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState, long_control_state_trans @@ -8,49 +8,52 @@ class TestLongControlStateTransition: def test_stay_stopped(self): CP = car.CarParams.new_message() + CP_SP = custom.CarParamsSP.new_message() active = True current_state = LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=True, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=True, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=True) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.pid active = False - next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.off def test_engage(): CP = car.CarParams.new_message() + CP_SP = custom.CarParamsSP.new_message() active = True current_state = LongCtrlState.off - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=True, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=True, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=True) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.pid def test_starting(): CP = car.CarParams.new_message(startingState=True, vEgoStarting=0.5) + CP_SP = custom.CarParamsSP.new_message() active = True current_state = LongCtrlState.starting - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.starting - next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.pid diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index a13c873fbe..4bc75021f7 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -159,7 +159,7 @@ class SelfdriveD(CruiseHelper): self.mads = ModularAssistiveDrivingSystem(self) self.icbm = IntelligentCruiseButtonManagement(self.CP, self.CP_SP) - self.car_events_sp = CarSpecificEventsSP(self.CP, self.params) + self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP) CruiseHelper.__init__(self, self.CP) diff --git a/sunnypilot/selfdrive/car/car_specific.py b/sunnypilot/selfdrive/car/car_specific.py index 7e6f300d73..97ce26429c 100644 --- a/sunnypilot/selfdrive/car/car_specific.py +++ b/sunnypilot/selfdrive/car/car_specific.py @@ -18,9 +18,9 @@ GearShifter = structs.CarState.GearShifter class CarSpecificEventsSP: - def __init__(self, CP: structs.CarParams, params): + def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP): self.CP = CP - self.params = params + self.CP_SP = CP_SP self.low_speed_alert = False @@ -42,4 +42,10 @@ class CarSpecificEventsSP: if self.low_speed_alert: events.add(EventName.belowSteerSpeed) + elif self.CP.brand == 'toyota': + if self.CP.openpilotLongitudinalControl: + if CS.cruiseState.standstill and not CS.brakePressed and self.CP_SP.enableGasInterceptor: + if events.has(EventName.resumeRequired): + events.remove(EventName.resumeRequired) + return events_sp From 92214b69d8e9045ea28e82c47debd1813a4af390 Mon Sep 17 00:00:00 2001 From: Nayan Date: Wed, 1 Oct 2025 12:37:10 -0400 Subject: [PATCH 5/5] feat: Green Traffic Light Alert (#1287) * init * fix * event * UI * events..for real * SP * ugh * toggles * read params first * stoopid it is * fix green light img * fix green light image. for real this time * move events to longitudinal_planner * move events to longitudinal_planner * move e2e alerts to separate class * green light alert only for this PR * fix * fixxxxxxx * blinky blink * blinky blink * slight cleanup * only used for params * a bit more * only when long is not engaged * too long * update description * always 3 seconds if not moving * initialize in constructor instead * less * rename * always init at 0 --------- Co-authored-by: Kumar <36933347+rav4kumar@users.noreply.github.com> Co-authored-by: Jason Wen --- cereal/custom.capnp | 6 ++ common/params_keys.h | 1 + .../qt/offroad/settings/visuals_panel.cc | 10 ++++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 55 +++++++++++++++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 8 +++ .../selfdrive/assets/images/green_light.png | 3 + .../controls/lib/e2e_alerts_helper.py | 50 +++++++++++++++++ .../controls/lib/longitudinal_planner.py | 10 +++- sunnypilot/selfdrive/selfdrived/events.py | 8 +++ 9 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 sunnypilot/selfdrive/assets/images/green_light.png create mode 100644 sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 674f109fc7..23e26a8ccb 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -149,6 +149,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { vTarget @4 :Float32; aTarget @5 :Float32; events @6 :List(OnroadEventSP.Event); + e2eAlerts @7 :E2eAlerts; struct DynamicExperimentalControl { state @0 :DynamicExperimentalControlState; @@ -246,6 +247,10 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { sccMap @2; speedLimitAssist @3; } + + struct E2eAlerts { + greenLightAlert @0 :Bool; + } } struct OnroadEventSP @0xda96579883444c35 { @@ -291,6 +296,7 @@ struct OnroadEventSP @0xda96579883444c35 { speedLimitActive @20; speedLimitChanged @21; speedLimitPending @22; + e2eChime @23; } } diff --git a/common/params_keys.h b/common/params_keys.h index 1056a3903e..b8cda83693 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -148,6 +148,7 @@ inline static std::unordered_map keys = { {"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}}, {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, + {"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index 10ead53774..07df99f726 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -49,6 +49,16 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { "", false, }, + { + "GreenLightAlert", + tr("Green Traffic Light Alert (Beta)"), + QString("%1
" + "

%2


") + .arg(tr("A chime and on-screen alert will play when the traffic light you are waiting for turns green and you have no vehicle in front of you.")) + .arg(tr("Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly.")), + "", + false, + }, }; // Add regular toggles first diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index df1bc3c002..d05822bb85 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -14,6 +14,11 @@ HudRendererSP::HudRendererSP() { plus_arrow_up_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_plus_arrow_up", {105, 105}); minus_arrow_down_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_minus_arrow_down", {105, 105}); + + int green_light_small_max = green_light_alert_small * 2 - 40; + int green_light_large_max = green_light_alert_large * 2 - 40; + green_light_alert_small_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {green_light_small_max, green_light_small_max}); + green_light_alert_large_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {green_light_large_max, green_light_large_max}); } void HudRendererSP::updateState(const UIState &s) { @@ -105,11 +110,15 @@ void HudRendererSP::updateState(const UIState &s) { smartCruiseControlVisionActive = lp_sp.getSmartCruiseControl().getVision().getActive(); smartCruiseControlMapEnabled = lp_sp.getSmartCruiseControl().getMap().getEnabled(); smartCruiseControlMapActive = lp_sp.getSmartCruiseControl().getMap().getActive(); + + greenLightAlert = lp_sp.getE2eAlerts().getGreenLightAlert(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); + e2eAlertDisplayTimer = std::max(0, e2eAlertDisplayTimer - 1); + p.save(); if (is_cruise_available) { @@ -194,6 +203,18 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { // Road Name drawRoadName(p, surface_rect); + + // Green Light Alert + if (greenLightAlert) { + e2eAlertDisplayTimer = 3 * UI_FREQ; + } + + if (e2eAlertDisplayTimer > 0) { + e2eAlertFrame++; + drawE2eAlert(p, surface_rect); + } else { + e2eAlertFrame = 0; + } } p.restore(); @@ -666,3 +687,37 @@ void HudRendererSP::drawSetSpeedSP(QPainter &p, const QRect &surface_rect) { p.setPen(set_speed_color); p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr); } + +void HudRendererSP::drawE2eAlert(QPainter &p, const QRect &surface_rect) { + int size = devUiInfo > 0 ? green_light_alert_small : green_light_alert_large; + int x = surface_rect.center().x() + surface_rect.width() / 4; + int y = surface_rect.center().y() + 40; + x += devUiInfo > 0 ? 0 : 50; + y += devUiInfo > 0 ? 0 : 80; + QRect alertRect(x - size, y - size, size * 2, size * 2); + + QString alert_text = tr("GREEN\nLIGHT"); + + // Alert Circle + QPoint center = alertRect.center(); + QColor frameColor = pulseElement(e2eAlertFrame) ? QColor(255, 255, 255, 75) : QColor(0, 255, 0, 75); + p.setPen(QPen(frameColor, 15)); + p.setBrush(QColor(0, 0, 0, 190)); + p.drawEllipse(center, size, size); + + // Alert Text + QColor txtColor = pulseElement(e2eAlertFrame) ? QColor(255, 255, 255, 255) : QColor(0, 255, 0, 255); + p.setFont(InterFont(48, QFont::Bold)); + p.setPen(txtColor); + QFontMetrics fm(p.font()); + QRect textRect = fm.boundingRect(alertRect, Qt::TextWordWrap, alert_text); + textRect.moveCenter({alertRect.center().x(), alertRect.center().y()}); + textRect.moveBottom(alertRect.bottom() - alertRect.height() / 7); + p.drawText(textRect, Qt::AlignCenter, alert_text); + + // Alert Image + QPixmap &alert_img = devUiInfo > 0 ? green_light_alert_small_img : green_light_alert_large_img; + QPointF pixmapCenterOffset = QPointF(alert_img.width() / 2.0, alert_img.height() / 2.0); + QPointF drawPoint = center - pixmapCenterOffset; + p.drawPixmap(drawPoint, alert_img); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 043536bf4c..b911167241 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -36,6 +36,7 @@ private: void drawRoadName(QPainter &p, const QRect &surface_rect); void drawSpeedLimitPreActiveArrow(QPainter &p, QRect &sign_rect); void drawSetSpeedSP(QPainter &p, const QRect &surface_rect); + void drawE2eAlert(QPainter &p, const QRect &surface_rect); bool lead_status; float lead_d_rel; @@ -93,4 +94,11 @@ private: int speedLimitAssistFrame; QPixmap plus_arrow_up_img; QPixmap minus_arrow_down_img; + int green_light_alert_small = 250; + int green_light_alert_large = 300; + QPixmap green_light_alert_small_img; + QPixmap green_light_alert_large_img; + bool greenLightAlert; + int e2eAlertFrame; + int e2eAlertDisplayTimer = 0; }; diff --git a/sunnypilot/selfdrive/assets/images/green_light.png b/sunnypilot/selfdrive/assets/images/green_light.png new file mode 100644 index 0000000000..2da2c13a82 --- /dev/null +++ b/sunnypilot/selfdrive/assets/images/green_light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3aa5ec9ac1daee6a549e62647d90bcaa66d2485f7df7f386ff902fcfb04c1716 +size 6583 diff --git a/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py new file mode 100644 index 0000000000..46657bd47c --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py @@ -0,0 +1,50 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" + +from cereal import messaging, custom + +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD +from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP + +TRIGGER_THRESHOLD = 30 + + +class E2EAlertsHelper: + def __init__(self): + self._params = Params() + self._frame = -1 + + self.green_light_alert = False + self.green_light_alert_enabled = self._params.get_bool("GreenLightAlert") + + def _read_params(self) -> None: + if self._frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.green_light_alert_enabled = self._params.get_bool("GreenLightAlert") + + self._frame += 1 + + def update(self, sm: messaging.SubMaster, events_sp: EventsSP) -> None: + self._read_params() + + if not self.green_light_alert_enabled: + return + + CS = sm['carState'] + CC = sm['carControl'] + + model_x = sm['modelV2'].position.x + max_idx = len(model_x) - 1 + has_lead = sm['radarState'].leadOne.status + + # Green light alert + self.green_light_alert = model_x[max_idx] > TRIGGER_THRESHOLD and \ + not has_lead and CS.standstill and not CS.gasPressed and not CC.enabled + + if self.green_light_alert: + events_sp.add(custom.OnroadEventSP.EventName.e2eChime) diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index ece2ff2419..e45d748f3b 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -10,6 +10,7 @@ from opendbc.car import structs from openpilot.common.constants import CV from openpilot.selfdrive.car.cruise import V_CRUISE_MAX from openpilot.sunnypilot.selfdrive.controls.lib.dec.dec import DynamicExperimentalController +from openpilot.sunnypilot.selfdrive.controls.lib.e2e_alerts_helper import E2EAlertsHelper from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.smart_cruise_control import SmartCruiseControl from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_resolver import SpeedLimitResolver @@ -30,6 +31,7 @@ class LongitudinalPlannerSP: self.sla = SpeedLimitAssist(CP) self.generation = int(model_bundle.generation) if (model_bundle := get_active_bundle()) else None self.source = LongitudinalPlanSource.cruise + self.e2e_alerts_helper = E2EAlertsHelper() self.output_v_target = 0. self.output_a_target = 0. @@ -53,8 +55,6 @@ class LongitudinalPlannerSP: long_enabled = sm['carControl'].enabled long_override = sm['carControl'].cruiseControl.override - self.events_sp.clear() - # Smart Cruise Control self.scc.update(sm, long_enabled, long_override, v_ego, a_ego, v_cruise) @@ -78,7 +78,9 @@ class LongitudinalPlannerSP: return self.output_v_target, self.output_a_target def update(self, sm: messaging.SubMaster) -> None: + self.events_sp.clear() self.dec.update(sm) + self.e2e_alerts_helper.update(sm, self.events_sp) def publish_longitudinal_plan_sp(self, sm: messaging.SubMaster, pm: messaging.PubMaster) -> None: plan_sp_send = messaging.new_message('longitudinalPlanSP') @@ -135,4 +137,8 @@ class LongitudinalPlannerSP: assist.vTarget = float(self.sla.output_v_target) assist.aTarget = float(self.sla.output_a_target) + # E2E Alerts + e2eAlerts = longitudinalPlanSP.e2eAlerts + e2eAlerts.greenLightAlert = self.e2e_alerts_helper.green_light_alert + pm.send('longitudinalPlanSP', plan_sp_send) diff --git a/sunnypilot/selfdrive/selfdrived/events.py b/sunnypilot/selfdrive/selfdrived/events.py index 7700550c2d..e9f4b29bae 100644 --- a/sunnypilot/selfdrive/selfdrived/events.py +++ b/sunnypilot/selfdrive/selfdrived/events.py @@ -224,4 +224,12 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 5.), }, + + EventNameSP.e2eChime: { + ET.PERMANENT: Alert( + "", + "", + AlertStatus.normal, AlertSize.none, + Priority.MID, VisualAlert.none, AudibleAlert.prompt, 0.1), + }, }