Datasets¶
Goal: put GraspNet-1Billion on disk and build the label assets your method trains from. GraspClutter6D is read the same way and is optional.
GraspPanda starts from GraspNet-1Billion and also reads GraspClutter6D, whose grasp
labels have the same format. Both are read in place: nothing is written into a dataset
tree. Derived assets live in their own store under $GRASPPANDA_CACHE, each found by a hash
of its generator, parameters and preprocessing, so a config never reads misaligned labels.
Testing needs none of them.
You need: the GraspNet-1Billion download (190 scenes, two cameras) and room for the asset store.
1. Tell GraspPanda where things are¶
export GRASPPANDA_GRASPNET1B_ROOT=/data/graspnet1b # the unpacked download
export GRASPPANDA_CACHE=/data/grasppanda_cache # where derived assets go
Where a dataset is looked for, and the expected tree
| What | Resolved from, in this order |
|---|---|
| GraspNet-1Billion | root in the dataset config, $GRASPPANDA_GRASPNET1B_ROOT, $GRASPPANDA_DATA/graspnet1b, ./data/graspnet1b |
| GraspClutter6D | root in the dataset config, $GRASPPANDA_GRASPCLUTTER6D_ROOT, $GRASPPANDA_DATA/graspclutter6d, ./data/graspclutter6d |
| Derived assets | $GRASPPANDA_CACHE |
GraspNet-1Billion as the official download unpacks it, 256 frames per scene and camera:
scenes/scene_XXXX/object_id_list.txt
scenes/scene_XXXX/{realsense,kinect}/{rgb,depth,label}/NNNN.png
scenes/scene_XXXX/{realsense,kinect}/meta/NNNN.mat intrinsics, depth factor, poses
scenes/scene_XXXX/{realsense,kinect}/annotations/NNNN.xml poses, four decimals
scenes/scene_XXXX/{realsense,kinect}/{camera_poses,cam0_wrt_table}.npy
grasp_label/NNN_labels.npz
collision_label/scene_XXXX/collision_labels.npz
models/NNN/nontextured.ply, dex_models/NNN.pkl
Splits (shipped in grasppanda/datasets/splits/graspnet1b.yaml): train (scenes 0 to
99), test_seen (100 to 129), test_similar (130 to 159), test_novel (160 to 189),
test (their union), train_dev / val_dev (90 and 10 training scenes) and sample
(eight frames of scene 0, for smoke tests and probes).
2. Check the tree¶
grasppanda prepare graspnet1b --check
It reports what the tree lacks, then which derived assets exist, and prints the command
for whatever is missing. Add --config <method config> to report the assets that config
reads.
3. Build the grasp-label store¶
grasppanda prepare graspnet1b --labels
The store holds the dense grasp labels of every object as memory-mapped files. Every other asset is generated from it. During training it is read by the methods on dense labels (GraspNet-baseline, GSNet, Scale-Balanced-Grasp); the others read their own asset.
4. Build what your method reads¶
| Method | Assets after the label store | Read during training |
|---|---|---|
| GraspNet-baseline | grasp tolerance | label store, tolerance |
| GSNet | point-wise graspness (camera-specific) | label store, graspness |
| Scale-Balanced-Grasp | grasp tolerance, scale statistic | label store, tolerance, statistic |
| EconomicGrasp | point-wise graspness, compact labels | graspness, compact labels |
| FineGrasp | graspness normalised per object, compact labels | graspness, compact labels |
| HGGD | per-view grasps (camera-specific) | per-view grasps |
The commands for the RealSense configs (EconomicGrasp and HGGD also ship a Kinect config:
use --camera kinect with it):
grasppanda prepare graspnet1b --labels
grasppanda prepare graspnet1b --tolerance \
--config graspnet_baseline/graspnet-baseline_pointnet2_g1b-realsense_18e
grasppanda prepare graspnet1b --labels
grasppanda prepare graspnet1b --graspness --camera realsense
grasppanda prepare graspnet1b --labels
grasppanda prepare graspnet1b --tolerance \
--config scale_balanced_grasp/sbg_pointnet2-transformer_g1b-realsense_18e
grasppanda prepare graspnet1b --scale-statistic \
--config scale_balanced_grasp/sbg_pointnet2-transformer_g1b-realsense_18e
grasppanda prepare graspnet1b --labels
grasppanda prepare graspnet1b --graspness --camera realsense
grasppanda prepare graspnet1b --compact-labels \
--config economicgrasp/economicgrasp_sunet14_g1b-realsense_10e
grasppanda prepare graspnet1b --labels
grasppanda prepare graspnet1b --graspness --camera realsense \
--config finegrasp/finegrasp_sunet14_g1b-realsense_10e
grasppanda prepare graspnet1b --compact-labels \
--config finegrasp/finegrasp_sunet14_g1b-realsense_10e
The compact labels are EconomicGrasp's asset: when it exists, nothing is generated.
grasppanda prepare graspnet1b --labels
grasppanda prepare graspnet1b --view-grasps --camera realsense \
--config _base_/datasets/graspnet1b_realsense_hggd.yaml
Every action reads a dataset config: the one named with --config, or else the shipped
base of the dataset and camera (_base_/datasets/graspnet1b_<camera>.yaml, the graspness
recipe of GSNet, EconomicGrasp and FineGrasp). What is built is exactly what that config
later asks for. --split and --scenes 5,9,13 restrict the scenes; generation is
resumable and finished shards are skipped.
Expected result: grasppanda prepare graspnet1b --check --config <method config> marks
the tree and every asset of that config with ✓. The test suite holds the commands above
to the dataset sections of the six method configs.
Troubleshooting
- "grasp labels of object N are not in the store": run
--labelsfirst; every other action needs the store. - "the dataset config has no
compact_labelssection" (ortolerance,view_grasps): pass--configwith the method config that declares it. - A probe needs the same assets for the split
sampleonly: add--split sample(What a probe needs). - The scale statistic of Scale-Balanced-Grasp reads 3200 training frames; its README says how to import the reference file instead (configs/scale_balanced_grasp).
GraspClutter6D¶
GraspClutter6D (RA-L 2025,
arXiv 2504.06866, data licence CC BY-SA 4.0) holds
1 000 scenes in BOP layout, 648 of them in its grasp splits. Every label generator of this
toolbox runs on it unchanged. Download and unpack it as its README says, set
GRASPPANDA_GRASPCLUTTER6D_ROOT, then run grasppanda prepare graspclutter6d --check.
Testing a GraspNet-1Billion model on it is the subject of
Cross-dataset evaluation.
The tree the reader needs
split_info/grasp_{train,test}_scene_ids.json the grasp splits (authoritative)
split_info/obj_ids_per_scene.json
scenes/<scene:06d>/{rgb,depth,label}/<image:06d>.png
scenes/<scene:06d>/{mask,mask_visib}/<image:06d>_<instance:06d>.png
scenes/<scene:06d>/scene_camera.json per image: cam_K, depth_scale, cam_{R,t}_w2c
scenes/<scene:06d>/scene_gt.json per image and instance: cam_{R,t}_m2c, obj_id
grasp_label/obj_<object:06d>_labels.npz
collision_label/<scene:06d>.npz one array per instance, in scene_gt order
models_m/obj_<object:06d>.ply object models in metres
dex_models/obj_<object:06d>.pkl force-closure data of the evaluator
Cameras
A scene has 13 annotated views, and every view was taken by four cameras. All 52 images
of a scene share the directories; the camera is encoded in the image id,
image = 4 * view + c. A SampleKey holds the camera name and the view (0 to 12).
Camera (camera:) |
c |
Image | Raw depth unit | Focal length (px) | Base config |
|---|---|---|---|---|---|
realsense-d415 |
1 | 1920 × 1080 | 1 mm | 1404 or 1429 | graspclutter6d_d415.yaml |
realsense-d435 |
2 | 1920 × 1080 | 1 mm | 1394 or 1415 | graspclutter6d_d435.yaml |
azure-kinect |
3 | 3840 × 2160 | 0.1 mm | 1996 or 2112 | graspclutter6d_kinect.yaml |
zivid |
4 | 1920 × 1200 | 0.1 mm | 2790 | graspclutter6d_zivid.yaml |
Intrinsics and depth scale are read per image from scene_camera.json. Three of the
cameras have two calibrations in the grasp splits (in the scenes inspected, view 0 has
one and views 1 to 12 the other), so one constant camera matrix per camera would be
wrong here. The depth scale was the same on all 8 424 images of each camera. The paper
reports its benchmark on the RealSense D435.
Splits
| Split | Scenes | Frames per camera | Object models | Source |
|---|---|---|---|---|
train |
413 | 5 369 | 123 (ids 69 to 198) | split_info/grasp_train_scene_ids.json |
test |
235 | 3 055 | 68 (ids 1 to 68) | split_info/grasp_test_scene_ids.json |
all |
648 | 8 424 | 191 | union of the two |
sample |
1 (scene 5) | 13 | 6 | first training scene, for smoke tests |
test_mini |
24 | 312 | 66 of the 68 | every tenth test scene by rank; shipped |
val_dev |
41 | 533 | 110 of the 123 | every tenth training scene by rank; shipped |
train_dev |
372 | 4 836 | 123 | train without val_dev |
- The test objects are all unseen. No object model occurs in both splits: the benchmark has no "seen" part, unlike GraspNet-1Billion.
- The three subsets are fixed scene lists in
grasppanda/datasets/splits/graspclutter6d.yaml. They exist only when the split files of the tree contain them.test_miniis for quick checks; a number measured on it is a subset number, not a benchmark result. Per-scene AP varies widely on this dataset (from below 1 to above 60 for one model), so the mean over 24 scenes carries a standard error of about 3 AP. - All objects of
val_devare training objects, so it measures fit to new arrangements, not to new objects. - The other 352 scenes of the dataset are in neither grasp split and are not read.
- The paper states 132 training objects. The split files give 123: object ids 112 to 117, 191, 199 and 200 occur in no scene of either grasp split.
What a frame holds
- Scenes are denser than in GraspNet-1Billion: 14.5 object instances per scene on
average (5 to 20), and in 84 % of the scenes at least one object model occurs more than
once. The
labelimage stores object ids and cannot tell two copies apart, so the reader builds the instance map from the per-instance visibility masks (mask_visib), and grasp labels, collision labels and compact labels are keyed by instance (position inscene_gt.json), not by object id. - The instance list and its order are the same for all 52 images of a scene (checked on all 648 scenes). The reader and the evaluator refuse a frame for which that fails.
- Lengths in the JSON files are millimetres; poses leave the reader in metres.
cam_R_w2c/cam_t_w2chold the camera pose in the world frame (camera to world), contrary to what the names say. The world frame is fixed to the rig, not to the table: bounds of aTableBoxWorkspaceare world coordinates here.scene_camera.jsonalso has entries-4to0; they have no image and are ignored.
Derived assets and their cost
Built on three training scenes (5, 9 and 13; 11 object models, 49 instances) on the development machine while it was heavily loaded, so the times are upper bounds:
| Asset | Command (add --scenes 5,9,13 for the three scenes) |
Three scenes | Whole train split, extrapolated |
|---|---|---|---|
| Grasp-label store | grasppanda prepare graspclutter6d --labels |
2.8 GB | about 55 GB (236 MB per object model, 62 MB per scene) |
| Graspness, one camera | ... --graspness --camera realsense-d435 |
2.2 MB, 3 min with 3 workers | about 0.3 GB, 5 h with 4 workers |
| Compact labels | ... --compact-labels --config economicgrasp/economicgrasp_sunet14_gc6d-d435_10e |
24 MB, 11 s | about 3 GB, 25 min |
| Tolerance | ... --tolerance --config _base_/datasets/graspclutter6d_d435_tolerance.yaml |
332 MB, 1 min with 4 workers | about 4 GB, 10 min |
| Per-view grasps, one camera | ... --view-grasps --camera realsense-d435 --config _base_/datasets/graspclutter6d_d435_hggd.yaml |
96 kB, 1 min with 3 workers | about 15 MB, 1.5 h with 4 workers |
The whole-split figures are extrapolations from the three scenes, not measurements. The
label store is the large one; only training reads it. The evaluator keeps a cache of its
own, extracted from dex_models/ and models_m/ on first use: about 7 MB per object
model, 0.5 GB for the test objects.
Two facts measured on those scenes that matter for training:
- Only 9.6 % of the annotated grasp points keep a collision-free grasp of friction ≤ 0.4 (10 401 of 108 094); on GraspNet-1Billion 39 % do. The scenes are far more cluttered, so compact labels supervise far fewer seeds per frame.
- The per-view labels of HGGD come to 17 to 67 per frame (GraspNet-1Billion scene 0: 59), from 471 to 1 964 candidate grasps per scene.
Dataset configs for GraspClutter6D
| Config | Data recipe carried over from | Cloud | Assets it reads for training |
|---|---|---|---|
_base_/datasets/graspclutter6d_d435_tolerance.yaml |
GraspNet-baseline, Scale-Balanced-Grasp | 20 000 points, official workspace crop | label store, tolerance |
_base_/datasets/graspclutter6d_{d415,d435,kinect,zivid}.yaml |
the graspness recipe of GSNet, EconomicGrasp and FineGrasp | 15 000 points, official workspace crop | label store, graspness |
economicgrasp/economicgrasp_sunet14_gc6d-d435_10e.yaml (on the D435 base) |
EconomicGrasp | 20 000 points, official workspace crop | compact labels, graspness |
_base_/datasets/graspclutter6d_d435_hggd.yaml |
HGGD | colour and depth images, 25 600 points, no crop | per-view grasps |
These carry the GraspNet-1Billion recipe of each method over and change only what the dataset fixes. None reproduces a published GraspClutter6D training recipe: none exists for the ported methods. HGGD's network image is 640 × 360, and the detector takes any sensor image that is an integer multiple of it: the D415, D435 (×3) and Azure Kinect (×6) images fit, the Zivid images (1920 × 1200) do not.
What differs between the two benchmarks
Measured values are medians over 20 test frames of GraspNet-1Billion (two frames of
every ninth test scene, RealSense unless a camera is named) and over 104 test frames of
GraspClutter6D (all 13 views of every third test_mini scene).
| GraspNet-1Billion | GraspClutter6D | |
|---|---|---|
| Scenes, frames | 190 scenes × 256 frames per camera | 648 scenes in the grasp splits × 13 views per camera |
| Cameras | realsense (D435), kinect (Azure Kinect), one directory each |
D415, D435, Azure Kinect, Zivid, interleaved by image id |
| Image | 1280 × 720 | 1920 × 1080, 3840 × 2160 (Kinect), 1920 × 1200 (Zivid) |
| Intrinsics | one calibration per camera | per image; two calibrations for three of the cameras |
| Raw depth unit | 1 mm | 1 mm (RealSense), 0.1 mm (Azure Kinect, Zivid); per image |
| Camera to objects | 0.44 m (0.31 to 0.52) | 0.70 m (0.36 to 1.04) on the D435; the paper states 0.31 to 1.37 m over all cameras |
| Size of a pixel on the objects | 0.47 mm (RealSense), 0.74 mm (Kinect) | 0.50 mm (D435), 0.47 (D415), 0.36 (Kinect), 0.26 (Zivid) |
| Object ids | 0 to 87; the segmentation stores id + 1 | 1 to 200; the segmentation stores the id |
| Instances | an object occurs once per scene | repeated objects; instances from mask_visib |
| Label files | grasp_label/NNN_labels.npz, collision_label/scene_XXXX/collision_labels.npz |
grasp_label/obj_NNNNNN_labels.npz, collision_label/NNNNNN.npz |
| Label grid | 300 views × 12 angles × 4 depths | the same |
| Label widths | gripper of 0.10 m | up to 0.15 m; gripper of 0.14 m |
| Object poses | meta/*.mat or annotations/*.xml |
scene_gt.json (millimetres) |
| Table frame | cam0_wrt_table.npy, z up, origin on the table |
the rig's world frame; the table is not at z = 0 |
| Reference workspace crop | 3-D box around the ground-truth segmentation, 2 cm margin (SegmentationBoxWorkspace) |
image rectangle around the ground-truth segmentation, 10 % margin (SegmentationRectWorkspace) |
| Cloud in that crop | 554 000 points, 0.48 × 0.35 × 0.26 m, 39 % on objects | 908 000 points, 0.91 × 0.57 × 0.81 m, 32 % on objects (D435) |
| Splits | train / seen / similar / novel | train / test, disjoint objects |
| Evaluator | GraspNet1BEvaluator, protocol graspnet1b-sv-v1 |
GraspClutter6DEvaluator, protocol graspclutter6d-sv-v1 |
| Ranks and frictions | top 50; μ = 0.2, 0.4, …, 1.2 | the same |
| Width clip | 0.10 m | 0.14 m |
| Foreground filter | none | grasps 5 cm or more from every object model are dropped before NMS |
| Collision scene | object models and a synthetic table | object models only |
Both reference crops are derived from the ground-truth segmentation, at test time
too. Results on them are stamped gt_assisted: [workspace]. HGGD crops nothing.
The evaluators, checked against the official tools
The evaluator constants are those of the official tools (graspnetAPI 1.2.x and
graspclutter6dAPI at ddb2ee7). For GraspNet-1Billion every stage equals graspnetAPI
value for value on 1,592 recorded frames: six whole test scenes of a detector's dump,
grasps drawn from the labels on both cameras and edge cases
(tests/integration/test_eval_parity.py; two frames with tied scores have no single
official result and are left out). For GraspClutter6D the equality is checked stage by
stage on label-derived grasps for all four cameras and on the dumps that grasppanda
test wrote for several detectors (tests/integration/test_eval_clutter_parity.py).
Next¶
- Train and test: train your method on what you just built.
- Cross-dataset evaluation: test GraspNet-1Billion weights on GraspClutter6D.