現象複現
- 手機平放桌面,未移動,加速度計讀數持續波動(x、y 軸非 0,z 軸不穩定在 9.8)。
- 首次註冊監聽後,傳感器持續上報 30+ 秒才進入穩態(僅在支持鎖屏運行傳感器的機型出現)。
- 嘗試通過積分計算位移,誤差極大,不可用。
核心原理:為什麼靜止也有數據?
- 重力分量投影:手機不可能絕對水平,微小傾角會將重力 g (9.8 m/s²) 分解到 x、y 軸。
a_x = g * sin(θ_x),1° 傾角產生 ~0.17 m/s² 偏移。
- 環境微振動:樓宇共振、風扇、腳步、甚至熱擴張收縮,均在 0.01-0.1 Hz、幅值 0.001-0.01 g 範圍,民用 MEMS 傳感器極其敏感。
- 傳感器固有噪聲:白噪聲、隨機游走、偏移漂移。典型消費級加速度計噪聲密度 100-400 µg/√Hz。
- 溫度漂移:MEMS 結構對溫度極敏感,溫度變化 1°C 可導致零點偏移 1-5 mg,積分後位移誤差隨時間平方級增長。
- 校準不完美:出廠校準僅修正靜態零點與標度因子,無法覆蓋全溫域、全姿態、老化變化。
為什麼積分計算位移不可行?(數學鐵律)
位移 = ∬ a(t) dt²。假設恆定偏移誤差 b = 0.01 m/s²:
| 時間 | 速度誤差 (m/s) | 位移誤差 (m) |
| 1 秒 | 0.01 | 0.005 |
| 10 秒 | 0.1 | 0.5 |
| 60 秒 | 0.6 | 18 |
| 10 分鐘 | 6 | 1800 |
結論:無外部修正(GPS、視覺里程計、UWB、地磁、WiFi 指紋),純慣導定位在消費級手機上純屬理論遊戲。
工程可行的對策
1. 濾波與平滑(降噪不消偏)
- 低通濾波器:
a_filtered = α * a_raw + (1-α) * a_prev (α=0.1-0.3),保留重力分量,抑制高頻抖動。
- 互補濾波 / 卡爾曼濾波:融合陀螺儀(短期精準)+ 加速度計(長期基準),估計姿態四元數,將重力從加速度中剝離,得到「線性加速度」
Sensor.TYPE_LINEAR_ACCELERATION(系統已內置融合)。
2. 靜止檢測與零點校準(消除靜態偏移)
// 簡易靜止檢測:連續 N 幀模值變化 < 閾值
if (Math.abs(currMag - prevMag) < 0.05 && Math.abs(currMag - 9.8) < 0.2) {
staticCount++;
if (staticCount > 20) { // 约 1 秒 @ 20Hz
// 校準零點偏移
biasX = lowPassX; biasY = lowPassY; biasZ = lowPassZ - 9.8;
}
} else {
staticCount = 0;
}
// 使用時扣除偏移
linearX = rawX - biasX;
3. 步數計數 / 活動識別(放棄連續位移,轉離散事件)
- 使用
Sensor.TYPE_STEP_COUNTER、Sensor.TYPE_STEP_DETECTOR(硬件級步進檢測,極低功耗)。
- 配合
ActivityRecognitionApi 識別走路、跑步、騎車、車輛、靜止。
- 步長模型估算距離:
distance = steps * (0.413 * height),誤差 ~10%,遠優於積分。
4. 融合定位(唯一正解)
Fused Location Provider (Google Play Services) / Android 12+ FusedLocationProviderClient:內部融合 GPS + WiFi + 藍牙 + 慣導 + 基站 + 地圖匹配,輸出最優位置與不確定性半徑。不要重複造輪子。
關於「首次啟動 30 秒持續上報」
部分廠商(如小米、華為早期機型)為節省功耗,傳感器 HAL 層實現「懶加載」:首次 registerListener 觸發固件初始化、自校準、熱機,期間以高頻輸出原始數據,直到進入穩態。屬於廠商行為差異,**不影響最終數據質量**,App 層可忽略前 2 秒數據或顯示「傳感器預熱中」。
總結
- 靜止有數據是**正常物理現象**(重力投影+環境振動+傳感器噪聲),非 Bug。
- 純加速度積分算位移**理論上不可行**,誤差隨時間發散。
- 工程上:用
LINEAR_ACCELERATION 獲取去重力加速度 → 靜止校準零點 → 步數/活動識別 → 融合定位 API。
- 別試圖用消費級手機做慣性導航,那是導彈、飛機、自動駕駛(配合 RTK-GNSS、光纖陀螺)的領域。
- 上一篇文章: iOS 系統自帶 UITabBar 的五大局限性,為何常需自定義?
- 下一篇文章: SQL 裡寫業務邏輯好嗎?性能、可維護性與架構分層的權衡
Copyright ©
程式碼之家 All Rights Reserved