Lego-like Geomagnetic Positioning
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:
numpypykrigematplotlib
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_crossingstep_length:fixed,weinbergheading:gyro,q_fused,tilt_compassmag:norm_last,norm_meanmotion:gaussianweight:ddtwparticle_size:kldresample_trigger:always,ess_or_targetresample: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-Magsource="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/andcurves/ - 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_resolutionmax_kriging_pointsseedvariogram_modeloutput_model_npzoutput_preview_npzoutput_jsonoutput_png
Typical returned fields include:
sourcecontinuous_mapoutput_model_npzoutput_preview_npzoutput_jsonoutput_pngzip_pathextract_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 metersorigin_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 magnitudex = origin_x + col * cell_sizey = 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
main.py: thin runtime entrypointGeomag/initiation.py: initialization orchestrationGeomag/experiment.py: experiment loop wrapperGeomag/pipeline.py: composable PDR and PF pipelineGeomag/models.py: shared state classes such asPFState,Particle, andRunContextGeomag/blocks.py: block interfaces and registriesGeomag/algorithms.py: map building, visualization, and algorithm implementations/placeholdersGeomag/nn.py: lightweightModuleandSequentialabstractionsGeomag/utils.py: helper utilities for sensor collection and map loading
Notes
- If
pykrigeis missing, continuous interpolation will fail with an explicit installation message. - If
matplotlibis 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
Metadata
Release files for lego-like-positioning 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lego_like_positioning-0.1.1.tar.gz | 31.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lego_like_positioning-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.3 kB
Release files / lego_like_positioning-0.1.1.tar.gz
| Download URL | lego_like_positioning-0.1.1.tar.gz |
|---|---|
| Size | 31.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b6a0026ab7449634ae6c28faffe4a7eb5db8f0d5bc76c6d42acc9248515d3d5
|
|
BLAKE2b-256 checksum How to use checksums |
72769825d5996b04cfc2c2086f633ff9e7d2d3ebe02da44b830a120506055441
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.6
|
Release files / lego_like_positioning-0.1.1-py3-none-any.whl
| Download URL | lego_like_positioning-0.1.1-py3-none-any.whl |
|---|---|
| Size | 34.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e55403755c6ab7918e5fdd6c59c5de33a237fac01739b44afa8aae5ffb5f98dd
|
|
BLAKE2b-256 checksum How to use checksums |
2f4627094e800a4017cb95daeb504c97a81afb9c2cd434e07118285b134d3fef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.6
|