スマートフォンの加速度計・ジャイロスコープ CSV から歩行軌跡を推定する PDR(Pedestrian Dead Reckoning)ライブラリです。
現在の標準設定は、ジャイロを体の向き、水平加速度を横歩き判定用の
移動特徴として使う gyro_accel_motion です。通常歩行の軌跡方位は
motion_heading を使います。同方向にまとまった横歩きは確定横歩きとして、
強い単発候補は横歩き疑いとして軌跡へ反映し、それ以外の単発判定は前進扱いにします。
uv sync --all-groupsAI エージェントや sandbox 環境で uv のホームキャッシュ権限に引っかかる場合は、
リポジトリ内キャッシュを使います。
UV_CACHE_DIR=.uv-cache uv run pytestパーティクルフィルタの MP4 アニメーション出力には ffmpeg が必要です。
brew install ffmpeginput/<データフォルダ>/ に phyphox 形式の CSV を置きます。
input/
└── my_walk/
├── Accelerometer.csv
└── Gyroscope.csv
対応する列名は次の通りです。
| ファイル | 対応列 |
|---|---|
Accelerometer.csv |
Time (s), Acceleration x/y/z (m/s^2) または X/Y/Z (m/s^2) |
Gyroscope.csv |
Time (s), Gyroscope x/y/z (rad/s) または X/Y/Z (rad/s) |
現在の既定入力は次です。
DATA_DIR = "input/1turn_rightsidestep_3turn_leftsidestep5"別データを使う場合は、CLI の -d で指定できます。
UV_CACHE_DIR=.uv-cache uv run rikka run -d input/my_walk標準設定で通常 PDR を実行します。プロット表示と PNG/CSV 保存を行います。
UV_CACHE_DIR=.uv-cache uv run rikka runプロット表示を止めてバッチ確認する場合だけ --no-plot を付けます。
UV_CACHE_DIR=.uv-cache uv run rikka run --no-plotpdr は run の別名です。
UV_CACHE_DIR=.uv-cache uv run rikka pdrパーティクルフィルタ付きで実行します。
UV_CACHE_DIR=.uv-cache uv run rikka particleグラフ表示なしでパーティクルフィルタのアニメーションだけ保存する場合:
UV_CACHE_DIR=.uv-cache uv run rikka particle --no-plot --save-animationセンサー波形を確認します。入力フォルダに sensor_plot.png を保存します。
UV_CACHE_DIR=.uv-cache uv run rikka sensorrun / pdr / particle は、同じ CSV 読み込みと PDR ステップ準備を通ります。
通常 PDR はそのステップ列をそのまま軌跡へ積み上げ、particle filter は同じステップ列を
フロアマップ制約で補正してから画像やアニメーションへ出力します。
flowchart TD
input_dir["input/<data_dir>/"] --> acc_csv["Accelerometer.csv"]
input_dir --> gyro_csv["Gyroscope.csv"]
floormap["input/Floormap_building14_5floor.png"] --> plot_pdr
floormap --> pf_map
acc_csv --> load["load_sensor_data()\n列名を t,x,y,z に正規化"]
gyro_csv --> load
load --> preprocess["process_sensor_data()\n重力推定 / 線形加速度 / 水平加速度 / gyro bias / low_angle"]
preprocess --> step_detect["detect_step_result()\n歩行ステップのピーク・区間を検出"]
preprocess --> heading["resolve_step_heading()\nbody_heading / motion_heading / movement_type を推定"]
step_detect --> heading
preprocess --> step_length["estimate_step_length()\nWeinberg などで歩幅候補を推定"]
step_detect --> step_length
heading --> sidestep["sidestep smoothing / heading stabilize\n横歩き判定を軌跡用 movement_type に整理"]
step_length --> sidestep
sidestep --> prepared["prepare_pdr_steps()\ntrajectory候補 / step_lengths / t_at_steps / step_headings"]
prepared --> pdr_branch{"コマンド"}
pdr_branch -->|rikka run / pdr| det_traj["通常 PDR\nstep_length × selected_heading を積み上げ"]
pdr_branch -->|rikka particle| pf["run_particle_filter()\n粒子をステップごとに予測・リサンプリング"]
pf_map["フロアマップ輝度\n通路/壁判定"] --> pf
pf --> pf_snap["平均軌跡を歩行可能画素へ補正"]
det_traj --> csv_common["CSV 出力\ntrajectory.csv / step_lengths.csv / step_headings.csv / gyro_bias.csv"]
det_traj --> plot_pdr["plot_trajectory()\ntrajectory.png"]
det_traj --> step_plots["plot_step_lengths() / plot_step_vectors()\nstep_lengths.png / step_vectors/step_*.png"]
pf_snap --> csv_common
pf_snap --> plot_pf["plot_particle_filter_trajectory()\npf_trajectory.png"]
pf --> anim["save_particle_animation()\nparticle_filter.mp4 または .gif"]
csv_common --> output_dir["output/<timestamp>/"]
plot_pdr --> output_dir
step_plots --> output_dir
plot_pf --> output_dir
anim --> output_dir
センサー波形だけを確認する sensor コマンドは、軌跡推定までは進まず、
前処理とステップ検出結果を入力フォルダ内の画像へ保存します。
flowchart LR
input["input/<data_dir>/\nAccelerometer.csv / Gyroscope.csv"] --> load["load_sensor_data()"]
load --> preprocess["process_sensor_data()"]
preprocess --> detect["detect_step_result()"]
detect --> sensor_plot["plot_sensor_data()\nsensor_plot.png"]
sensor_plot --> input
uv run rikka run の現在の主要な既定値です。
| 項目 | 既定値 | 説明 |
|---|---|---|
DATA_DIR |
input/1turn_rightsidestep_3turn_leftsidestep5 |
入力データ |
FLOORMAP_PATH |
input/Floormap_building14_5floor.png |
背景マップ |
FLOORMAP_ORIGIN_PX |
(2050, 600) |
軌跡の開始ピクセル |
FLOORMAP_SCALE |
0.01 |
1px あたりのメートル数 |
INITIAL_DIRECTION |
90.0 |
歩行開始方向 [deg] |
STEP_DETECTION_METHOD |
peak |
ステップ検出 |
HEADING_METHOD |
gyro_accel_motion |
方位・移動方向推定 |
FORWARD_HEADING_SOURCE |
motion |
通常歩行の軌跡方位は水平加速度由来の移動方向を使用 |
GYRO_BIAS_METHOD |
prewalk_robust |
ジャイロバイアス推定 |
USER_HEIGHT_M |
1.68 |
Weinberg 歩幅補正用の身長 |
SIDESTEP_LATERAL_RATIO |
1.2 |
横方向/前方向の比率がこの値以上で横歩き候補 |
SIDESTEP_MIN_LATERAL_DISPLACEMENT_M |
0.03 |
横歩き判定に必要な横方向変位 [m] |
SIDESTEP_SMOOTHING_METHOD |
clustered |
同方向 evidence の連続クラスタを評価し、確定横歩きまたは横歩き疑いとして軌跡へ反映 |
SIDESTEP_LENGTH_SCALE |
1 |
横歩き歩幅の倍率 |
TURNING_LENGTH_SCALE |
0.3 |
旋回中歩幅の倍率 |
gyro_accel_motion では次を分けて扱います。
body_heading: ジャイロから推定した体/端末の向きmotion_heading: 水平加速度から推定した1歩ごとの移動方向特徴movement_type: センサー上の判定結果trajectory_movement_type: 軌跡計算に使った移動タイプforward_heading_source:forward判定ステップの軌跡方位ソース
実行後、output/<timestamp>/step_headings.csv を確認します。
重要な列は次です。
| 列 | 意味 |
|---|---|
movement_type |
センサー上の判定。sidestep_left/right なら横歩きとして検出済み |
trajectory_movement_type |
軌跡に反映した移動タイプ。forward なら検出は横歩きだが軌跡上は前進扱い |
body_heading_deg |
体/端末の向き |
motion_heading_deg |
水平加速度から見た移動方向 |
selected_heading_deg |
実際に軌跡へ使った方位 |
forward_heading_source |
forward 判定ステップの軌跡方位ソース |
lateral_forward_ratio |
横方向変位 / 前方向変位 |
forward_displacement |
体方向への変位特徴 |
lateral_displacement |
横方向への変位特徴 |
motion_heading_correction_deg |
水平加速度方向の補正角 |
標準設定の clustered では、同方向の横歩き evidence が連続する区間をクラスタとして
評価します。条件を満たす1歩の隙間は最大1つまでクラスタに含め、横歩き evidence が
2歩以上かつクラスタ全体の横方向変位が閾値を満たす場合、確定横歩きとして軌跡へ
反映します。
確定しなかった強い単発 evidence は、標準の --sidestep-suspect-mode motion では
trajectory_movement_type="sidestep_suspect_left/right" として motion_heading を
軌跡へ反映します。それ以外の単発判定は trajectory_movement_type="forward" として
前進扱いにします。
また、forward 判定ステップは水平加速度由来の motion_heading で軌跡へ積みます。
ジャイロ由来の body_heading で積む場合は次を指定します。
UV_CACHE_DIR=.uv-cache uv run rikka run --forward-heading-source body横歩き判定を軌跡へそのまま反映して比較したい場合:
UV_CACHE_DIR=.uv-cache uv run rikka run --sidestep-smoothing none旧方式の単発横歩き抑制と比較したい場合:
UV_CACHE_DIR=.uv-cache uv run rikka run --sidestep-smoothing isolated横歩き判定を増やす/減らす場合:
# 拾いやすくする
UV_CACHE_DIR=.uv-cache uv run rikka run --sidestep-lateral-ratio 1.0
# 厳しくする
UV_CACHE_DIR=.uv-cache uv run rikka run --sidestep-lateral-ratio 1.52つ目のサンプルデータは prewalk_robust のバイアス推定で軌跡が曲がりやすいです。
比較用には手動バイアスも使えます。
UV_CACHE_DIR=.uv-cache uv run rikka run \
-d input/1turn_rightsidestep_3turn_leftsidestep2 \
--gyro-bias-method manual \
--gyro-bias 0.002通常 PDR は output/<timestamp>/ に保存します。
| ファイル | 内容 |
|---|---|
trajectory.csv |
移動後座標。列は timestamp_s,x,y |
trajectory.png |
フロアマップ上の軌跡 |
step_lengths.csv |
ステップごとの歩幅 |
step_lengths.png |
歩幅グラフ |
step_vectors.csv |
ステップごとの変位ベクトル |
step_vectors/step_*.png |
各ステップの変位と加速度分布 |
step_headings.csv |
方位候補、横歩き判定、軌跡反映タイプ |
gyro_bias.csv |
ジャイロバイアス推定の診断情報 |
step_segments.csv |
paper_vertical_threshold 使用時のステップ区間 |
パーティクルフィルタでは追加で次を保存します。
| ファイル | 内容 |
|---|---|
pf_trajectory.png |
PF の平均軌跡 |
particle_filter.mp4 / .gif |
パーティクル分布アニメーション |
PDR 本体は src/rikka/analyze/pdr/ パッケージに分割されています。
rikka.analyze.pdr からの既存 import は互換 facade として維持しています。
| ファイル | 役割 |
|---|---|
pdr/__init__.py |
互換 facade。既存の from rikka.analyze.pdr import run などを維持 |
pdr/common.py |
共通定数、角度処理、モード検証、パラメータ検証 |
pdr/models.py |
StepHeading、StepMotion、PreparedPdrSteps などの共有データ型 |
pdr/sensors.py |
CSV 読み込み、列名正規化、加速度・ジャイロの前処理 |
pdr/gyro_bias.py |
ジャイロバイアス推定 |
pdr/step_detection.py |
ステップピーク・接地区間の検出 |
pdr/step_length.py |
Weinberg / forward 系の歩幅推定 |
pdr/heading.py |
ジャイロ・加速度・水平加速度からのステップ方位候補推定 |
pdr/sidestep.py |
横歩き判定、クラスタ平滑化、軌跡用方位の安定化 |
pdr/trajectory.py |
決定論的 PDR 軌跡生成と prepare_pdr_steps() |
pdr/outputs.py |
CSV 出力用 DataFrame 生成 |
pdr/plotting.py |
通常 PDR の軌跡描画 |
pdr/pipeline.py |
run() の実行 orchestration |
pdr/particle_api.py |
particle filter が利用する PDR API の bridge |
src/rikka/analyze/particle_filter.py は、prepare_pdr_steps() で作った
決定論的なステップ方位・歩幅・時刻を受け取り、フロアマップ制約で軌跡を補正します。
PDR の内部 helper を直接参照せず、pdr/particle_api.py 経由で必要な API だけを使います。
import pandas as pd
from rikka.analyze.pdr import run
df_acc = pd.DataFrame(...) # 列: t, x, y, z
df_gyro = pd.DataFrame(...) # 列: t, x, y, z
trajectory = run(df_acc=df_acc, df_gyro=df_gyro)df_acc と df_gyro は両方渡すか、両方省略してください。片方だけ渡すと
ValueError になります。
グラフを表示しない場合:
trajectory = run(df_acc=df_acc, df_gyro=df_gyro, plot=False)パーティクルフィルタを使う場合:
trajectory = run(
df_acc=df_acc,
df_gyro=df_gyro,
use_particle_filter=True,
)UV_CACHE_DIR=.uv-cache uv run ruff format
UV_CACHE_DIR=.uv-cache uv run ruff check
UV_CACHE_DIR=.uv-cache uv run mypy src/
UV_CACHE_DIR=.uv-cache uv run pytest
UV_CACHE_DIR=.uv-cache uv buildCI と同等の pre-commit チェック:
UV_CACHE_DIR=.uv-cache uv run pre-commit run --all-filesリポジトリ管理の Git hook を使う場合:
git config core.hooksPath .githooksfrom rikka import ping
print(ping()) # Hello, rikka
