Totally random events

Added toggle to enable a small chance of a random event occuring when certain conditions are met.
This commit is contained in:
FrogAi
2024-02-27 16:34:47 -07:00
parent a0209cf918
commit 075e81ce44
20 changed files with 274 additions and 43 deletions

View File

@@ -18,18 +18,7 @@
#include "selfdrive/ui/qt/maps/map_panel.h"
#endif
static void drawIcon(QPainter &p, const QPoint &center, 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 &center, const QPixmap &img, const QBrush &bg, float opacity, const int angle) {
static void drawIcon(QPainter &p, const QPoint &center, 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 &center, const QPixmap &img
p.restore();
}
static void drawIconGif(QPainter &p, const QPoint &center, 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);
}
}
}

View File

@@ -2,6 +2,8 @@
#include <memory>
#include <QMovie>
#include <QLabel>
#include <QPushButton>
#include <QStackedLayout>
#include <QWidget>
@@ -78,11 +80,20 @@ private:
// FrogPilot variables
UIScene &scene;
std::map<int, QPixmap> wheelImages;
QMap<int, QPixmap> wheelImages;
QMap<int, QMovie*> wheelImagesGif;
QMovie engage_gif;
QLabel *gifLabel;
bool firefoxRandomEventTriggered;
bool rotatingWheel;
bool treeFiddyRandomEventTriggered;
bool weebRandomEventTriggered;
int steeringAngleDeg;
int wheelIcon;
int wheelIconGif;
int y_offset;
};

View File

@@ -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")

View File

@@ -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) {

View File

@@ -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;