fix(alignment): 0/6 walls sanity check · 부착 안 됐을 때 "위로 올려" false positive 방지

증상 (사용자 보고 2026-08-05):
  Alignment 모드에서 센서를 부착하지 않았는데 "↑ 위로 올려" 힌트가 계속 노출.

원인:
  DetachmentDetection 임계 (mean AND std 둘 다 < 30) 를 노이즈로 통과하면
  alignment 알고리즘이 그대로 실행됨. AlignmentAdvice 는 CH3 미검출을
  "misaligned" 로 해석 → MOVE_UP 반환. "detached" 케이스와 구분 못함.

수정 (Option B: sanity check + Option C: 명확 문구):
  PlacementGuideView V2 branch 에서 v2Aligner.push 결과의
    detected.count { it } == 0 (6채널 모두 wall 미검출) 감지 시
  alignment advice 무시하고 placement_check_attachment 힌트로 override.

  strings.xml (KR/EN):
    placement_check_attachment
      · KR: "부착 상태 확인 필요 — 모든 채널에서 신호가 감지되지 않습니다.
             센서를 치골 위에 밀착시켜 주세요."
      · EN: "Attachment check needed — no signal from any channel.
             Ensure sensor is firmly placed above pubic bone."

효과:
  - 노이즈만 있고 실제 부착 없는 경우 "위로 올려" 반복 대신 명확한 부착 안내
  - alignment 알고리즘 자체는 유지 (0/6 만 특별 처리 · 1/6 이상은 정상 흐름)
  - DetachmentDetection 임계는 그대로 (실제 부착·미부착 경계 케이스 영향 없음)

검증: BUILD SUCCESSFUL 17s
This commit is contained in:
2026-08-05 16:25:45 +09:00
parent 13ba88b72b
commit 41ca909888
3 changed files with 15 additions and 1 deletions
@@ -921,11 +921,21 @@ fun PlacementGuideView(appState: AppState) {
}
}
bleManager.debugLogger.info("ALIGN_V2 phase=${v2Aligner.phase} state=${st.state} action=${st.action} u4=${st.summary?.u4} u5=${st.summary?.u5} ch3=${st.summary?.ch3} bestSet=${v2Aligner.bestCenterSet}")
// 2026-08-05 sanity check: 6채널 모두 wall 미검출 → 부착 이슈 가능성.
// DetachmentDetection AND (mean·std) 임계를 통과했더라도 EMI/노이즈로
// 실제 접촉 없이 alignment 가 "위로 올려" 힌트 반복 노출하는 케이스 방지.
val detectedCount = st.summary?.detected?.count { it } ?: 0
// Localized message via string resource (falls back to st.msg for dev builds)
val localizedMsg = st.msgKey?.let { key ->
context.getString(key, *st.msgArgs.toTypedArray())
} ?: st.msg
if (st.state == "accum") {
if (detectedCount == 0) {
// 0/6 walls · alignment advice 무시 · 부착 확인 안내로 override.
directionHint = context.getString(R.string.placement_check_attachment)
directionIcon = ""
placementScore = 0
bleManager.debugLogger.info("ALIGN_V2 sanity: 0/6 walls · override to attachment check")
} else if (st.state == "accum") {
directionHint = localizedMsg
directionIcon = ""
placementScore = 5