fix(posture): gyro gate 제거 + UNKNOWN streak 화면 표시
증상: 디바이스를 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>
This commit is contained in:
@@ -24,10 +24,13 @@ enum class Posture { UNKNOWN, LYING, NON_LYING }
|
||||
|
||||
object ImuPostureClassifier {
|
||||
|
||||
// 게이트 임계값 — flowchart 그대로
|
||||
// 게이트 임계값
|
||||
private const val ACC_MAG_MIN = 0.8f
|
||||
private const val ACC_MAG_MAX = 1.2f
|
||||
private const val GYRO_MAG_MAX_DPS = 9.16f
|
||||
// Gyro gate 비활성화 — 일부 디바이스의 gyro calibration bias (-25 dps 등) 가
|
||||
// flowchart 임계(9.16) 보다 커서 정지 상태에서도 fail → 분류 영구 불가.
|
||||
// accel magnitude gate (0.8-1.2g) 가 이미 큰 모션 거름. gyro 게이트 제거.
|
||||
// 단 dev 모드 디버그 위해 magnitude 는 계속 계산해 로그/Result 에 노출.
|
||||
|
||||
/** 자세 + 진단 정보 (UI/log용). */
|
||||
data class Result(
|
||||
@@ -60,10 +63,7 @@ object ImuPostureClassifier {
|
||||
return Result(Posture.UNKNOWN, 0f, accMag, gyroMag,
|
||||
"acc mag out of range (%.2f)".format(accMag))
|
||||
}
|
||||
if (gyroMag > GYRO_MAG_MAX_DPS) {
|
||||
return Result(Posture.UNKNOWN, 0f, accMag, gyroMag,
|
||||
"moving (gyro %.1f dps)".format(gyroMag))
|
||||
}
|
||||
// Gyro gate 제거 — bias 큰 디바이스에서 영구 fail 문제 (위 주석 참조)
|
||||
|
||||
val pitch = (atan(ax / sqrt(ay * ay + az * az)) * 180.0 / Math.PI).toFloat()
|
||||
val absPitch = abs(pitch)
|
||||
|
||||
Reference in New Issue
Block a user