Skip to content

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 ​

python
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,
    )
)
API Reference
Full parameter and return type documentation for generate_grasps_using_antipodal_sampler.
View Reference →

Example ​

Input

Triangle mesh of an object to grasp

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

Result

Generated antipodal grasp poses and contact pairs

Valid parallel-jaw grasp poses with their paired surface contacts and normals.

The Code ​

python
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:

bash
cd telekinesis-examples
python examples/point_cloud/generate_grasps_using_antipodal_sampler.py

Parameter Configuration ​

ParameterTypeDefaultDescription
meshdatatypes.Mesh3D | np.ndarray | listrequiredTriangle mesh of the object, with dimensions in metres.
num_graspsdatatypes.Int | intrequiredNumber of unique valid grasp poses to request. Must be non-negative; the sampler can return fewer if it exhausts its retry budget.
w_T_objectdatatypes.Transform3D | np.ndarray | listrequiredInvertible 4 x 4 pose of the object frame O in the world frame W. Returned grasps are expressed in this world frame.
antipodal_threshdatatypes.Float | float-0.95Maximum accepted dot product between the two contact normals, in [-1, 1]. More negative values require more directly opposing normals.
max_pt_distdatatypes.Float | float0.04Maximum 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_distdatatypes.Float | float0.005Minimum permitted distance between contacts, in metres. Must be non-negative and less than max_pt_dist.
max_sample_retriesdatatypes.Int | int100Maximum number of rejected ray, contact, or near-duplicate sampling attempts before returning the valid grasps found so far. Must be non-negative.
seeddatatypes.Int | int | None42Random seed for reproducible sampling. None omits the field, so the server uses its default seed (42).
alignment_axis_Wdatatypes.Array | np.ndarray | list | NoneNoneDesired world-frame TCP +Z direction, a finite nonzero vector of shape (3,) that need not be normalized. None uses object-frame -Z.
alignment_cost_weightdatatypes.Float | float20.0Finite non-negative weight of the alignment loss.
contact_cost_weightdatatypes.Float | float1.0Finite non-negative weight of the contact-normal loss. At least one cost weight must be positive.
normal_patch_sizedatatypes.Float | float0.0Finite non-negative side length, in metres, of the square contact patch. 0 uses only the sampled normals.
max_total_costdatatypes.Float | float | NoneNoneAccept only costs strictly below this threshold, in [0, 1]. None disables cost thresholding.
min_contact_qualitydatatypes.Float | float0.0Minimum contact-normal quality, in [0, 1].
max_alignment_angle_degdatatypes.Float | float180.0Maximum TCP +Z alignment angle, in [0, 180] degrees.

Returns ​

TypeDescription
datatypes.Transforms3Dgrasps: 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.Arrayscores: K normalized costs in [0, 1] with shape (K,). Lower values are better. Access them through .data.
datatypes.Arrayantipodal_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.Stringray_backend: identifies the trimesh ray-intersection backend, for example "trimesh.ray.ray_pyembree" when embreex is active.

Raises ​

ExceptionCondition
TypeErrorA parameter cannot be converted to its expected datatype.
ValueErrorA 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.
ConfigurationErrorThe TELEKINESIS_API_KEY environment variable is not set.
SerializationErrorThe request input or response cannot be serialized or deserialized.
RequestTimeoutErrorThe request to the Vitreous service times out.
TransportErrorA network failure occurs before a response is received.
ClientErrorThe Vitreous service rejects invalid or malformed input or returns another unexpected 4xx response.
AuthenticationErrorThe API key is invalid or expired.
AuthenticationServiceErrorThe authentication service is unavailable, times out, or returns an invalid response.
ServerErrorThe Vitreous service returns a 5xx or another unexpected response.

How to Tune the Parameters ​

  • num_grasps controls the target number of unique candidates. Request more when a downstream collision checker or motion planner needs alternatives, but expect longer sampling time.
  • antipodal_thresh controls contact quality. Values near -1 accept only nearly opposite normals; raising it toward 0 accepts more candidates but permits less stable pinches.
  • min_pt_dist and max_pt_dist define 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_retries controls 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_object transforms 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.
  • seed makes sampling repeatable (default 42). Keep a fixed seed for testing and comparisons; change the value to get different candidates. None does not randomize, because the server then falls back to its default seed.
  • alignment_axis_W, alignment_cost_weight, contact_cost_weight rank candidates by how well the TCP +Z axis points along a desired world direction and by contact-normal quality. Raise alignment_cost_weight to prefer approach directions close to alignment_axis_W; at least one weight must stay positive.
  • max_total_cost, min_contact_quality, max_alignment_angle_deg are optional filters. Lower max_total_cost or raise min_contact_quality to keep only the best candidates; lower max_alignment_angle_deg to reject grasps that tilt away from alignment_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_object to obtain grasp poses directly in the robot's world frame.

Alternative Skills ​

SkillComparison with Generate Grasps Using Antipodal Sampler
generate_grasps_using_graspgenxUses 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 BoxProvides 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_graspgenx with a segmented object point cloud and gripper geometry instead.
  • The end effector is not a parallel-jaw gripper — The returned +Y closing 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_object are necessary for physically meaningful grasp widths and world-frame poses.