A ROS2 implementation of Grasp Pose Detection (GPD) for robotic grasping applications. This package provides both streaming and service-based interfaces for detecting 6-DOF grasp poses from point cloud data.
This project ports the GPD library to ROS2, providing:
- Real-time grasp detection from point cloud streams
- Service-based grasp detection for on-demand processing
- Multiple point cloud input formats (PointCloud2, indexed clouds, sampled clouds)
- RViz visualization of detected grasps
- Comprehensive testing tools for development and validation
The project consists of two main packages:
Custom ROS2 message and service definitions:
- Messages:
GraspConfig
,GraspConfigList
,CloudSources
,CloudIndexed
,CloudSamples
- Services:
DetectGrasps
Core implementation with multiple nodes and tools:
- Streaming Node: Continuous grasp detection from point cloud topics
- Service Node: On-demand grasp detection via ROS2 services
- Testing Tools: PCD file processing and point cloud publishing utilities
- ROS2 Humble (or compatible distribution)
- PCL (Point Cloud Library)
- Eigen3
- OpenCV (for GPD)
The GPD library must be installed separately:
# Clone and build GPD
git clone https://github.com/atenpas/gpd.git
cd gpd
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
# Ensure library path is available
export LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}"
# Install ROS2 dependencies
sudo apt install ros-humble-pcl-conversions ros-humble-pcl-msgs ros-humble-sensor-msgs
# Create workspace
mkdir -p ~/grasp_ws/src
cd ~/grasp_ws/src
# Clone this repository
git clone <repository-url> grasp_detection_ros2
# Build the workspace
cd ~/grasp_ws
colcon build --packages-select gpd_ros2_interfaces gpd_ros2 --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo
# Source the workspace
source install/setup.bash
# Start the grasp detection server
ros2 launch gpd_ros2 grasp_detection_server.launch.py
# Or use the convenience script
./src/grasp_detection_ros2/gpd_ros2/launch/grasp_detection_server.sh
# Test grasp detection with a sample PCD file
./src/grasp_detection_ros2/gpd_ros2/launch/run_pcd_service_client.sh
# Test with custom PCD file
./src/grasp_detection_ros2/gpd_ros2/launch/run_pcd_service_client.sh /path/to/your/file.pcd
Streaming grasp detection from point cloud topics.
ros2 launch gpd_ros2 grasp_detection.launch.py \
config_file:=/path/to/gpd/config.cfg \
cloud_topic:=/camera/depth_registered/points
Features:
- Processes point clouds at ~100Hz
- Publishes detected grasps to
/clustered_grasps
- Supports multiple input formats (PointCloud2, CloudIndexed, CloudSamples)
- Optional RViz visualization
- Memory-safe processing with automatic cleanup
Service-based grasp detection for on-demand processing.
A synchronous service interface for grasp detection that processes point clouds on request rather than continuously. Ideal for integration with manipulation pipelines that need precise control over when detection occurs.
# Basic server launch
ros2 launch gpd_ros2 grasp_detection_server.launch.py
# Custom configuration with visualization
ros2 launch gpd_ros2 grasp_detection_server.launch.py \
config_file:=/path/to/your/config.cfg \
rviz_topic:=/grasp_markers
# Use convenience script with production settings
./src/grasp_detection_ros2/gpd_ros2/launch/grasp_detection_server.sh \
--auto-restart --config-file /path/to/production.cfg
Request-Response Pipeline:
- Service Request Reception: Receives CloudIndexed messages with point cloud and sample indices
- Memory-Safe Processing: Same cloud history buffer as streaming node for stability
- GPD Execution: Runs full preprocessing and detection pipeline synchronously
- Dual Output: Returns results via service response AND publishes to topic
Key Features:
- Synchronous Processing: Blocks until detection completes, ensuring deterministic behavior
- CloudIndexed Input: Accepts pre-processed clouds with specific sample points
- Dual Publication: Results available via both service response and topic subscription
- Memory Management: Same robust cloud lifecycle management as streaming node
- RViz Integration: Optional visualization of detected grasps
Service Definition:
# gpd_ros2_interfaces/srv/DetectGrasps.srv
# Request
gpd_ros2_interfaces/CloudIndexed cloud_indexed
gpd_ros2_interfaces/CloudSources cloud_sources
sensor_msgs/PointCloud2 cloud # Input point cloud
geometry_msgs/Point[] view_points # Camera viewpoints
uint32[] camera_source # Camera source mapping
int64[] indices # Sample point indices
---
# Response
gpd_ros2_interfaces/GraspConfigList grasp_configs
std_msgs/Header header
gpd_ros2_interfaces/GraspConfig[] grasps # Detected grasp poses
Service Usage:
# Check service availability
ros2 service list | grep detect_grasps
# Manual service call (for testing)
ros2 service call /detect_grasps gpd_ros2_interfaces/srv/DetectGrasps "{...}"
# Service info
ros2 service type /detect_grasps
Core Parameters:
config_file
(string): Path to GPD configuration filerviz_topic
(string): RViz marker topic (empty disables visualization)
Advanced Parameters:
workspace
(double[]): Spatial bounds for detectioncamera_position
(double[]): Default camera viewpoint[x,y,z]
use_asan
(bool): Enable AddressSanitizer for memory debugging
Published Topics:
/clustered_grasps
(gpd_ros2_interfaces/GraspConfigList
): Detected grasp poses (same as service response){rviz_topic}
(visualization_msgs/MarkerArray
): RViz visualization (optional)
Service:
/detect_grasps
(gpd_ros2_interfaces/srv/DetectGrasps
): Main detection service
The server implements the same memory safety mechanisms as the streaming node:
Cloud History Buffer:
- Maintains
MAX_CLOUD_HISTORY = 3
recent clouds in shared ownership - Prevents premature deletion during GPD processing
- Deep copying of PCL data structures to avoid pointer conflicts
Service Call Isolation:
- Each service call processes independently
- No interference between concurrent requests (though processing is sequential)
- Automatic cleanup after each detection cycle
- Latency: 100-500ms per request depending on cloud size and complexity
- Throughput: ~2-10 requests/second depending on point cloud density
- Memory: ~3x cloud size overhead for history buffer
- Concurrency: Sequential processing (one request at a time)
Python Service Client:
import rclpy
from gpd_ros2_interfaces.srv import DetectGrasps
from gpd_ros2_interfaces.msg import CloudIndexed, CloudSources
# Create service client
client = node.create_client(DetectGrasps, '/detect_grasps')
client.wait_for_service()
# Prepare request
request = DetectGrasps.Request()
request.cloud_indexed = CloudIndexed()
request.cloud_indexed.cloud_sources = your_cloud_sources
request.cloud_indexed.indices = your_sample_indices
# Call service
future = client.call_async(request)
response = future.result()
# Process results
if response.grasp_configs.grasps:
print(f"Detected {len(response.grasp_configs.grasps)} grasps")
best_grasp = response.grasp_configs.grasps[0] # Highest scoring
C++ Service Client:
#include "gpd_ros2_interfaces/srv/detect_grasps.hpp"
auto client = node->create_client<gpd_ros2_interfaces::srv::DetectGrasps>("/detect_grasps");
auto request = std::make_shared<gpd_ros2_interfaces::srv::DetectGrasps::Request>();
// Fill request...
request->cloud_indexed = your_cloud_indexed;
// Synchronous call
auto result = client->async_send_request(request);
if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS) {
auto response = result.get();
// Process response->grasp_configs...
}
Integration with Manipulation Pipeline:
# 1. Start detection server
ros2 launch gpd_ros2 grasp_detection_server.launch.py
# 2. In your manipulation node, call service when needed
# 3. Use returned grasps for motion planning
# 4. Execute grasp with robot controller
Robust Server Launch:
# Auto-restart with memory debugging
./src/grasp_detection_ros2/gpd_ros2/launch/grasp_detection_server.sh \
--auto-restart \
--max-restarts 10 \
--use-asan \
--config-file /opt/gpd/production.cfg
Monitoring and Health Checks:
# Check service health
ros2 service call /detect_grasps gpd_ros2_interfaces/srv/DetectGrasps
# Monitor topic output
ros2 topic echo /clustered_grasps
# Check node status
ros2 node info /detect_grasps_server
Aspect | Server Node | Streaming Node |
---|---|---|
Processing | On-demand | Continuous |
Latency | Higher (full pipeline) | Lower (pre-processed) |
Control | Precise timing | Real-time flow |
Resource Usage | Bursty | Steady |
Use Case | Manipulation pipelines | Real-time monitoring |
Integration | Service calls | Topic subscriptions |
Publishes PCD/PLY files as PointCloud2 messages for testing and development.
A simple utility that loads point cloud files and publishes them to ROS2 topics, useful for testing grasp detection without live sensors.
Features:
- Supports both PCD and PLY file formats
- Configurable publishing rate or single-shot mode
- Automatic field layout detection
- Proper timestamp handling
Usage:
# Publish once and exit
ros2 run gpd_ros2 pcd_publisher \
--file /path/to/cloud.pcd \
--topic /cloud_stitched \
--frame camera_link \
--once
# Publish continuously at 2 Hz
ros2 run gpd_ros2 pcd_publisher \
--file /path/to/cloud.pcd \
--topic /cloud_stitched \
--frame camera_link \
--rate 2.0
# Use convenience script
./src/grasp_detection_ros2/gpd_ros2/launch/run_pcd_publisher.sh
Command Line Options:
--file/-f
: Path to PCD or PLY file (required)--topic/-t
: Output topic name (default:/cloud_stitched
)--frame/-F
: Frame ID for the point cloud (default:camera_link
)--rate/-r
: Publishing rate in Hz (default:2.0
)--once
: Publish once and exit (overrides rate)--help/-h
: Show usage information
Environment Variables:
PCD_FILE
: Default file pathCLOUD_TOPIC
: Default topic nameFRAME
: Default frame ID
Converts segmented object point clouds to GPD-compatible format.
Bridges segmentation pipelines (like mask2pcl
) with GPD by forwarding and optionally reformatting point clouds.
Features:
- Real-time forwarding of segmented point clouds
- Optional frame ID override for coordinate frame consistency
- Repeating mode for continuous processing
- Automatic timestamping
Usage:
# Basic forwarding from segmentation to GPD
ros2 run gpd_ros2 mask2gpd \
--ros-args \
-p input_topic:=object_cloud \
-p output_topic:=/cloud_stitched
# With frame override and repeating
ros2 run gpd_ros2 mask2gpd \
--ros-args \
-p input_topic:=segmented_objects \
-p output_topic:=/cloud_stitched \
-p frame_override:=camera_optical_frame \
-p repeat_rate_hz:=5.0
Parameters:
input_topic
(string): Source topic from segmentation (default:object_cloud
)output_topic
(string): Destination topic for GPD (default:/cloud_stitched
)frame_override
(string): Override frame ID (empty = keep original)repeat_rate_hz
(double): Republish rate in Hz (0.0 = no repeating)
Typical Pipeline:
Camera → Segmentation → mask2gpd → GPD Detection
(SAM2, mask2pcl) (pcl2gpd) (detect_grasps)
Comprehensive testing tool for the grasp detection service.
[Already documented above with enhanced features]
Complete Testing Pipeline:
# Terminal 1: Start grasp detection service
ros2 launch gpd_ros2 grasp_detection_server.launch.py
# Terminal 2: Publish test data
./src/grasp_detection_ros2/gpd_ros2/launch/run_pcd_publisher.sh
# Terminal 3: Test service with detailed output
./src/grasp_detection_ros2/gpd_ros2/launch/run_pcd_service_client.sh \
--show-detailed 5 --show-summary
Live Segmentation Pipeline:
# Terminal 1: Start streaming detection
ros2 launch gpd_ros2 grasp_detection.launch.py \
cloud_topic:=/cloud_stitched
# Terminal 2: Run segmentation and forwarding
ros2 run your_segmentation_pkg mask2pcl [args] &
ros2 run gpd_ros2 mask2gpd \
--ros-args \
-p input_topic:=object_cloud \
-p output_topic:=/cloud_stitched \
-p repeat_rate_hz:=2.0
GPD requires a configuration file (typically ros_eigen_params.cfg
). Key parameters:
# Example GPD configuration
workspace: [-1, 1, -1, 1, -1, 1] # [xmin, xmax, ymin, ymax, zmin, zmax]
camera_position: [0, 0, 0] # Camera viewpoint
num_samples: 1000 # Number of grasp candidates to evaluate
num_threads: 4 # Parallel processing threads
config_file
: Path to GPD configuration filecloud_topic
: Input point cloud topicrviz_topic
: RViz marker topic (empty to disable)frame
: Point cloud frame ID
use_asan
: Enable AddressSanitizer for debugging memory issuesauto_restart
: Automatically restart node on crashesworkspace
: Spatial limits for grasp detection
Describes a single 6-DOF grasp pose:
geometry_msgs/Point position # Grasp position
geometry_msgs/Vector3 approach # Approach direction
geometry_msgs/Vector3 binormal # Hand closing direction
geometry_msgs/Vector3 axis # Hand axis
float32 width # Required gripper opening
float32 score # Grasp quality score
geometry_msgs/Point sample # Detection point
Collection of grasp poses with metadata:
std_msgs/Header header
gpd_ros2_interfaces/GraspConfig[] grasps
The implementation includes temporary memory management solutions for GPD stability:
- Cloud history buffers prevent premature memory deallocation
- ASAN-compatible modes for memory debugging
- Automatic restart capabilities for production use
# Launch with debug options
ros2 launch gpd_ros2 grasp_detection_debug.launch.py debugger:=gdbserver gdb_port:=3333 cloud_type:=0 cloud_topic:=/cloud_stitched rviz_topic:="/grasp_poses"
- Monitor
/clustered_grasps
topic rate - Check node CPU/memory usage with
htop
- Use RViz markers to visualize detection quality
The tutorials/
directory contains sample PCD files:
mug.pcd
: Simple mug objecttable_mug.pcd
: Mug on table surfacekrylon.pcd
: Spray can object
-
GPD Library Not Found
export LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}"
-
Memory Issues
- Use
--use-asan
flag for debugging - Enable auto-restart for production:
--auto-restart
- Use
-
No Grasps Detected
- Check point cloud density and quality
- Verify workspace parameters in config file
- Ensure proper camera viewpoint configuration
-
Service Not Available
# Check if service is running ros2 service list | grep detect_grasps # Test service availability ros2 service call /detect_grasps gpd_ros2_interfaces/srv/DetectGrasps
- Adjust
num_samples
in GPD config for speed/quality tradeoff - Use
num_threads
to leverage multiple CPU cores - Consider point cloud downsampling for faster processing
When contributing to this project:
- Test thoroughly with the provided sample data
- Update documentation for any new features or parameters
- Follow ROS2 best practices for node lifecycle and parameter handling
- Consider memory safety when modifying core detection loops
This project follows the same license as the original GPD library. See LICENSE file for details.