Skip to content

Conversation

@JalajShuklaSS
Copy link

Summary

Adds @rpc generate_grasps(pointcloud, scene_pointcloud) -> PoseArray to ManipulationModule that lazily spins up a DockerModule(GraspGenModule) on first call, managing the full Docker lifecycle

How it works
ManipulationModule lazily creates and starts a GraspGen Docker container on first generate_grasps() call, to the point cloud to GraspGenModule via LCMRPC, and returns ranked grasp poses as PoseArray.

Changes
dimos/manipulation/manipulation_module.py

Closes #1130 DIM-390

Jalaj Shukla and others added 4 commits February 10, 2026 13:49
Adds a generate_grasps RPC method to ManipulationModule that lazily
starts a GraspGen Docker container (GPU) on first call and returns
ranked grasp poses (PoseArray) for a given point cloud.

- Config: graspgen_docker_image, gripper_type, num_grasps, topk
- _get_graspgen(): lazy DockerModule init with LFS checkpoint pull
- Cleanup in stop() to tear down Docker container
- GPU integration test with synthetic cube point cloud
Adds a generate_grasps RPC method to ManipulationModule that lazily
starts a GraspGen Docker container (GPU) on first call and returns
ranked grasp poses (PoseArray) for a given point cloud.

- Config: graspgen_docker_image, gripper_type, num_grasps, topk
- _get_graspgen(): lazy DockerModule init with LFS checkpoint pull
- Cleanup in stop() to tear down Docker container
@greptile-apps
Copy link

greptile-apps bot commented Feb 11, 2026

Greptile Overview

Greptile Summary

Adds GraspGen grasp generation capability to ManipulationModule via a new @rpc generate_grasps() method. The implementation lazily initializes a DockerModule(GraspGenModule) on first call and properly cleans it up in the stop() method.

Key Changes:

  • Added 8 configurable GraspGen parameters to ManipulationModuleConfig (gripper type, number of grasps, collision filtering, etc.)
  • Implemented lazy initialization pattern in _get_graspgen() that creates the Docker container only when needed
  • Added proper lifecycle management by stopping the Docker container in stop()
  • Updated unit tests to initialize _graspgen field

Issues Found:

  • Missing exception handling in _get_graspgen() - if Docker initialization or startup fails, the method returns None without logging the error
  • The generate_grasps() RPC method silently returns None when GraspGen is unavailable without informing callers why

Confidence Score: 3/5

  • Safe to merge with minor risk - missing error handling could cause silent failures
  • The implementation follows good patterns (lazy initialization, proper lifecycle management, test updates) but lacks exception handling in the critical _get_graspgen() method. Docker initialization failures will silently return None without logging errors, making debugging difficult.
  • Pay close attention to dimos/manipulation/manipulation_module.py - add error handling to _get_graspgen() method

Important Files Changed

Filename Overview
dimos/manipulation/manipulation_module.py Adds lazy-initialized GraspGen Docker integration with generate_grasps() RPC method. Missing exception handling in _get_graspgen() could cause silent failures.
dimos/manipulation/test_manipulation_unit.py Adds _graspgen initialization to test fixture - correctly maintains test isolation.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ManipulationModule
    participant DockerModule
    participant GraspGenModule
    
    Client->>ManipulationModule: generate_grasps(pointcloud, scene_pointcloud)
    ManipulationModule->>ManipulationModule: _get_graspgen()
    
    alt First call (lazy init)
        ManipulationModule->>ManipulationModule: get_data("models_graspgen")
        ManipulationModule->>DockerModule: new DockerModule(GraspGenModule, ...)
        ManipulationModule->>DockerModule: start()
        DockerModule-->>ManipulationModule: started
    else Subsequent calls
        Note over ManipulationModule: Return cached _graspgen
    end
    
    ManipulationModule->>GraspGenModule: generate_grasps(pointcloud, scene_pointcloud)
    GraspGenModule->>GraspGenModule: Run inference
    GraspGenModule-->>ManipulationModule: PoseArray
    ManipulationModule-->>Client: PoseArray
    
    Client->>ManipulationModule: stop()
    ManipulationModule->>DockerModule: stop()
    DockerModule-->>ManipulationModule: stopped
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 614 to 646
def _get_graspgen(self) -> DockerModule | None:
"""Get or create GraspGen Docker module (lazy init)."""
if self._graspgen is not None:
return self._graspgen

from dimos.core.docker_runner import DockerModule
from dimos.manipulation.grasping.graspgen_module import GraspGenModule
from dimos.utils.data import get_data
from dimos.utils.path_utils import get_project_root

# Ensure GraspGen model checkpoints are pulled from LFS
get_data("models_graspgen")

project_root = get_project_root()
docker_file = (
project_root / "dimos" / "manipulation" / "grasping" / "docker_context" / "Dockerfile"
)
self._graspgen = DockerModule(
GraspGenModule,
docker_file=docker_file,
docker_build_context=project_root,
docker_image=self.config.graspgen_docker_image,
docker_env={"CI": "1"}, # skip interactive system config prompt in container
gripper_type=self.config.graspgen_gripper_type,
num_grasps=self.config.graspgen_num_grasps,
topk_num_grasps=self.config.graspgen_topk_num_grasps,
grasp_threshold=self.config.graspgen_grasp_threshold,
filter_collisions=self.config.graspgen_filter_collisions,
save_visualization_data=self.config.graspgen_save_visualization_data,
visualization_output_path=self.config.graspgen_visualization_output_path,
)
self._graspgen.start()
return self._graspgen
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling - if get_data(), get_project_root(), DockerModule(), or .start() raise exceptions, _graspgen remains None but no error is logged or raised.

Suggested change
def _get_graspgen(self) -> DockerModule | None:
"""Get or create GraspGen Docker module (lazy init)."""
if self._graspgen is not None:
return self._graspgen
from dimos.core.docker_runner import DockerModule
from dimos.manipulation.grasping.graspgen_module import GraspGenModule
from dimos.utils.data import get_data
from dimos.utils.path_utils import get_project_root
# Ensure GraspGen model checkpoints are pulled from LFS
get_data("models_graspgen")
project_root = get_project_root()
docker_file = (
project_root / "dimos" / "manipulation" / "grasping" / "docker_context" / "Dockerfile"
)
self._graspgen = DockerModule(
GraspGenModule,
docker_file=docker_file,
docker_build_context=project_root,
docker_image=self.config.graspgen_docker_image,
docker_env={"CI": "1"}, # skip interactive system config prompt in container
gripper_type=self.config.graspgen_gripper_type,
num_grasps=self.config.graspgen_num_grasps,
topk_num_grasps=self.config.graspgen_topk_num_grasps,
grasp_threshold=self.config.graspgen_grasp_threshold,
filter_collisions=self.config.graspgen_filter_collisions,
save_visualization_data=self.config.graspgen_save_visualization_data,
visualization_output_path=self.config.graspgen_visualization_output_path,
)
self._graspgen.start()
return self._graspgen
def _get_graspgen(self) -> DockerModule | None:
"""Get or create GraspGen Docker module (lazy init)."""
if self._graspgen is not None:
return self._graspgen
try:
from dimos.core.docker_runner import DockerModule
from dimos.manipulation.grasping.graspgen_module import GraspGenModule
from dimos.utils.data import get_data
from dimos.utils.path_utils import get_project_root
# Ensure GraspGen model checkpoints are pulled from LFS
get_data("models_graspgen")
project_root = get_project_root()
docker_file = (
project_root / "dimos" / "manipulation" / "grasping" / "docker_context" / "Dockerfile"
)
self._graspgen = DockerModule(
GraspGenModule,
docker_file=docker_file,
docker_build_context=project_root,
docker_image=self.config.graspgen_docker_image,
docker_env={"CI": "1"}, # skip interactive system config prompt in container
gripper_type=self.config.graspgen_gripper_type,
num_grasps=self.config.graspgen_num_grasps,
topk_num_grasps=self.config.graspgen_topk_num_grasps,
grasp_threshold=self.config.graspgen_grasp_threshold,
filter_collisions=self.config.graspgen_filter_collisions,
save_visualization_data=self.config.graspgen_save_visualization_data,
visualization_output_path=self.config.graspgen_visualization_output_path,
)
self._graspgen.start()
return self._graspgen
except Exception as e:
logger.error(f"Failed to initialize GraspGen Docker module: {e}")
return None

Comment on lines 648 to 657
@rpc
def generate_grasps(
self,
pointcloud: PointCloud2,
scene_pointcloud: PointCloud2 | None = None,
) -> PoseArray | None:
graspgen = self._get_graspgen()
if graspgen is None:
return None
return graspgen.generate_grasps(pointcloud, scene_pointcloud)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No error logging when _get_graspgen() returns None - the RPC call silently returns None without informing the caller why it failed

Suggested change
@rpc
def generate_grasps(
self,
pointcloud: PointCloud2,
scene_pointcloud: PointCloud2 | None = None,
) -> PoseArray | None:
graspgen = self._get_graspgen()
if graspgen is None:
return None
return graspgen.generate_grasps(pointcloud, scene_pointcloud)
@rpc
def generate_grasps(
self,
pointcloud: PointCloud2,
scene_pointcloud: PointCloud2 | None = None,
) -> PoseArray | None:
graspgen = self._get_graspgen()
if graspgen is None:
logger.error("GraspGen Docker module not available")
return None
return graspgen.generate_grasps(pointcloud, scene_pointcloud)

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.

Spec sheet for integration of graspgen and manipulation module with dimos for end to end grasping baseline version Integrate GraspGen

1 participant