4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

qnoteAdvent Calendar 2021

Day 7

[Kotlin] 加速度センサーで歩数カウント

Last updated at Posted at 2021-12-07

###はじめに
学校の卒業制作でjavaの歩数によってgifが変わるアプリを作ったので、kotlinでリメイクしました。
Androidには歩数計センサーもありますがAndroid10以上かつ使用できる端末が限られていたので加速度センサーを使用しました。

歩数計算の方法はこちらの記事を参考にさせていただきました。
[Android]歩数計アプリを作ってみた。

##歩数カウント
Android端末には3軸の加速度センサーが存在します。
この3軸のセンサーから得られる加速度を合成した値の増減を利用し、歩数をカウントします。

3軸の加速度の合計
無題78_20211207184705.PNG

 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

実際のコード

StepCounterService.kt
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)以降を搭載するデバイスでは、バックグラウンドで実行されるアプリに次の制限があります。

 ・継続的報告モードを使用するセンサー(加速度計やジャイロスコープなど)では、イベントが受信されません。

##完成したアプリ
無題79_20211207194609.jpg

実機動画(Twitter)

歩数はスマホを持って10歩歩いて誤差+1でした。
検証が少ないですがスマホの状態にも大きく影響されやいので改良したいと思います。
歩数以外でも納得できる出来にはなっていないので改良を重ね、いつかストアに上げるまでできたらいいなと思います。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?