diff --git a/common/params.cc b/common/params.cc index 8520e6404..213bbd96e 100644 --- a/common/params.cc +++ b/common/params.cc @@ -345,6 +345,7 @@ std::unordered_map keys = { {"PauseAOLOnBrake", PERSISTENT}, {"PauseLateralOnSignal", PERSISTENT}, {"PauseLateralSpeed", PERSISTENT}, + {"PedalsOnUI", PERSISTENT}, {"PreferredSchedule", PERSISTENT}, {"PromptDistractedVolume", PERSISTENT}, {"PromptVolume", PERSISTENT}, diff --git a/selfdrive/frogpilot/assets/other_images/brake_pedal.png b/selfdrive/frogpilot/assets/other_images/brake_pedal.png new file mode 100644 index 000000000..f4fe0ef46 Binary files /dev/null and b/selfdrive/frogpilot/assets/other_images/brake_pedal.png differ diff --git a/selfdrive/frogpilot/assets/other_images/gas_pedal.png b/selfdrive/frogpilot/assets/other_images/gas_pedal.png new file mode 100644 index 000000000..ef1a87e58 Binary files /dev/null and b/selfdrive/frogpilot/assets/other_images/gas_pedal.png differ diff --git a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc index 3a59cda2e..9fad0334b 100644 --- a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc +++ b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.cc @@ -25,6 +25,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"FPSCounter", tr("FPS Counter"), tr("Display the 'Frames Per Second' (FPS) of your onroad UI for monitoring system performance."), ""}, {"LeadInfo", tr("Lead Info and Logics"), tr("Get detailed information about the vehicle ahead, including speed and distance, and the logic behind your following distance."), ""}, {"CustomPaths", tr("Paths"), tr("Show your projected acceleration on the driving path, detected adjacent lanes, or when a vehicle is detected in your blindspot."), ""}, + {"PedalsOnUI", tr("Pedals Being Pressed"), tr("Display the brake and gas pedals on the onroad UI below the steering wheel icon."), ""}, {"RoadNameUI", tr("Road Name"), tr("Display the current road's name at the bottom of the screen. Sourced from OpenStreetMap."), ""}, {"CustomTheme", tr("Custom Themes"), tr("Enable the ability to use custom themes."), "../frogpilot/assets/wheel_images/frog.png"}, diff --git a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h index 776de6725..95b1521b2 100644 --- a/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h +++ b/selfdrive/frogpilot/ui/qt/offroad/visual_settings.h @@ -25,7 +25,7 @@ private: std::set alertVolumeControlKeys = {"DisengageVolume", "EngageVolume", "PromptDistractedVolume", "PromptVolume", "RefuseVolume", "WarningImmediateVolume", "WarningSoftVolume"}; std::set customAlertsKeys = {"GreenLightAlert", "LeadDepartingAlert", "LoudBlindspotAlert"}; - std::set customOnroadUIKeys = {"Compass", "CustomPaths", "DeveloperUI", "FPSCounter", "LeadInfo", "RoadNameUI"}; + std::set customOnroadUIKeys = {"Compass", "CustomPaths", "DeveloperUI", "FPSCounter", "LeadInfo", "PedalsOnUI", "RoadNameUI"}; std::set customThemeKeys = {"CustomColors", "CustomIcons", "CustomSignals", "CustomSounds", "HolidayThemes"}; std::set modelUIKeys = {"DynamicPathWidth", "HideLeadMarker", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", "RoadEdgesWidth", "UnlimitedLength"}; std::set qolKeys = {"BigMap", "CameraView", "DriverCamera", "FullMap", "HideSpeed", "NumericalTemp"}; diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index cbfb167c2..783806b0e 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -430,8 +430,21 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* par main_layout->setMargin(UI_BORDER_SIZE); main_layout->setSpacing(0); + QHBoxLayout *buttons_layout = new QHBoxLayout(); + buttons_layout->setSpacing(0); + experimental_btn = new ExperimentalButton(this); - main_layout->addWidget(experimental_btn, 0, Qt::AlignTop | Qt::AlignRight); + buttons_layout->addWidget(experimental_btn); + + QVBoxLayout *top_right_layout = new QVBoxLayout(); + top_right_layout->setSpacing(0); + top_right_layout->addLayout(buttons_layout); + + pedal_icons = new PedalIcons(this); + top_right_layout->addWidget(pedal_icons, 0, Qt::AlignRight); + + main_layout->addLayout(top_right_layout, 0); + main_layout->setAlignment(top_right_layout, Qt::AlignTop | Qt::AlignRight); map_settings_btn = new MapSettingsButton(this); main_layout->addWidget(map_settings_btn, 0, Qt::AlignBottom | Qt::AlignRight); @@ -1235,6 +1248,12 @@ void AnnotatedCameraWidget::paintFrogPilotWidgets(QPainter &p) { bottom_layout->setAlignment(distance_btn, (rightHandDM ? Qt::AlignRight : Qt::AlignLeft)); } + bool enablePedalIcons = scene.pedals_on_ui && !bigMapOpen; + pedal_icons->setVisible(enablePedalIcons); + if (enablePedalIcons) { + pedal_icons->updateState(); + } + map_settings_btn_bottom->setEnabled(map_settings_btn->isEnabled()); if (map_settings_btn_bottom->isEnabled()) { map_settings_btn_bottom->setVisible(!hideBottomIcons && !compass); @@ -1512,6 +1531,44 @@ void AnnotatedCameraWidget::drawLeadInfo(QPainter &p) { p.restore(); } +PedalIcons::PedalIcons(QWidget *parent) : QWidget(parent), scene(uiState()->scene) { + setFixedSize(btn_size, btn_size); + + brake_pedal_img = loadPixmap("../frogpilot/assets/other_images/brake_pedal.png", QSize(img_size, img_size)); + gas_pedal_img = loadPixmap("../frogpilot/assets/other_images/gas_pedal.png", QSize(img_size, img_size)); +} + +void PedalIcons::updateState() { + acceleration = scene.acceleration; + + accelerating = acceleration > 0.25; + decelerating = acceleration < -0.25; + + if (accelerating || decelerating) { + update(); + } +} + +void PedalIcons::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + int totalWidth = 2 * img_size; + int startX = (width() - totalWidth) / 2; + + int brakeX = startX + img_size / 2; + int gasX = startX + img_size; + + float brakeOpacity = scene.standstill ? 1.0f : decelerating ? std::max(0.25f, std::abs(acceleration)) : 0.25f; + float gasOpacity = accelerating ? std::max(0.25f, acceleration) : 0.25f; + + p.setOpacity(brakeOpacity); + p.drawPixmap(brakeX, (height() - img_size) / 2, brake_pedal_img); + + p.setOpacity(gasOpacity); + p.drawPixmap(gasX, (height() - img_size) / 2, gas_pedal_img); +} + void AnnotatedCameraWidget::drawStatusBar(QPainter &p) { p.save(); diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 071206a11..bc971864a 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -120,6 +120,27 @@ private: QPixmap settings_img; }; +class PedalIcons : public QWidget { + Q_OBJECT + +public: + explicit PedalIcons(QWidget *parent = 0); + void updateState(); + +private: + void paintEvent(QPaintEvent *event) override; + + QPixmap brake_pedal_img; + QPixmap gas_pedal_img; + + UIScene &scene; + + bool accelerating; + bool decelerating; + + float acceleration; +}; + // container window for the NVG UI class AnnotatedCameraWidget : public CameraWidget { Q_OBJECT @@ -171,6 +192,7 @@ private: Compass *compass_img; DistanceButton *distance_btn; + PedalIcons *pedal_icons; QHBoxLayout *bottom_layout; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 0458f7713..f9ccb7da1 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -233,6 +233,7 @@ static void update_state(UIState *s) { scene.blind_spot_left = carState.getLeftBlindspot(); scene.blind_spot_right = carState.getRightBlindspot(); scene.reverse = carState.getGearShifter() == cereal::CarState::GearShifter::REVERSE; + scene.standstill = carState.getStandstill(); scene.turn_signal_left = carState.getLeftBlinker(); scene.turn_signal_right = carState.getRightBlinker(); } @@ -322,6 +323,7 @@ void ui_update_frogpilot_params(UIState *s) { scene.compass = custom_onroad_ui && params.getBool("Compass"); scene.fps_counter = custom_onroad_ui && params.getBool("FPSCounter"); 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.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"); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index a192538cc..930d3e3ca 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -207,6 +207,7 @@ typedef struct UIScene { bool numerical_temp; bool online; bool onroad_distance_button; + bool pedals_on_ui; bool reverse; bool reverse_cruise; bool reverse_cruise_ui; @@ -216,6 +217,7 @@ typedef struct UIScene { bool show_cem_status_bar; bool show_jerk; bool show_tuning; + bool standstill; bool turn_signal_left; bool turn_signal_right; bool unlimited_road_ui_length;