diff --git a/cereal/car.capnp b/cereal/car.capnp index e6476fb..8699a35 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -407,6 +407,8 @@ struct CarControl { prompt @6; promptRepeat @7; promptDistracted @8; + + firefox @9; } } diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 7f7f4ee..3d93306 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -24,6 +24,9 @@ enum FrogPilotEvents @0xf35cc4560bbf6ec2 { torqueNNLoad @3; turningLeft @4; turningRight @5; + + # Random Events + firefoxSteerSaturated @6; } struct FrogPilotLateralPlan @0xda96579883444c35 { diff --git a/common/params.cc b/common/params.cc index 8efbe29..3517aa1 100644 --- a/common/params.cc +++ b/common/params.cc @@ -243,6 +243,7 @@ std::unordered_map keys = { {"CEStopLightsLead", PERSISTENT}, {"Compass", PERSISTENT}, {"ConditionalExperimental", PERSISTENT}, + {"CurrentRandomEvent", PERSISTENT}, {"CurveSensitivity", PERSISTENT}, {"CustomColors", PERSISTENT}, {"CustomIcons", PERSISTENT}, @@ -317,6 +318,7 @@ std::unordered_map keys = { {"PreviousSpeedLimit", PERSISTENT}, {"QOLControls", PERSISTENT}, {"QOLVisuals", PERSISTENT}, + {"RandomEvents", PERSISTENT}, {"RelaxedFollow", PERSISTENT}, {"RelaxedJerk", PERSISTENT}, {"ReverseCruise", PERSISTENT}, diff --git a/selfdrive/assets/sounds/firefox.wav b/selfdrive/assets/sounds/firefox.wav new file mode 100644 index 0000000..c3ea4d5 Binary files /dev/null and b/selfdrive/assets/sounds/firefox.wav differ diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index aa077a1..22699bb 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -82,8 +82,11 @@ class Controls: fire_the_babysitter = self.params.get_bool("FireTheBabysitter") mute_dm = fire_the_babysitter and self.params.get_bool("MuteDM") + self.random_event_triggered = False self.stopped_for_light_previously = False + self.random_event_timer = 0 + ignore = self.sensor_packets + ['testJoystick'] if SIMULATION: ignore += ['driverCameraState', 'managerState'] @@ -629,6 +632,14 @@ class Controls: long_plan = self.sm['longitudinalPlan'] frogpilot_long_plan = self.sm['frogpilotLongitudinalPlan'] + # Reset the Random Event flag + if self.random_event_triggered: + self.random_event_timer += 1 + if self.random_event_timer >= 400: + self.random_event_triggered = False + self.random_event_timer = 0 + self.params_memory.remove("CurrentRandomEvent") + CC = car.CarControl.new_message() CC.enabled = self.enabled @@ -730,8 +741,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(FrogPilotEventName.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: + lac_log.active and self.events.add(FrogPilotEventName.firefoxSteerSaturated) + self.params_memory.put_int("CurrentRandomEvent", 1) + self.random_event_triggered = True + else: + lac_log.active and self.events.add(FrogPilotEventName.frogSteerSaturated if self.goat_scream else EventName.steerSaturated) elif lac_log.saturated: dpath_points = lat_plan.dPathPoints if len(dpath_points): @@ -1004,6 +1020,8 @@ class Controls: self.reverse_cruise_increase = self.params.get_bool("ReverseCruise") and quality_of_life self.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") + def main(): controls = Controls() controls.controlsd_thread() diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index 2c4f262..0bb8296 100755 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -1028,6 +1028,14 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { Priority.LOW, VisualAlert.none, AudibleAlert.none, .1, alert_rate=0.75), }, + # Random Events + FrogPilotEventName.firefoxSteerSaturated: { + ET.WARNING: Alert( + "Turn Exceeds Steering Limit", + "IE Has Stopped Responding...", + AlertStatus.userPrompt, AlertSize.mid, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.firefox, 4.), + }, } diff --git a/selfdrive/frogpilot/assets/custom_themes/frog_theme/sounds/firefox.wav b/selfdrive/frogpilot/assets/custom_themes/frog_theme/sounds/firefox.wav new file mode 100644 index 0000000..c3ea4d5 Binary files /dev/null and b/selfdrive/frogpilot/assets/custom_themes/frog_theme/sounds/firefox.wav differ diff --git a/selfdrive/frogpilot/assets/custom_themes/stalin_theme/sounds/firefox.wav b/selfdrive/frogpilot/assets/custom_themes/stalin_theme/sounds/firefox.wav new file mode 100644 index 0000000..c3ea4d5 Binary files /dev/null and b/selfdrive/frogpilot/assets/custom_themes/stalin_theme/sounds/firefox.wav differ diff --git a/selfdrive/frogpilot/assets/custom_themes/stock_theme/sounds/firefox.wav b/selfdrive/frogpilot/assets/custom_themes/stock_theme/sounds/firefox.wav new file mode 100644 index 0000000..c3ea4d5 Binary files /dev/null and b/selfdrive/frogpilot/assets/custom_themes/stock_theme/sounds/firefox.wav differ diff --git a/selfdrive/frogpilot/assets/custom_themes/tesla_theme/sounds/firefox.wav b/selfdrive/frogpilot/assets/custom_themes/tesla_theme/sounds/firefox.wav new file mode 100644 index 0000000..c3ea4d5 Binary files /dev/null and b/selfdrive/frogpilot/assets/custom_themes/tesla_theme/sounds/firefox.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/assets/wheel_images/firefox.png b/selfdrive/frogpilot/assets/wheel_images/firefox.png new file mode 100644 index 0000000..6c3a418 Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/firefox.png differ diff --git a/selfdrive/frogpilot/ui/visual_settings.cc b/selfdrive/frogpilot/ui/visual_settings.cc index 117ad8f..b825287 100644 --- a/selfdrive/frogpilot/ui/visual_settings.cc +++ b/selfdrive/frogpilot/ui/visual_settings.cc @@ -35,6 +35,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"HideSpeed", "Hide Speed", "Hide the speed indicator in the onroad UI.", ""}, {"ShowSLCOffset", "Show Speed Limit Offset", "Show the speed limit offset seperated from the speed limit in the onroad UI when using 'Speed Limit Controller'.", ""}, + {"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"}, {"ScreenBrightness", "Screen Brightness", "Customize your screen brightness.", "../frogpilot/assets/toggle_icons/icon_light.png"}, {"SilentMode", "Silent Mode", "Mute openpilot sounds for a quieter driving experience.", "../frogpilot/assets/toggle_icons/icon_mute.png"}, {"WheelIcon", "Steering Wheel Icon", "Replace the default steering wheel icon with a custom design, adding a unique touch to your interface.", "../assets/offroad/icon_openpilot.png"}, diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index fea0732..64bccf3 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -376,7 +376,8 @@ 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/wheel_images/firefox.png", {img_size, img_size})} }; } @@ -405,13 +406,20 @@ void ExperimentalButton::updateState(const UIState &s, bool leadInfo) { } // FrogPilot variables + firefoxRandomEventTriggered = scene.current_random_event == 1; rotatingWheel = scene.rotating_wheel; wheelIcon = scene.wheel_icon; y_offset = leadInfo ? 10 : 0; + if (firefoxRandomEventTriggered) { + static int rotationDegree = 0; + rotationDegree = (rotationDegree + 36) % 360; + steeringAngleDeg = rotationDegree; + wheelIcon = 7; + update(); // Update the icon so the steering wheel rotates in real time - if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) { + } else if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) { steeringAngleDeg = scene.steering_angle_deg; update(); } @@ -431,7 +439,7 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { QColor(0, 0, 0, 166)); if (!scene.show_driver_camera) { - if (rotatingWheel) { + if (rotatingWheel || firefoxRandomEventTriggered) { 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); } 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); diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 5265eaa..a5a4cc6 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -85,6 +85,7 @@ private: std::map wheelImages; + bool firefoxRandomEventTriggered; bool rotatingWheel; int steeringAngleDeg; int wheelIcon; diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 9766a6c..5b6451b 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -40,6 +40,8 @@ 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), + + AudibleAlert.firefox: ("firefox.wav", None, MAX_VOLUME), } def check_controls_timeout_alert(sm): diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 48b8081..4597f75 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -330,6 +330,7 @@ void ui_update_params(UIState *s) { scene.quality_of_life_visuals = params.getBool("QOLVisuals"); scene.full_map = params.getBool("QOLVisuals") && scene.quality_of_life_visuals; + scene.random_events = params.getBool("RandomEvents"); scene.rotating_wheel = params.getBool("RotatingWheel"); scene.screen_brightness = params.getInt("ScreenBrightness"); scene.speed_limit_controller = params.getBool("SpeedLimitController"); @@ -410,6 +411,9 @@ void UIState::update() { if (scene.conditional_experimental) { scene.conditional_status = paramsMemory.getInt("CEStatus"); } + 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 9ed1d3a..bedf45b 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -192,6 +192,7 @@ typedef struct UIScene { bool mute_dm; bool personalities_via_screen; bool quality_of_life_visuals; + bool random_events; bool road_name_ui; bool rotating_wheel; bool show_driver_camera; @@ -218,6 +219,7 @@ typedef struct UIScene { int conditional_speed; int conditional_speed_lead; int conditional_status; + int current_random_event; int custom_colors; int custom_signals; int desired_follow;