feat: FFI for Rust modules#2351
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Greptile SummaryThis 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 (
Confidence Score: 4/5Merge 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
Sequence DiagramsequenceDiagram
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
Reviews (5): Last reviewed commit: "Add tests" | Re-trigger Greptile |
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
Run tests on imported FFI
Contributor License Agreement