fix(alignment): detach 지연 · 힌트 왔다갔다 fix · V1 sanity + Detachment OR 규칙
증상 (사용자 보고 2026-08-11 · demo-final):
센서가 아예 분리된 상태인데 · alignment 화면에서 전벽/후벽이 하나씩
잡혀 "위로/아래로" 힌트가 왔다갔다 · 몇 초 기다린 후에야 "분리됨"
팝업이 뜸.
원인 (두 요인 조합):
1) DetachmentDetection AND 규칙 (mean<30 AND std<30) 이 노이즈 상황에
너무 관대. 공기 중 EMI/RF 노이즈로 std 가 30 이상인 경우 흔해
detach 판정 지연.
2) Method C detection 이 노이즈 peak 을 우연히 벽으로 오검출 · alignment
computePlacementGuide 가 그 벽으로 힌트 계산 → 왔다갔다.
3) V1 default 흐름에는 0/6 walls sanity check 없음 (V2 전용).
수정:
1) DetachmentDetection: AND → OR
mean·std 둘 중 하나만 30 미만이면 detach. 노이즈 std 높아도 mean
낮으면 즉시 판정. 실제 방광 신호는 mean·std 둘 다 100+ 수준이라
false positive 실질 낮음.
2) PlacementGuideView V1 브랜치 sanity check 이식 (V2 line 924-949 로직
동일).
6채널 모두 wall 미검출 → 부착 확인 안내 · Start 후면 waitingForStart
복귀 + 팝업 강제 (2026-08-05 V2 sanity 와 동일 UX).
Method C 노이즈 오검출 자체는 별건 · sanity + 강화된 Detachment 로 UX
관점 방어.
This commit is contained in:
@@ -79,8 +79,14 @@ object DetachmentDetection {
|
|||||||
val meanAbs = meanAbsPerCh.average()
|
val meanAbs = meanAbsPerCh.average()
|
||||||
val stdVal = stdPerCh.average()
|
val stdVal = stdPerCh.average()
|
||||||
|
|
||||||
// "and" rule: 둘 다 threshold 미만이면 미부착
|
// 2026-08-11: AND → OR 로 변경.
|
||||||
val isDetached = meanAbs < THR_MEAN && stdVal < THR_STD
|
// 기존 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(
|
return DetachmentResult(
|
||||||
isDetached = isDetached,
|
isDetached = isDetached,
|
||||||
|
|||||||
@@ -997,6 +997,27 @@ fun PlacementGuideView(appState: AppState) {
|
|||||||
}
|
}
|
||||||
} // end of !waitingForStart V2 algorithm
|
} // end of !waitingForStart V2 algorithm
|
||||||
} else {
|
} 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 모드에서 사용, 다른 모드에서는 무시됨)
|
// Sphere-fit 계산 (SWEEP 모드에서 사용, 다른 모드에서는 무시됨)
|
||||||
val fitResult = com.medithings.vesiscan.managers.BladderSphereSeek
|
val fitResult = com.medithings.vesiscan.managers.BladderSphereSeek
|
||||||
.fitSagittalCircle(allWalls, detected)
|
.fitSagittalCircle(allWalls, detected)
|
||||||
|
|||||||
Reference in New Issue
Block a user