diff --git a/common/params.cc b/common/params.cc index 619d9f3..fece057 100644 --- a/common/params.cc +++ b/common/params.cc @@ -326,6 +326,7 @@ std::unordered_map keys = { {"PathEdgeWidth", PERSISTENT}, {"PathWidth", PERSISTENT}, {"PauseLateralOnSignal", PERSISTENT}, + {"PedalsOnUI", PERSISTENT}, {"PreferredSchedule", PERSISTENT}, {"PromptVolume", PERSISTENT}, {"PromptDistractedVolume", 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 0000000..f4fe0ef 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 0000000..ef1a87e Binary files /dev/null and b/selfdrive/frogpilot/assets/other_images/gas_pedal.png differ diff --git a/selfdrive/frogpilot/ui/visual_settings.cc b/selfdrive/frogpilot/ui/visual_settings.cc index 6c460eb..4af2377 100644 --- a/selfdrive/frogpilot/ui/visual_settings.cc +++ b/selfdrive/frogpilot/ui/visual_settings.cc @@ -32,6 +32,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"BlindSpotPath", "Blind Spot Path", "Visualize your blind spots with a red path when another vehicle is detected nearby.", ""}, {"FPSCounter", "FPS Counter", "Display the Frames Per Second (FPS) of your onroad UI for monitoring system performance.", ""}, {"LeadInfo", "Lead Info and Logics", "Get detailed information about the vehicle ahead, including speed and distance, and the logic behind your following distance.", ""}, + {"PedalsOnUI", "Pedals Being Pressed", "Display which pedals are being pressed on the onroad UI below the steering wheel icon.", ""}, {"RoadNameUI", "Road Name", "See the name of the road you're on at the bottom of your screen. Sourced from OpenStreetMap.", ""}, {"DriverCamera", "Driver Camera On Reverse", "Show the driver's camera feed when you shift to reverse.", "../assets/img_driver_face_static.png"}, diff --git a/selfdrive/frogpilot/ui/visual_settings.h b/selfdrive/frogpilot/ui/visual_settings.h index 8b4c92c..600c7e1 100644 --- a/selfdrive/frogpilot/ui/visual_settings.h +++ b/selfdrive/frogpilot/ui/visual_settings.h @@ -30,7 +30,7 @@ private: std::set alertVolumeControlKeys = {"EngageVolume", "DisengageVolume", "RefuseVolume", "PromptVolume", "PromptDistractedVolume", "WarningSoftVolume", "WarningImmediateVolume"}; std::set customAlertsKeys = {"GreenLightAlert", "LeadDepartingAlert", "LoudBlindspotAlert"}; - std::set customOnroadUIKeys = {"AccelerationPath", "AdjacentPath", "BlindSpotPath", "FPSCounter", "LeadInfo", "RoadNameUI"}; + std::set customOnroadUIKeys = {"AccelerationPath", "AdjacentPath", "BlindSpotPath", "FPSCounter", "LeadInfo", "PedalsOnUI", "RoadNameUI"}; std::set customThemeKeys = {"HolidayThemes", "CustomColors", "CustomIcons", "CustomSignals", "CustomSounds"}; std::set modelUIKeys = {"DynamicPathWidth", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", "RoadEdgesWidth", "UnlimitedLength"}; std::set qolKeys = {"DriveStats", "FullMap", "HideSpeed"}; diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 207f7a9..b2af00f 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -400,8 +400,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); @@ -1137,6 +1150,8 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) { mapOpen = scene.map_open; fullMapOpen = mapOpen && scene.full_map; + pedalsOnUI = scene.pedals_on_ui; + roadNameUI = scene.road_name_ui; showDriverCamera = scene.show_driver_camera; @@ -1170,6 +1185,12 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) { bottom_layout->setAlignment(compass_img, (rightHandDM ? Qt::AlignLeft : Qt::AlignRight)); } + bool enablePedalIcons = pedalsOnUI && !(fullMapOpen || showDriverCamera); + 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); @@ -1446,6 +1467,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 bd734e2..e56be95 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -93,6 +93,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 @@ -143,6 +164,7 @@ private: UIScene &scene; Compass *compass_img; + PedalIcons *pedal_icons; QHBoxLayout *bottom_layout; @@ -156,6 +178,7 @@ private: bool fullMapOpen; bool leadInfo; bool mapOpen; + bool pedalsOnUI; bool roadNameUI; bool showDriverCamera; bool turnSignalLeft; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index f20af63..27cad0d 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -231,6 +231,12 @@ static void update_state(UIState *s) { if (scene.driver_camera) { scene.show_driver_camera = carState.getGearShifter() == cereal::CarState::GearShifter::REVERSE; } + if (scene.lead_info || scene.pedals_on_ui) { + scene.acceleration = carState.getAEgo(); + } + if (scene.pedals_on_ui) { + scene.standstill = carState.getStandstill(); + } } if (sm.updated("controlsState")) { auto controlsState = sm["controlsState"].getControlsState(); @@ -308,6 +314,7 @@ void ui_update_frogpilot_params(UIState *s) { scene.fps_counter = custom_onroad_ui && params.getBool("FPSCounter"); scene.lead_info = custom_onroad_ui && params.getBool("LeadInfo"); scene.use_si = scene.lead_info && params.getBool("UseSI"); + scene.pedals_on_ui = custom_onroad_ui && params.getBool("PedalsOnUI"); scene.road_name_ui = custom_onroad_ui && params.getBool("RoadNameUI"); bool custom_theme = params.getBool("CustomTheme"); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 37c5321..43a5aa1 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -200,15 +200,18 @@ typedef struct UIScene { bool map_open; bool model_ui; bool numerical_temp; + bool pedals_on_ui; bool reverse_cruise; bool reverse_cruise_ui; bool road_name_ui; bool show_driver_camera; + bool standstill; bool turn_signal_left; bool turn_signal_right; bool unlimited_road_ui_length; bool use_si; + float acceleration; float adjusted_cruise; float lane_line_width; float lane_width_left;