dimos map tooling, stream alignment#2306
Merged
Merged
Conversation
Replaces the monolithic pgo_then_voxels with four primitives over mem2 Streams and Transforms: pgo_keyframes(lidar) -> Stream[Keyframe] keyframes_to_corrections(kfs) -> Stream[Transform] (world_corrected <- world_raw) make_interpolator(corrections) -> (ts) -> Transform (SLERP + linear, endpoint-clipped) apply_corrections(stream, corr) -> Stream[T] (shuffles obs.pose) Drift correction is now a first-class, reusable Stream[Transform] that any pose-stamped consumer can apply — same math as before (rigid T_corr = T_global @ T_local^-1 per keyframe, SLERP + linear interpolation between bracketing keyframes), just composable. dimos map --pgo migrates to the new primitives; pgo_then_voxels is deleted. The internal _SimplePGO / PGOConfig / _KeyPose machinery stays in pgo.py and is imported by pgo2.
Renames: pgo.py -> pgo_internals.py (gtsam/ICP machinery) pgo2.py -> pgo.py (public Stream-shaped API) `dimos.mapping.relocalization.pgo` is now the canonical import path (`pgo_keyframes`, `keyframes_to_corrections`, `make_interpolator`, `apply_corrections`, `correction_at`, `Keyframe`). The internal _SimplePGO / PGOConfig / _KeyPose / _icp / _voxel_downsample helpers live in pgo_internals.py and are imported lazily inside pgo.py to keep gtsam off the public-API import path.
Adds test_pgo.py covering pose normalization on Observation, the Transform↔Pose3 conversion helpers, the interpolator edge cases, apply_corrections behavior, and a real-recording smoke test (skipped when data/go2_short.db is absent). Annotates the two map.py helpers so they pass mypy. Removes leftover section divider comments to satisfy the no-section-markers project rule.
The colors-copy block in `PointCloud2.transform` calls `self.pointcloud` to check `has_colors()`, which forces a tensor->legacy conversion on every invocation. With `pgo --full-pgo` rebuilding from hundreds of lidar frames, that hidden allocation dominates the per-frame cost. The colors path was lidar-irrelevant (lidar clouds have no colors anyway) and the feature it was meant to support never landed; remove it so transform() stays a clean numpy round-trip.
…s into feat/ivan/pgo_rewrite
leshy
added a commit
that referenced
this pull request
Jun 1, 2026
Add from_time/to_time (relative to the first observation) and from_timestamp/to_timestamp (absolute epoch seconds) for windowing a stream by time. A trailing to_time is a duration measured from the current start, so from_time(2).to_time(30) reads as "skip 2s, take the following 30s"; frames mix freely (from_timestamp(ts).to_time(30)). Shared base for the stream-alignment (#2306) and go2dds (#2314) branches, which both need this windowing API.
Pulls the stairs dataset LFS pointer from feat/ivan/go2stairs so the map tooling can use it; object already on remote LFS store.
…nment # Conflicts: # dimos/memory2/stream.py # dimos/memory2/test_stream.py
Closed
The self-hosted CI image's published :dev tag is stale (predates libturbojpeg0-dev in docker/python/Dockerfile), so TurboJPEG() raises at runtime and the four verbs that decode the color_image stream fail. Guard them with skipif so they skip on a lib-less image and still run where the native lib is present.
- dimos map global / replay: new --bottom-cutoff option, threaded to PointCloud2.to_rerun(bottom_cutoff=) for global/accumulated maps only (raw lidar frames untouched); e.g. --bottom-cutoff 0 strips the floor. - rename/summary/replay/replay-marker: usage docs now reference the `dimos map <verb>` commands instead of `python -m ...cli.<mod>`. - observation: drop redundant explicit _data_lock=Lock() in with_pose/tag/ derive; __init__ creates a fresh per-instance lock when None.
The entry point is `dimos map <verb>` (self-documented via --help); don't document running the modules directly. summary.py keeps its rewritten usage line per reviewer suggestion.
Both copied the source's _data_lock through the fields() dict while setting _loader=lambda: self.data. Accessing the derived obs while the source was still unloaded re-entered the same non-reentrant lock on one thread → deadlock. Caught by test_attaches_pose_and_keeps_payload_lazy. Regression from 07f4e4a, which dropped the explicit _data_lock=threading.Lock() from both methods.
paul-nechifor
previously approved these changes
Jun 3, 2026
…nment # Conflicts: # dimos/mapping/utils/cli/map.py # dimos/memory2/store/base.py # dimos/memory2/stream.py # dimos/memory2/test_stream.py
paul-nechifor
approved these changes
Jun 3, 2026
Open
bogwi
added a commit
that referenced
this pull request
Jun 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dimos maputilities for dataset collection teamyou can ignore those, they are temporary,
changing pose source for observation stream, rendering global map, loop closures etc. lots of tooling (temporary and will change a lot)
dataset validation instructions document
stream alignment
a very simple stream.align tool - this needs much more work. multi stream input and output, interpolation of poses/transforms etc