From f824e6c0ec1b7b2ead345b09d13b7c120494e24b Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 9 Jun 2025 11:08:01 +0800 Subject: [PATCH] ui: implement reset calibration feature in device settings (#35479) * implement reset calibration feature in device settings * check confirm dialog result * fix null check * use enum * use enum --- selfdrive/ui/layouts/settings/device.py | 37 ++++++++++++++++++++----- system/ui/lib/application.py | 6 ++-- system/ui/widgets/confirm_dialog.py | 25 ++++++++++++----- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/selfdrive/ui/layouts/settings/device.py b/selfdrive/ui/layouts/settings/device.py index f7b011c1ea..741e0b0aa8 100644 --- a/selfdrive/ui/layouts/settings/device.py +++ b/selfdrive/ui/layouts/settings/device.py @@ -1,12 +1,15 @@ import os import json -from openpilot.system.ui.lib.application import gui_app, Widget -from openpilot.system.ui.lib.list_view import ListView, text_item, button_item -from openpilot.selfdrive.ui.onroad.driver_camera_dialog import DriverCameraDialog + +from openpilot.common.basedir import BASEDIR from openpilot.common.params import Params -from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog +from openpilot.selfdrive.ui.onroad.driver_camera_dialog import DriverCameraDialog +from openpilot.selfdrive.ui.ui_state import ui_state from openpilot.system.hardware import TICI -from openpilot.common.basedir import BASEDIR +from openpilot.system.ui.lib.application import gui_app, Widget, DialogResult +from openpilot.system.ui.lib.list_view import ListView, text_item, button_item +from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog +from openpilot.system.ui.widgets.confirm_dialog import confirm_dialog, alert_dialog # Description constants @@ -34,7 +37,7 @@ class DeviceLayout(Widget): text_item("Serial", serial), button_item("Pair Device", "PAIR", DESCRIPTIONS['pair_device'], self._on_pair_device), button_item("Driver Camera", "PREVIEW", DESCRIPTIONS['driver_camera'], callback=self._on_driver_camera), - button_item("Reset Calibration", "RESET", DESCRIPTIONS['reset_calibration'], self._on_reset_calibration), + button_item("Reset Calibration", "RESET", DESCRIPTIONS['reset_calibration'], callback=self._on_reset_calibration), button_item("Review Training Guide", "REVIEW", DESCRIPTIONS['review_guide'], self._on_review_training_guide), ] @@ -74,7 +77,27 @@ class DeviceLayout(Widget): gui_app.set_modal_overlay(self._driver_camera, callback=lambda result: setattr(self, '_driver_camera', None)) + def _on_reset_calibration(self): + if ui_state.engaged: + gui_app.set_modal_overlay(lambda: alert_dialog("Disengage to Reset Calibration")) + return + + gui_app.set_modal_overlay( + lambda: confirm_dialog("Are you sure you want to reset calibration?", "Reset"), + callback=self._reset_calibration, + ) + + def _reset_calibration(self, result: int): + if ui_state.engaged or result != DialogResult.CONFIRM: + return + + self._params.remove("CalibrationParams") + self._params.remove("LiveTorqueParameters") + self._params.remove("LiveParameters") + self._params.remove("LiveParametersV2") + self._params.remove("LiveDelay") + self._params.put_bool("OnroadCycleRequested", True) + def _on_pair_device(self): pass - def _on_reset_calibration(self): pass def _on_review_training_guide(self): pass def _on_regulatory(self): pass diff --git a/system/ui/lib/application.py b/system/ui/lib/application.py index fb1d0eeb9c..0d39ce829e 100644 --- a/system/ui/lib/application.py +++ b/system/ui/lib/application.py @@ -205,9 +205,11 @@ class GuiApplication: else: raise Exception - if result >= 0 and self._modal_overlay.callback is not None: + if result >= 0: # Execute callback with the result and clear the overlay - self._modal_overlay.callback(result) + if self._modal_overlay.callback is not None: + self._modal_overlay.callback(result) + self._modal_overlay = ModalOverlay() else: yield diff --git a/system/ui/widgets/confirm_dialog.py b/system/ui/widgets/confirm_dialog.py index f3ef79942d..777d0a7a31 100644 --- a/system/ui/widgets/confirm_dialog.py +++ b/system/ui/widgets/confirm_dialog.py @@ -1,5 +1,5 @@ import pyray as rl -from openpilot.system.ui.lib.application import gui_app, DialogResult +from openpilot.system.ui.lib.application import gui_app, DialogResult, FontWeight from openpilot.system.ui.lib.button import gui_button, ButtonStyle from openpilot.system.ui.lib.label import gui_text_box @@ -30,13 +30,14 @@ def confirm_dialog(message: str, confirm_text: str, cancel_text: str = "Cancel") rl.draw_rectangle_rec(dialog_rect, BACKGROUND_COLOR) # Draw the message in the dialog, centered - text_rect = rl.Rectangle(dialog_rect.x, dialog_rect.y, dialog_rect.width, dialog_rect.height - TEXT_AREA_HEIGHT_REDUCTION) + text_rect = rl.Rectangle(dialog_rect.x + MARGIN, dialog_rect.y, dialog_rect.width - 2 * MARGIN, dialog_rect.height - TEXT_AREA_HEIGHT_REDUCTION) gui_text_box( text_rect, message, - font_size=88, + font_size=70, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER, alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE, + font_weight=FontWeight.BOLD, ) # Initialize result; -1 means no action taken yet @@ -49,9 +50,19 @@ def confirm_dialog(message: str, confirm_text: str, cancel_text: str = "Cancel") result = DialogResult.CANCEL # Check for button clicks - if gui_button(yes_button, confirm_text, button_style=ButtonStyle.PRIMARY): - result = DialogResult.CONFIRM - if gui_button(no_button, cancel_text): - result = DialogResult.CANCEL + if cancel_text: + if gui_button(yes_button, confirm_text, button_style=ButtonStyle.PRIMARY): + result = DialogResult.CONFIRM + if gui_button(no_button, cancel_text): + result = DialogResult.CANCEL + else: + centered_button_x = dialog_rect.x + (dialog_rect.width - button_width) / 2 + centered_yes_button = rl.Rectangle(centered_button_x, button_y, button_width, BUTTON_HEIGHT) + if gui_button(centered_yes_button, confirm_text, button_style=ButtonStyle.PRIMARY): + result = DialogResult.CONFIRM return result + + +def alert_dialog(message: str, button_text: str = "OK") -> DialogResult: + return confirm_dialog(message, button_text, cancel_text="")