Skip to main content

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.

CI PyPI License: Apache 2.0 Python 3.10+

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 include GET /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_batch write-through, restore_from_backend()).
  • CLI — pytm (setup, configure, version, query) and pytm-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

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.

Browse all projects →

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)

Source distribution for pyterrainMap 1.10.1
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)

Table of built distributions (wheels) for pyterrainMap 1.10.1
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page