Operators¶
The geometric operators the models are built from, in their pure-PyTorch reference form. Compiled backends, conventions and speed: Operators and backends.
grasppanda.ops
¶
Geometric operators.
Every function here has a pure-PyTorch reference implementation that runs on CPU and
defines correct behaviour. Furthest point sampling, the ball and cylinder queries and
kNN can also run on optional compiled kernels, which are used only after reproducing
the reference exactly; :mod:grasppanda.ops.backends selects and reports them.
VoxelGrid
¶
Bases: NamedTuple
Result of :func:voxelize.
Attributes:
| Name | Type | Description |
|---|---|---|
voxels |
Tensor
|
|
inverse |
Tensor
|
|
first |
Tensor
|
|
inverse_distance_weights(distance, *, power=1.0, eps=1e-08)
¶
Normalised weights w ∝ 1 / (distance ** power + eps) over the last axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance
|
Tensor
|
|
required |
power
|
float
|
Exponent |
1.0
|
eps
|
float
|
Added to the denominator so that a coincident neighbour (distance 0) receives almost all the weight instead of dividing by zero. |
1e-08
|
Returns:
| Type | Description |
|---|---|
Tensor
|
|
three_interpolate(feats, index, weight)
¶
Weighted sum of neighbour features.
out[b, n] = Σₖ weight[b, n, k] · feats[b, index[b, n, k]]. The name is the
PointNet++ one; any number of neighbours K is accepted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
feats
|
Tensor
|
|
required |
index
|
Tensor
|
|
required |
weight
|
Tensor
|
|
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
grasp_nms(translation, rotation, score, *, translation_threshold=0.03, rotation_threshold=math.radians(30.0))
¶
Greedy suppression of near-duplicate grasps.
Grasps are visited in descending score order (stable, so ties keep input order). A
kept grasp suppresses every later grasp whose translation distance is strictly
below translation_threshold and whose rotation angle is strictly below
rotation_threshold.
This operator is a model post-processor. Benchmark evaluators keep their own pinned copy of the rule, so changing this function can never change a reported AP.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
translation
|
Tensor
|
|
required |
rotation
|
Tensor
|
|
required |
score
|
Tensor
|
|
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Indices of the kept grasps, in descending score order. |
ball_query(query, support, radius, nsample, *, chunk=256)
¶
Support points strictly within radius of every query point.
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Tensor
|
(capped at |
box_query(query, support, rotation, lower, upper, nsample, *, chunk=256)
¶
Support points inside an oriented box at every query point.
The box is axis-aligned in the frame of its query: a support point p is inside
when d = Rᵀ (p - q) satisfies lower < d < upper on all three axes (strict).
Column 0 of rotation is the approach axis, as for :func:cylinder_query, and
the conventions for the returned members are the same (first hits in index order,
missing slots repeat the first, no hit returns index 0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
Tensor
|
|
required |
support
|
Tensor
|
|
required |
rotation
|
Tensor
|
|
required |
lower
|
tuple[float, float, float]
|
Lower corner of the box in its frame, metres. |
required |
upper
|
tuple[float, float, float]
|
Upper corner of the box in its frame, metres. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Tensor
|
(capped at |
cylinder_query(query, support, rotation, radius, hmin, hmax, nsample, *, chunk=256)
¶
Support points inside an oriented cylinder at every query point.
The cylinder axis is column 0 of rotation (the approach axis). A support point
p is inside when, with d = Rᵀ (p - q), hmin < d.x < hmax and
d.y² + d.z² < radius² (all strict).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
Tensor
|
|
required |
support
|
Tensor
|
|
required |
rotation
|
Tensor
|
|
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Tensor
|
(capped at |
gather_points(values, index)
¶
Select (B, M, C) rows of values (B, N, C) with index (B, M).
group_points(values, index)
¶
Select (B, M, K, C) neighbourhoods of values (B, N, C) with index (B, M, K).
knn(query, support, k, *, chunk=1024)
¶
k nearest support points of every query point.
Indices are 0-based and equidistant neighbours are ordered by index.
Returns:
| Type | Description |
|---|---|
tuple[Tensor, Tensor]
|
|
furthest_point_sample(points, num_samples, *, skip_near_origin=False, tie_break='lowest_index')
¶
Iterative furthest point sampling.
The first sample is always index 0 and ties are resolved by a fixed rule, so the
result is deterministic and the same on every device. Which points become seeds
decides whether a ported checkpoint reproduces, so faster backends are held to
exactly this behaviour (:mod:grasppanda.ops.backends).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
|
required |
num_samples
|
int
|
Number of points to pick, at most |
required |
skip_near_origin
|
bool
|
Never pick points whose squared norm is ≤ 1e-3 (apart from index 0), as the widely used PointNet++ CUDA kernel does. Needed only for parity with checkpoints trained against that kernel. |
False
|
tie_break
|
Literal['lowest_index', 'pointnet2_cuda']
|
Which point wins when several are equally far from the selected
set. |
'lowest_index'
|
Returns:
| Type | Description |
|---|---|
Tensor
|
|
generalized_furthest_point_sample(coords, num_samples, *, feats=None, metric='concat', coord_weight=1.0, weights=None, start=None)
¶
Furthest point sampling of one cloud under a feature distance and with point weights.
The generalisation the detection literature uses to make the sampler choose instead
of only spread: a distance that includes features (F-FPS of 3DSSD) and a weight on
the running distance of every point (S-FPS of SASA). Without features and weights it
is :func:furthest_point_sample with tie_break="lowest_index". A picked point is
never picked again, so the indices are distinct even on duplicated coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coords
|
Tensor
|
|
required |
num_samples
|
int
|
Points to pick, at most |
required |
feats
|
Tensor | None
|
|
None
|
metric
|
Literal['concat', 'sum']
|
With features. |
'concat'
|
coord_weight
|
float
|
Weight of the coordinates against the features. |
1.0
|
weights
|
Tensor | None
|
|
None
|
start
|
int | None
|
Index of the first pick. |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
|
hilbert_code(grid, depth)
¶
Hilbert-curve index of non-negative integer coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
Tensor
|
|
required |
depth
|
int
|
Number of bits per axis. The curve depends on it: the same cell has a different index on a deeper curve. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
serialization_code(grid, depth, order='z', batch_index=None)
¶
Sort key of every voxel along one space-filling curve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
Tensor
|
|
required |
depth
|
int
|
Number of bits per axis. |
required |
order
|
SerializationOrder
|
Curve. The |
'z'
|
batch_index
|
Tensor | None
|
|
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
|
z_order_code(grid, depth)
¶
Morton code of non-negative integer coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
Tensor
|
|
required |
depth
|
int
|
Number of bits per axis. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
approach_to_rotation(approach, angle=None)
¶
Gripper frame from an approach direction and an in-plane rotation.
Column 0 of the result is the normalised approach axis. Column 1 is horizontal
([-a_y, a_x, 0] normalised, or [0, 1, 0] when the approach is vertical),
column 2 completes the right-handed frame, and the frame is then rotated by
angle about the approach axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
approach
|
Tensor
|
|
required |
angle
|
Tensor | None
|
|
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
|
fibonacci_views(num_views=300, *, dtype=torch.float32)
¶
Viewpoints on the unit sphere from a Fibonacci lattice.
This is the view grid of the GraspNet-1Billion grasp labels: view i of the
label tensors is row i here. The approach direction of a view is the vector
from the viewpoint to the origin, i.e. -views[i].
Returns:
| Type | Description |
|---|---|
Tensor
|
|
healpix_views(nside=4, *, dtype=torch.float32)
¶
Viewpoints at the pixel centres of a HEALPix grid (through healpix).
HEALPix cuts the sphere into 12 · nside**2 pixels of exactly equal area on
rings of constant latitude: nside 2, 4, 5, 8 give 48, 192, 300, 768 views.
Pixels are in RING order.
Returns:
| Type | Description |
|---|---|
Tensor
|
|
icosphere_views(subdivisions=2, *, dtype=torch.float32)
¶
Viewpoints at the vertices of a subdivided icosahedron (through trimesh).
subdivisions 0, 1, 2, 3, 4 give 12, 42, 162, 642, 2562 views; the count is
10 · 4**subdivisions + 2. The vertices are almost evenly spaced and, unlike a
Fibonacci lattice, come with a mesh (every view knows its neighbours).
Returns:
| Type | Description |
|---|---|
Tensor
|
|
nearest_view(directions, views)
¶
(...) index of the row of views closest in angle to each direction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directions
|
Tensor
|
|
required |
views
|
Tensor
|
|
required |
rotation_angle(first, second)
¶
Angle in radians of the rotation taking first to second ((..., 3, 3)).
two_vector_rotation(first, second)
¶
Rotation whose first column is first and whose second lies towards second.
Gram-Schmidt on two free 3-vectors: first is normalised, second loses its
component along it and is normalised, the third column is their cross product. This
is the mapping of the 6-D rotation representation (Zhou et al., CVPR 2019), and,
with the roles of the two vectors exchanged, how Contact-GraspNet builds a grasp
frame from a predicted baseline and approach.
Returns:
| Type | Description |
|---|---|
Tensor
|
|
voxelize(coords, voxel_size, batch_index=None)
¶
Quantise points to a regular grid by flooring coords / voxel_size.