diff --git a/cereal/car.capnp b/cereal/car.capnp index f265f15..92ea0db 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -118,16 +118,22 @@ struct CarEvent @0x9b1657f34caf3ad3 { paramsdPermanentError @119; # FrogPilot events - frogSteerSaturated @122; - greenLight @123; - holidayActive @124; - laneChangeBlockedLoud @125; - leadDeparting @126; - noLaneAvailable @127; - openpilotCrashed @128; - pedalInterceptorNoBrake @130; - speedLimitChanged @131; - torqueNNLoad @132; + accel30 @120; + accel35 @121; + firefoxSteerSaturated @122; + frogSteerSaturated @123; + greenLight @124; + holidayActive @125; + laneChangeBlockedLoud @126; + leadDeparting @127; + noLaneAvailable @128; + openpilotCrashed @129; + openpilotCrashedRandomEvents @130; + pedalInterceptorNoBrake @131; + speedLimitChanged @132; + torqueNNLoad @133; + vCruise69 @136; + yourFrogTriedToKillMe @137; radarCanErrorDEPRECATED @15; communityFeatureDisallowedDEPRECATED @62; @@ -420,6 +426,17 @@ struct CarControl { prompt @6; promptRepeat @7; promptDistracted @8; + + # Random Events + angry @9; + fart @10; + firefox @11; + nessie @12; + noice @13; + uwu @14; + + # Other + goat @15; } } diff --git a/common/params.cc b/common/params.cc index fc1aeb8..eb38f4e 100644 --- a/common/params.cc +++ b/common/params.cc @@ -246,6 +246,7 @@ std::unordered_map keys = { {"ConditionalExperimental", PERSISTENT}, {"CrosstrekTorque", PERSISTENT}, {"CurrentHolidayTheme", PERSISTENT}, + {"CurrentRandomEvent", PERSISTENT}, {"CustomAlerts", PERSISTENT}, {"CustomColors", PERSISTENT}, {"CustomIcons", PERSISTENT}, @@ -358,6 +359,7 @@ std::unordered_map keys = { {"PromptDistractedVolume", PERSISTENT}, {"QOLControls", PERSISTENT}, {"QOLVisuals", PERSISTENT}, + {"RandomEvents", PERSISTENT}, {"RefuseVolume", PERSISTENT}, {"RelaxedFollow", PERSISTENT}, {"RelaxedJerk", PERSISTENT}, diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index b769122..67e1fbc 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -181,13 +181,18 @@ class Controls: self.frogpilot_variables = SimpleNamespace() self.driving_gear = False + self.fcw_random_event_triggered = False self.holiday_theme_alerted = False self.previously_enabled = False self.openpilot_crashed = False + self.previously_enabled = False + self.random_event_triggered = False self.stopped_for_light_previously = False + self.max_acceleration = 0 self.previous_lead_distance = 0 self.previous_speed_limit = SpeedLimitController.desired_speed_limit + self.random_event_timer = 0 ignore = self.sensor_packets + ['testJoystick'] if SIMULATION: @@ -331,7 +336,9 @@ class Controls: # Show crash log event if openpilot crashed if os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt')): self.events.add(EventName.openpilotCrashed) - return + if self.random_events and not self.openpilot_crashed: + self.events.add(EventName.openpilotCrashedRandomEvents) + self.openpilot_crashed = True # Show holiday related event to indicate which holiday is active if self.sm.frame >= 1000 and self.holiday_themes and self.params_memory.get_int("CurrentHolidayTheme") != 0 and not self.holiday_theme_alerted: @@ -538,6 +545,11 @@ class Controls: planner_fcw = self.sm['longitudinalPlan'].fcw and self.enabled if planner_fcw or model_fcw: self.events.add(EventName.fcw) + self.fcw_random_event_triggered = True + elif self.fcw_random_event_triggered and self.random_events: + self.events.add(EventName.yourFrogTriedToKillMe) + self.fcw_random_event_triggered = False + self.random_event_triggered = True for m in messaging.drain_sock(self.log_sock, wait_for_one=False): try: @@ -562,6 +574,26 @@ class Controls: if self.sm['modelV2'].frameDropPerc > 20: self.events.add(EventName.modeldLagging) + # Acceleration Random Event alerts + if self.random_events: + acceleration = CS.aEgo + + if not CS.gasPressed: + self.max_acceleration = max(acceleration, self.max_acceleration) + else: + self.max_acceleration = 0 + + if 3.5 > self.max_acceleration >= 3.0 and acceleration < 1.5: + self.events.add(EventName.accel30) + self.params_memory.put_int("CurrentRandomEvent", 2) + self.random_event_triggered = True + self.max_acceleration = 0 + elif self.max_acceleration >= 3.5 and acceleration < 1.5: + self.events.add(EventName.accel35) + self.params_memory.put_int("CurrentRandomEvent", 3) + self.random_event_triggered = True + self.max_acceleration = 0 + # Green light alert if self.green_light_alert: stopped_for_light = frogpilot_plan.redLight and CS.standstill @@ -633,6 +665,19 @@ class Controls: else: self.FPCC.speedLimitChanged = False + # vCruise set to 69 Random Event alert + if self.random_events: + conversion = 1 if self.is_metric else CV.KPH_TO_MPH + v_cruise = self.v_cruise_helper.v_cruise_cluster_kph if self.v_cruise_helper.v_cruise_cluster_kph != 0.0 else self.v_cruise_helper.v_cruise_kph + v_cruise *= conversion + + if 70 > v_cruise >= 69: + if not self.vCruise69_alert_played: + self.events.add(EventName.vCruise69) + self.vCruise69_alert_played = True + else: + self.vCruise69_alert_played = False + def data_sample(self): """Receive data from sockets and update carState""" @@ -793,6 +838,14 @@ class Controls: # FrogPilot functions frogpilot_plan = self.sm['frogpilotPlan'] + # Reset the Random Event flag after 5 seconds + if self.random_event_triggered: + self.random_event_timer += 1 + if self.random_event_timer * DT_CTRL >= 4: + self.random_event_triggered = False + self.random_event_timer = 0 + self.params_memory.remove("CurrentRandomEvent") + # Update Experimental Mode if self.frogpilot_variables.conditional_experimental_mode: self.experimental_mode = frogpilot_plan.conditionalExperimental @@ -883,8 +936,13 @@ class Controls: turning = abs(lac_log.desiredLateralAccel) > 1.0 good_speed = CS.vEgo > 5 max_torque = abs(self.last_actuators.steer) > 0.99 - if undershooting and turning and good_speed and max_torque: - lac_log.active and self.events.add(EventName.frogSteerSaturated if self.goat_scream else EventName.steerSaturated) + if undershooting and turning and good_speed and max_torque and not self.random_event_triggered: + if self.sm.frame % 10000 == 0 and self.random_events: + lac_log.active and self.events.add(EventName.firefoxSteerSaturated) + self.params_memory.put_int("CurrentRandomEvent", 1) + self.random_event_triggered = True + else: + lac_log.active and self.events.add(EventName.frogSteerSaturated if self.goat_scream else EventName.steerSaturated) elif lac_log.saturated: # TODO probably should not use dpath_points but curvature dpath_points = model_v2.position.y @@ -1156,6 +1214,8 @@ class Controls: self.frogpilot_variables.reverse_cruise_increase = quality_of_life and self.params.get_bool("ReverseCruise") self.frogpilot_variables.set_speed_offset = self.params.get_int("SetSpeedOffset") * (1 if self.is_metric else CV.MPH_TO_KPH) if quality_of_life else 0 + self.random_events = self.params.get_bool("RandomEvents") + self.speed_limit_controller = self.params.get_bool("SpeedLimitController") self.frogpilot_variables.force_mph_dashboard = self.speed_limit_controller and self.params.get_bool("ForceMPHDashboard") self.frogpilot_variables.set_speed_limit = self.speed_limit_controller and self.params.get_bool("SetSpeedLimit") diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index d6b946b..56b32d6 100644 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -1014,7 +1014,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { "Turn Exceeds Steering Limit", "JESUS TAKE THE WHEEL!!", AlertStatus.userPrompt, AlertSize.mid, - Priority.LOW, VisualAlert.steerRequired, AudibleAlert.warningSoft, 2.), + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.goat, 2.), }, EventName.greenLight: { @@ -1076,6 +1076,55 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { EventName.torqueNNLoad: { ET.PERMANENT: torque_nn_load_alert, }, + + # Random Events + EventName.accel30: { + ET.WARNING: Alert( + "UwU u went a bit fast there!", + "(⁄ ⁄•⁄ω⁄•⁄ ⁄)", + AlertStatus.frogpilot, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.uwu, 4.), + }, + + EventName.accel35: { + ET.WARNING: Alert( + "I ain't giving you no tree-fiddy", + "you damn Loch Ness monsta!", + AlertStatus.frogpilot, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.nessie, 4.), + }, + + EventName.firefoxSteerSaturated: { + ET.WARNING: Alert( + "Turn Exceeds Steering Limit", + "IE Has Stopped Responding...", + AlertStatus.userPrompt, AlertSize.mid, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.firefox, 4.), + }, + + EventName.openpilotCrashedRandomEvents: { + ET.PERMANENT: Alert( + "openpilot crashed 💩", + "Please post the error log in the FrogPilot Discord!", + AlertStatus.normal, AlertSize.mid, + Priority.HIGHEST, VisualAlert.none, AudibleAlert.fart, 4.), + }, + + EventName.vCruise69: { + ET.PERMANENT: Alert( + "Lol 69", + "", + AlertStatus.frogpilot, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.noice, 2.), + }, + + EventName.yourFrogTriedToKillMe: { + ET.PERMANENT: Alert( + "Your frog tried to kill me...", + "😡", + AlertStatus.frogpilot, AlertSize.mid, + Priority.MID, VisualAlert.none, AudibleAlert.angry, 5.), + }, } diff --git a/selfdrive/frogpilot/assets/random_events/images/firefox.png b/selfdrive/frogpilot/assets/random_events/images/firefox.png new file mode 100644 index 0000000..6c3a418 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/images/firefox.png differ diff --git a/selfdrive/frogpilot/assets/random_events/images/tree_fiddy.gif b/selfdrive/frogpilot/assets/random_events/images/tree_fiddy.gif new file mode 100644 index 0000000..3207179 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/images/tree_fiddy.gif differ diff --git a/selfdrive/frogpilot/assets/random_events/images/weeb_wheel.gif b/selfdrive/frogpilot/assets/random_events/images/weeb_wheel.gif new file mode 100644 index 0000000..0c8374e Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/images/weeb_wheel.gif differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/angry.wav b/selfdrive/frogpilot/assets/random_events/sounds/angry.wav new file mode 100644 index 0000000..6bc6991 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/angry.wav differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/fart.wav b/selfdrive/frogpilot/assets/random_events/sounds/fart.wav new file mode 100644 index 0000000..d825cba Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/fart.wav differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/firefox.wav b/selfdrive/frogpilot/assets/random_events/sounds/firefox.wav new file mode 100644 index 0000000..9b0668f Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/firefox.wav differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/nessie.wav b/selfdrive/frogpilot/assets/random_events/sounds/nessie.wav new file mode 100644 index 0000000..899dc72 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/nessie.wav differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/noice.wav b/selfdrive/frogpilot/assets/random_events/sounds/noice.wav new file mode 100644 index 0000000..95c8d01 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/noice.wav differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/uwu.wav b/selfdrive/frogpilot/assets/random_events/sounds/uwu.wav new file mode 100644 index 0000000..830360c Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/uwu.wav differ diff --git a/selfdrive/frogpilot/assets/toggle_icons/icon_random.png b/selfdrive/frogpilot/assets/toggle_icons/icon_random.png new file mode 100644 index 0000000..0a3e4b3 Binary files /dev/null and b/selfdrive/frogpilot/assets/toggle_icons/icon_random.png differ diff --git a/selfdrive/frogpilot/ui/visual_settings.cc b/selfdrive/frogpilot/ui/visual_settings.cc index 4370b93..ed53909 100644 --- a/selfdrive/frogpilot/ui/visual_settings.cc +++ b/selfdrive/frogpilot/ui/visual_settings.cc @@ -55,6 +55,8 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"HideSpeed", "Hide Speed", "Hide the speed indicator in the onroad UI. Additional toggle allows it to be hidden/shown via tapping the speed itself.", ""}, {"MapStyle", "Map Style", "Use a custom map style to be used for 'Navigate on openpilot'.", ""}, + {"RandomEvents", "Random Events", "Enjoy a bit of unpredictability with random events that can occur during certain driving conditions.", "../frogpilot/assets/toggle_icons/icon_random.png"}, + {"ScreenManagement", "Screen Management", "Manage your screen's brightness, timeout settings, and hide specific onroad UI elements.", "../frogpilot/assets/toggle_icons/icon_light.png"}, {"HideUIElements", "Hide UI Elements", "Hide the selected UI elements from the onroad screen.", ""}, {"ScreenBrightness", "Screen Brightness", "Customize your screen brightness when offroad.", ""}, diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index d57a5de..a491f62 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -18,18 +18,7 @@ #include "selfdrive/ui/qt/maps/map_panel.h" #endif -static void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity) { - p.setRenderHint(QPainter::Antialiasing); - p.setOpacity(1.0); // bg dictates opacity of ellipse - p.setPen(Qt::NoPen); - p.setBrush(bg); - p.drawEllipse(center, btn_size / 2, btn_size / 2); - p.setOpacity(opacity); - p.drawPixmap(center - QPoint(img.width() / 2, img.height() / 2), img); - p.setOpacity(1.0); -} - -static void drawIconRotate(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity, const int angle) { +static void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity, const int angle = 0) { p.setRenderHint(QPainter::Antialiasing); p.setOpacity(1.0); // bg dictates opacity of ellipse p.setPen(Qt::NoPen); @@ -44,6 +33,18 @@ static void drawIconRotate(QPainter &p, const QPoint ¢er, const QPixmap &img p.restore(); } +static void drawIconGif(QPainter &p, const QPoint ¢er, const QMovie &img, const QBrush &bg, float opacity) { + p.setRenderHint(QPainter::Antialiasing); + p.setOpacity(1.0); // bg dictates opacity of ellipse + p.setPen(Qt::NoPen); + p.setBrush(bg); + p.drawEllipse(center.x() - btn_size / 2, center.y() - btn_size / 2, btn_size, btn_size); + p.setOpacity(opacity); + QPixmap currentFrame = img.currentPixmap(); + p.drawPixmap(center - QPoint(currentFrame.width() / 2, currentFrame.height() / 2), currentFrame); + p.setOpacity(1.0); +} + OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent), scene(uiState()->scene) { QVBoxLayout *main_layout = new QVBoxLayout(this); main_layout->setMargin(UI_BORDER_SIZE); @@ -387,8 +388,12 @@ ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(fals {3, loadPixmap("../frogpilot/assets/wheel_images/frog.png", {img_size, img_size})}, {4, loadPixmap("../frogpilot/assets/wheel_images/rocket.png", {img_size, img_size})}, {5, loadPixmap("../frogpilot/assets/wheel_images/hyundai.png", {img_size, img_size})}, - {6, loadPixmap("../frogpilot/assets/wheel_images/stalin.png", {img_size, img_size})} + {6, loadPixmap("../frogpilot/assets/wheel_images/stalin.png", {img_size, img_size})}, + {7, loadPixmap("../frogpilot/assets/random_events/images/firefox.png", {img_size, img_size})}, }; + + wheelImagesGif[1] = new QMovie("../frogpilot/assets/random_events/images/weeb_wheel.gif", QByteArray(), this); + wheelImagesGif[2] = new QMovie("../frogpilot/assets/random_events/images/tree_fiddy.gif", QByteArray(), this); } void ExperimentalButton::changeMode() { @@ -416,15 +421,59 @@ void ExperimentalButton::updateState(const UIState &s, bool leadInfo) { } // FrogPilot variables + firefoxRandomEventTriggered = scene.current_random_event == 1; + treeFiddyRandomEventTriggered = scene.current_random_event == 3; + weebRandomEventTriggered = scene.current_random_event == 2; rotatingWheel = scene.rotating_wheel; wheelIcon = scene.wheel_icon; + wheelIconGif = 0; y_offset = leadInfo ? 10 : 0; - // Update the icon so the steering wheel rotates in real time - if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) { - steeringAngleDeg = scene.steering_angle_deg; + if (firefoxRandomEventTriggered) { + static int rotationDegree = 0; + rotationDegree = (rotationDegree + 36) % 360; + steeringAngleDeg = rotationDegree; + wheelIcon = 7; update(); + + } else if (treeFiddyRandomEventTriggered || weebRandomEventTriggered) { + if (!gifLabel) { + gifLabel = new QLabel(this); + QMovie *movie; + + if (treeFiddyRandomEventTriggered) { + movie = wheelImagesGif[2]; + } else if (weebRandomEventTriggered) { + movie = wheelImagesGif[1]; + } + + if (movie) { + gifLabel->setMovie(movie); + gifLabel->setFixedSize(img_size, img_size); + gifLabel->move((width() - gifLabel->width()) / 2, (height() - gifLabel->height()) / 2 + y_offset); + } + } + if (gifLabel->movie()) { + gifLabel->movie()->start(); + } + gifLabel->show(); + wheelIconGif = weebRandomEventTriggered ? 1 : 2; + update(); + + } else { + if (gifLabel) { + gifLabel->hide(); + } + if (rotatingWheel) { + // Update the icon so the steering wheel rotates in real time + if (steeringAngleDeg != scene.steering_angle_deg) { + steeringAngleDeg = scene.steering_angle_deg; + update(); + } + } else { + steeringAngleDeg = 0; + } } } @@ -438,18 +487,21 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { engage_img = wheelImages[wheelIcon]; 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))))) : - QColor(0, 0, 0, 166); + QMovie *gif = wheelImagesGif[wheelIconGif]; + + QColor background_color = wheelIcon != 0 && !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)))))) : + QColor(0, 0, 0, 166); if (!(scene.show_driver_camera || scene.map_open && scene.full_map)) { - if (rotatingWheel) { - drawIconRotate(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !(engageable || scene.always_on_lateral_active)) ? 0.6 : 1.0, steeringAngleDeg); + if (wheelIconGif != 0) { + QBrush backgroundBrush(background_color); + drawIconGif(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), *gif, backgroundBrush, 1.0); } else { - drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !(engageable || scene.always_on_lateral_active)) ? 0.6 : 1.0); + drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !(engageable || scene.always_on_lateral_active)) ? 0.6 : 1.0, steeringAngleDeg); } } } diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 23d2b12..6feaa5f 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -2,6 +2,8 @@ #include +#include +#include #include #include #include @@ -78,11 +80,20 @@ private: // FrogPilot variables UIScene &scene; - std::map wheelImages; + QMap wheelImages; + QMap wheelImagesGif; + QMovie engage_gif; + QLabel *gifLabel; + + bool firefoxRandomEventTriggered; bool rotatingWheel; + bool treeFiddyRandomEventTriggered; + bool weebRandomEventTriggered; + int steeringAngleDeg; int wheelIcon; + int wheelIconGif; int y_offset; }; diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 191d011..4df3147 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -1,5 +1,6 @@ import math import numpy as np +import os import time import wave @@ -40,6 +41,17 @@ sound_list: Dict[int, Tuple[str, Optional[int], float]] = { AudibleAlert.warningSoft: ("warning_soft.wav", None, MAX_VOLUME), AudibleAlert.warningImmediate: ("warning_immediate.wav", None, MAX_VOLUME), + + # Random Events + AudibleAlert.angry: ("angry.wav", 1, MAX_VOLUME), + AudibleAlert.fart: ("fart.wav", 1, MAX_VOLUME), + AudibleAlert.firefox: ("firefox.wav", 1, MAX_VOLUME), + AudibleAlert.noice: ("noice.wav", 1, MAX_VOLUME), + AudibleAlert.nessie: ("nessie.wav", 1, MAX_VOLUME), + AudibleAlert.uwu: ("uwu.wav", 1, MAX_VOLUME), + + # Other + AudibleAlert.goat: ("goat.wav", 1, MAX_VOLUME), } def check_controls_timeout_alert(sm): @@ -58,6 +70,8 @@ class Soundd: self.params = Params() self.params_memory = Params("/dev/shm/params") + self.random_events_directory = BASEDIR + "/selfdrive/frogpilot/assets/random_events/sounds/" + self.update_frogpilot_params() self.load_sounds() @@ -77,7 +91,10 @@ class Soundd: for sound in sound_list: filename, play_count, volume = sound_list[sound] - wavefile = wave.open(self.sound_directory + filename, 'r') + if os.path.exists(os.path.join(self.random_events_directory, filename)): + wavefile = wave.open(self.random_events_directory + filename, 'r') + else: + wavefile = wave.open(self.sound_directory + filename, 'r') assert wavefile.getnchannels() == 1 assert wavefile.getsampwidth() == 2 @@ -160,6 +177,10 @@ class Soundd: elif self.alert_volume_control and self.current_alert in self.volume_map: self.current_volume = self.volume_map[self.current_alert] / 100.0 + # Increase the volume for Random Events + elif self.current_alert in self.random_events_map: + self.current_volume = self.random_events_map[self.current_alert] + self.get_audible_alert(sm) rk.keep_time() @@ -171,6 +192,15 @@ class Soundd: self.update_frogpilot_params() def update_frogpilot_params(self): + self.random_events_map = { + AudibleAlert.angry: MAX_VOLUME, + AudibleAlert.fart: MAX_VOLUME, + AudibleAlert.firefox: MAX_VOLUME, + AudibleAlert.nessie: MAX_VOLUME, + AudibleAlert.noice: MAX_VOLUME, + AudibleAlert.uwu: MAX_VOLUME, + } + self.alert_volume_control = self.params.get_bool("AlertVolumeControl") self.volume_map = { @@ -183,7 +213,9 @@ class Soundd: AudibleAlert.promptDistracted: self.params.get_int("PromptDistractedVolume"), AudibleAlert.warningSoft: self.params.get_int("WarningSoftVolume"), - AudibleAlert.warningImmediate: self.params.get_int("WarningImmediateVolume") + AudibleAlert.warningImmediate: self.params.get_int("WarningImmediateVolume"), + + AudibleAlert.goat: self.params.get_int("WarningSoftVolume"), } custom_theme = self.params.get_bool("CustomTheme") diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index f037a34..78d41df 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -371,6 +371,7 @@ void ui_update_frogpilot_params(UIState *s) { scene.map_style = quality_of_life_visuals ? params.getInt("MapStyle") : 0; scene.personalities_via_screen = params.getBool("PersonalitiesViaScreen") && params.getBool("AdjustablePersonalities"); + scene.random_events = params.getBool("RandomEvents"); scene.rotating_wheel = params.getBool("RotatingWheel"); bool screen_management = params.getBool("ScreenManagement"); @@ -474,6 +475,9 @@ void UIState::update() { if (scene.holiday_themes) { scene.current_holiday_theme = paramsMemory.getInt("CurrentHolidayTheme"); } + if (scene.random_events) { + scene.current_random_event = paramsMemory.getInt("CurrentRandomEvent"); + } } void UIState::setPrimeType(PrimeType type) { diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 6c7cd11..a42c104 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -81,7 +81,7 @@ struct Alert { alert = {"openpilot crashed", "Please post the error log in the FrogPilot Discord!", "controlsWaiting", cereal::ControlsState::AlertSize::MID, cereal::ControlsState::AlertStatus::NORMAL, - AudibleAlert::NONE}; + Params().getBool("RandomEvents") ? AudibleAlert::FART : AudibleAlert::NONE}; } else if (controls_frame < started_frame) { // car is started, but controlsState hasn't been seen at all alert = {"openpilot Unavailable", "Waiting for controls to start", @@ -211,6 +211,7 @@ typedef struct UIScene { bool parked; bool pedals_on_ui; bool personalities_via_screen; + bool random_events; bool reverse_cruise; bool reverse_cruise_ui; bool right_hand_drive; @@ -252,6 +253,7 @@ typedef struct UIScene { int conditional_speed_lead; int conditional_status; int current_holiday_theme; + int current_random_event; int custom_colors; int custom_icons; int custom_signals;