diff --git a/common/params.cc b/common/params.cc index 6bb78f6..3fc1935 100644 --- a/common/params.cc +++ b/common/params.cc @@ -408,6 +408,7 @@ std::unordered_map keys = { {"UseVienna", PERSISTENT}, {"WarningSoftVolume", PERSISTENT}, {"WarningImmediateVolume", PERSISTENT}, + {"WheelIcon", PERSISTENT}, }; } // namespace diff --git a/selfdrive/frogpilot/assets/wheel_images/frog.png b/selfdrive/frogpilot/assets/wheel_images/frog.png new file mode 100644 index 0000000..f0aca65 Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/frog.png differ diff --git a/selfdrive/frogpilot/assets/wheel_images/hyundai.png b/selfdrive/frogpilot/assets/wheel_images/hyundai.png new file mode 100644 index 0000000..7f7308d Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/hyundai.png differ diff --git a/selfdrive/frogpilot/assets/wheel_images/lexus.png b/selfdrive/frogpilot/assets/wheel_images/lexus.png new file mode 100644 index 0000000..1be4431 Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/lexus.png differ diff --git a/selfdrive/frogpilot/assets/wheel_images/rocket.png b/selfdrive/frogpilot/assets/wheel_images/rocket.png new file mode 100644 index 0000000..abe753a Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/rocket.png differ diff --git a/selfdrive/frogpilot/assets/wheel_images/stalin.png b/selfdrive/frogpilot/assets/wheel_images/stalin.png new file mode 100644 index 0000000..f1feebb Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/stalin.png differ diff --git a/selfdrive/frogpilot/assets/wheel_images/toyota.png b/selfdrive/frogpilot/assets/wheel_images/toyota.png new file mode 100644 index 0000000..0e8cf4c Binary files /dev/null and b/selfdrive/frogpilot/assets/wheel_images/toyota.png differ diff --git a/selfdrive/frogpilot/ui/visual_settings.cc b/selfdrive/frogpilot/ui/visual_settings.cc index ac6631d..083a0b5 100644 --- a/selfdrive/frogpilot/ui/visual_settings.cc +++ b/selfdrive/frogpilot/ui/visual_settings.cc @@ -62,6 +62,8 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"ScreenTimeout", "Screen Timeout", "Customize how long it takes for your screen to turn off.", ""}, {"ScreenTimeoutOnroad", "Screen Timeout (Onroad)", "Customize how long it takes for your screen to turn off after going onroad.", ""}, {"StandbyMode", "Standby Mode", "Turn the screen off after your screen times out when onroad but wake it back up when engagement state changes or important alerts are triggered.", ""}, + + {"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"}, }; for (const auto &[param, title, desc, icon] : visualToggles) { @@ -199,6 +201,12 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot } else if (param == "ScreenTimeout" || param == "ScreenTimeoutOnroad") { toggle = new FrogPilotParamValueControl(param, title, desc, icon, 5, 60, std::map(), this, false, " seconds"); + } else if (param == "WheelIcon") { + std::vector wheelToggles{"RotatingWheel"}; + std::vector wheelToggleNames{tr("Rotating")}; + std::map steeringWheelLabels = {{-1, "None"}, {0, "Stock"}, {1, "Lexus"}, {2, "Toyota"}, {3, "Frog"}, {4, "Rocket"}, {5, "Hyundai"}, {6, "Stalin"}}; + toggle = new FrogPilotParamValueToggleControl(param, title, desc, icon, -1, 6, steeringWheelLabels, this, true, "", 1, wheelToggles, wheelToggleNames); + } else { toggle = new ParamControl(param, title, desc, icon, this); } diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 6972c16..9487fe9 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -378,6 +378,17 @@ ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(fals engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size}); experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size, img_size}); QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode); + + // Custom steering wheel images + wheelImages = { + {0, loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size})}, + {1, loadPixmap("../frogpilot/assets/wheel_images/lexus.png", {img_size, img_size})}, + {2, loadPixmap("../frogpilot/assets/wheel_images/toyota.png", {img_size, img_size})}, + {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})} + }; } void ExperimentalButton::changeMode() { @@ -406,6 +417,7 @@ void ExperimentalButton::updateState(const UIState &s, bool leadInfo) { // FrogPilot variables rotatingWheel = scene.rotating_wheel; + wheelIcon = scene.wheel_icon; y_offset = leadInfo ? 10 : 0; @@ -422,13 +434,22 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { } QPainter p(this); - QPixmap img = experimental_mode ? experimental_img : engage_img; + // Custom steering wheel icon + 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); 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, QColor(0, 0, 0, 166), (isDown() || !(engageable || scene.always_on_lateral_active)) ? 0.6 : 1.0, steeringAngleDeg); + 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, QColor(0, 0, 0, 166), (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); } } } diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 92bcf61..ae75444 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -78,8 +78,11 @@ private: // FrogPilot variables UIScene &scene; + std::map wheelImages; + bool rotatingWheel; int steeringAngleDeg; + int wheelIcon; int y_offset; }; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index c099575..057f121 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -387,6 +387,8 @@ void ui_update_frogpilot_params(UIState *s) { scene.show_slc_offset = scene.speed_limit_controller && params.getBool("ShowSLCOffset"); scene.show_slc_offset_ui = scene.speed_limit_controller && params.getBool("ShowSLCOffsetUI"); scene.use_vienna_slc_sign = scene.speed_limit_controller && params.getBool("UseVienna"); + + scene.wheel_icon = params.getInt("WheelIcon"); } void UIState::updateStatus() { diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 40e2f83..15be138 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -263,6 +263,7 @@ typedef struct UIScene { int screen_timeout_onroad; int steering_angle_deg; int stopped_equivalence; + int wheel_icon; QPolygonF track_adjacent_vertices[6]; QPolygonF track_edge_vertices;