Skip to main content

Geomagnetic + IMU fusion experiments with PF/DDTW on UJIIndoorLoc-Mag.

Project description

Lego-like Geomagnetic Positioning

Python License

First of All

This is the package I am using for testing my own geomagnetic positioning project using Particle filter, and I am trying to make the project more lego-like such as pytorch , and you can see some of the characteristics are from pytorch, actually. I am going to make this a acedemic-directed tool, everyone who come up with an idea of, whatever the filter problem is, can immediately turn on the mac, quickly have a simulation, and feel free to build anything you like. World of Machine Learning can do it, I hope we will do it.

Although the algorithm I've written in the main.py is still dumb and I am still seeking the reason why it is performing below my expectation, however, like someone said on Youtube, I am the guy interested in building shovels, and I hope there will be more contributers can participate in it.

The project per se is just in testing right now, with so many functional issues yet to be finished, but I hope this project, conversely, will never be an end, with firm cooperation of the intelligence of the community. A project with continuous maintainence and contributers is a healthy project.

For anyone who is interested, email kudoumakoto6523@gmail.com (same as the github account).

Below are the content.

Lego-style geomagnetic indoor positioning for fast academic prototyping.

This repository is a testing package for geomagnetic positioning with particle filtering, IMU-based PDR, and DDTW-oriented magnetic matching. The current algorithm in main.py is still experimental and its performance is not yet where I want it to be, but the goal of the project is already clear:

  • make geomagnetic positioning experiments easy to assemble
  • expose reusable building blocks instead of one hard-coded pipeline
  • let researchers quickly try a new filter idea, run a simulation, and inspect results

The project is closer to "building shovels" than claiming a finished localization system. If PyTorch can give machine learning researchers a flexible toolbox, this project aims to do something similar for geomagnetic and filter-oriented indoor positioning research.

Status

This project is under active restructuring.

  • The package layout is already modular and usable for experiments.
  • The particle-filter pipeline is configurable and reorderable.
  • UJI map building and visualization are implemented.
  • Some algorithm hooks are still placeholders or baseline implementations.
  • End-to-end accuracy is still being improved.

If you are interested in contributing ideas, code, experiments, or criticism, contributions are welcome.

What The Repository Currently Covers

The current pipeline combines:

  • IMU-based PDR for step and heading estimation
  • geomagnetic matching
  • particle filtering with DDTW-oriented weighting design
  • UJIIndoorLoc-Mag map building
  • direct user-defined magnetic map input

Installation

Python >= 3.11 is required.

python -m venv .venv
source .venv/bin/activate
pip install -e .

Current package dependencies from pyproject.toml:

  • numpy
  • pykrige
  • matplotlib

Quick Start

Run the default experiment:

python main.py

Test UJI map building plus user-map visualization:

python main_get_map_temp.py

Plot true route overlays:

python main_get_true_route.py

Inspect sensor streams and visualization outputs:

python main_get_sensor_and_len.py

Design Goal: Lego-Style Pipeline

The package is intentionally structured in a PyTorch-like style. Instead of forcing one giant script, it separates:

  • orchestration
  • state models
  • block registries
  • configurable PDR modules
  • configurable PF modules

The default flow is:

Initializer -> RunContext -> Experiment -> GeomagPipeline

Basic example:

from Geomag import Experiment, Initializer, PDRConfig, PFConfig

ctx = Initializer(
    num_runs=1,
    window_size=400,
    route_source="uji",
    sensor_source="uji",
    uji_test_file="tt01.txt",
).create_context()

pdr = PDRConfig(
    step_judge="peak_dynamic",
    step_judge_params={"peak_sigma": 0.40, "peak_prominence": 0.16},
    step_length="weinberg",
    step_length_params={"weinberg_k": 0.45},
    heading="gyro",
    heading_params={"dt": 0.02},
    mag="norm_mean",
)

pf = PFConfig(
    state_params={"num_particles": 500, "min_particles": 120, "max_particles": 5000},
    motion="gaussian",
    motion_params={"heading_noise_std": 0.10, "step_noise_std": 0.20},
    weight="ddtw",
    weight_params={"sigma": 6.0, "max_hist": 80},
    particle_size="kld",
    particle_size_params={"epsilon": 0.10},
    resample_trigger="ess_or_target",
    resample_trigger_params={"ess_ratio_threshold": 0.45},
    resample="cso",
)

result = Experiment(ctx, pdr_config=pdr, pf_config=pf).run(show=True)

Reordering The Particle Filter

The PF side is built from composable stages, so you can rearrange them when needed.

from Geomag import (
    ParticleSizeStage,
    PredictStage,
    ResampleDecisionStage,
    ResampleStage,
    UpdateStage,
    build_pf_sequential,
)

pf = build_pf_sequential(
    ("predict", PredictStage(motion="gaussian")),
    ("particle_size", ParticleSizeStage(particle_size="kld")),
    ("update", UpdateStage(weight="ddtw")),
    ("resample_decision", ResampleDecisionStage(trigger="ess_or_target")),
    ("resample", ResampleStage(resample="cso")),
)

You can inspect the registered blocks at runtime:

from Geomag import Experiment, GeomagPipeline

print(GeomagPipeline.available_blocks())
print(Experiment.describe_api())

Current block families include:

  • step_judge: autocorr, frequency_fft, peak_dynamic, peak_fixed, valley_peak, zero_crossing
  • step_length: fixed, weinberg
  • heading: gyro, q_fused, tilt_compass
  • mag: norm_last, norm_mean
  • motion: gaussian
  • weight: ddtw
  • particle_size: kld
  • resample_trigger: always, ess_or_target
  • resample: cso

Map API

Geomag/algorithms.py exposes the public map entrypoint:

from Geomag.algorithms import get_map

Two branches are currently supported:

  • source="uji": build a continuous map from UJIIndoorLoc-Mag
  • source="own": use a user-defined magnetic map, with direct matrix input preferred

UJI Branch

from Geomag.algorithms import get_map

uji_map = get_map(source="uji")
print(uji_map)

Behavior:

  • downloads the UJI zip if missing
  • extracts the dataset if missing
  • parses lines/ and curves/
  • reconstructs sample positions
  • fits an Ordinary Kriging model
  • writes processed artifacts
  • returns a metadata dictionary

Configuration lives in pyproject.toml under [tool.map_builder].

Relevant keys:

  • preview_resolution
  • max_kriging_points
  • seed
  • variogram_model
  • output_model_npz
  • output_preview_npz
  • output_json
  • output_png

Typical returned fields include:

  • source
  • continuous_map
  • output_model_npz
  • output_preview_npz
  • output_json
  • output_png
  • zip_path
  • extract_dir

Own Branch

Preferred input is a directly editable 2D matrix:

from Geomag.algorithms import get_map

own_map = get_map(
    source="own",
    own_grid_array=[
        [45.10, 45.22, 45.31],
        [44.97, 45.05, 45.27],
        [44.83, 44.96, 45.14],
    ],
    own_grid_meta={
        "cell_size_m": 0.5,
        "origin_xy_m": [0.0, 0.0],
        "variogram_model": "spherical",
    },
)
print(own_map)

Important metadata:

  • cell_size_m: distance between neighboring cells in meters
  • origin_xy_m: physical origin for mapping matrix indices to world coordinates
  • optional variogram_model: interpolation choice for visualization

Matrix convention:

  • matrix[row][col] stores magnetic magnitude
  • x = origin_x + col * cell_size
  • y = origin_y + row * cell_size

Visualization

Use visualize(...) with mode selection:

from Geomag.algorithms import visualize

UJI map preview:

visualize(geomag_map=uji_map, mode="ujimap")

User map preview:

visualize(geomag_map=own_map, mode="usermap")

The visualization API also supports route and sensor overlays, as shown in:

Repository Layout

Notes

  • If pykrige is missing, continuous interpolation will fail with an explicit installation message.
  • If matplotlib is missing, visualization will fail with an explicit installation message.
  • The initializer tries to build the UJI map first and can fall back to existing processed artifacts if rebuilding is unavailable.
  • The first get_map(source="uji") call may download the dataset automatically.

Roadmap

Near-term goals:

  • improve particle-filter performance and diagnostics
  • replace baseline or placeholder parts with stronger research-grade implementations
  • make more blocks plug-and-play
  • add more examples, tests, and benchmark scripts
  • make the package easier for outside contributors to extend

Contributing

This project is meant to keep evolving. If you have:

  • a new filter idea
  • a better weighting method
  • a stronger step detector
  • a new dataset adapter
  • a cleaner interface design

then this repository is intended to be a place where that idea can be tested quickly.

Pull requests, issue reports, design suggestions, and academic collaboration are all welcome.

Contact

For collaboration or questions, email:

kudoumakoto6523@gmail.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lego_like_positioning-0.1.1.tar.gz (31.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lego_like_positioning-0.1.1-py3-none-any.whl (34.7 kB view details)

Uploaded Python 3

File details

Details for the file lego_like_positioning-0.1.1.tar.gz.

File metadata

  • Download URL: lego_like_positioning-0.1.1.tar.gz
  • Upload date:
  • Size: 31.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.6

File hashes

Hashes for lego_like_positioning-0.1.1.tar.gz
Algorithm Hash digest
SHA256 5b6a0026ab7449634ae6c28faffe4a7eb5db8f0d5bc76c6d42acc9248515d3d5
MD5 893df8dc2a1d98d23bf4090da3a7bdc5
BLAKE2b-256 72769825d5996b04cfc2c2086f633ff9e7d2d3ebe02da44b830a120506055441

See more details on using hashes here.

File details

Details for the file lego_like_positioning-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for lego_like_positioning-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e55403755c6ab7918e5fdd6c59c5de33a237fac01739b44afa8aae5ffb5f98dd
MD5 2d15ebb6cee4d1066e3e09b199cb8e44
BLAKE2b-256 2f4627094e800a4017cb95daeb504c97a81afb9c2cd434e07118285b134d3fef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page