AWARE Framework を使ったモバイルセンシングを自分のiPhoneで試してみた

2025/01/06に公開

タイトルの付け方がちょっと怪しいです。

まえがき

記事の中身ですが、昨年末にAWARE Framework をプライベートで使ってみたという話です。西山先生に教えてもらった1年前ぐらいからちょくちょく見ていたのですが、だいぶ遅くなってしまいました(昨年末にこの記事の内容を調べて、ブログに書くまでに年が変わっていました…)。

Frameworkについては [1][2] あたりを見ていただくと詳しいですが、ユーザの端末(ここではiPhone)を通じてセンサー情報などを収集するためのものです。

背景

普段 Garmin のスマートウォッチを使い、歩数やジョギングの状況をモニタリングしています。ジョギングした後は Garmin Connect → Strava でジョギングのサマリーを取得して X に投稿しています。

このデータは(おそらく)スマートウォッチ単体のものですが、せっかく普段からスマホを持ち歩くので、スマホのデータも使いたいなと思いました。また、ちょうど会社で歩数をカウントする社内イベントをやっていたので、せっかくなのでGPSデータでも定期的に取得してみるかとなり、冒頭のフレームワークを使ってみました。

以降では、まずiPhoneを操作してデータを収集し、次にMacでデータ解析をしました。

iPhone側でデータを収集する

AWARE V2 アプリの設定

インストール(AWARE V2というアプリです。リンク先はApple Store)は2023年12月ぐらいにしてありました。

いざ使うにあたり、しばらく動かしていなかった&フレームワークの詳細をそこまで調べているわけではないので、軽く悩みました。しばらく試行錯誤して、とりあえず起動し、以下のデータを取得するようにしました。

  • 「設定」→「加速度計」→「status_accelerometer」: true
  • 「設定」→「総合位置情報」→「status_google_fused_location」: true

残りの設定は(おそらく)デフォルトです。ここまでしてデータが溜まると「Context」のタブからデータが見えます(ただし、accelerometerをtrueにしていると、ものすごく重いです)。

実験

2024/11/17〜2024/12/25 ぐらいまで、アプリを起動&設定をtrue にしておいてデータを取得しました。若干バッテリーを多く消費した気がしますが、普段ドラクエウォークがほとんどのバッテリーを持っていくので誤差です。

データ出力

後でデータ収集を停止し、データをiPhoneから取り出します。

  • 「設定」→「詳細設定」→「Export DB」

ここでポップアップメニューが出てくるので、以下を出力しておきました。

  • AWARE.sqlite
    • 11.9MBありました
  • AWARE_Accelerometer.sqlite
    • 1.37GBありました

以降のデータ処理はMac側で行います。先に AWARE.sqlite を確認し、次にファイルサイズが大きい AWARE_Accelerometer.sqlite を確認することにします。

Mac側でデータを処理する | AWARE.sqlite編

適当な作業フォルダで作業していきます。

データベースファイルの確認

転送してきたデータベース AWARE.sqlite をビューワで開いてテーブルを確認してみます。とりあえず何かしらデータが格納されるテーブルが準備されていることがわかります。

どこにデータが入っていそうか確認してみましょう。

sqlite3_analyzer AWARE.sqlite > output.txt

中身を見てみるとEVENTLOG、SIGNIFICANTMOTION (説明省略してます)、LOCATIONあたりにデータが残っていそうです。

# output.txtの一部
*** Page counts for all tables with their indices

ZENTITYEVENTLOG................................... 1772        60.9% 
ZENTITYSIGNIFICANTMOTION.......................... 815         28.0% 
ZENTITYLOCATION................................... 235          8.1% 

スキーマとデータの確認

sqlite3を起動してLOCATIONのスキーマも確認しておきます。緯度経度が取得できていそうです。

sqlite> .schema ZENTITYLOCATION
CREATE TABLE ZENTITYLOCATION ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZACCURACY INTEGER, ZDOUBLE_ALTITUDE FLOAT, ZDOUBLE_BEARING FLOAT, ZDOUBLE_LATITUDE FLOAT, ZDOUBLE_LONGITUDE FLOAT, ZDOUBLE_SPEED FLOAT, ZTIMESTAMP FLOAT, ZDEVICE_ID VARCHAR, ZLABEL VARCHAR, ZPROVIDER VARCHAR );

sqlite> select ZDOUBLE_LONGITUDE, ZDOUBLE_LATITUDE from ZENTITYLOCATION;
139.XXXX|35.YYYY
(以下続く)

あとはPythonでデータを処理します。

Pandas+Matplotlibによるデータ加工と可視化

雑に書いてみます。

import os
import sqlite3
import pandas as pd
import matplotlib.pyplot as plt

def read_database(fn: str = "./AWARE.sqlite") -> None:
    if not os.path.exists(fn):
        return None
    plt.style.use("ggplot")

    # cursorを使わずにpandasで直接読み込む
    conn = sqlite3.connect(fn)
    str_sqrt = "select ZDOUBLE_LONGITUDE, ZDOUBLE_LATITUDE from ZENTITYLOCATION"
    df = pd.read_sql(str_sqrt, conn)
    
    # (Long, Lat) の可視化
    f = plt.figure(dpi=300)
    a = f.gca()
    df.plot.scatter(x="ZDOUBLE_LONGITUDE", y="ZDOUBLE_LATITUDE", ax=a, marker="x")
    f.tight_layout()
    f.savefig("scatter.png", bbox_inches="tight")
    plt.close()

    return

if __name__ == '__main__':
    fn_dbfile = "./AWARE.sqlite"
    read_database(fn_dbfile)

概ねデータがとれていそうです!(ちょっと変なの入ってますが…)。

前処理してお掃除してみます。匿名化のために緯度経度の軸を軽く隠してみましたが、明らかに東海道新幹線で移動していますね(濃いところは東京と愛知)。そこそこ取れていました。

タイムスタンプを処理して1日あたりのデータ件数も確認してみます。アプリの設定はこのあたりに影響してきそうですね。すごく細かいという感じではないですが、概ねのデータ取得ならデフォルト設定でいけそうです。

Mac側でデータを処理する | AWARE_Accelerometer.sqlite編

続いて(おそらく)スマホに内蔵されているIMUの加速度データも見てみます。

データベースファイルの確認

だいたい同じ処理です。スキーマを確認すると

  • ZAWAREACCELEROMETTEROM

これがそれっぽいデータになっています。コマンド打ってもだいたい同じです。

*** Page counts for all tables with their indices

ZAWAREBATCHDATAOM................................. 222235      66.6% 
ZAWAREACCELEROMETEROM............................. 111027      33.3% 

スキーマも真面目にみるとこういうものです。

# Timestamp, Values 0, 1, 2がある
sqlite> .schema ZAWAREACCELEROMETEROM
CREATE TABLE ZAWAREACCELEROMETEROM ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZACCURACY INTEGER, ZTIMESTAMP INTEGER, ZDOUBLE_VALUES_0 FLOAT, ZDOUBLE_VALUES_1 FLOAT, ZDOUBLE_VALUES_2 FLOAT, ZDEVICE_ID VARCHAR, ZLABEL VARCHAR );

# Count, Timestampがある
sqlite> .schema ZAWAREBATCHDATAOM
CREATE TABLE ZAWAREBATCHDATAOM ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZCOUNT INTEGER, ZTIMESTAMP INTEGER, ZBATCH_DATA BLOB );

Pythonでの処理

AWARE.sql の処理と同様に件数を確認してみます。データ量が大きくなっているのは単にデータが多いからみたいですね。1日は24×60×60で86400秒なので、1秒あたり10回 (10Hz) データを取るだけでも約1M点になりますね。

せっかくなので、ある1日だけサンプルし、プロットしてみます。少し変な感じですね。データ処理するときに時差の処理を忘れたかもしれません。マニュアルなどを読んでいないので、詳細は不明です。

3つのデータ軸(Z0、Z1、Z2)がありますが、Z2だけ明らかに少しズレているので、Z2がy軸(重力加速度の影響)と考えられます。こちらも、マニュアルなどを読んでいないので、詳細は不明です。しかし、データは取れていそうな感じがしますね。

後は細かく設定を調整して、データ取得ができそうですね。

まとめ

この記事では、昨年末に調べていたことをまとめました。

具体的には AWARE Framework を使ったデータ収集方法とデータ解析方法について、以下の点を忘れないように書いておきました。

  • AWARE V2 アプリを iPhone にインストールする
  • アプリがデータを収集するできるように設定する
  • アプリのデータを Python で解析する
脚注
  1. https://awareframework.com/ ↩︎

  2. https://www.mcl.iis.u-tokyo.ac.jp/2020/11/08/aware-framework-an-open-source-mobile-sensing-framework-for-ios-and-android/ ↩︎

Discussion