diff --git a/cereal/car.capnp b/cereal/car.capnp index 57f3e28fe..7972533dd 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -118,7 +118,11 @@ struct CarEvent @0x9b1657f34caf3ad3 { paramsdPermanentError @119; # FrogPilot events + accel30 @120; + accel35 @121; + accel40 @122; blockUser @123; + firefoxSteerSaturated @124; goatSteerSaturated @125; greenLight @126; holidayActive @127; @@ -126,9 +130,12 @@ struct CarEvent @0x9b1657f34caf3ad3 { leadDeparting @129; noLaneAvailable @130; openpilotCrashed @131; + openpilotCrashedRandomEvents @132; pedalInterceptorNoBrake @133; speedLimitChanged @134; torqueNNLoad @135; + vCruise69 @138; + yourFrogTriedToKillMe @139; radarCanErrorDEPRECATED @15; communityFeatureDisallowedDEPRECATED @62; @@ -420,6 +427,15 @@ struct CarControl { promptRepeat @7; promptDistracted @8; + # Random Events + angry @9; + doc @10; + fart @11; + firefox @12; + nessie @13; + noice @14; + uwu @15; + # Other goat @16; } diff --git a/common/params.cc b/common/params.cc index 35afa1290..281333cbb 100644 --- a/common/params.cc +++ b/common/params.cc @@ -250,6 +250,7 @@ std::unordered_map keys = { {"ConditionalExperimental", PERSISTENT}, {"CrosstrekTorque", PERSISTENT}, {"CurrentHolidayTheme", PERSISTENT}, + {"CurrentRandomEvent", PERSISTENT}, {"CustomAlerts", PERSISTENT}, {"CustomColors", PERSISTENT}, {"CustomCruise", PERSISTENT}, @@ -367,6 +368,7 @@ std::unordered_map keys = { {"PromptVolume", 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 7729eed3b..2873f95c2 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -191,13 +191,18 @@ class Controls: self.always_on_lateral = self.params.get_bool("AlwaysOnLateral") self.always_on_lateral_main = self.always_on_lateral and self.params.get_bool("AlwaysOnLateralMain") + self.fcw_random_event_triggered = False self.holiday_theme_alerted = False self.onroad_distance_pressed = False + self.openpilot_crashed_triggered = False self.previously_enabled = False + self.random_event_triggered = False self.speed_check = False + self.max_acceleration = 0 self.previous_lead_distance = 0 self.previous_speed_limit = 0 + self.random_event_timer = 0 self.speed_limit_timer = 0 self.green_light_mac = MovingAverageCalculator() @@ -418,6 +423,10 @@ 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 for m in messaging.drain_sock(self.log_sock, wait_for_one=False): try: @@ -678,8 +687,13 @@ class Controls: turning = abs(lac_log.desiredLateralAccel) > 1.0 good_speed = CS.vEgo > 5 max_torque = abs(actuators.steer) > 0.99 - if undershooting and turning and good_speed and max_torque: - lac_log.active and self.events.add(EventName.goatSteerSaturated 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.goatSteerSaturated 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 @@ -923,6 +937,32 @@ class Controls: self.events.add(EventName.blockUser) return + 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 4.0 > 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 + + elif self.max_acceleration >= 4.0 and acceleration < 1.5: + self.events.add(EventName.accel40) + self.params_memory.put_int("CurrentRandomEvent", 4) + self.random_event_triggered = True + self.max_acceleration = 0 + if self.green_light_alert: green_light = not self.sm['frogpilotPlan'].redLight green_light &= not CS.gasPressed @@ -953,7 +993,12 @@ class Controls: self.events.add(EventName.leadDeparting) if os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt')) and not self.openpilot_crashed_triggered: - self.events.add(EventName.openpilotCrashed) + if self.random_events: + self.events.add(EventName.openpilotCrashedRandomEvents) + else: + self.events.add(EventName.openpilotCrashed) + + self.openpilot_crashed_triggered = True if self.speed_limit_alert or self.speed_limit_confirmation: current_speed_limit = self.sm['frogpilotPlan'].slcSpeedLimit @@ -1005,6 +1050,17 @@ class Controls: if self.sm.frame == 550 and self.CP.lateralTuning.which() == 'torque' and self.CI.use_nnff: self.events.add(EventName.torqueNNLoad) + if self.random_events: + conversion = 1 if self.is_metric else CV.KPH_TO_MPH + v_cruise = max(self.v_cruise_helper.v_cruise_cluster_kph, self.v_cruise_helper.v_cruise_kph) * 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 update_frogpilot_variables(self, CS): self.driving_gear = CS.gearShifter not in (GearShifter.neutral, GearShifter.park, GearShifter.reverse, GearShifter.unknown) @@ -1029,6 +1085,13 @@ class Controls: self.previously_enabled |= (self.enabled or self.FPCC.alwaysOnLateral) and CS.vEgo > CRUISING_SPEED self.previously_enabled &= self.driving_gear + if self.random_event_triggered: + self.random_event_timer += DT_CTRL + if self.random_event_timer >= 4: + self.random_event_triggered = False + self.random_event_timer = 0 + self.params_memory.remove("CurrentRandomEvent") + signal_check = CS.vEgo >= self.pause_lateral_below_speed or not (CS.leftBlinker or CS.rightBlinker) or CS.standstill self.speed_check = CS.vEgo >= self.pause_lateral_below_speed or CS.standstill or signal_check and self.pause_lateral_below_signal @@ -1055,6 +1118,7 @@ class Controls: frog_sounds = custom_sounds == 1 self.goat_scream = frog_sounds and self.params.get_bool("GoatScream") self.holiday_themes = custom_theme and self.params.get_bool("HolidayThemes") + self.random_events = custom_theme and self.params.get_bool("RandomEvents") device_management = self.params.get_bool("DeviceManagement") self.increase_thermal_limits = device_management and self.params.get_bool("IncreaseThermalLimits") diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index fbbe82325..f08144bce 100644 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -1083,6 +1083,63 @@ EVENTS: dict[int, dict[str, 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.accel40: { + ET.WARNING: Alert( + "Great Scott!", + "🚗💨", + AlertStatus.frogpilot, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.doc, 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, 10.), + }, + + 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 000000000..6c3a418c9 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/images/firefox.png differ diff --git a/selfdrive/frogpilot/assets/random_events/images/great_scott.gif b/selfdrive/frogpilot/assets/random_events/images/great_scott.gif new file mode 100644 index 000000000..a29ca8ec1 Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/images/great_scott.gif 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 000000000..3207179f8 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 000000000..0c8374eac 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 000000000..6bc69913b Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/angry.wav differ diff --git a/selfdrive/frogpilot/assets/random_events/sounds/doc.wav b/selfdrive/frogpilot/assets/random_events/sounds/doc.wav new file mode 100644 index 000000000..9fd679e3f Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/doc.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 000000000..d825cbaee 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 000000000..9b0668f83 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 000000000..899dc7296 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 000000000..95c8d01ca 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 000000000..830360ccd Binary files /dev/null and b/selfdrive/frogpilot/assets/random_events/sounds/uwu.wav differ diff --git a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc index 8b51b574c..fbf997fe9 100644 --- a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc +++ b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc @@ -35,6 +35,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"CustomSignals", tr("Turn Signals"), tr("Add themed animation for your turn signals.\n\nWant to submit your own turn signal animation? Post it in the 'feature-request' channel in the FrogPilot Discord!"), ""}, {"CustomSounds", tr("Sound Pack"), tr("Switch out the standard openpilot sounds with a set of themed sounds.\n\nWant to submit your own sound pack? Post it in the 'feature-request' channel in the FrogPilot Discord!"), ""}, {"HolidayThemes", tr("Holiday Themes"), tr("The openpilot theme changes according to the current/upcoming holiday. Minor holidays last a day, while major holidays (Easter, Christmas, Halloween, etc.) last a week."), ""}, + {"RandomEvents", tr("Random Events"), tr("Enjoy a bit of unpredictability with random events that can occur during certain driving conditions. This is purely cosmetic and has no impact on driving controls!"), ""}, {"ModelUI", tr("Model UI"), tr("Customize the model visualizations on the screen."), "../assets/offroad/icon_calibration.png"}, {"DynamicPathWidth", tr("Dynamic Path Width"), tr("Have the path width dynamically adjust based on the current engagement state of openpilot."), ""}, diff --git a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h index f4121f9d5..63b2cbca4 100644 --- a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h +++ b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h @@ -28,7 +28,7 @@ private: std::set alertVolumeControlKeys = {"DisengageVolume", "EngageVolume", "PromptDistractedVolume", "PromptVolume", "RefuseVolume", "WarningImmediateVolume", "WarningSoftVolume"}; std::set customAlertsKeys = {"GreenLightAlert", "LeadDepartingAlert", "LoudBlindspotAlert"}; std::set customOnroadUIKeys = {"Compass", "CustomPaths", "DeveloperUI", "FPSCounter", "LeadInfo", "PedalsOnUI", "RoadNameUI", "WheelIcon"}; - std::set customThemeKeys = {"CustomColors", "CustomIcons", "CustomSignals", "CustomSounds", "HolidayThemes"}; + std::set customThemeKeys = {"CustomColors", "CustomIcons", "CustomSignals", "CustomSounds", "HolidayThemes", "RandomEvents"}; std::set modelUIKeys = {"DynamicPathWidth", "HideLeadMarker", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", "RoadEdgesWidth", "UnlimitedLength"}; std::set qolKeys = {"BigMap", "CameraView", "DriverCamera", "FullMap", "HideSpeed", "MapStyle", "NumericalTemp"}; std::set screenKeys = {"HideUIElements", "ScreenBrightness", "ScreenBrightnessOnroad", "ScreenRecorder", "ScreenTimeout", "ScreenTimeoutOnroad", "StandbyMode"}; diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index fd87782c4..fb64ffaef 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -33,6 +33,18 @@ static void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, cons 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); @@ -410,7 +422,12 @@ ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(fals {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})}, + {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); + wheelImagesGif[3] = new QMovie("../frogpilot/assets/random_events/images/great_scott.gif", QByteArray(), this); } void ExperimentalButton::changeMode() { @@ -436,12 +453,41 @@ void ExperimentalButton::updateState(const UIState &s, bool leadInfo) { } // FrogPilot variables + int randomEvent = scene.current_random_event; + rotatingWheel = scene.rotating_wheel; wheelIcon = scene.wheel_icon; + wheelIconGif = 0; y_offset = leadInfo ? 10 : 0; - if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) { + if (randomEvent == 0 && gifLabel) { + delete gifLabel; + gifLabel = nullptr; + } else if (randomEvent == 1) { + static int rotationDegree = 0; + rotationDegree = (rotationDegree + 36) % 360; + steeringAngleDeg = rotationDegree; + wheelIcon = 7; + update(); + + } else if (randomEvent == 2 || randomEvent == 3 || randomEvent == 4) { + if (!gifLabel) { + gifLabel = new QLabel(this); + QMovie *movie = wheelImagesGif[randomEvent - 1]; + if (movie) { + gifLabel->setMovie(movie); + gifLabel->setFixedSize(img_size, img_size); + gifLabel->move((width() - gifLabel->width()) / 2, (height() - gifLabel->height()) / 2 + y_offset); + gifLabel->movie()->start(); + } + } + gifLabel->show(); + wheelIconGif = randomEvent - 1; + update(); + + } else if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) { + steeringAngleDeg = scene.steering_angle_deg; update(); steeringAngleDeg = scene.steering_angle_deg; } else if (!rotatingWheel) { @@ -457,6 +503,7 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { QPainter p(this); engage_img = wheelImages[wheelIcon]; QPixmap img = wheelIcon != 0 ? engage_img : (experimental_mode ? experimental_img : engage_img); + QMovie *gif = wheelImagesGif[wheelIconGif]; QColor background_color = wheelIcon != 0 && !isDown() && engageable ? (scene.always_on_lateral_active ? QColor(10, 186, 181, 255) : @@ -466,7 +513,11 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { QColor(0, 0, 0, 166); if (!(scene.map_open && scene.big_map)) { - drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg); + if (wheelIconGif != 0) { + drawIconGif(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), *gif, background_color, 1.0); + } else { + drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg); + } } } @@ -1583,11 +1634,24 @@ void AnnotatedCameraWidget::drawLeadInfo(QPainter &p) { } double acceleration = std::round(scene.acceleration * 100) / 100; + int randomEvent = scene.current_random_event; if (acceleration > maxAcceleration && status == STATUS_ENGAGED) { maxAcceleration = acceleration; isFiveSecondsPassed = false; timer.start(); + } else if (randomEvent == 2 && maxAcceleration < 3.0) { + maxAcceleration = 3.0; + isFiveSecondsPassed = false; + timer.start(); + } else if (randomEvent == 3 && maxAcceleration < 3.5) { + maxAcceleration = 3.5; + isFiveSecondsPassed = false; + timer.start(); + } else if (randomEvent == 4 && maxAcceleration < 4.0) { + maxAcceleration = 4.0; + isFiveSecondsPassed = false; + timer.start(); } else { isFiveSecondsPassed = timer.hasExpired(maxAccelDuration); } diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index e8b948b5a..3c2854b23 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -2,6 +2,8 @@ #include +#include +#include #include #include #include @@ -106,11 +108,20 @@ private: UIScene &scene; QMap wheelImages; + QMap wheelImagesGif; + QMovie engage_gif; + QLabel *gifLabel; + + bool docRandomEventTriggered; + 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 a076052f9..7a9c612f8 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,15 @@ sound_list: dict[int, tuple[str, int | None, 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.doc: ("doc.wav", 1, MAX_VOLUME), + AudibleAlert.fart: ("fart.wav", 1, MAX_VOLUME), + AudibleAlert.firefox: ("firefox.wav", 1, MAX_VOLUME), + AudibleAlert.nessie: ("nessie.wav", 1, MAX_VOLUME), + AudibleAlert.noice: ("noice.wav", 1, MAX_VOLUME), + AudibleAlert.uwu: ("uwu.wav", 1, MAX_VOLUME), + # Other AudibleAlert.goat: ("goat.wav", None, MAX_VOLUME), } @@ -61,6 +71,17 @@ class Soundd: self.params_memory = Params("/dev/shm/params") self.previous_sound_directory = None + self.random_events_directory = BASEDIR + "/selfdrive/frogpilot/assets/random_events/sounds/" + + self.random_events_map = { + AudibleAlert.angry: MAX_VOLUME, + AudibleAlert.doc: MAX_VOLUME, + AudibleAlert.fart: MAX_VOLUME, + AudibleAlert.firefox: MAX_VOLUME, + AudibleAlert.nessie: MAX_VOLUME, + AudibleAlert.noice: MAX_VOLUME, + AudibleAlert.uwu: MAX_VOLUME, + } self.update_frogpilot_params() @@ -82,10 +103,13 @@ class Soundd: filename, play_count, volume = sound_list[sound] - try: - wavefile = wave.open(self.sound_directory + filename, 'r') - except FileNotFoundError: - wavefile = wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r') + if sound in self.random_events_map: + wavefile = wave.open(self.random_events_directory + filename, 'r') + else: + try: + wavefile = wave.open(self.sound_directory + filename, 'r') + except FileNotFoundError: + wavefile = wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r') assert wavefile.getnchannels() == 1 assert wavefile.getsampwidth() == 2 @@ -168,6 +192,9 @@ 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 + 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() diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 362a0c24c..bb6675381 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -344,6 +344,7 @@ void ui_update_frogpilot_params(UIState *s) { scene.custom_icons = custom_theme ? params.getInt("CustomIcons") : 0; scene.custom_signals = custom_theme ? params.getInt("CustomSignals") : 0; scene.holiday_themes = custom_theme && params.getBool("HolidayThemes"); + scene.random_events = custom_theme && params.getBool("RandomEvents"); scene.disable_smoothing_mtsc = params.getBool("MTSCEnabled") && params.getBool("DisableMTSCSmoothing"); scene.experimental_mode_via_screen = scene.longitudinal_control && params.getBool("ExperimentalModeActivation") && params.getBool("ExperimentalModeViaTap"); @@ -467,6 +468,7 @@ void UIState::update() { // FrogPilot live variables that need to be constantly checked scene.conditional_status = scene.conditional_experimental ? paramsMemory.getInt("CEStatus") : 0; scene.current_holiday_theme = scene.holiday_themes ? paramsMemory.getInt("CurrentHolidayTheme") : 0; + scene.current_random_event = scene.random_events ? paramsMemory.getInt("CurrentRandomEvent") : 0; scene.driver_camera_timer = (scene.driver_camera && scene.reverse) ? scene.driver_camera_timer + 1 : 0; } diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 8534bec7c..9c82fe8b6 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -213,6 +213,7 @@ typedef struct UIScene { bool onroad_distance_button; bool parked; bool pedals_on_ui; + bool random_events; bool reverse; bool reverse_cruise; bool reverse_cruise_ui; @@ -267,6 +268,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;