mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-01 05:33:49 +08:00
Visuals - Custom Themes - Random Events
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!
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import math
|
||||
import random
|
||||
import time
|
||||
import threading
|
||||
from typing import SupportsFloat
|
||||
@@ -73,16 +74,21 @@ class Controls:
|
||||
self.frogpilot_toggles = FrogPilotVariables.toggles
|
||||
|
||||
self.drive_added = False
|
||||
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.display_timer = 0
|
||||
self.drive_distance = 0
|
||||
self.drive_time = 0
|
||||
self.max_acceleration = 0
|
||||
self.previous_speed_limit = 0
|
||||
self.previous_v_cruise = 0
|
||||
self.random_event_timer = 0
|
||||
self.speed_limit_timer = 0
|
||||
|
||||
self.green_light_mac = MovingAverageCalculator()
|
||||
@@ -415,6 +421,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.frogpilot_toggles.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:
|
||||
@@ -673,8 +683,18 @@ 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.goatSteerSaturated if self.frogpilot_toggles.goat_scream else EventName.steerSaturated)
|
||||
if undershooting and turning and good_speed and max_torque and not self.random_event_triggered:
|
||||
event_choices = [1, 2]
|
||||
if self.sm.frame % (10000 // len(event_choices)) == 0 and self.frogpilot_toggles.random_events:
|
||||
event_choice = random.choice(event_choices)
|
||||
if event_choice == 1:
|
||||
lac_log.active and self.events.add(EventName.firefoxSteerSaturated)
|
||||
self.params_memory.put_int("CurrentRandomEvent", 1)
|
||||
elif event_choice == 2:
|
||||
lac_log.active and self.events.add(EventName.goatSteerSaturated)
|
||||
self.random_event_triggered = True
|
||||
else:
|
||||
lac_log.active and self.events.add(EventName.goatSteerSaturated if self.frogpilot_toggles.goat_scream else EventName.steerSaturated)
|
||||
elif lac_log.saturated:
|
||||
# TODO probably should not use dpath_points but curvature
|
||||
dpath_points = model_v2.position.y
|
||||
@@ -936,7 +956,10 @@ class Controls:
|
||||
self.events.add(EventName.blockUser)
|
||||
|
||||
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.frogpilot_toggles.random_events:
|
||||
self.events.add(EventName.openpilotCrashedRandomEvents)
|
||||
else:
|
||||
self.events.add(EventName.openpilotCrashed)
|
||||
self.openpilot_crashed_triggered = True
|
||||
|
||||
if self.frogpilot_toggles.green_light_alert:
|
||||
@@ -957,6 +980,45 @@ class Controls:
|
||||
if self.frogpilot_toggles.lead_departing_alert and self.sm['frogpilotPlan'].leadDeparting:
|
||||
self.events.add(EventName.leadDeparting)
|
||||
|
||||
if self.frogpilot_toggles.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
|
||||
|
||||
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 self.sm.frame % 25 == 0:
|
||||
if v_cruise == self.previous_v_cruise and not self.vCruise69_alert_played:
|
||||
self.events.add(EventName.vCruise69)
|
||||
self.vCruise69_alert_played = True
|
||||
self.previous_v_cruise = v_cruise
|
||||
else:
|
||||
self.vCruise69_alert_played = False
|
||||
self.previous_v_cruise = v_cruise
|
||||
|
||||
if self.frogpilot_toggles.speed_limit_alert or self.frogpilot_toggles.speed_limit_confirmation:
|
||||
current_speed_limit = self.sm['frogpilotPlan'].slcSpeedLimit
|
||||
desired_speed_limit = self.sm['frogpilotPlan'].unconfirmedSlcSpeedLimit
|
||||
@@ -1058,6 +1120,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.frogpilot_toggles.pause_lateral_below_speed or not (CS.leftBlinker or CS.rightBlinker) or CS.standstill
|
||||
self.speed_check = CS.vEgo >= self.frogpilot_toggles.pause_lateral_below_speed or CS.standstill or signal_check and self.frogpilot_toggles.pause_lateral_below_signal
|
||||
|
||||
|
||||
@@ -1097,6 +1097,63 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1, alert_rate=0.75),
|
||||
},
|
||||
|
||||
# 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.),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 221 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 160 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 52 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.
@@ -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);
|
||||
@@ -296,7 +308,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() {
|
||||
@@ -322,10 +339,39 @@ void ExperimentalButton::updateState(const UIState &s) {
|
||||
}
|
||||
|
||||
// FrogPilot variables
|
||||
int randomEvent = scene.current_random_event;
|
||||
|
||||
rotatingWheel = scene.rotating_wheel;
|
||||
wheelIcon = scene.wheel_icon;
|
||||
wheelIconGif = 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);
|
||||
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) {
|
||||
@@ -341,6 +387,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 ? bg_colors[STATUS_ALWAYS_ON_LATERAL_ACTIVE] :
|
||||
@@ -350,7 +397,11 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) {
|
||||
(scene.navigate_on_openpilot ? bg_colors[STATUS_NAVIGATION_ACTIVE] : QColor(0, 0, 0, 166)))))) :
|
||||
QColor(0, 0, 0, 166);
|
||||
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg);
|
||||
if (wheelIconGif != 0) {
|
||||
drawIconGif(p, QPoint(btn_size / 2, btn_size / 2), *gif, background_color, 1.0);
|
||||
} else {
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QMovie>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStackedLayout>
|
||||
#include <QWidget>
|
||||
@@ -106,11 +108,20 @@ private:
|
||||
UIScene &scene;
|
||||
|
||||
QMap<int, QPixmap> wheelImages;
|
||||
QMap<int, QMovie*> wheelImagesGif;
|
||||
|
||||
QMovie engage_gif;
|
||||
QLabel *gifLabel;
|
||||
|
||||
bool docRandomEventTriggered;
|
||||
bool firefoxRandomEventTriggered;
|
||||
bool rotatingWheel;
|
||||
bool treeFiddyRandomEventTriggered;
|
||||
bool weebRandomEventTriggered;
|
||||
|
||||
int steeringAngleDeg;
|
||||
int wheelIcon;
|
||||
int wheelIconGif;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+31
-4
@@ -42,6 +42,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),
|
||||
}
|
||||
@@ -70,6 +79,18 @@ class Soundd:
|
||||
self.frogpilot_toggles = FrogPilotVariables.toggles
|
||||
|
||||
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.goat: MAX_VOLUME,
|
||||
AudibleAlert.nessie: MAX_VOLUME,
|
||||
AudibleAlert.noice: MAX_VOLUME,
|
||||
AudibleAlert.uwu: MAX_VOLUME,
|
||||
}
|
||||
|
||||
self.update_frogpilot_sounds()
|
||||
|
||||
@@ -80,12 +101,15 @@ class Soundd:
|
||||
for sound in sound_list:
|
||||
filename, play_count, volume = sound_list[sound]
|
||||
|
||||
try:
|
||||
if sound in self.random_events_map:
|
||||
wavefile = wave.open(self.random_events_directory + filename, 'r')
|
||||
else:
|
||||
if sound == AudibleAlert.goat and not self.frogpilot_toggles.goat_scream:
|
||||
continue
|
||||
wavefile = wave.open(self.sound_directory + filename, 'r')
|
||||
except FileNotFoundError:
|
||||
wavefile = wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r')
|
||||
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
|
||||
@@ -171,6 +195,9 @@ class Soundd:
|
||||
elif self.frogpilot_toggles.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()
|
||||
|
||||
@@ -321,6 +321,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.disable_smoothing_vtsc = params.getBool("VisionTurnControl") && params.getBool("DisableVTSCSmoothing");
|
||||
@@ -419,6 +420,7 @@ void UIState::update() {
|
||||
// FrogPilot live variables that need to be constantly checked
|
||||
scene.conditional_status = scene.conditional_experimental && scene.enabled ? 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;
|
||||
}
|
||||
|
||||
void UIState::setPrimeType(PrimeType type) {
|
||||
|
||||
@@ -208,6 +208,7 @@ typedef struct UIScene {
|
||||
bool onroad_distance_button;
|
||||
bool parked;
|
||||
bool pedals_on_ui;
|
||||
bool random_events;
|
||||
bool reverse_cruise;
|
||||
bool reverse_cruise_ui;
|
||||
bool right_hand_drive;
|
||||
@@ -247,6 +248,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;
|
||||
|
||||
Reference in New Issue
Block a user