Skip to content

Commit

Permalink
Animated frog turn signal
Browse files Browse the repository at this point in the history
Added toggle for a turn signal animation of a frog jumping across the screen.
  • Loading branch information
FrogAi committed Aug 19, 2023
1 parent c7ab832 commit 9da2086
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 2 deletions.
1 change: 1 addition & 0 deletions common/params.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"FrogColors", PERSISTENT},
{"FrogIcons", PERSISTENT},
{"FrogPilotTogglesUpdated", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"FrogSignals", PERSISTENT},
{"FrogSounds", PERSISTENT},
{"FrogTheme", PERSISTENT},
{"GitBranch", PERSISTENT},
Expand Down
Binary file added selfdrive/assets/images/frog_turn_signal_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added selfdrive/assets/images/frog_turn_signal_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added selfdrive/assets/images/frog_turn_signal_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added selfdrive/assets/images/frog_turn_signal_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions selfdrive/ui/qt/offroad/frogpilot_settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(QWidget *parent) : FrogPilotPanel(p
{"FrogColors", "Colors"},
{"FrogIcons", "Icons"},
{"FrogSounds", "Sounds"},
{"FrogSignals", "Turn Signals"}
}, mainLayout);
} else if (key == "CustomRoadUI") {
createSubControl(key, label, desc, icon, {
Expand Down
66 changes: 65 additions & 1 deletion selfdrive/ui/qt/onroad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <QDebug>
#include <QMouseEvent>
#include <QTimer>

#include "common/timing.h"
#include "selfdrive/ui/qt/util.h"
Expand Down Expand Up @@ -363,6 +364,30 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* par
{3, loadPixmap("../assets/frog.png", {img_size, img_size})},
{4, loadPixmap("../assets/rocket.png", {img_size, img_size})}
};

// Turn signal images
const QStringList imagePaths = {
"../assets/images/frog_turn_signal_1.png",
"../assets/images/frog_turn_signal_2.png",
"../assets/images/frog_turn_signal_3.png",
"../assets/images/frog_turn_signal_4.png"
};
signalImgVector.reserve(2 * imagePaths.size() + 1);
for (int i = 0; i < 2; ++i) {
for (const QString& path : imagePaths) {
signalImgVector.push_back(QPixmap(path));
}
}
// Add the blindspot signal image to the vector
signalImgVector.push_back(QPixmap("../assets/images/frog_turn_signal_1_red.png"));

// Initialize the timer for the turn signal animation
auto animationTimer = new QTimer(this);
connect(animationTimer, &QTimer::timeout, this, [this] {
animationFrameIndex = (animationFrameIndex + 1) % totalFrames;
update();
});
animationTimer->start(totalFrames * 11); // 50 milliseconds per frame; syncs up perfectly with my 2019 Lexus ES 350 turn signal clicks
}

void AnnotatedCameraWidget::updateState(const UIState &s) {
Expand Down Expand Up @@ -408,7 +433,7 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
setProperty("speed", cur_speed);
setProperty("setSpeed", set_speed);
setProperty("speedUnit", s.scene.is_metric ? tr("km/h") : tr("mph"));
setProperty("hideBottomIcons", (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE));
setProperty("hideBottomIcons", (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE) || frogSignals && (turnSignalLeft || turnSignalRight));
setProperty("status", s.status);

// update engageability/experimental mode button
Expand Down Expand Up @@ -437,10 +462,13 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
setProperty("compass", s.scene.compass);
setProperty("experimentalMode", s.scene.experimental_mode);
setProperty("frogColors", s.scene.frog_colors);
setProperty("frogSignals", s.scene.frog_signals);
setProperty("muteDM", s.scene.mute_dm);
setProperty("rotatingWheel", s.scene.rotating_wheel);
setProperty("steeringAngleDeg", s.scene.steering_angle_deg);
setProperty("steeringWheel", s.scene.steering_wheel);
setProperty("turnSignalLeft", s.scene.turn_signal_left);
setProperty("turnSignalRight", s.scene.turn_signal_right);
}

void AnnotatedCameraWidget::drawHud(QPainter &p) {
Expand Down Expand Up @@ -551,6 +579,11 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
drawCompass(p);
}

// Frog turn signal animation
if (frogSignals && (turnSignalLeft || turnSignalRight)) {
drawFrogSignals(p);
}

// Rotating steering wheel
if (rotatingWheel) {
const auto &scene = uiState()->scene;
Expand Down Expand Up @@ -999,6 +1032,37 @@ void AnnotatedCameraWidget::drawCompass(QPainter &p) {
p.restore();
}

void AnnotatedCameraWidget::drawFrogSignals(QPainter &p) {
// Declare the turn signal size
constexpr int signalHeight = 480;
constexpr int signalWidth = 360;

// Calculate the vertical position for the turn signals
const int baseYPosition = (height() - signalHeight) / 2 + 300;
// Calculate the x-coordinates for the turn signals
int leftSignalXPosition = 75 + width() - signalWidth - 300 * (blindSpotLeft ? 0 : animationFrameIndex);
int rightSignalXPosition = -75 + 300 * (blindSpotRight ? 0 : animationFrameIndex);

// Enable Antialiasing
p.setRenderHint(QPainter::Antialiasing);

// Draw the turn signals
if (animationFrameIndex < static_cast<int>(signalImgVector.size())) {
const auto drawSignal = [&](const bool signalActivated, const int xPosition, const bool flip, const bool blindspot) {
if (signalActivated) {
// Get the appropriate image from the signalImgVector
QPixmap signal = signalImgVector[(blindspot ? signalImgVector.size()-1 : animationFrameIndex % totalFrames)].transformed(QTransform().scale(flip ? -1 : 1, 1));
// Draw the image
p.drawPixmap(xPosition, baseYPosition, signalWidth, signalHeight, signal);
}
};

// Display the animation based on which signal is activated
drawSignal(turnSignalLeft, leftSignalXPosition, false, blindSpotLeft);
drawSignal(turnSignalRight, rightSignalXPosition, true, blindSpotRight);
}
}

void AnnotatedCameraWidget::drawStatusBar(QPainter &p) {
p.save();

Expand Down
10 changes: 10 additions & 0 deletions selfdrive/ui/qt/onroad.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ class AnnotatedCameraWidget : public CameraWidget {
Q_PROPERTY(bool compass MEMBER compass);
Q_PROPERTY(bool experimentalMode MEMBER experimentalMode);
Q_PROPERTY(bool frogColors MEMBER frogColors);
Q_PROPERTY(bool frogSignals MEMBER frogSignals);
Q_PROPERTY(bool muteDM MEMBER muteDM);
Q_PROPERTY(bool rotatingWheel MEMBER rotatingWheel);
Q_PROPERTY(bool turnSignalLeft MEMBER turnSignalLeft);
Q_PROPERTY(bool turnSignalRight MEMBER turnSignalRight);
Q_PROPERTY(int bearingDeg MEMBER bearingDeg);
Q_PROPERTY(int steeringAngleDeg MEMBER steeringAngleDeg);
Q_PROPERTY(int steeringWheel MEMBER steeringWheel);
Expand All @@ -113,6 +116,7 @@ class AnnotatedCameraWidget : public CameraWidget {

// FrogPilot widgets
void drawCompass(QPainter &p);
void drawFrogSignals(QPainter &p);
void drawStatusBar(QPainter &p);

QVBoxLayout *main_layout;
Expand Down Expand Up @@ -143,15 +147,21 @@ class AnnotatedCameraWidget : public CameraWidget {
bool compass;
bool experimentalMode;
bool frogColors;
bool frogSignals;
bool muteDM;
bool rotatingWheel;
bool turnSignalLeft;
bool turnSignalRight;
int animationFrameIndex;
int bearingDeg;
int steeringAngleDeg;
int steeringWheel;
QPixmap compass_inner_img;
QPixmap engage_img;
QPixmap experimental_img;
static constexpr int totalFrames = 8;
std::map<int, QPixmap> wheel_images;
std::vector<QPixmap> signalImgVector;

protected:
void paintGL() override;
Expand Down
7 changes: 6 additions & 1 deletion selfdrive/ui/ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,14 @@ static void update_state(UIState *s) {
}
if (sm.updated("carState")) {
const auto carState = sm["carState"].getCarState();
if (scene.blind_spot_path) {
if (scene.blind_spot_path || scene.frog_signals) {
scene.blind_spot_left = carState.getLeftBlindspot();
scene.blind_spot_right = carState.getRightBlindspot();
}
if (scene.frog_signals) {
scene.turn_signal_left = carState.getLeftBlinker();
scene.turn_signal_right = carState.getRightBlinker();
}
if (scene.blind_spot_path || scene.rotating_wheel) {
scene.steering_angle_deg = carState.getSteeringAngleDeg();
}
Expand Down Expand Up @@ -275,6 +279,7 @@ void ui_update_params(UIState *s) {
scene.blind_spot_path = scene.custom_road_ui && params.getBool("BlindSpotPath");
scene.frog_theme = params.getBool("FrogTheme");
scene.frog_colors = scene.frog_theme && params.getBool("FrogColors");
scene.frog_signals = scene.frog_theme && params.getBool("FrogSignals");
scene.lane_line_width = params.getInt("LaneLinesWidth") / 12.0 * 0.1524; // Convert from inches to meters
scene.mute_dm = params.getBool("FireTheBabysitter") && params.getBool("MuteDM");
scene.path_edge_width = params.getInt("PathEdgeWidth");
Expand Down
3 changes: 3 additions & 0 deletions selfdrive/ui/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,14 @@ typedef struct UIScene {
bool enabled;
bool experimental_mode;
bool frog_colors;
bool frog_signals;
bool frog_theme;
bool frogpilot_toggles_updated;
bool mute_dm;
bool rotating_wheel;
bool toyota_car = true;
bool turn_signal_left;
bool turn_signal_right;
bool unlimited_road_ui_length;
bool wide_camera_disabled;
float lane_line_width;
Expand Down

0 comments on commit 9da2086

Please sign in to comment.