PyTerrainMap
Spatial intelligence platform for multi-robot terrain mapping — an append-only, H3-indexed observation store with temporal decay, a real HTTP/HTTPS API server, and terrain-intelligence helpers, built on a Rust core with PyO3 bindings.
What it is
PyTerrainMap is an append-only observation store for multi-robot terrain data (TerrainMap), indexed spatially on an H3 hexagonal grid and temporally with confidence that decays with age. It exposes spatial + temporal querying, a real HTTP/HTTPS server you can start from Python (start_server(...)), and terrain-intelligence helpers (analyze_terrain(), assess_mobility(), is_accessible(), explain_field()). The core is Rust; the Python bindings are built with PyO3/maturin. Observations can be added and queried but never deleted or overwritten through the normal API.
Features
- Append-only, H3-indexed store — observations keyed by
(H3Cell, ElevationBucket)with exponential/linear confidence decay. - Real HTTP/HTTPS API server —
pyterrain_map.start_server(host, port, tls=...); tested end-to-end in Rust and Python (including a TLS handshake). Endpoints includeGET /health,GET /stats,POST /observations,POST /query/spatial. - Terrain intelligence —
analyze_terrain()queries real elevation (Open-Meteo / Copernicus DEM GLO-90) at the center and four cardinal points and derives a real measured slope;assess_mobility()scales difficulty, speed, and traversability per robot type (drone / wheeled / quadruped / humanoid). - Traversability knowledge graph — implemented and tested.
- 3D reconstruction — SLAM (loop closure, bag-of-words), real multi-view photogrammetry geometry, and Cesium 3D Tiles export (Rust core; see status for exposure).
- Gaussian-splatting probabilistic mapping — fusion and storage work; frontier scoring and semantic classification are partial.
- Persistent storage — PostgreSQL is real end-to-end from Python (
TerrainMap.with_postgres(...),push_observation/push_batchwrite-through,restore_from_backend()). - CLI —
pytm(setup,configure,version,query) andpytm-setup.
Who it's for / Use cases
- Fusing terrain observations from multiple robots into one spatially and temporally queryable index with age-decayed confidence.
- Standing up an HTTP API over the store for other services to query without building a server layer.
- Robot-specific mobility assessment — decide whether a drone/wheeled/quadruped/humanoid platform can traverse an area, from real slope data.
- 3D Tiles export for SLAM/photogrammetry output.
- Persistence from Python — write-through and restore-on-startup against PostgreSQL.
What it is not
- Not a full camera-to-map SLAM pipeline. Photogrammetry requires caller-supplied 2D keypoint detections (imaging is deliberately Python-side) and is Rust-level only today, not exposed via the Python API.
- Not fully offline.
analyze_terrain()makes a real network call to a public elevation API and raises an error (rather than fabricating data) if it cannot reach it. - Not all storage backends are live. SQLite and BigQuery are config/schema types with no live connection; only PostgreSQL is real end-to-end.
- Gaussian-splatting mapping is partially implemented — frontier "strategic value" scoring and semantic terrain classification are placeholder, and splat temporal decay is a no-op.
- Not a hosted service and not ML-based object classification.
Project status
Alpha (Development Status 3), version 1.10.1. The append-only store, H3/temporal indexing, HTTP/HTTPS server, PostgreSQL persistence, and terrain-slope intelligence are implemented and tested. The Rust core is now cargo clippy --release -- -D warnings clean (0 warnings) and cargo test passes except for one documented, pre-existing failing test (exploration::gaussian_frontier_integration::tests::test_score_frontier_with_high_uncertainty); the remaining dead-code fields have been wired into real behavior (temporal decay application, cache update policy, scheduler temporal-correction queue, fleet conflict resolution, predictive-caching learning rates, Postgres table name, federated query accessors). Prebuilt wheels are published for macOS arm64 only; other platforms build from the source distribution with a Rust toolchain. See docs/DATA_INTEGRITY.md and docs/ for details.
Installation
pip install pyterrainMap
# or with uv
uv pip install pyterrainMap
python -c "import pyterrain_map; print(pyterrain_map.__version__)"
Requires Python 3.10+. Prebuilt wheels are macOS arm64 only; on other platforms build from source:
git clone https://github.com/Mullassery/PyTerrainMap.git
cd PyTerrainMap
pip install maturin
maturin develop --release
Quick start
import json, time
from pyterrain_map import TerrainMap, Observation, GeoPoint, analyze_terrain, assess_mobility
terrain = TerrainMap() # in-memory, append-only
terrain.push_observation(Observation(
robot_id="robot-1", timestamp=int(time.time()),
lat=40.7128, lon=-74.0060, sensor_type="thermal",
value_json=json.dumps({"celsius": 22.5}), confidence=0.95,
))
result = terrain.query(GeoPoint(40.7128, -74.0060), region_radius_km=1.0, time_window_seconds=3600)
print(f"Found {result.count} observations, avg confidence {result.avg_confidence:.1%}")
terrain_info = analyze_terrain(40.7128, -74.0060, radius_km=1.0)
for robot_type in ("drone", "wheeled", "quadruped", "humanoid"):
mobility = assess_mobility(terrain_info, robot_type)
print(robot_type, mobility.traversable, mobility.difficulty_label())
Usage
Start the API server (plain HTTP in-process; tls=True uses a self-signed dev certificate):
from pyterrain_map import start_server
handle = start_server(host="127.0.0.1", port=8080)
# GET /health, GET /stats, POST /observations, POST /query/spatial ...
handle.stop()
curl -X POST http://127.0.0.1:8080/observations \
-H "Content-Type: application/json" \
-d '{"robot_id":"robot-1","timestamp":1700000000000000,"latitude":40.7128,"longitude":-74.0060,"sensor_type":"thermal","sensor_value":{"celsius":22.5},"confidence":0.9,"metadata":{}}'
curl http://127.0.0.1:8080/stats
pytm setup # interactive configuration wizard
pytm query --lat 40.1 --lon -74.5 --radius-km 0.5 --json
PostgreSQL persistence from Python:
terrain = TerrainMap.with_postgres("postgres://user:pass@localhost/terrain", pool_size=5)
terrain.restore_from_backend()
Documentation
- docs/PYTHON_BINDINGS.md — Python API reference
- docs/ARCHITECTURE.md — architecture overview
- docs/DATA_INTEGRITY.md — append-only guarantees
- docs/TEMPORAL_NORMALIZATION.md — temporal decay and clock handling
- docs/ROS_BRIDGE_ARCHITECTURE.md — ROS integration design
- docs/ — full documentation index
- python/examples/01_quick_start.py — runnable quick start
- CHANGELOG.md — notable changes
Contributing
See CONTRIBUTING.md. Bug reports: GitHub Issues. Support: mullassery@gmail.com.
Decentralized fleet sync with SyncFleet (planned integration)
PyTerrainMap pairs with SyncFleet, a secure, local-first, peer-to-peer SQLite synchronization engine. The intended design gives a multi-robot edge swarm an out-of-the-box decentralized map-sharing protocol: each robot accumulates terrain observations in its local PyTerrainMap store, and SyncFleet replicates the selected observation table to authorized peers over mutual-TLS 1.3 — with no cloud round-trip or broker, so it keeps working across intermittent or air-gapped links.
Why they fit together
- Observations are append-only, so cross-robot inserts never conflict — the case SyncFleet's single-writer default handles cleanly, without needing CRDTs.
- The observation table maps to a SyncFleet dataset (table allowlist), and
each observation UUID becomes an operation
entity_id. - Both are Rust + Tokio + rustls / TLS 1.3 with an edge, local-first focus.
- SyncFleet supplies mutual-TLS transport, peer enrollment, and per-dataset ACLs for the replication channel.
Status: not wired up yet. This is a design goal, not a current capability. Before it works, SyncFleet must (1) materialize replicated operations into the allowlisted table (today it only replicates its journal), (2) share a live storage substrate (SyncFleet is SQLite; PyTerrainMap's live backend is PostgreSQL), and (3) capture PyTerrainMap writes as SyncFleet operations via an outbox/CDC bridge. Until then, treat the two as independent, complementary tools.
Part of the robotics & autonomy family
PyTerrainMap is one of six complementary, composable tools in the Mullassery robotics & autonomy family. Together they form a single stack: perceive → map → simulate → learn → debug → coordinate the fleet.
| Tool | Role | What it does |
|---|---|---|
| PyRoboVision | Perception | Multi-object tracker (Kalman filter + Hungarian algorithm) and trajectory predictor for robot perception. |
| PyTerrainMap | Mapping / SLAM | This project — fuses multi-robot terrain observations into a spatial-temporal store, with H3 spatial indexing and SLAM. |
| PyRoboSimulator | Simulation | World simulator for autonomous systems, with a FastAPI backend. |
| PyRoboFrames | Learning data | Rust-backed ML dataloader for robot-learning datasets (native LeRobot format, Apple Silicon hardware video decode). |
| PyRoboReplay | Mission forensics | Forensic-debugging and causal-analysis engine for autonomous robot mission replay. |
| SyncFleet | Fleet coordination | Rust + SQLite, peer-to-peer state sync for robotics fleets — mutual-TLS 1.3, version-vector replication, mDNS discovery; conflict resolution on the roadmap. |
Each works standalone, but they're complementary by design. The planned integration with SyncFleet (detailed below) will allow terrain maps to sync across fleets without relying on a central database.
License
Apache License 2.0 — see LICENSE.
Metadata
Release files for pyterrainMap 1.10.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 | Provenance | Actions |
|---|---|---|---|---|
| pyterrainmap-1.10.1.tar.gz | 653.1 kB | Without provenance | Details for pyterrainmap-1.10.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pyterrainmap-1.10.1-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details for pyterrainmap-1.10.1-cp310-abi3-macosx_11_0_arm64.whl |
Total release size: 3.2 MB
Release files / pyterrainmap-1.10.1.tar.gz
| Download URL | pyterrainmap-1.10.1.tar.gz |
|---|---|
| Size | 653.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e492c62c7a7ac7034c2a512798ca699ac5a6700cec14d6c0aedebc141ea909dc
|
|
BLAKE2b-256 checksum How to use checksums |
daa8713a094debdeeb5cc9f94bece261b100d0173c8d4f913d0f435d2f829b78
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / pyterrainmap-1.10.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | pyterrainmap-1.10.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
97724a8f27bc9d2b7b99d03aeec705be3369dbafc1dcd3a44543e5f2e496d033
|
|
BLAKE2b-256 checksum How to use checksums |
3e8ddf9f07630675d360d0dd29d5da227b9fd078c2f25716dee907aebdea6c75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Security for pyterrainMap 1.10.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.