Random Events

This commit is contained in:
James
2025-12-01 12:00:00 -07:00
parent fec050a3c1
commit cfb0d01ebd
28 changed files with 262 additions and 15 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

+4 -2
View File
@@ -10,7 +10,7 @@ from urllib.parse import quote_plus
from openpilot.frogpilot.common.frogpilot_download_utilities import GITLAB_URL, download_file, get_repository_url, handle_error, verify_download
from openpilot.frogpilot.common.frogpilot_utilities import delete_file, extract_zip, load_json_file, update_json_file
from openpilot.frogpilot.common.frogpilot_variables import ACTIVE_THEME_PATH, RESOURCES_REPO, THEME_SAVE_PATH
from openpilot.frogpilot.common.frogpilot_variables import ACTIVE_THEME_PATH, RANDOM_EVENTS_PATH, RESOURCES_REPO, THEME_SAVE_PATH
CANCEL_DOWNLOAD_PARAM = "CancelThemeDownload"
DOWNLOAD_PROGRESS_PARAM = "ThemeDownloadProgress"
@@ -542,11 +542,13 @@ class ThemeManager:
self.update_theme_params(downloadable_colors, downloadable_distance_icons, downloadable_icons, downloadable_signals, downloadable_sounds, downloadable_wheels)
def update_wheel_image(self, image, boot_run=False):
def update_wheel_image(self, image, boot_run=False, random_event=False):
wheel_save_location = ACTIVE_THEME_PATH / "steering_wheel"
if self.holiday_theme != "stock":
wheel_location = HOLIDAY_THEME_PATH / self.holiday_theme / "steering_wheel"
elif random_event:
wheel_location = RANDOM_EVENTS_PATH / "steering_wheels"
elif image == "stock":
wheel_location = STOCKOP_THEME_PATH / "steering_wheel"
elif image in HOLIDAY_SLUGS:
+2 -2
View File
@@ -20,13 +20,13 @@ from openpilot.frogpilot.controls.lib.frogpilot_following import FrogPilotFollow
from openpilot.frogpilot.controls.lib.frogpilot_vcruise import FrogPilotVCruise
class FrogPilotPlanner:
def __init__(self, error_log):
def __init__(self, error_log, ThemeManager):
self.params = Params(return_defaults=True)
self.params_memory = Params(memory=True)
self.frogpilot_acceleration = FrogPilotAcceleration(self)
self.frogpilot_cem = ConditionalExperimentalMode(self)
self.frogpilot_events = FrogPilotEvents(self, error_log)
self.frogpilot_events = FrogPilotEvents(self, error_log, ThemeManager)
self.frogpilot_following = FrogPilotFollowing(self)
self.frogpilot_vcruise = FrogPilotVCruise(self)
+115 -3
View File
@@ -1,18 +1,33 @@
#!/usr/bin/env python3
import random
from openpilot.common.constants import ACCELERATION_DUE_TO_GRAVITY, CV
from openpilot.common.realtime import DT_MDL
from openpilot.selfdrive.selfdrived.events import ET, EVENT_NAME, FROGPILOT_EVENT_NAME, EventName, FrogPilotEventName, Events
from openpilot.frogpilot.common.frogpilot_variables import NON_DRIVING_GEARS
from openpilot.frogpilot.common.frogpilot_variables import CRUISING_SPEED, NON_DRIVING_GEARS
DEJA_VU_G_FORCE = 0.75
RANDOM_EVENTS_CHANCE = 0.01 * DT_MDL
RANDOM_EVENTS_LENGTH = 5
RANDOM_EVENT_START = FrogPilotEventName.accel30
RANDOM_EVENT_END = FrogPilotEventName.youveGotMail
class FrogPilotEvents:
def __init__(self, FrogPilotPlanner, error_log):
def __init__(self, FrogPilotPlanner, error_log, ThemeManager):
self.frogpilot_planner = FrogPilotPlanner
self.theme_manager = ThemeManager
self.events = Events(frogpilot=True)
self.always_on_lateral_enabled_previously = False
self.random_event_playing = False
self.startup_seen = False
self.stopped_for_light = False
self.max_acceleration = 0
self.random_event_timer = 0
self.tracked_lead_distance = 0
self.played_events = set()
@@ -63,8 +78,105 @@ class FrogPilotEvents:
if "nnffLoaded" not in self.played_events and self.startup_seen and alerts_empty and len(self.events) == 0 and self.frogpilot_planner.params.get("NNFFModelName") is not None and frogpilot_toggles.nnff:
self.events.add(FrogPilotEventName.nnffLoaded)
if self.random_event_playing:
self.random_event_timer += DT_MDL
if self.random_event_timer >= RANDOM_EVENTS_LENGTH:
self.theme_manager.update_wheel_image(frogpilot_toggles.wheel_image)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
self.random_event_playing = False
self.random_event_timer = 0
if not self.random_event_playing and frogpilot_toggles.random_events:
if "accel30" not in self.played_events and 3.5 > self.max_acceleration >= 3.0 and acceleration < 1.5:
self.events.add(FrogPilotEventName.accel30)
self.theme_manager.update_wheel_image("accel30", random_event=True)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
self.max_acceleration = 0
elif "accel35" not in self.played_events and 4.0 > self.max_acceleration >= 3.5 and acceleration < 1.5:
self.events.add(FrogPilotEventName.accel35)
self.theme_manager.update_wheel_image("accel35", random_event=True)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
self.max_acceleration = 0
elif "accel40" not in self.played_events and self.max_acceleration >= 4.0 and acceleration < 1.5:
self.events.add(FrogPilotEventName.accel40)
self.theme_manager.update_wheel_image("accel40", random_event=True)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
self.max_acceleration = 0
if "dejaVuCurve" not in self.played_events and sm["carState"].vEgo > CRUISING_SPEED:
if self.frogpilot_planner.lateral_acceleration >= DEJA_VU_G_FORCE * ACCELERATION_DUE_TO_GRAVITY:
self.events.add(FrogPilotEventName.dejaVuCurve)
if "hal9000" not in self.played_events and (ET.NO_ENTRY in current_alert or ET.NO_ENTRY in current_frogpilot_alert):
self.events.add(FrogPilotEventName.hal9000)
if f"{EVENT_NAME[EventName.steerSaturated]}/" in current_alert or f"{FROGPILOT_EVENT_NAME[FrogPilotEventName.goatSteerSaturated]}/" in current_frogpilot_alert:
event_choices = []
if "firefoxSteerSaturated" not in self.played_events:
event_choices.append("firefoxSteerSaturated")
if "goatSteerSaturated" not in self.played_events:
event_choices.append("goatSteerSaturated")
if "thisIsFineSteerSaturated" not in self.played_events:
event_choices.append("thisIsFineSteerSaturated")
if event_choices and random.random() < RANDOM_EVENTS_CHANCE:
event_choice = random.choice(event_choices)
if event_choice == "firefoxSteerSaturated":
self.events.add(FrogPilotEventName.firefoxSteerSaturated)
self.theme_manager.update_wheel_image("firefoxSteerSaturated", random_event=True)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
elif event_choice == "goatSteerSaturated":
self.events.add(FrogPilotEventName.goatSteerSaturated)
self.theme_manager.update_wheel_image("goatSteerSaturated", random_event=True)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
elif event_choice == "thisIsFineSteerSaturated":
self.events.add(FrogPilotEventName.thisIsFineSteerSaturated)
self.theme_manager.update_wheel_image("thisIsFineSteerSaturated", random_event=True)
self.frogpilot_planner.params_memory.put_bool("UpdateWheelImage", True)
if "vCruise69" not in self.played_events and 70 > max(sm["carState"].vCruise, sm["carState"].vCruiseCluster) * (1 if frogpilot_toggles.is_metric else CV.KPH_TO_MPH) >= 69:
self.events.add(FrogPilotEventName.vCruise69)
if f"{EVENT_NAME[EventName.fcw]}/" in current_alert or f"{EVENT_NAME[EventName.stockAeb]}/" in current_alert:
event_choices = []
if "toBeContinued" not in self.played_events:
event_choices.append("toBeContinued")
if "yourFrogTriedToKillMe" not in self.played_events:
event_choices.append("yourFrogTriedToKillMe")
if event_choices:
event_choice = random.choice(event_choices)
if event_choice == "toBeContinued":
self.events.add(FrogPilotEventName.toBeContinued)
elif event_choice == "yourFrogTriedToKillMe":
self.events.add(FrogPilotEventName.yourFrogTriedToKillMe)
if "youveGotMail" not in self.played_events and sm["frogpilotCarState"].alwaysOnLateralEnabled and not self.always_on_lateral_enabled_previously:
if random.random() < RANDOM_EVENTS_CHANCE / DT_MDL:
self.events.add(FrogPilotEventName.youveGotMail)
self.always_on_lateral_enabled_previously = sm["frogpilotCarState"].alwaysOnLateralEnabled
self.random_event_playing |= bool({event for event in self.events.names if RANDOM_EVENT_START <= event <= RANDOM_EVENT_END})
if self.error_log.is_file():
self.events.add(FrogPilotEventName.openpilotCrashed)
if frogpilot_toggles.random_events:
self.events.add(FrogPilotEventName.openpilotCrashedRandomEvent)
else:
self.events.add(FrogPilotEventName.openpilotCrashed)
self.startup_seen |= sm["frogpilotSelfdriveState"].alertText1 == frogpilot_toggles.startup_alert_top and sm["frogpilotSelfdriveState"].alertText2 == frogpilot_toggles.startup_alert_bottom
+1 -1
View File
@@ -108,7 +108,7 @@ def frogpilot_thread():
run_update_checks = True
elif started and not started_previously:
frogpilot_planner = FrogPilotPlanner(error_log)
frogpilot_planner = FrogPilotPlanner(error_log, theme_manager)
frogpilot_tracking = FrogPilotTracking(frogpilot_planner, frogpilot_toggles)
transition_onroad(error_log)
+103
View File
@@ -1179,6 +1179,109 @@ FROGPILOT_EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
AlertStatus.critical, AlertSize.mid,
Priority.HIGHEST, VisualAlert.none, AudibleAlert.prompt, .1),
},
# Random Events
FrogPilotEventName.accel30: {
ET.WARNING: Alert(
"UwU u went a bit fast there!",
"( ⁄•⁄ω⁄•⁄ )",
FrogPilotAlertStatus.frogpilot, AlertSize.mid,
Priority.LOW, VisualAlert.none, FrogPilotAudibleAlert.uwu, 4.),
},
FrogPilotEventName.accel35: {
ET.WARNING: Alert(
"I ain't giving you no tree-fiddy",
"You damn Loch Ness Monsta!",
FrogPilotAlertStatus.frogpilot, AlertSize.mid,
Priority.LOW, VisualAlert.none, FrogPilotAudibleAlert.nessie, 4.),
},
FrogPilotEventName.accel40: {
ET.WARNING: Alert(
"Great Scott!",
"🚗💨",
FrogPilotAlertStatus.frogpilot, AlertSize.mid,
Priority.LOW, VisualAlert.none, FrogPilotAudibleAlert.doc, 4.),
},
FrogPilotEventName.dejaVuCurve: {
ET.PERMANENT: Alert(
"♬♪ Deja vu! ᕕ(⌐■_■)ᕗ ♪♬",
"🏎️",
FrogPilotAlertStatus.frogpilot, AlertSize.mid,
Priority.LOW, VisualAlert.none, FrogPilotAudibleAlert.dejaVu, 4.),
},
FrogPilotEventName.firefoxSteerSaturated: {
ET.WARNING: Alert(
"IE Has Stopped Responding...",
"Turn Exceeds Steering Limit",
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.steerRequired, FrogPilotAudibleAlert.firefox, 4.),
},
FrogPilotEventName.hal9000: {
ET.WARNING: Alert(
"I'm sorry Dave",
"I'm afraid I can't do that...",
AlertStatus.normal, AlertSize.mid,
Priority.HIGH, VisualAlert.none, FrogPilotAudibleAlert.hal9000, 4.),
},
FrogPilotEventName.openpilotCrashedRandomEvent: {
ET.IMMEDIATE_DISABLE: Alert(
"openpilot crashed 💩",
"Please post the 'Error Log' in the FrogPilot Discord!",
AlertStatus.normal, AlertSize.mid,
Priority.HIGHEST, VisualAlert.none, FrogPilotAudibleAlert.fart, 10.),
ET.NO_ENTRY: Alert(
"openpilot crashed 💩",
"Please post the 'Error Log' in the FrogPilot Discord!",
AlertStatus.normal, AlertSize.mid,
Priority.HIGHEST, VisualAlert.none, FrogPilotAudibleAlert.fart, 10.),
},
FrogPilotEventName.thisIsFineSteerSaturated: {
ET.WARNING: Alert(
"This is fine ☕",
"Turn Exceeds Steering Limit",
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.steerRequired, FrogPilotAudibleAlert.thisIsFine, 2.),
},
FrogPilotEventName.toBeContinued: {
ET.PERMANENT: Alert(
"To be continued...",
"⬅️",
FrogPilotAlertStatus.frogpilot, AlertSize.mid,
Priority.MID, VisualAlert.none, FrogPilotAudibleAlert.continued, 7.),
},
FrogPilotEventName.vCruise69: {
ET.WARNING: Alert(
"Lol 69",
"",
FrogPilotAlertStatus.frogpilot, AlertSize.small,
Priority.LOW, VisualAlert.none, FrogPilotAudibleAlert.noice, 2.),
},
FrogPilotEventName.yourFrogTriedToKillMe: {
ET.PERMANENT: Alert(
"Your Frog tried to kill me...",
"👺",
FrogPilotAlertStatus.frogpilot, AlertSize.mid,
Priority.MID, VisualAlert.none, FrogPilotAudibleAlert.angry, 5.),
},
FrogPilotEventName.youveGotMail: {
ET.WARNING: Alert(
"You've got mail! 📧",
"",
FrogPilotAlertStatus.frogpilot, AlertSize.small,
Priority.LOW, VisualAlert.none, FrogPilotAudibleAlert.mail, 3.),
},
}
+13 -5
View File
@@ -38,11 +38,19 @@ OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, const SubMaster
Alert a = {};
static QString crash_log_path = "/data/error_logs/error.txt";
if (QFile::exists(crash_log_path)) {
a = {tr("openpilot crashed"),
tr("Please post the \"Error Log\" in the FrogPilot Discord!"),
"openpilotCrashed",
cereal::SelfdriveState::AlertSize::MID,
cereal::SelfdriveState::AlertStatus::CRITICAL};
if (frogpilot_toggles.value("random_events").toBool()) {
a = {tr("openpilot crashed 💩"),
tr("Please post the \"Error Log\" in the FrogPilot Discord!"),
"openpilotCrashedRandomEvent",
cereal::SelfdriveState::AlertSize::MID,
cereal::SelfdriveState::AlertStatus::CRITICAL};
} else {
a = {tr("openpilot crashed"),
tr("Please post the \"Error Log\" in the FrogPilot Discord!"),
"openpilotCrashed",
cereal::SelfdriveState::AlertSize::MID,
cereal::SelfdriveState::AlertStatus::CRITICAL};
}
return a;
} else if (selfdrive_frame >= started_frame) { // Don't get old alert.
a = {ss.getAlertText1().cStr(), ss.getAlertText2().cStr(),
+5
View File
@@ -54,6 +54,11 @@ void ExperimentalButton::updateState(const UIState &s, const FrogPilotUIState &f
const cereal::CarState::Reader &carState = (*s.sm)["carState"].getCarState();
updateBackgroundColor();
if (params_memory.getBool("UpdateWheelImage")) {
updateTheme();
params_memory.remove("UpdateWheelImage");
}
}
void ExperimentalButton::paintEvent(QPaintEvent *event) {
+19 -2
View File
@@ -16,7 +16,7 @@ from openpilot.common.swaglog import cloudlog
from openpilot.system import micd
from openpilot.system.hardware import HARDWARE
from openpilot.frogpilot.common.frogpilot_variables import ACTIVE_THEME_PATH, ERROR_LOGS_PATH, get_frogpilot_toggles
from openpilot.frogpilot.common.frogpilot_variables import ACTIVE_THEME_PATH, ERROR_LOGS_PATH, RANDOM_EVENTS_PATH, get_frogpilot_toggles
SAMPLE_RATE = 48000
SAMPLE_BUFFER = 4096 # (approx 100ms)
@@ -52,7 +52,20 @@ sound_list: dict[int, tuple[str, int | None, float]] = {
AudibleAlert.warningImmediate: ("warning_immediate.wav", None, MAX_VOLUME),
# FrogPilot variables
FrogPilotAudibleAlert.angry: ("angry.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.continued: ("continued.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.dejaVu: ("dejaVu.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.doc: ("doc.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.fart: ("fart.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.firefox: ("firefox.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.goat: ("goat.wav", None, MAX_VOLUME),
FrogPilotAudibleAlert.hal9000: ("hal9000.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.mail: ("mail.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.nessie: ("nessie.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.noice: ("noice.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.startup: ("startup.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.thisIsFine: ("this_is_fine.wav", 1, MAX_VOLUME),
FrogPilotAudibleAlert.uwu: ("uwu.wav", 1, MAX_VOLUME),
}
if HARDWARE.get_device_type() in ("tici", "tizi"):
sound_list.update({
@@ -92,6 +105,7 @@ class Soundd:
self.previous_sound_pack = None
self.error_log = ERROR_LOGS_PATH / "error.txt"
self.random_events_directory = RANDOM_EVENTS_PATH / "sounds"
self.update_frogpilot_sounds()
@@ -102,6 +116,7 @@ class Soundd:
for sound in sound_list:
filename, play_count, volume = sound_list[sound]
random_events_path = self.random_events_directory / filename
sounds_path = self.sound_directory / filename
if not sounds_path.exists() and "_tizi" in filename:
@@ -109,7 +124,9 @@ class Soundd:
if standard_path.exists():
sounds_path = standard_path
if sounds_path.exists():
if random_events_path.exists():
wavefile = wave.open(str(random_events_path), 'r')
elif sounds_path.exists():
wavefile = wave.open(str(sounds_path), 'r')
else:
if filename == "startup.wav":