GraspGen: A Diffusion-based Framework for 6-DOF Grasping

repository·main·Indexed 19 days ago

https://github.com/nvlabs/graspgen

A modular, diffusion-based framework for generating 6-DOF robotic grasps in cluttered environments. It supports multiple gripper types (e.g., Franka Panda, Robotiq 2F-140, single suction cup) and varying point cloud observability. GraspGen can be deployed as a ZMQ server for real-time inference via a Python API or integrated with LLMs through a Model Context Protocol (MCP) server.

Tokens
16K
Snippets
53
Records
69
Agent score
68%

What's inside GraspGen

  1. Overview of GraspGen capabilities

    main

    GraspGen is a modular framework for diffusion-based 6-DOF robotic grasp generation. It is designed to scale across:

    • Embodiments: Supports 3 gripper types (Franka-Panda, Robotiq-2f-140, and suction cup).
    • Observability: Robust to both partial and complete 3D point clouds.
    • Complexity: Handles both single-object grasping and cluttered scenes.

    Note on Grippers: This repository specifically supports the three grippers mentioned above. For other grippers (e.g., DROID, robotiq-2f-85), use the GraspGen-X extension.

  2. How the GraspGen MCP Server works

    main

    The GraspGen MCP Server acts as a lightweight bridge between LLMs (like Claude or Cursor) and the GraspGen inference engine. It does not require CUDA or model weights itself; instead, it connects to a running GraspGen ZMQ inference server via TCP.

    Architecture Flow:

    1. LLM/AI Agent calls tools via MCP (stdio).
    2. MCP Server receives the call and forwards requests to the GraspGen Server via ZMQ (tcp).
    3. GraspGen Server (running on GPU with model loaded) processes the point cloud and returns grasps to the MCP server, which then returns them to the LLM.
  3. GraspGen Dataset Format Requirements

    main

    GraspGen requires a dataset organized into two main components: Splits and a Grasp Dataset.

    1. Splits

    Objects must be divided into training and validation/test sets using *.txt files. Each line in these files should contain either:

    • A uuid (if using Objaverse).
    • A relative path to the object mesh file (.obj or .stl), relative to the root of the object dataset.

    If an object is used for both training and testing, it must be included in both text files.

    2. Grasp Dataset

    Grasp data must be stored in a separate directory containing *.json files. Each JSON file represents the grasp data for a specific object.

  4. How the GraspGen Standalone Server works

    main

    GraspGen can be deployed as a standalone ZMQ server. This allows any application (Python, C++, Rust, etc.) to request 6-DOF grasp predictions over a network without needing a GPU or CUDA installed on the client machine.

    Architecture:

    • Server: Loads a specific gripper model (e.g., Franka Panda, Robotiq 2F-140) and listens on a ZMQ REP socket. It handles the GPU-intensive inference.
    • Client: Sends point clouds (as numpy arrays serialized with msgpack) to the server and receives back 6-DOF grasp poses and confidence scores.
    • Communication: Uses ZMQ (TCP) with msgpack serialization.
  5. Retargeting the model for similar grippers

    main

    If your gripper is similar to an existing one, you may be able to retarget the model instead of full re-training:

    Antipodal Grippers (e.g., Franka/Robotiq): If the stroke length/width is similar, you can apply a Z-axis offset to align the base link frames:

    import trimesh.transformations as tra
    new_grasp = grasp @ tra.translation_matrix([0, 0, -Z_OFFSET])

    Suction Grippers: If using a single-cup suction gripper, you can retarget the 30mm suction model by rescaling the object point cloud/mesh input:

    import trimesh.transformations as tra
    mat = tra.scale_matrix(r / 0.030)  # where r is your suction cup radius
    import trimesh.transformations as tra
    # For antipodal offset
    new_grasp = grasp @ tra.translation_matrix([0, 0, -Z_OFFSET])
    
    # For suction rescaling
    mat = tra.scale_matrix(r / 0.030)
  6. Generate a dataset for a single object

    main

    Use the generate_dataset_suction_single_object.py script to create a dataset for a single object using a suction cup gripper. This script generates both an object dataset and a grasp dataset following the GraspGen Dataset Format.

    Parameters:

    • --object_path: Path to your object mesh file (required).
    • --output_dir: Directory to save datasets (default: /results/tutorial).
    • --num_grasps: Total number of grasps to generate (default: 2000).
    • --object_scale: Scale factor for the object (default: 1.0).
    • --gripper_config: Gripper configuration file (default: single_suction_cup_30mm.yaml).
    • --num_disturbances: Number of disturbance samples for evaluation (default: 10).
    • --no_visualization: Disable visualization.
    cd /code && python tutorials/generate_dataset_suction_single_object.py \
        --object_path /models/sample_data/meshes/box.obj \
        --object_scale 1.0 \
        --output_dir /results/tutorial \
        --no_visualization
  7. Visualize grasp predictions

    main

    Visualize grasp predictions from your trained model on an object mesh using an interactive 3D visualization.

    Parameters:

    • --mesh_file: Path to the object mesh file.
    • --mesh_scale: Scale factor for the object mesh (default: 1.0).
    • --gripper_config: Path to the config file created in the checkpoint generation step (e.g., /results/tutorial/models/tutorial_model_config.yaml).

    Visualization Features:

    • Interactive 3D view of the object mesh.
    • Generated grasp poses overlaid on the object.
    • Color-coded grasp quality scores.
    • Highlighting of the best grasps.
    cd /code && python scripts/demo_object_mesh.py \
        --mesh_file /models/sample_data/meshes/box.obj \
        --mesh_scale 1.0 \
        --gripper_config /results/tutorial/models/tutorial_model_config.yaml
  8. Install and run GraspGen without Docker

    main

    If you prefer not to use Docker, you must manually manage the CUDA environment and dependencies.

    1. Start the Server

    Ensure you have an environment with CUDA and all GraspGen dependencies installed (e.g., via Conda):

    conda activate GraspGen
    # or source .venv/bin/activate
    
    # Install serving dependencies
    pip install pyzmq msgpack msgpack-numpy
    
    # Start the server
    python client-server/graspgen_server.py \
        --gripper_config /path/to/GraspGenModels/checkpoints/graspgen_robotiq_2f_140.yml \
        --port 5556

    2. Run the Client

    Follow the same uv setup steps as the Docker instructions to create a lightweight client environment without CUDA requirements.

    # Start the server:
    python client-server/graspgen_server.py \
        --gripper_config /path/to/GraspGenModels/checkpoints/graspgen_robotiq_2f_140.yml \
        --port 5556
  9. Create a simulation USD for Isaac Sim (Play-to-Grasp)

    main

    You can generate a simulation-ready USD file containing multiple environments (up to 10) where each environment has an object and a gripper at a predicted grasp pose. When played in Isaac Sim, the grippers will automatically close on the object.

    Workflow:

    1. Run inference to get a YAML of grasps (limit to 10 for the sim USD).
    2. Build the sim USD using scripts/create_grasp_sim_usd.py.
    3. Run in Isaac Sim: Open the USD, press Play, and run scripts/run_grasp_sim_omniverse.py in the Window → Script Editor to trigger the grasping motion.

    create_grasp_sim_usd.py Options:

    • --object_usd: Path to the object USD.
    • --grasps_yaml: Path to the predicted grasps YAML.
    • --output: Path for the generated simulation USD.
    • --num_envs: Number of environments to create (default 10).
    • --gripper_usd: Path to the gripper USD (default assets/bots/robotiq_2f_85.usd).
    • --env_spacing: Spacing between environments in meters (default 0.6).
    # 1. Run inference (max 10 grasps)
    python scripts/demo_object_mesh.py --mesh_file /tmp/box.usd --mesh_scale 1.0 \
      --gripper_config GRIPPER_CONFIG --output_file /tmp/box_grasps.yml --no-visualization --num_grasps 10
    
    # 2. Build the sim USD
    python scripts/create_grasp_sim_usd.py --object_usd assets/objects/box.usd \
      --grasps_yaml /tmp/box_grasps.yml --output assets/objects/box_with_grasps_sim.usd --num_envs 10
  10. Install GraspGen using Docker

    main

    Use Docker for a complete environment suitable for both training and inference. This is the recommended method for training tasks.

    git clone https://github.com/NVlabs/GraspGen.git && cd GraspGen
    bash docker/build.sh
    git clone https://github.com/NVlabs/GraspGen.git && cd GraspGen
    bash docker/build.sh # This will take a while
  11. Train GraspGen Models on Existing Datasets

    main

    To train the generator (diffusion model) or the discriminator, you must first start a Docker container with all necessary dataset paths mounted.

    1. Setup Docker for Training

    # For training only.
    mkdir -p <path_to_results>
    bash docker/run.sh <path_to_graspgen_code> --grasp_dataset <path_to_grasp_dataset> --object_dataset <path_to_object_dataset> --results <path_to_results>

    2. Run Training Scripts

    Training is performed using shell scripts located in the runs/ directory. For example, to train for the Robotiq 2f-140 gripper:

    • Train Generator: bash runs/train_graspgen_robotiq_2f_140_gen.sh

    • Train Discriminator: bash runs/train_graspgen_robotiq_2f_140_dis.sh

    Important Training Arguments

    • NGPU: Number of GPUs to use.
    • LOG_DIR: Directory for Tensorboard logs, checkpoints, and console logs.
    • NWORKERS: Number of CPU workers (suggested: CPU_CORES / NUM_GPUS).
    • NUM_REDUNDANT_DATAPOINTS: Controls camera viewpoint redundancy in cache building (default: 7). Higher values improve sim2real transfer but may cause OOM errors.
    • train.debug=True: Set this to run on a single GPU with 1 worker for debugging.

    Training Notes

    • Caching: The script automatically builds an .h5 cache if it doesn't exist. If a cache is present, it skips to training.
    • Convergence: Generators typically require ~3K epochs (~40 hrs on 8x A100). Discriminators require ~3K epochs (~90 hrs on 8x A100).
    # Example usage for training the generator
    cd /code && bash runs/train_graspgen_robotiq_2f_140_gen.sh
    
    # Example usage for training the discriminator
    cd /code && bash runs/train_graspgen_robotiq_2f_140_dis.sh
  12. Fine-tuning on new object datasets

    main

    While GraspGen is designed for zero-shot generalization, you can fine-tune the model on specific object/grasp datasets. To do this:

    1. Pass the existing pretrained checkpoint to the train.checkpoint argument in the training script.
    2. Update the paths to point to your new grasp/object dataset following the docs/GRASP_DATASET_FORMAT.md convention.