###はじめに
学校の卒業制作でjavaの歩数によってgifが変わるアプリを作ったので、kotlinでリメイクしました。
Androidには歩数計センサーもありますがAndroid10以上かつ使用できる端末が限られていたので加速度センサーを使用しました。
歩数計算の方法はこちらの記事を参考にさせていただきました。
[Android]歩数計アプリを作ってみた。
##歩数カウント
Android端末には3軸の加速度センサーが存在します。
この3軸のセンサーから得られる加速度を合成した値の増減を利用し、歩数をカウントします。
val sumAcceleration = sqrt(value[0].toDouble().pow(2.0) + value[1].toDouble().pow(2.0) + value[2].toDouble().pow(2.0)).toFloat()
センサーから取得した生データにはノイズが含まれるため、ローパスフィルタというフィルタリング処理を行いデータを精査します。
ローパスフィルタとは
ローパスフィルタ
private var raw: Float = 0f //計測値
private var lastRaw: Float = 0f //前回の計測値
private var filter: Float = 0.6f //フィルタリング係数 (0 < filter < 1)
lastRaw = filter * sumAcceleration + (1 - filter) * raw
実際のコード
class StepCounterService : Service(), SensorEventListener {
private var first = true
private var up = false
private var raw: Float = 0f //計測値
private var lastRaw: Float = 0f //前回の計測値
private var filter: Float = 0.72f //フィルタリング係数 (0 < filter < 1)
override fun onCreate() {
super.onCreate()
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onSensorChanged(event: SensorEvent) {
val value: FloatArray = event.values
//3軸の加速度の合計
val sumAcceleration = sqrt(value[0].toDouble().pow(2.0) + value[1].toDouble().pow(2.0) + value[2].toDouble().pow(2.0)).toFloat()
if (first) {
first = false
up = true
raw = filter * sumAcceleration
} else {
//ローパスフィルタリング 時系列の細かいデータを平滑化
lastRaw = filter * sumAcceleration + (1 - filter) * raw
if (up && lastRaw < raw) {
up = false
//ここで歩数がカウントされる
} else if(!up && lastRaw > raw) {
up = true
raw = lastRaw
}
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { }
}
このソースではバックグラウンドで値を取るのにServiceを使用してしまっていますが、Android9以降受信されないようなので注意してください。
Android 9(API レベル 28)以降を搭載するデバイスでは、バックグラウンドで実行されるアプリに次の制限があります。
・継続的報告モードを使用するセンサー(加速度計やジャイロスコープなど)では、イベントが受信されません。
歩数はスマホを持って10歩歩いて誤差+1でした。
検証が少ないですがスマホの状態にも大きく影響されやいので改良したいと思います。
歩数以外でも納得できる出来にはなっていないので改良を重ね、いつかストアに上げるまでできたらいいなと思います。