증상: 앉아있다 일어서기만 해도 walking false-trigger.
원인: 사용자 실측 데이터 분석 — stand-up + 자세 조정 motion 이 wmean
5-10 dps 로 약 3-5초 지속. 이전 default (Start Wmean=4, Hold=1s) 는
이 motion 을 walking 으로 잡음.
수정:
Start Wmean: 4 → 15 (stand-up 의 typical wmean 보다 위)
Start Hold: 1초 → 6초 (stand-up settling 보다 김)
근거:
- 사용자 측정 stand-up motion: wmean 5-10 (저강도) ~ 100 (spike)
- 진짜 보행 (body-mounted, 예상): wmean 50+ 지속
- Hold 6초 — 정상 보행은 무한 지속이라 자동 만족, stand-up 은 5초 미만
비고:
- 임계는 여전히 dev slider 로 조정 가능 (이전 commit 18a4cee)
- 사용자별 / 디바이스별 튜닝 가능
- 향후 periodicity check (FFT) 추가 시 임계 다시 완화 가능
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
증상: 앉아있다 일어서기만 해도 WALKING false-trigger (두 번 연속 발생).
원인 (로그 분석):
앉아있음(pitch=20-30°) → 일어남 burst (gyro 90-220 dps) → 서있음(pitch=82°)
타임라인:
T=0 pitch=37° wmean=49 (burst 시작, pitch < 45 → pitchOk=false)
T=1 pitch=14° wmean=110 (더 큰 burst, pitchOk=false)
T=2 pitch=32° wmean=174 (burst 최고, pitchOk=false)
T=3 pitch=82° wmean=190 ← pitchOk=true 된 순간 window 에 burst 가득
→ start cond 즉시 만족, 카운트 시작
T=4 pitch=50° wmean=82 (burst 빠지는 중)
T=5 pitch=46° wmean=12 (거의 빠짐, 그래도 > Start Wmean(4))
T=6 pitch=57° wmean=24 → "WALKING start (held 3091ms)" ❌
핵심: pitch 가 45° 통과한 순간 window 안엔 이미 burst data. burst 가 다
빠지기 전에 (~1.5초) + 3초 hold 누적 = false-trigger.
수정: WalkingDetector 에 lastPitchOk 추적 + false→true 전이 시
buffer.clear() + startCondSinceMs=null.
if (pitchOk && !lastPitchOk && !walking) {
buffer.clear() // burst data 폐기
startCondSinceMs = null // hold 카운트 리셋
}
결과: pitch 가 45° 넘는 순간부터 fresh sample 만 누적. 사용자가 일어서서
가만히 있으면 wmean=1-2 (정상 정지값) → cond 안 met → trigger 안 됨.
실제 보행 시작하면 새 wmean 이 30-50+ 까지 올라가 → 3초 hold → trigger.
walking 중에는 pitchOk false→true 가 발생해도 (잠깐 앉았다 일어남 등) buffer
안 비움 (walking 상태 유지 — keep cond 가 처리).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
사용자: walking 이 너무 예민하게 뜸. 모든 임계를 dev settings 에서 조절하고 싶음.
추가된 슬라이더 (Pitch Threshold 아래에 그룹별 정렬):
1) Posture
- Pitch Threshold (lying ↔ non-lying) 기존
- Poll Interval 기존
2) Walking Thresholds
- Min Pitch (walking 인정 최소 pitch) 기존
- Start Wmean (시작 평균 gyro) 기존
- Start Wstd (시작 표준편차) 기존
- Keep Wmean (유지 평균) — range 0.5~30 (이전 10) 신규 범위↑
- **Start Hold** (시작 조건 hold 시간, 0.2~5초) ⭐신규
- **Keep Grace** (종료 grace 시간, 0.5~10초) ⭐신규
- **Window** (sliding window 크기, 0.5~5초) ⭐신규
3) Acc Magnitude Gate
- **Min** (UNKNOWN 하한, 0.3~1.0g) ⭐신규
- **Max** (UNKNOWN 상한, 1.0~3.0g) ⭐신규
내부 변경:
- GreenZoneConstants 에 postureAccMagMin/Max 추가
- ImuPostureClassifier 의 const ACC_MAG_MIN/MAX → GreenZoneConstants 참조
(런타임 변경 가능)
총 11개 슬라이더 — 사용자가 실측하며 튜닝 가능.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
증상: 로그캣 분석 — 활발히 걷는 중 (accMag > 1.2g) 일수록 화면에 안 보임.
11:24:03 NON_LYING → WALKING 성공
11:24:04 accMag=1.80 → UNKNOWN, walking 도 grace 들어감
11:24:05 grace 2초 초과 → walking 종료
→ 활발 보행 = 가장 위험한 순간에 알람 사라짐 (정반대)
원인 두 가지:
1) Classifier 가 acc gate fail 시 pitch=0 반환
→ WalkingDetector 가 pitch=0 받아서 pitchOk=false → grace 진입
2) Composite 로직: r.posture==UNKNOWN 이면 WALKING 무시하고 UNKNOWN 표시
수정:
1) ImuPostureClassifier: pitch 계산을 acc gate 이전으로 옮김
→ UNKNOWN Result 에도 실제 pitch 값 포함
→ WalkingDetector 가 정확한 pitch 로 grace 판단 가능
2) PiezoMonitoringView composite 순서 변경:
when {
isWalkingNow -> WALKING // 우선 (자체 게이트 신뢰)
r.posture==UNKNOWN -> UNKNOWN
else -> r.posture
}
walking detector 가 walking 이라고 하면 acc gate 실패해도 표시.
walking 자체에 시간/wmean/wstd 게이트 있어 false-positive 거의 없음.
테스트 시나리오:
정지 lying → 흔들면서 걷기 (pitch>45°) → walking 검출 → 격하게 흔들기
(accMag>1.2g) 도 → "Walking" 계속 표시 + 빨간 팝업 유지.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
새 flowchart 의 walking 검출 추가:
1) Posture enum: UNKNOWN/LYING/NON_LYING + **WALKING** (4-state)
2) WalkingDetector.kt 신규 (flowchart Path B 구현)
- Sliding window (default 1.5초) buffer 에 gyro magnitude 누적
- 매 cycle 마다 wmean (이동평균) + wstd (이동표준편차) 계산
- State machine:
IDLE → WALKING:
|pitch| > 45° AND wmean > 4 AND wstd > 2
→ 1초 이상 연속 만족 시 전이
WALKING → IDLE:
|pitch| > 45° AND wmean > 2
→ 미달 후 2초 grace 지나면 전이
3) GreenZoneConstants 에 walking 임계 7개 추가 (모두 dev 조정 가능):
- walkingMinPitchDeg=45, walkingStartWmean=4, walkingStartWstd=2,
walkingStartHoldMs=1000, walkingKeepWmean=2, walkingKeepHoldMs=2000,
walkingWindowMs=1500
4) PiezoMonitoring:
- walkingDetector 인스턴스
- imuCollector.onComplete: classifier + detector 동시 호출,
composite posture (WALKING > NON_LYING > LYING) 결정
- NON_WALKING → WALKING 전이 시 critical 알람 trigger
5) UI:
- 상단 status bar: Walking 아이콘 (DirectionsWalk, 빨강) 추가
- 기존 wakeup 팝업 색: 빨강 → 주황 (warning level)
- 신규 walking 팝업: 빨강 + DirectionsWalk + "환자가 걷고 있습니다 — fall risk"
6) Dev settings: walking 임계 슬라이더 4개 추가
(Min Pitch / Start Wmean / Start Wstd / Keep Wmean)
sliding window / hold 시간은 default 유지 (필요 시 추가)
2단계 알람 체계 (의료적):
- 주황 (warning): LYING N초 → NON_LYING/WALKING 전이 (일어남 감지)
- 빨강 (critical): NON_WALKING → WALKING 전이 (보행 시작 — fall risk 최고)
Tag phase2-pre-walking (28a8769) 이전 상태로 복원 가능.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
낙상 예방 시나리오상 자세 변화 즉시 감지 중요 → 1초 polling 으로 단축.
canSendMaa() 500ms throttle + mtb 응답 ~400ms 이라 1초가 사실상 한계.
사용자가 slider 로 더 늦출 수도 있음 (1~15초 범위).
BLE 부담: device active ~40% (mtb 한 cycle ≈ 400ms × 매초).
배터리 영향은 짧은 모니터링 세션 (수십분~수시간) 수준에선 무시 가능.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
증상 1: 디바이스 평평하게 둠 → "Upright" / 세움 → "Lying" (또는 기존 빌드의
"Sitting") 으로 사용자 직관과 반대.
진단: 사용자 raw 데이터 분석
- 평평 (AZ dominant, AZ ≈ 1g): pitch ≈ 0° → 코드가 NON_LYING (Upright) 반환
- 세움 (AX dominant, AX ≈ 1g): pitch ≈ 80~90° → 코드가 LYING 반환
사용자 직관: 평평=Lying, 세움=Upright → 코드 inversion.
수정 1: ImuPostureClassifier 의 분류 조건 invert
- 기존: |pitch| > threshold → LYING
- 신규: |pitch| ≤ threshold → LYING (작은 pitch = AZ 가 중력 = 센서 평평)
- dev slider hint 도 "|pitch|≤N°→Lying" 으로 동기화
수정 2: PiezoMonitoring 의 dev settings overlay 에도 기상 알람 토글 추가
- 기존: PiezoPersonalizationView 에만 존재
- 신규: dev settings panel (Pitch Threshold slider 아래) 에 동일 토글
- 두 위치 모두 같은 WakeupAlarmPrefs 사용 — sync 됨
- 사용자가 monitoring 페이지에서 바로 켜고 끌 수 있음
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
증상: 디바이스를 lying 상태로 둬도 "Upright" 표시가 안 바뀜.
진단 (raw 로그 분석):
- 디바이스 정지 상태에서도 gyro y 축 ≈ -25 dps 일관 표시
- 이는 IMU 칩의 **calibration bias** (정지 시 zero offset 안 됨)
- flowchart 의 gyro gate (9.16 dps) 가 항상 fail → classifier 영구 UNKNOWN
- currentPosture 가 UNKNOWN 시 업데이트 안 되는 로직 때문에 첫 valid
값 (NON_LYING, 사용자가 손에 들고 진입한 순간) 으로 stuck
- 사용자가 눕혀도 분류 자체가 안 되니 "Upright" 그대로
수정:
1) ImuPostureClassifier: gyro gate 제거
- accel magnitude gate (0.8-1.2g) 가 큰 모션은 이미 거름
- gyro magnitude 는 Result/log 에 계속 노출 (디버그용)
- flowchart 그대로 따르려면 gyro 도 활용해야 하지만, bias 큰
디바이스에선 무용지물이라 실용성 우선
2) PiezoMonitoringView: UNKNOWN streak 카운터
- 3회 연속 UNKNOWN 이면 currentPosture = UNKNOWN 으로 강제 표시
- silent stuck 상태 (잘못된 자세 계속 보여줌) 방지
- 잠시 1-2 cycle 동안 motion artifact 로 UNKNOWN 떠도 직전
자세 유지 (이전 동작 보존)
3) Log: unknownStreak 도 출력 → 디버그 시 stuck 케이스 가시화
테스트:
- lying → upright 전환 시 즉시 "Upright" 표시되어야 함
- 정지 시 "Lying" 또는 "Upright" 안정적 유지
- 큰 모션 (들어올림 등) 중에는 3 cycle 후 "—" 표시
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
증상: ch3 확인 통과 후 LR_BALANCE 단계에서 좌/우 화살표가 빠른
간격으로 번갈아 나타남.
원인:
AlignGuide4Stage.LR_BALANCE 의 hill-climbing 반전 조건이
imbal > lateralImbal 만 검사 → 1 sample 라도 늘면 즉시 반전.
- 노이즈/호흡 으로 imbal 가 ±1-2 fluctuate → 잘못된 반전
- sliding window 평균 (10-frame) 잔여 효과: 방향 바꿔도 직전
데이터 섞여 imbal 변화 못 따라옴 → 가짜 "악화" 판정
- 사용자 반응 지연 동안 imbal 더 누적 → 또 반전 → ←→←→ 진동
수정 (A + C 조합):
1) A. 반전 deadband (lrReverseDeadband = 3 samples ≈ 6 mm)
imbal 가 직전보다 "deadband 초과" 증가해야 악화로 카운트.
LAT_TOL(8) 의 약 1/3 — 정렬 완료 조건 위협하지 않으면서 노이즈
흡수.
2) C. 연속 N회 악화 요구 (lrReverseConsecutive = 2)
deadband 초과 증가가 2 commit 연속이어야 방향 반전.
단발 노이즈/sliding window 잔여 효과 흡수.
상태 추가: lateralWorseStreak Int (reset 포함).
로직:
- 개선 또는 deadband 안 변동 → 같은 방향 유지, streak = 0
- deadband 초과 증가 → streak++
- streak >= 2 → 방향 반전, streak = 0
lateralImbal 은 매 commit 갱신 (기존 동작 유지).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
feature/tab-navigation 의 V2 코드를 demo-final 로 가져와 임상 alignment session
에서 V1/V2 둘 다 선택 가능하도록.
복사된 파일 (feature/tab-navigation 그대로):
walldetect/algo/SgSmoothGeneric.kt
walldetect/algo/methodd/MethodDParams.kt
walldetect/algo/methodd/MethodDPreprocessing.kt
walldetect/algo/methodd/MethodDSpan.kt
walldetect/algo/methodd/MethodDWallSelect.kt
walldetect/algo/methodd/MethodDTgc.kt
walldetect/MethodDDetector.kt
walldetect/MethodDRunner.kt
managers/AlignmentAdvisorV2.kt
(RollingAligner + AlignGuide4Stage + AlignmentAdvice — alignment.py 1:1)
확장:
walldetect/algo/Otsu.kt
+ otsu1dWithSeparability(values) — Python otsu_1d 의 (threshold, sep) tuple 호환
method_d span fallback gate 에서 사용
managers/GreenZoneConstants.kt
+ enum AlignmentAlgo { V1, V2 }
+ @Volatile var alignmentAlgo: AlignmentAlgo = V1 (default = legacy)
ui/views/monitoring/PlacementGuideView.kt
+ val v2Aligner = remember { RollingAligner() }
+ V2 분기 (alignmentAlgo == V2 시): raw 6ch → push → state(accum/commit)
→ directionHint/directionIcon/placementScore/LED 설정
→ bleManager.debugLogger.info("ALIGN_V2 phase=... state=... bestSet=...")
+ ⚙ Settings overlay 에 V1 (legacy) / V2 (new) 토글 (보라색)
+ addAlignmentFrame 호출 시 V2 활성이면 v2Aligner.phase.name 사용 (4-stage)
ui/views/clinical/ClinicalHomeView.kt
+ ClinicalSession.alignmentAlgo 를 현재 GreenZoneConstants.alignmentAlgo 값으로 채움
(이전 demo-final 은 "V1" 하드코딩)
→ V2 토글 후 Sensor Alignment 진입 시 alignment_algo="V2" 가 json 에 기록
영향:
- 기존 V1 동작 그대로 (default 가 V1, 토글 안 하면 동일)
- V2 선택 시 demo-final 에서도 4-stage 진행 가능 + json 라벨 V2 명시
- 알고리즘 토글은 dev 모드 (⚙ 버튼) 에서만 가능 — 일반 사용자 노출 X
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## 측정 화면 (PiezoMonitoringView)
- BoxWithConstraints + donutFitSize: 가로/작은 화면에서도 donut+Bladdy+buttons
모두 들어오도록 height-aware sizing (cap 120~360dp)
- nonDevSpacing: available height 기반 단계 (18/22/28/36) — 큰 화면 답답함 해소
- center 4 중 1개라도 missing → 즉시 realign prompt (이전: AutoMeasure 5회 누적)
- 6채널 중 3개 이상 missing 시 위치 이탈 알림 (모드 무관)
- 다이얼로그 문구: "Position Lost or Insufficient Gel"
- V41 결과 후처리 — walls를 PiezoEchoAnalyzer 기준으로 강제 (UI 차트와 일관)
· ant = analyzer.result.ant
· post = analyzer.result.lowEnd + 3
- CH3 secondary echo 잡힘 / CH4·CH5 lateral ant too-deep 문제 해결
- Bladdy 3-tap → Developer Mode toggle (측정 화면에서도)
## Placement 가이드 (PlacementGuideView)
- 가로 모드 대응: bodyW = min(w, h*0.7f) — 태블릿 가로에서 portrait 비율 유지
- Sensor 이미지를 Canvas drawImage 로 이동 — bladder oval 좌표계와 정확히 정렬
- Start Alignment 버튼: enabled = true 명시
## Settings overlay
- "Ant Offset" 숫자 입력 필드 (0~20mm, dev mode 전용)
· BV 계산 시 ant 를 입력값만큼 probe 쪽으로 당김 (chord 증가 → BV 증가)
· mm→samples 변환은 PiezoHW.distancePerSample
· V41 SphereFit BV 는 offset≠0 일 때 우회 → 6ch estimate
- "Version" row 추가 (BuildConfig.VERSION_NAME)
- Save 버튼: 실제 UserStorage 영구 저장 + state 재전파
· AppState.savePiezoSettingsNow() 추가
- 전체 overlay 에 verticalScroll + Card maxHeight 90% — dev 컨텐츠 길어도 Save 도달
## DPS 동기화 (긴급 수정)
설정의 DPS 변경이 V41Detector(Geometry/AnatomicalGate)에 반영 안 되던 문제:
- WdConfig.DPS_DEFAULT: const val → @Volatile @JvmField var
- PiezoHW.distancePerSample setter 가 WdConfig.DPS_DEFAULT 자동 동기화
- 시작 시점 1.968.also { WdConfig.DPS_DEFAULT = it } 로 두 값 일치
## 버전
- versionName: VBTAND0101 → 2026005-101
- versionCode: 2 → 3
## 신규 모듈
- services/ScanLogStore.kt — dev mode 진단 로그 (마지막 Single Scan summary)
· WALLS CSV (ch,ant,post,urine), DATA CSV (raw ADC), antOffsetMm
- ui/components/ScanLogDialog.kt — 클립보드 복사 다이얼로그
· xbench (CharlesKWONsLaw) MbbLogDialog 패턴 차용
· SelectionContainer + monospace + Copy/Clear/Close
- 측정 화면 dev panel 에 "Scan Log (N)" 버튼 추가
## 데이터 모델
- PiezoSettings.antOffsetMm: Int = 0 필드 추가
## 단위 테스트
- V41DetectorCH4Test.kt — 2026-05-06 floating-signal 캡쳐 6채널 raw 를
V41Detector.detect 에 통과시켜 결과 출력 (CH4 가짜 wall 진단용)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 좌우 방향 전면 수정: ch4(왼쪽)길다→←, ch5(오른쪽)길다→→
ch4만 감지→← (기기 오른쪽 치우침), ch5만→→
- Almost there 제거: 방향OK+CV미달 → 그냥 GREEN 통과
- postMaxIdx 런타임 슬라이더 (개발자 설정, 기본 80, 범위 50-95)
Method A/B 공통 적용 — 바닥반사 peak 무시
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Detection(A/B/C)과 BV(Frustum/V41) 독립 설정 (개발자 모드)
기본값: Detection=C, BV=V41
- Spot: 3회 median → 5회 1.5초간격 trimmed mean (Auto와 동일)
최대 8회 재시도, 최소 유효 3개
- 일반 모드 도넛 320dp, 간격 28dp, 버튼 62dp (화면 여유)
- Placement mm 표시 제거 — 방향만 안내
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- autoDetectPreset: 기기이름 뒤에서 3번째 글자로 각도타입 판별
VBT26050301 → '3' → V2 (기존: VBT2604 매칭 실패 → V0 → 각도 0° → BV 절반)
- 도넛차트: level 단계별 → maxVolumeMl/maxVolume 연속 비율로 변경
- Placement "Almost there" 3회 연속 → 자동 GREEN 통과
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- #1 배터리 최적화 페이지 이동 제거 (ForegroundService+WakeLock만)
- #2 Auto 첫 측정 대기 시 "Measuring... (n/5)" loading 표시
- #3 Placement 멘트 정리 — 방향만 남기기 (CH 언급 제거)
- #4 CH0~CH5 dot row 개발자 모드 전용
- #5 Spot 재시도 로직 (최대 6회, 유효 3개 목표, 300ms 간격)
- LR 좌우 조건 완화: ±8mm, symmetry≥0.5, lrDev≤0.35
- |len4-len5|≤10 → LATERAL 건너뛰고 바로 GREEN
- GREEN 미달 시 CV만 간당간당하면 GREEN 유지 ("Almost there...")
- CV 기본 임계 0.08→0.12, 디바운스 3초→1.5초
- BV 타원 피팅 outlier 반복 제거 (appshare #22)
- README v3 업데이트 (3모드 placement, BV 파이프라인, 상태표)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Port of appshare #21 merge (bv_estimation.py):
- repairCenterWallsFor6ch: gap=1 보간, gap>=2 top 그룹 제거
- computeLrRatio: chord 비율 → x-z 6점 타원 피팅 (b_lr/a_ap)
- Post-median outlier 제거 (median ±25%, ≥3ch)
- Cap 높이: ellipseCapHeights 삭제 → y-z 8점 타원 피팅 inline
- Top cap 상한: 미검출 상위 채널 빔 y좌표 기준 제한
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Developer mode: 캐릭터 3탭 토글, dev-only settings/graphs/logs
- SWEEP placement (CKLaw): BladderSphereSeek circle fit + RTracker
+ argmax + coronal lateral + R-peak gate GREEN lock
- Gradient placement: weighted center gradient 기반 상하 판정,
방향 로직 수정 (ch0=위, ch3=아래), 초기 멘트 "치골 위에 배치"
- Spot 측정: isSpotInProgress 플래그로 중간값 화면 깜빡임 제거
- 좌우 애매한 ↔ 멘트 제거 → 구체적 방향 또는 상태 안내
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Method B:
- 채널별 otsu_ratio = OTSU_RATIO × cos(θ) 보정
- 큰 각도 채널은 threshold 완화 → 약한 후위벽 감지 개선
- detectLowEcho에 otsuRatioOverride 파라미터 추가
- analyzeMultiChannelWithTgc: initial + rerun 모두 각도 보정 적용
Method A:
- 채널별 min_wall_contrast_ratio = 1.2 × cos(θ) 보정
- detectMethodA에 contrastRatioOverride 파라미터 추가
- analyzeChannel에서 PiezoHW.degreeAll 기반 자동 계산
Monitoring:
- Detachment LED: 상태 변경 시에만 전송 (wasDetached 추적)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Foreground Service (BleForegroundService.kt):
- BLE 연결 시 자동 시작, 해제 시 자동 중단
- PARTIAL_WAKE_LOCK (최대 4시간)
- Notification: "VesiScan - BLE 기기 연결 중..."
- connectedDevice foregroundServiceType
- Doze 모드에서도 BLE 통신 유지
- keepScreenOn도 유지 (추가 안전장치)
Detachment 개선:
- THR_MEAN/STD 100→30 (완전 탈착만 감지, 거리 약화 무시)
- 6채널 모두 수신됐을 때만 체크 (BLE 거리 문제와 구분)
- Placement: if(false) 제거 → 활성화 + "센서가 부착되지 않았습니다"
- Monitoring: 정상 복귀 시 LED OFF
Placement 가이드 모드:
- Simple (기본): 3+채널 → 바로 좌우 (기존)
- Boundary: 올라갔다 내려오기 패턴 (경계 감지 → 최적점 복귀)
- 설정 톱니바퀴에 Simple/Boundary 스위치
BLE 로그:
- 역순 표시 (최신이 위) — 스크롤 위치 유지
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PiezoEchoAnalyzer.useSgFilter: true/false로 SG 필터 on/off
- OFF 시 raw ADC 그대로 low-echo detection에 사용
- Settings 패널에 Switch 토글 추가 (기본 ON)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Low Echo Threshold: 800~2000 슬라이더 (기본 1150, 주황색)
→ GreenZoneConstants.lowEchoAmp 런타임 변경
→ CH4/CH5 threshold 조절로 lateral 감지 개선
2. Distance/Sample: 1.5~2.5mm 슬라이더 (기본 1.771, 초록색)
→ PiezoHW.distancePerSample 런타임 변경
→ 기기별 캘리브레이션 가능
3. 도넛차트 ml 실시간 표시: estimatedVolume → lastVolumeMl 직접 표시
→ 측정 즉시 정확한 ml 반영 (기존: 레벨 변환 후 재계산으로 지연)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
원인: CH4/CH5 lateral이 center 대비 짧아서 lr_ratio=0.32 계산
→ S = π/4 × D² × 0.32 → 용적 68% 과소평가
수정: computeLrRatio() 반환값에 .coerceAtLeast(1.0) 추가
원형(1.0)보다 좁은 방광 단면은 물리적으로 불가능하므로 하한 제한
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
detectLowEcho: 고정 1150 → adaptive threshold (기본 활성화)
1. ringSkip(3) 이후 신호에서 q25/q50/q75 계산
2. percentile 기반: q25 + iqr*0.3 ~ q50 - iqr*0.3
3. 고정값(1150) 범위 제한: ×0.7 ~ ×1.5 (805~1725)
4. 가중 평균: 고정 40% + adaptive 60%
→ 신호 레벨에 자동 적응하되 급격한 변동 방지
WaveformChart: threshold 점선도 adaptive 값으로 표시
useAdaptiveThreshold 플래그로 on/off 전환 가능
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GreenZoneConstants.kt — all 16 constants (thresholds, physical)
UrinAI.kt — urine gatekeeper (binary threshold detection)
PiezoEchoAnalyzer.kt — low-echo detection with prominence-based wall selection
PiezoBVEstimator.kt — Frustum BV estimation with device presets
1:1 port from Swift, same logic, same constants.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A. Reminder: ReminderService (AlarmManager chain), ReminderSettingsView,
bell icon in Piezo top bar, reschedule on catheterization
B. Consent: ConsentView (3 mandatory items), onboarding→consent→registration flow,
persistent consent storage, sex field in User + Registration Step 2
C. Diary: 24hUV, NUV, NPI, max capacity, day/night frequency metrics card
D. Design: DesignTokens.kt, 48dp touch targets, DonutChart semantics, pressScale modifier
E. Quality: BuildConfig.DEBUG log wrapping, DateFormatter caching, background I/O for diary store
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix BLE API deprecation warnings with API 33+ version checks
- Move isServiceReady to onDescriptorWrite for reliable CCCD setup
- Fix battery polling: immediate query on connect, pause during NIRS streaming
- Add mcj retry mechanism for NIRS streaming reliability
- Add debug logging to BLE, NIRS parsing, and processing pipeline
- Add catheter count feature to Piezo monitoring (persistent count, add dialog, auto-decrement on catheterize)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port of MedilightV2 iOS app to Android with Kotlin + Jetpack Compose.
Includes BLE connectivity, NIRS/Piezo sensor modes, Rive animations,
interactive measurement history charts, and foldable device support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>