diff --git a/app/src/main/java/com/medithings/vesiscan/managers/DetachmentDetection.kt b/app/src/main/java/com/medithings/vesiscan/managers/DetachmentDetection.kt index af217dc..37942fa 100644 --- a/app/src/main/java/com/medithings/vesiscan/managers/DetachmentDetection.kt +++ b/app/src/main/java/com/medithings/vesiscan/managers/DetachmentDetection.kt @@ -79,8 +79,14 @@ object DetachmentDetection { val meanAbs = meanAbsPerCh.average() val stdVal = stdPerCh.average() - // "and" rule: 둘 다 threshold 미만이면 미부착 - val isDetached = meanAbs < THR_MEAN && stdVal < THR_STD + // 2026-08-11: AND → OR 로 변경. + // 기존 AND: mean·std 둘 다 30 미만이어야 detach. 공기 중 EMI/RF 노이즈로 + // std 가 30 이상인 경우가 흔해 detach 판정이 지연 · 사용자가 몇 초 + // 기다린 후에야 팝업 뜨는 문제. + // 신규 OR: 둘 중 하나만 30 미만이어도 detach. 노이즈로 std 높아도 mean 낮으면 + // 즉시 판정. 실제 신호 약할 때 false positive 위험 있으나 · 방광 신호는 + // mean·std 둘 다 100+ 수준이라 실제로 오탐 가능성 낮음. + val isDetached = meanAbs < THR_MEAN || stdVal < THR_STD return DetachmentResult( isDetached = isDetached, diff --git a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt index 2a89d24..9fac660 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt @@ -997,6 +997,27 @@ fun PlacementGuideView(appState: AppState) { } } // end of !waitingForStart V2 algorithm } else { + // 2026-08-11: V1 sanity check (V2 와 동일 로직 이식 · line 924-949). + // 6채널 모두 wall 미검출 → 부착 이슈 · alignment advice 무시 · 즉시 + // 부착 확인 안내. Start 후면 Start 화면 복귀 + 팝업 강제. + // DetachmentDetection AND→OR 완화 (2026-08-11) 로 대부분 잡히지만 + // Method C 검출이 노이즈에 우연히 반응하는 경우 이 sanity 가 backstop. + val v1DetectedCount = detected.count { it } + if (v1DetectedCount == 0) { + directionHint = context.getString(R.string.placement_check_attachment) + directionIcon = "" + placementScore = 0 + if (!waitingForStart) { + isContinuousMode = false + waitingForStart = true + prevDetached = true + showDetachAlert = true + bleManager.debugLogger.warn("ALIGN_V1 sanity: 0/6 walls · Start 후 부착 실패 · waitingForStart 복귀 + 팝업") + } else { + bleManager.debugLogger.info("ALIGN_V1 sanity: 0/6 walls · override to attachment check") + } + return@post + } // Sphere-fit 계산 (SWEEP 모드에서 사용, 다른 모드에서는 무시됨) val fitResult = com.medithings.vesiscan.managers.BladderSphereSeek .fitSagittalCircle(allWalls, detected)