Skip to content

feat: FFI for Rust modules#2351

Open
aclauer wants to merge 15 commits into
mainfrom
andrew/feat/rust-mapper-ffi
Open

feat: FFI for Rust modules#2351
aclauer wants to merge 15 commits into
mainfrom
andrew/feat/rust-mapper-ffi

Conversation

@aclauer
Copy link
Copy Markdown
Collaborator

@aclauer aclauer commented Jun 3, 2026

Problem

For testing and dev with mem2, it's easier to call core module functionality as functions instead of deploying a blueprint.

Closes DIM-974

Solution

Refactor the ray trace mapper and 3d planner to include Python Rust bindings. Now we can call the core functionality of each in Python.

How to Test

Build .so files for both

uv run maturin develop --uv --release -m dimos/mapping/ray_tracing/rust/Cargo.toml
uv run maturin develop --uv --release -m dimos/navigation/nav_3d/mls_planner/rust/Cargo.toml

Run tests on imported FFI

uv run pytest dimos/mapping/ray_tracing/test_voxel_map.py dimos/navigation/nav_3d/mls_planner/test_mls_planner.py

Contributor License Agreement

  • I have read and approved the CLA.

@aclauer aclauer linked an issue Jun 3, 2026 that may be closed by this pull request
@aclauer aclauer changed the title Andrew/feat/rust mapper ffi feat: FFI for Rust modules Jun 3, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

❌ Patch coverage is 6.25000% with 90 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../navigation/nav_3d/mls_planner/test_mls_planner.py 5.76% 49 Missing ⚠️
dimos/mapping/ray_tracing/test_voxel_map.py 6.81% 41 Missing ⚠️

📢 Thoughts on this report? Let us know!

@aclauer aclauer marked this pull request as ready for review June 3, 2026 21:24
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 3, 2026

Greptile Summary

This PR adds PyO3 Python bindings for two Rust modules — the voxel ray-tracing mapper and the MLS path planner — exposing them as importable Python classes (VoxelRayMapper, MLSPlanner) via thin wrapper modules and accompanying .pyi stubs.

  • The Rust core logic is refactored out of main.rs into voxel_ray_tracer.rs / mls_planner.rs libraries; main.rs now depends on those libraries as an rlib crate, and a new cdylib target is added to each Cargo.toml for the PyO3 extension.
  • pyproject.toml adds tomli as a conditional build-system dependency and maturin>=1.7 as a test extra; Python test files use pytest.importorskip to skip gracefully when the Rust extensions aren't compiled.

Confidence Score: 4/5

Merge with caution — the Python bindings lack input validation on coordinate tuples passed directly to the Rust core, allowing non-finite values to silently produce corrupted state or silently return empty results.

The Rust core logic and its extraction into shared library crates look correct and are well-tested. The PyO3 bindings correctly filter point-cloud rows for NaN/inf before passing them to the Rust core, but the coordinate tuples used as sensor origins and path endpoints bypass that same guard — a non-finite value passed there can corrupt the internal voxel map or produce a misleading empty reply without any error raised to the caller.

dimos/mapping/ray_tracing/rust/src/python.rs and dimos/navigation/nav_3d/mls_planner/rust/src/python.rs — specifically the origin/start/goal tuple parameters that reach the Rust core without finiteness checks.

Important Files Changed

Filename Overview
dimos/mapping/ray_tracing/rust/src/python.rs New PyO3 bindings for VoxelRayMapper; points are NaN-filtered but the origin tuple is forwarded to update_map unvalidated (flagged in prior review).
dimos/navigation/nav_3d/mls_planner/rust/src/python.rs New PyO3 bindings for MLSPlanner; points are NaN-filtered but start/goal are passed to planner.plan unvalidated (flagged in prior review).
dimos/mapping/ray_tracing/rust/src/voxel_ray_tracer.rs Core voxel map logic extracted from main.rs; DDA ray traversal, health-based miss/hit accounting, and shadow region logic are unchanged and well-tested.
dimos/navigation/nav_3d/mls_planner/rust/src/mls_planner.rs Config and Planner state extracted into their own file; update_global_map and plan delegates are clean with appropriate early returns.
pyproject.toml Adds tomli conditional dep and maturin test extra; the **/*.pyi glob in the setuptools exclude list will strip type stubs from installed wheels (flagged in prior review).
dimos/mapping/ray_tracing/test_voxel_map.py Good coverage: empty frame, shape rejection, NaN point filtering, cylinder filter, and clear are all tested with pytest.importorskip guard.
dimos/navigation/nav_3d/mls_planner/test_mls_planner.py Tests surface/node/edge construction, path planning on a flat floor, None returns for empty graph and unreachable goal, and clear semantics.

Sequence Diagram

sequenceDiagram
    participant Py as Python caller
    participant VM as voxel_map.py
    participant Rust_VR as dimos_voxel_ray_tracing (PyO3)
    participant Core_VR as voxel_ray_tracer.rs

    Py->>VM: import VoxelRayMapper
    VM->>Rust_VR: from dimos_voxel_ray_tracing import VoxelRayMapper
    Py->>Rust_VR: VoxelRayMapper(voxel_size, max_range, ...)
    Rust_VR->>Core_VR: Config::validate()
    Rust_VR-->>Py: VoxelRayMapper instance

    Py->>Rust_VR: add_frame(points_np, origin)
    Rust_VR->>Rust_VR: NaN-filter points rows
    Rust_VR->>Core_VR: update_map(map, origin, pts, cfg) [GIL released]
    Core_VR-->>Rust_VR: updated VoxelMap
    Rust_VR-->>Py: None

    Py->>Rust_VR: global_map()
    Rust_VR->>Core_VR: iter_global_points(map, voxel_size) [GIL released]
    Core_VR-->>Rust_VR: Vec float32
    Rust_VR-->>Py: NDArray float32 (M, 3)

    participant MP as mls_planner.py
    participant Rust_MLS as dimos_mls_planner (PyO3)
    participant Core_MLS as mls_planner.rs + planner.rs

    Py->>MP: import MLSPlanner
    MP->>Rust_MLS: from dimos_mls_planner import MLSPlanner
    Py->>Rust_MLS: MLSPlanner(voxel_size, robot_height, ...)
    Rust_MLS->>Core_MLS: Config::validate()
    Rust_MLS-->>Py: MLSPlanner instance

    Py->>Rust_MLS: update_global_map(points_np)
    Rust_MLS->>Rust_MLS: NaN-filter points
    Rust_MLS->>Core_MLS: planner.update_global_map(pts, config) [GIL released]
    Core_MLS-->>Rust_MLS: graph rebuilt

    Py->>Rust_MLS: plan(start, goal)
    Rust_MLS->>Core_MLS: planner.plan(start, goal, config) [GIL released]
    Core_MLS->>Core_MLS: snap_pose_to_cell + Dijkstra
    Core_MLS-->>Rust_MLS: Option Vec waypoints
    Rust_MLS-->>Py: NDArray float32 (W, 3) or None
Loading

Reviews (5): Last reviewed commit: "Add tests" | Re-trigger Greptile

Comment thread setup.py
Comment thread setup.py Outdated
Comment thread pyproject.toml
Comment thread dimos/mapping/ray_tracing/rust/src/python.rs
Comment thread dimos/navigation/nav_3d/mls_planner/rust/src/python.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rust FFI

1 participant