From b7bc4a56bb1b3e05602f9c6d762b20e95c25d175 Mon Sep 17 00:00:00 2001 From: James <91348155+FrogAi@users.noreply.github.com> Date: Thu, 15 Jan 2026 07:25:28 -0700 Subject: [PATCH] Fixes --- .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 .../{traditional_100 => traditional_150} | 0 frogpilot/common/frogpilot_utilities.py | 4 ++ .../qt/onroad/frogpilot_annotated_camera.cc | 34 ++++++++------ .../ui/qt/onroad/frogpilot_annotated_camera.h | 2 + frogpilot/ui/qt/widgets/frogpilot_controls.cc | 45 ++++++++++++++++--- opendbc_repo/opendbc/car/chrysler/carstate.py | 6 ++- opendbc_repo/opendbc/car/interfaces.py | 10 ++--- opendbc_repo/opendbc/car/nissan/carstate.py | 6 ++- opendbc_repo/opendbc/car/rivian/carstate.py | 2 +- opendbc_repo/opendbc/car/toyota/carstate.py | 8 ++-- selfdrive/monitoring/dmonitoringd.py | 5 ++- 23 files changed, 87 insertions(+), 35 deletions(-) rename frogpilot/assets/holiday_themes/april_fools/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/christmas_week/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/cinco_de_mayo/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/easter_week/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/fourth_of_july/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/halloween_week/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/may_the_fourth/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/new_years/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/st_patricks_day/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/stitch_day/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/thanksgiving_week/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/valentines_day/signals/{traditional_100 => traditional_150} (100%) rename frogpilot/assets/holiday_themes/world_frog_day/signals/{traditional_100 => traditional_150} (100%) diff --git a/frogpilot/assets/holiday_themes/april_fools/signals/traditional_100 b/frogpilot/assets/holiday_themes/april_fools/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/april_fools/signals/traditional_100 rename to frogpilot/assets/holiday_themes/april_fools/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/christmas_week/signals/traditional_100 b/frogpilot/assets/holiday_themes/christmas_week/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/christmas_week/signals/traditional_100 rename to frogpilot/assets/holiday_themes/christmas_week/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/cinco_de_mayo/signals/traditional_100 b/frogpilot/assets/holiday_themes/cinco_de_mayo/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/cinco_de_mayo/signals/traditional_100 rename to frogpilot/assets/holiday_themes/cinco_de_mayo/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/easter_week/signals/traditional_100 b/frogpilot/assets/holiday_themes/easter_week/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/easter_week/signals/traditional_100 rename to frogpilot/assets/holiday_themes/easter_week/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/fourth_of_july/signals/traditional_100 b/frogpilot/assets/holiday_themes/fourth_of_july/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/fourth_of_july/signals/traditional_100 rename to frogpilot/assets/holiday_themes/fourth_of_july/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/halloween_week/signals/traditional_100 b/frogpilot/assets/holiday_themes/halloween_week/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/halloween_week/signals/traditional_100 rename to frogpilot/assets/holiday_themes/halloween_week/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/may_the_fourth/signals/traditional_100 b/frogpilot/assets/holiday_themes/may_the_fourth/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/may_the_fourth/signals/traditional_100 rename to frogpilot/assets/holiday_themes/may_the_fourth/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/new_years/signals/traditional_100 b/frogpilot/assets/holiday_themes/new_years/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/new_years/signals/traditional_100 rename to frogpilot/assets/holiday_themes/new_years/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/st_patricks_day/signals/traditional_100 b/frogpilot/assets/holiday_themes/st_patricks_day/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/st_patricks_day/signals/traditional_100 rename to frogpilot/assets/holiday_themes/st_patricks_day/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/stitch_day/signals/traditional_100 b/frogpilot/assets/holiday_themes/stitch_day/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/stitch_day/signals/traditional_100 rename to frogpilot/assets/holiday_themes/stitch_day/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/thanksgiving_week/signals/traditional_100 b/frogpilot/assets/holiday_themes/thanksgiving_week/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/thanksgiving_week/signals/traditional_100 rename to frogpilot/assets/holiday_themes/thanksgiving_week/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/valentines_day/signals/traditional_100 b/frogpilot/assets/holiday_themes/valentines_day/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/valentines_day/signals/traditional_100 rename to frogpilot/assets/holiday_themes/valentines_day/signals/traditional_150 diff --git a/frogpilot/assets/holiday_themes/world_frog_day/signals/traditional_100 b/frogpilot/assets/holiday_themes/world_frog_day/signals/traditional_150 similarity index 100% rename from frogpilot/assets/holiday_themes/world_frog_day/signals/traditional_100 rename to frogpilot/assets/holiday_themes/world_frog_day/signals/traditional_150 diff --git a/frogpilot/common/frogpilot_utilities.py b/frogpilot/common/frogpilot_utilities.py index 6cd938954..7d9362c38 100644 --- a/frogpilot/common/frogpilot_utilities.py +++ b/frogpilot/common/frogpilot_utilities.py @@ -217,6 +217,10 @@ def load_json_file(path): def lock_doors(lock_doors_timer, sm, params): wait_for_no_driver(params, sm, door_checks=True, time_threshold=lock_doors_timer) + sm.update() + if any(ps.ignitionLine or ps.ignitionCan for ps in sm["pandaStates"] if ps.pandaType != log.PandaState.PandaType.unknown): + return + can_parser = CANParser("toyota_nodsu_pt_generated", [("DOOR_LOCKS", 3)], bus=0) can_sock = messaging.sub_sock("can", timeout=100) diff --git a/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.cc b/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.cc index 92f5d3f1f..bbabf60bf 100644 --- a/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.cc +++ b/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.cc @@ -52,7 +52,9 @@ void FrogPilotAnnotatedCameraWidget::showEvent(QShowEvent *event) { void FrogPilotAnnotatedCameraWidget::updateSignals() { QVector().swap(blindspotImages); + QVector().swap(blindspotImagesRight); QVector().swap(signalImages); + QVector().swap(signalImagesRight); bool isGif = false; @@ -70,19 +72,26 @@ void FrogPilotAnnotatedCameraWidget::updateSignals() { int frameCount = movie.frameCount(); signalImages.reserve(frameCount); + signalImagesRight.reserve(frameCount); for (int i = 0; i < frameCount; ++i) { movie.jumpToFrame(i); - QImage image = movie.currentPixmap().toImage().convertToFormat(QImage::Format_Indexed8); - QPixmap frame = QPixmap::fromImage(image); + QPixmap frame = movie.currentPixmap(); signalImages.append(frame); + signalImagesRight.append(frame.transformed(QTransform().scale(-1, 1))); } movie.stop(); } else if (fileName.endsWith(".png", Qt::CaseInsensitive)) { - QVector &targetList = fileName.contains("blindspot", Qt::CaseInsensitive) ? blindspotImages : signalImages; - targetList.append(QPixmap::fromImage(QImage(filePath).convertToFormat(QImage::Format_Indexed8))); + QPixmap img(filePath); + if (fileName.contains("blindspot", Qt::CaseInsensitive)) { + blindspotImages.append(img); + blindspotImagesRight.append(img.transformed(QTransform().scale(-1, 1))); + } else { + signalImages.append(img); + signalImagesRight.append(img.transformed(QTransform().scale(-1, 1))); + } } else { QStringList parts = fileName.split('_'); if (parts.size() == 2) { @@ -1100,7 +1109,7 @@ void FrogPilotAnnotatedCameraWidget::paintStoppingPoint(QPainter &p) { } void FrogPilotAnnotatedCameraWidget::paintTurnSignals(QPainter &p) { - p.save(); + int frameIndex = qBound(0, animationFrameIndex, totalFrames - 1); bool blindspotActive = blinkerLeft ? blindspotLeft : blindspotRight; @@ -1112,23 +1121,20 @@ void FrogPilotAnnotatedCameraWidget::paintTurnSignals(QPainter &p) { signalYPosition = signalHeight / 2; } else { if (signalStyle == "traditional_gif") { - signalXPosition = blinkerLeft ? width() - (animationFrameIndex * signalMovement) + signalWidth : (animationFrameIndex * signalMovement) - signalWidth; + signalXPosition = blinkerLeft ? width() - (frameIndex * signalMovement) + signalWidth : (frameIndex * signalMovement) - signalWidth; } else { - signalXPosition = blinkerLeft ? width() - ((animationFrameIndex + 1) * signalWidth) : animationFrameIndex * signalWidth; + signalXPosition = blinkerLeft ? width() - ((frameIndex + 1) * signalWidth) : frameIndex * signalWidth; } signalYPosition = height() - signalHeight - alertHeight; } - QPixmap *imgToDraw = (blindspotActive && !blindspotImages.empty()) ? &blindspotImages[0] : &signalImages[animationFrameIndex]; if (blinkerLeft) { - p.drawPixmap(signalXPosition, signalYPosition, signalWidth, signalHeight, *imgToDraw); + QPixmap &imgToDraw = (blindspotActive && !blindspotImages.empty()) ? blindspotImages[0] : signalImages[frameIndex]; + p.drawPixmap(signalXPosition, signalYPosition, signalWidth, signalHeight, imgToDraw); } else { - p.translate(signalXPosition + signalWidth, signalYPosition); - p.scale(-1, 1); - p.drawPixmap(0, 0, signalWidth, signalHeight, *imgToDraw); + QPixmap &imgToDraw = (blindspotActive && !blindspotImagesRight.empty()) ? blindspotImagesRight[0] : signalImagesRight[frameIndex]; + p.drawPixmap(signalXPosition, signalYPosition, signalWidth, signalHeight, imgToDraw); } - - p.restore(); } void FrogPilotAnnotatedCameraWidget::paintWeather(QPainter &p) { diff --git a/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.h b/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.h index 2966163a9..fac5ffe1a 100644 --- a/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.h +++ b/frogpilot/ui/qt/onroad/frogpilot_annotated_camera.h @@ -174,5 +174,7 @@ private: QTimer *animationTimer; QVector blindspotImages; + QVector blindspotImagesRight; QVector signalImages; + QVector signalImagesRight; }; diff --git a/frogpilot/ui/qt/widgets/frogpilot_controls.cc b/frogpilot/ui/qt/widgets/frogpilot_controls.cc index 6dd8f80ff..aa0a7ef83 100644 --- a/frogpilot/ui/qt/widgets/frogpilot_controls.cc +++ b/frogpilot/ui/qt/widgets/frogpilot_controls.cc @@ -33,6 +33,22 @@ void clearMovie(QSharedPointer &movie, QWidget *parent) { } void loadGif(const QString &gifPath, QSharedPointer &movie, const QSize &size, QWidget *parent) { + if (!parent || gifPath.isEmpty()) { + return; + } + + if (movie && movie->fileName() == gifPath && movie->state() == QMovie::Running) { + if (movie->scaledSize() != size) { + movie->setScaledSize(size); + } + return; + } + + if (!QFileInfo::exists(gifPath)) { + clearMovie(movie, parent); + return; + } + clearMovie(movie, parent); movie = QSharedPointer::create(gifPath); @@ -50,13 +66,35 @@ void loadGif(const QString &gifPath, QSharedPointer &movie, const QSize } void loadImage(const QString &basePath, QPixmap &pixmap, QSharedPointer &movie, const QSize &size, QWidget *parent) { - if (!parent) { + if (!parent || basePath.isEmpty()) { return; } + static QHash pixmapCache; + QString cacheKey = basePath + QString("_%1x%2").arg(size.width()).arg(size.height()); + QString gifPath = basePath + ".gif"; if (QFileInfo::exists(gifPath)) { loadGif(gifPath, movie, size, parent); + if (!pixmap.isNull()) { + pixmap = QPixmap(); + } + return; + } + + clearMovie(movie, parent); + + if (pixmapCache.contains(cacheKey)) { + QPixmap &cached = pixmapCache[cacheKey]; + if (pixmap.cacheKey() != cached.cacheKey()) { + pixmap = cached; + parent->update(); + } + return; + } + + QString pngPath = basePath + ".png"; + if (!QFileInfo::exists(pngPath)) { if (!pixmap.isNull()) { pixmap = QPixmap(); parent->update(); @@ -64,13 +102,10 @@ void loadImage(const QString &basePath, QPixmap &pixmap, QSharedPointer return; } - QString pngPath = basePath + ".png"; - - clearMovie(movie, parent); - QPixmap loadedPixmap(pngPath); if (!loadedPixmap.isNull()) { pixmap = loadedPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + pixmapCache.insert(cacheKey, pixmap); } else { pixmap = QPixmap(); } diff --git a/opendbc_repo/opendbc/car/chrysler/carstate.py b/opendbc_repo/opendbc/car/chrysler/carstate.py index 38d51bd37..86cc6a933 100644 --- a/opendbc_repo/opendbc/car/chrysler/carstate.py +++ b/opendbc_repo/opendbc/car/chrysler/carstate.py @@ -102,7 +102,7 @@ class CarState(CarStateBase): self.lkas_car_model = cp_cam.vl["DAS_6"]["CAR_MODEL"] self.button_counter = cp.vl[self.button_message]["COUNTER"] - ret.buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) # FrogPilot variables fp_ret = custom.FrogPilotCarState.new_message() @@ -113,10 +113,12 @@ class CarState(CarStateBase): else: self.lkas_button = cp.vl["TRACTION_BUTTON"]["TOGGLE_LKAS"] == 1 - ret.buttonEvents = list(ret.buttonEvents) + [ + buttonEvents += [ *create_button_events(self.lkas_button, self.prev_lkas_button, {1: ButtonType.lkas}), ] + ret.buttonEvents = buttonEvents + return ret, fp_ret @staticmethod diff --git a/opendbc_repo/opendbc/car/interfaces.py b/opendbc_repo/opendbc/car/interfaces.py index 525d86558..e9104fa3a 100644 --- a/opendbc_repo/opendbc/car/interfaces.py +++ b/opendbc_repo/opendbc/car/interfaces.py @@ -333,13 +333,11 @@ class CarInterfaceBase(ABC): # FrogPilot variables prev_distance_button = self.distance_button - self.distance_button = bool(self.CS.distance_button) - self.distance_button |= self.params_memory.get_bool("OnroadDistanceButtonPressed") + self.distance_button = self.params_memory.get_bool("OnroadDistanceButtonPressed") + if self.distance_button != prev_distance_button: + ret.buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) - distance_events = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) - ret.buttonEvents = list(ret.buttonEvents) + [e for e in distance_events if not any(b.type == e.type for b in ret.buttonEvents)] - - fp_ret.distancePressed = self.distance_button + fp_ret.distancePressed = self.distance_button or bool(self.CS.distance_button) fp_ret.ecoGear |= ret.gearShifter == GearShifter.eco fp_ret.sportGear |= ret.gearShifter == GearShifter.sport diff --git a/opendbc_repo/opendbc/car/nissan/carstate.py b/opendbc_repo/opendbc/car/nissan/carstate.py index eec9dc635..d9aee75e9 100644 --- a/opendbc_repo/opendbc/car/nissan/carstate.py +++ b/opendbc_repo/opendbc/car/nissan/carstate.py @@ -130,7 +130,7 @@ class CarState(CarStateBase): self.lkas_hud_msg = copy.copy(cp_adas.vl["PROPILOT_HUD"]) self.lkas_hud_info_msg = copy.copy(cp_adas.vl["PROPILOT_HUD_INFO_MSG"]) - ret.buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) # FrogPilot variables fp_ret = custom.FrogPilotCarState.new_message() @@ -138,10 +138,12 @@ class CarState(CarStateBase): self.prev_lkas_button = self.lkas_button self.lkas_button = ret.invalidLkasSetting - ret.buttonEvents = list(ret.buttonEvents) + [ + buttonEvents += [ *create_button_events(self.lkas_button, self.prev_lkas_button, {1: ButtonType.lkas, 0: ButtonType.lkas}), ] + ret.buttonEvents = buttonEvents + return ret, fp_ret @staticmethod diff --git a/opendbc_repo/opendbc/car/rivian/carstate.py b/opendbc_repo/opendbc/car/rivian/carstate.py index acf205ecf..52445a201 100644 --- a/opendbc_repo/opendbc/car/rivian/carstate.py +++ b/opendbc_repo/opendbc/car/rivian/carstate.py @@ -54,7 +54,7 @@ class CarState(CarStateBase): ret.cruiseState.speed = self.last_speed * CV.MPH_TO_MS # detected speed limit if not self.CP.openpilotLongitudinalControl: ret.cruiseState.speed = -1 - ret.cruiseState.available = True # cp.vl["VDM_AdasSts"]["VDM_AdasInterfaceStatus"] == 1 + ret.cruiseState.available = cp.vl["VDM_AdasSts"]["VDM_AdasInterfaceStatus"] in (1, 2) ret.cruiseState.standstill = cp.vl["VDM_AdasSts"]["VDM_AdasVehicleHoldStatus"] == 1 # ACM_Status->ACM_FaultSupervisorState normally 1, appears to go to 3 when either: diff --git a/opendbc_repo/opendbc/car/toyota/carstate.py b/opendbc_repo/opendbc/car/toyota/carstate.py index e8e5526e4..7aaecb04f 100644 --- a/opendbc_repo/opendbc/car/toyota/carstate.py +++ b/opendbc_repo/opendbc/car/toyota/carstate.py @@ -222,8 +222,6 @@ class CarState(CarStateBase): buttonEvents += create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) - ret.buttonEvents = buttonEvents - # FrogPilot variables fp_ret = custom.FrogPilotCarState.new_message() @@ -231,9 +229,9 @@ class CarState(CarStateBase): prev_distance_button = self.distance_button self.distance_button = cp.vl["SDSU"]["FD_BUTTON"] - ret.buttonEvents = list(ret.buttonEvents) + create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + buttonEvents += create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) - ret.buttonEvents = list(ret.buttonEvents) + [ + buttonEvents += [ *create_button_events(self.pcm_acc_status == 9, False, {1: ButtonType.accelCruise}), *create_button_events(self.pcm_acc_status == 10, False, {1: ButtonType.decelCruise}), ] @@ -260,6 +258,8 @@ class CarState(CarStateBase): if abs(ret.steeringAngleDeg - zorro_steer_value) < 4.0: ret.steeringAngleDeg = zorro_steer_value + ret.buttonEvents = buttonEvents + return ret, fp_ret @staticmethod diff --git a/selfdrive/monitoring/dmonitoringd.py b/selfdrive/monitoring/dmonitoringd.py index 2a657f7ba..d2a6163a7 100644 --- a/selfdrive/monitoring/dmonitoringd.py +++ b/selfdrive/monitoring/dmonitoringd.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 import cereal.messaging as messaging +from opendbc.car import structs from openpilot.common.params import Params from openpilot.common.realtime import config_realtime_process from openpilot.selfdrive.monitoring.helpers import DriverMonitoring +GearShifter = structs.CarState.GearShifter + def dmonitoringd_thread(): config_realtime_process([0, 1, 2, 3], 5) @@ -43,7 +46,7 @@ def dmonitoringd_thread(): # load live always-on toggle if sm['driverStateV2'].frameId % 40 == 1: DM.always_on = params.get_bool("AlwaysOnDM") - demo_mode = params.get_bool("IsDriverViewEnabled") + demo_mode = params.get_bool("IsDriverViewEnabled") and sm["carState"].gearShifter != GearShifter.reverse # save rhd virtual toggle every 5 mins if (sm['driverStateV2'].frameId % 6000 == 0 and not demo_mode and