diff --git a/common/params.cc b/common/params.cc index eeb1b1d48..1fca19106 100644 --- a/common/params.cc +++ b/common/params.cc @@ -359,6 +359,7 @@ std::unordered_map keys = { {"RoadEdgesWidth", PERSISTENT}, {"RoadName", PERSISTENT}, {"RoadNameUI", PERSISTENT}, + {"RotatingWheel", PERSISTENT}, {"SchedulePending", PERSISTENT}, {"SearchInput", PERSISTENT}, {"ShowCPU", PERSISTENT}, diff --git a/selfdrive/frogpilot/assets/toggle_icons/icon_rotate.png b/selfdrive/frogpilot/assets/toggle_icons/icon_rotate.png new file mode 100644 index 000000000..1503308e5 Binary files /dev/null and b/selfdrive/frogpilot/assets/toggle_icons/icon_rotate.png differ diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 783806b0e..d4b121570 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -18,15 +18,19 @@ #include "selfdrive/ui/qt/maps/map_panel.h" #endif -static void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity) { +static void drawIcon(QPainter &p, const QPoint ¢er, 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); p.setBrush(bg); p.drawEllipse(center, btn_size / 2, btn_size / 2); + p.save(); + p.translate(center); + p.rotate(-angle); p.setOpacity(opacity); - p.drawPixmap(center - QPoint(img.width() / 2, img.height() / 2), img); + p.drawPixmap(-QPoint(img.width() / 2, img.height() / 2), img); p.setOpacity(1.0); + p.restore(); } OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent), scene(uiState()->scene) { @@ -394,14 +398,23 @@ void ExperimentalButton::updateState(const UIState &s, bool leadInfo) { } // FrogPilot variables + rotatingWheel = scene.rotating_wheel; + y_offset = leadInfo ? 10 : 0; + + if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) { + update(); + steeringAngleDeg = scene.steering_angle_deg; + } else if (!rotatingWheel) { + steeringAngleDeg = 0; + } } void ExperimentalButton::paintEvent(QPaintEvent *event) { QPainter p(this); QPixmap img = experimental_mode ? experimental_img : engage_img; if (!(scene.map_open && scene.big_map)) { - drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0); + drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg); } } diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index bc971864a..95f3dde23 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -104,6 +104,9 @@ private: Params paramsMemory{"/dev/shm/params"}; UIScene &scene; + bool rotatingWheel; + + int steeringAngleDeg; int y_offset; }; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 4b749d9c9..f9acfbfa8 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -234,6 +234,7 @@ static void update_state(UIState *s) { scene.blind_spot_right = carState.getRightBlindspot(); scene.reverse = carState.getGearShifter() == cereal::CarState::GearShifter::REVERSE; scene.standstill = carState.getStandstill(); + scene.steering_angle_deg = carState.getSteeringAngleDeg(); scene.turn_signal_left = carState.getLeftBlinker(); scene.turn_signal_right = carState.getRightBlinker(); } @@ -325,6 +326,7 @@ void ui_update_frogpilot_params(UIState *s) { scene.lead_info = scene.longitudinal_control && custom_onroad_ui && params.getBool("LeadInfo"); scene.pedals_on_ui = custom_onroad_ui && params.getBool("PedalsOnUI"); scene.road_name_ui = custom_onroad_ui && params.getBool("RoadNameUI"); + scene.rotating_wheel = custom_onroad_ui && params.getBool("RotatingWheel"); scene.show_jerk = scene.longitudinal_control && developer_ui && params.getBool("ShowJerk"); scene.show_tuning = scene.has_auto_tune && developer_ui && !(params.getBool("LateralTune") && params.getBool("NNFF")) && params.getBool("ShowTuning"); scene.use_si = (scene.lead_info || developer_ui) && params.getBool("UseSI"); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 88bfbc92e..a1f792ae6 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -214,6 +214,7 @@ typedef struct UIScene { bool reverse_cruise_ui; bool right_hand_drive; bool road_name_ui; + bool rotating_wheel; bool show_aol_status_bar; bool show_cem_status_bar; bool show_jerk; @@ -256,6 +257,7 @@ typedef struct UIScene { int driver_camera_timer; int obstacle_distance; int obstacle_distance_stock; + int steering_angle_deg; int stopped_equivalence; QPolygonF track_adjacent_vertices[6];