Generate Grasps Using Antipodal Sampler
SUMMARY
Generate Grasps Using Antipodal Sampler samples pairs of opposing contacts on a triangle mesh, filters them by surface-normal alignment and gripper opening, and returns world-frame grasp poses with scores and contact data.
The Skill
from telekinesis import vitreous
grasps, scores, antipodal_candidates, ray_backend = (
vitreous.generate_grasps_using_antipodal_sampler(
mesh=mesh,
num_grasps=20,
w_T_object=w_T_object,
)
)Example
Input

A triangle mesh, expressed in metres, representing the object to grasp.
Result

Valid parallel-jaw grasp poses with their paired surface contacts and normals.
The Code
import numpy as np
from telekinesis import datatypes, vitreous
# Load the object mesh. Mesh dimensions must be in metres.
mesh = datatypes.Mesh3D.from_url(
url="https://assets.telekinesis.ai/examples/v1/meshes/male_pin_connector.obj",
use_cache=True,
)
# Place the object's coordinate frame at the world origin.
w_T_object = np.eye(4, dtype=np.float32)
# Run the skill.
grasps, scores, antipodal_candidates, ray_backend = (
vitreous.generate_grasps_using_antipodal_sampler(
mesh=mesh,
num_grasps=20,
w_T_object=w_T_object,
antipodal_thresh=-0.95,
max_pt_dist=0.08,
min_pt_dist=0.005,
max_sample_retries=500,
seed=42,
)
)
# grasps, scores and antipodal_candidates are index-aligned. ray_backend names the
# ray-intersection backend that was used.
if len(grasps.data):
best_pose = grasps.data[0]
best_score = scores.data[0]
contact_points = antipodal_candidates.data[0, :2]
contact_normals = antipodal_candidates.data[0, 2:]Runnable examples are available in the Telekinesis examples repository.
Follow the README in that repository to set up the environment, then run this example with:
cd telekinesis-examples
python examples/point_cloud/generate_grasps_using_antipodal_sampler.pyParameter Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
mesh | datatypes.Mesh3D | np.ndarray | list | required | Triangle mesh of the object, with dimensions in metres. |
num_grasps | datatypes.Int | int | required | Number of unique valid grasp poses to request. Must be non-negative; the sampler can return fewer if it exhausts its retry budget. |
w_T_object | datatypes.Transform3D | np.ndarray | list | required | Invertible 4 x 4 pose of the object frame O in the world frame W. Returned grasps are expressed in this world frame. |
antipodal_thresh | datatypes.Float | float | -0.95 | Maximum accepted dot product between the two contact normals, in [-1, 1]. More negative values require more directly opposing normals. |
max_pt_dist | datatypes.Float | float | 0.04 | Maximum permitted distance between contacts, in metres. Must be positive and greater than min_pt_dist; normally set this to the gripper's maximum usable opening. |
min_pt_dist | datatypes.Float | float | 0.005 | Minimum permitted distance between contacts, in metres. Must be non-negative and less than max_pt_dist. |
max_sample_retries | datatypes.Int | int | 100 | Maximum number of rejected ray, contact, or near-duplicate sampling attempts before returning the valid grasps found so far. Must be non-negative. |
seed | datatypes.Int | int | None | 42 | Random seed for reproducible sampling. None omits the field, so the server uses its default seed (42). |
alignment_axis_W | datatypes.Array | np.ndarray | list | None | None | Desired world-frame TCP +Z direction, a finite nonzero vector of shape (3,) that need not be normalized. None uses object-frame -Z. |
alignment_cost_weight | datatypes.Float | float | 20.0 | Finite non-negative weight of the alignment loss. |
contact_cost_weight | datatypes.Float | float | 1.0 | Finite non-negative weight of the contact-normal loss. At least one cost weight must be positive. |
normal_patch_size | datatypes.Float | float | 0.0 | Finite non-negative side length, in metres, of the square contact patch. 0 uses only the sampled normals. |
max_total_cost | datatypes.Float | float | None | None | Accept only costs strictly below this threshold, in [0, 1]. None disables cost thresholding. |
min_contact_quality | datatypes.Float | float | 0.0 | Minimum contact-normal quality, in [0, 1]. |
max_alignment_angle_deg | datatypes.Float | float | 180.0 | Maximum TCP +Z alignment angle, in [0, 180] degrees. |
Returns
| Type | Description |
|---|---|
datatypes.Transforms3D | grasps: K world-frame TCP poses with shape (K, 4, 4), where K can be smaller than num_grasps. Each origin is the contact midpoint; +Z points from the gripper toward the object, and +Y is the finger-closing axis. Access the matrices through .data. |
datatypes.Array | scores: K normalized costs in [0, 1] with shape (K,). Lower values are better. Access them through .data. |
datatypes.Array | antipodal_candidates: contact data with shape (K, 4, 3), index-aligned with grasps and scores. Each item contains point_1, point_2, normal_1, and normal_2, in that order. |
datatypes.String | ray_backend: identifies the trimesh ray-intersection backend, for example "trimesh.ray.ray_pyembree" when embreex is active. |
Raises
| Exception | Condition |
|---|---|
TypeError | A parameter cannot be converted to its expected datatype. |
ValueError | A count is negative, antipodal_thresh is outside [-1, 1], a distance is invalid, min_pt_dist >= max_pt_dist, or w_T_object is not a valid transform. |
ConfigurationError | The TELEKINESIS_API_KEY environment variable is not set. |
SerializationError | The request input or response cannot be serialized or deserialized. |
RequestTimeoutError | The request to the Vitreous service times out. |
TransportError | A network failure occurs before a response is received. |
ClientError | The Vitreous service rejects invalid or malformed input or returns another unexpected 4xx response. |
AuthenticationError | The API key is invalid or expired. |
AuthenticationServiceError | The authentication service is unavailable, times out, or returns an invalid response. |
ServerError | The Vitreous service returns a 5xx or another unexpected response. |
How to Tune the Parameters
num_graspscontrols the target number of unique candidates. Request more when a downstream collision checker or motion planner needs alternatives, but expect longer sampling time.antipodal_threshcontrols contact quality. Values near-1accept only nearly opposite normals; raising it toward0accepts more candidates but permits less stable pinches.min_pt_distandmax_pt_distdefine the usable finger-opening interval. Set them from the gripper's minimum and maximum reliable grasp widths, with clearance for the fingertips and object geometry.max_sample_retriescontrols how long the sampler searches after rejected or duplicate candidates. Increase it for small contact regions or strict thresholds. Exhausting the budget is not an error: the skill returns the valid grasps found so far.w_T_objecttransforms object-frame grasp geometry into the world frame. Use the object's current estimated pose, or the identity transform when the mesh frame is already the desired planning frame.seedmakes sampling repeatable (default42). Keep a fixed seed for testing and comparisons; change the value to get different candidates.Nonedoes not randomize, because the server then falls back to its default seed.alignment_axis_W,alignment_cost_weight,contact_cost_weightrank candidates by how well the TCP+Zaxis points along a desired world direction and by contact-normal quality. Raisealignment_cost_weightto prefer approach directions close toalignment_axis_W; at least one weight must stay positive.max_total_cost,min_contact_quality,max_alignment_angle_degare optional filters. Lowermax_total_costor raisemin_contact_qualityto keep only the best candidates; lowermax_alignment_angle_degto reject grasps that tilt away fromalignment_axis_W.
TIP
Best practice: Match the contact-distance limits to the physical gripper, keep a fixed seed while tuning, and always collision-check the returned poses against the gripper and scene before execution.
Where to Use the Skill
Common pipelines include:
- CAD-based bin picking — Generate candidate parallel-jaw grasps from a known object mesh, then rank them using reachability and collision checks.
- Offline grasp library generation — Precompute repeatable grasp poses for known parts and store the candidates with their scores.
- Pose-aware pick planning — Supply an estimated
w_T_objectto obtain grasp poses directly in the robot's world frame.
Alternative Skills
| Skill | Comparison with Generate Grasps Using Antipodal Sampler |
|---|---|
generate_grasps_using_graspgenx | Uses a learned cross-embodiment model on a segmented object point cloud and explicit gripper geometry. Use it for more general 6-DOF scene-aware proposals; use the antipodal sampler for fast, interpretable, reproducible parallel-jaw candidates from a clean mesh. |
| Calculate Oriented Bounding Box | Provides a simple object center, extent, and orientation but does not test opposing surface contacts. Use it only when a coarse geometry-based pick pose is sufficient. |
When Not to Use the Skill
Do not use Generate Grasps Using Antipodal Sampler when:
- Only a partial or noisy point cloud is available — Use
generate_grasps_using_graspgenxwith a segmented object point cloud and gripper geometry instead. - The end effector is not a parallel-jaw gripper — The returned
+Yclosing axis and contact-pair assumptions do not model suction, multi-finger, or magnetic grasping. - Scene collision avoidance is required from this call alone — The sampler evaluates object-surface contacts, not the full robot or surrounding scene; run collision and reachability checks before execution.
- The mesh scale or object pose is unknown — Correct metre-scale geometry and a valid
w_T_objectare necessary for physically meaningful grasp widths and world-frame poses.