fix: 加速度计要求连续3个高值才触发,防摆动尖峰误触发
实测小幅摆动时Z在-2~10间剧烈跳动,单个尖峰Z=10就触发了。 改为要求连续3个采样≥8(约0.6秒持续高值)才触发: - 真正抬手:Z稳定在8-9多个采样 → 连续3个≥8 ✅ - 小幅摆动:尖峰后立即回落 → 连续不到3个 ❌ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,8 @@ class FiseAccelerometerWake @Inject constructor(
|
||||
private const val Z_MIN_THRESHOLD = 3f
|
||||
/** 方案C:当前值阈值,超过此值认为"手臂已明确抬起"(实测:放下过程Z≈5-7,抬起稳定Z≈8-9) */
|
||||
private const val Z_CURRENT_THRESHOLD = 8f
|
||||
/** 方案C:连续高值计数要求(需连续N个采样≥阈值才触发,防摆动尖峰误触发) */
|
||||
private const val HIGH_COUNT_REQUIRED = 3
|
||||
/** 方案C:触发后冷却采样数(防连续触发,10个≈2秒) */
|
||||
private const val COOLDOWN_SAMPLES = 10
|
||||
}
|
||||
@@ -64,6 +66,8 @@ class FiseAccelerometerWake @Inject constructor(
|
||||
private var windowFilled = false
|
||||
/** 触发后冷却计数器 */
|
||||
private var cooldownCount = 0
|
||||
/** 连续高值计数器(Z >= 阈值的连续采样数) */
|
||||
private var highCount = 0
|
||||
|
||||
/**
|
||||
* 开始监听传感器
|
||||
@@ -138,13 +142,15 @@ class FiseAccelerometerWake @Inject constructor(
|
||||
// === 方案C 核心逻辑 ===
|
||||
|
||||
/**
|
||||
* 最小值跳变检测
|
||||
* 追踪近期(最近5个采样≈1秒)的最小Z值:
|
||||
* - 如果近期最小值 < 5(说明手臂曾经放下过)
|
||||
* - 并且当前Z值 ≥ 7(说明手臂已抬起)
|
||||
* → 判定为"抬手"动作
|
||||
* 最小值 + 连续高值检测
|
||||
*
|
||||
* 优点:只需一个低值采样即可触发,比均值方案灵敏得多
|
||||
* 两个条件同时满足才触发:
|
||||
* 1. 近期5个采样中有值 < 3(手臂曾明确下垂)
|
||||
* 2. 当前连续 3 个采样都 ≥ 8(手臂已抬起并稳定,非瞬间尖峰)
|
||||
*
|
||||
* 连续高值要求可区分:
|
||||
* - 真正抬手:Z 稳定在 8-9 持续多个采样 → 连续 3 个 ≥ 8 ✅
|
||||
* - 小幅摆动:Z 在 0-10 间剧烈跳动,尖峰后立即回落 → 连续不到 3 个 ❌
|
||||
*/
|
||||
private fun detectWristRaise(z: Float) {
|
||||
// 冷却期:刚触发过,等待冷却结束
|
||||
@@ -153,7 +159,7 @@ class FiseAccelerometerWake @Inject constructor(
|
||||
return
|
||||
}
|
||||
|
||||
// 写入环形缓冲区
|
||||
// 写入环形缓冲区(追踪近期最小值)
|
||||
val pos = windowIndex % MIN_WINDOW_SIZE
|
||||
zWindow[pos] = z
|
||||
windowIndex++
|
||||
@@ -163,6 +169,13 @@ class FiseAccelerometerWake @Inject constructor(
|
||||
}
|
||||
if (!windowFilled) return
|
||||
|
||||
// 更新连续高值计数
|
||||
if (z >= Z_CURRENT_THRESHOLD) {
|
||||
highCount++
|
||||
} else {
|
||||
highCount = 0
|
||||
}
|
||||
|
||||
// 找近期最小值
|
||||
var recentMin = Float.MAX_VALUE
|
||||
for (i in 0 until MIN_WINDOW_SIZE) {
|
||||
@@ -170,14 +183,15 @@ class FiseAccelerometerWake @Inject constructor(
|
||||
}
|
||||
|
||||
// DEBUG: 输出每次计算结果,用于调参(正式发布时删除)
|
||||
Timber.v("抬手亮屏: Z=%.1f recentMin=%.1f (阈值: min<%.0f AND cur>=%.0f)",
|
||||
z, recentMin, Z_MIN_THRESHOLD, Z_CURRENT_THRESHOLD)
|
||||
Timber.v("抬手亮屏: Z=%.1f recentMin=%.1f highCount=%d (阈值: min<%.0f AND %d连续>=%.0f)",
|
||||
z, recentMin, highCount, Z_MIN_THRESHOLD, HIGH_COUNT_REQUIRED, Z_CURRENT_THRESHOLD)
|
||||
|
||||
// 判断:近期有低值(手臂曾下垂)且当前值高(手臂已抬起)
|
||||
if (recentMin < Z_MIN_THRESHOLD && z >= Z_CURRENT_THRESHOLD) {
|
||||
// 判断:近期有低值(手臂曾下垂)且连续高值达标(手臂已稳定抬起)
|
||||
if (recentMin < Z_MIN_THRESHOLD && highCount >= HIGH_COUNT_REQUIRED) {
|
||||
wakeScreenIfOff()
|
||||
// 触发后进入冷却期 + 清空窗口
|
||||
// 触发后进入冷却期 + 清空状态
|
||||
cooldownCount = COOLDOWN_SAMPLES
|
||||
highCount = 0
|
||||
resetWindow()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user