Geometry
Base geom.
Lifecycle
geom = BoxGeom(...) # store raw inputs (CPU) scene.add(geom) # calls geom.build(device): allocate capacity-padded GPU arrays geom.update(...) # fixed buffers update in place; resource swaps advance graph_revision
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
Allocate the GPU arrays; called by WarpScene.add, or directly for scene-less query_sdf.
Heterogeneous batched scene SDF query.
Example
>>> import numpy as np >>> import torch >>> import warp as wp >>> from robokit.geom.geoms import SphereGeom >>> wp.init() >>> scene = WarpScene(num_scenes=1, device="cpu").add( ... SphereGeom(np.array([1.0]), np.array([0, 1], dtype=np.int32)) ... ) >>> signed_dists, _, _ = scene.query_sdf_torch( ... torch.tensor([[2.0, 0.0, 0.0], [0.5, 0.0, 0.0]]), ... torch.tensor([0, 2]), ... ) >>> bool(torch.allclose(signed_dists, torch.tensor([1.0, -0.5]))) True >>> normal_jacobians = wp.empty(1, dtype=wp.mat33, device="cpu") >>> _ = scene.query_sdf( ... wp.array([[2.0, 0.0, 0.0]], dtype=wp.vec3, device="cpu"), ... scene_indices=wp.array([0], dtype=wp.int32, device="cpu"), ... out_normal_jacobians=normal_jacobians, ... ) >>> np.allclose(normal_jacobians.numpy()[0], np.diag([0.0, 0.5, 0.5])) True >>> observed = wp.empty(1, dtype=wp.bool, device="cpu") >>> _ = scene.query_sdf(wp.array([[2.0, 0.0, 0.0]], dtype=wp.vec3, device="cpu"), ... scene_indices=wp.array([0], dtype=wp.int32, device="cpu"), out_observed=observed) >>> bool(observed.numpy()[0]) # analytical geometry is fully known True
from robokit.geom.scene import WarpScene
import numpy as np
import torch
import warp as wp
from robokit.geom.geoms import SphereGeom
wp.init()
scene = WarpScene(num_scenes=1, device="cpu").add(
SphereGeom(np.array([1.0]), np.array([0, 1], dtype=np.int32))
)
signed_dists, _, _ = scene.query_sdf_torch(
torch.tensor([[2.0, 0.0, 0.0], [0.5, 0.0, 0.0]]),
torch.tensor([0, 2]),
)
bool(torch.allclose(signed_dists, torch.tensor([1.0, -0.5])))
normal_jacobians = wp.empty(1, dtype=wp.mat33, device="cpu")
_ = scene.query_sdf(
wp.array([[2.0, 0.0, 0.0]], dtype=wp.vec3, device="cpu"),
scene_indices=wp.array([0], dtype=wp.int32, device="cpu"),
out_normal_jacobians=normal_jacobians,
)
np.allclose(normal_jacobians.numpy()[0], np.diag([0.0, 0.5, 0.5]))
observed = wp.empty(1, dtype=wp.bool, device="cpu")
_ = scene.query_sdf(wp.array([[2.0, 0.0, 0.0]], dtype=wp.vec3, device="cpu"),
scene_indices=wp.array([0], dtype=wp.int32, device="cpu"), out_observed=observed)
bool(observed.numpy()[0]) # analytical geometry is fully knownTotal element count across all attached geoms (a MeshGeom of N meshes counts N).
Monotonic revision of resources referenced by captured graphs.
Attach a geom: allocates its GPU arrays on this scene's device; update in place via geom.update(...).
Query the scene SDF (min over all attached geoms) at points.
Query points, any shape (flattened to n internally).
CSR boundaries into the flat points, int32, length num_scenes+1. Pass exactly one of scene_offsets / scene_indices.
Scene id of each point, int32, one per point. Skips the derivation launch, so hot loops pass a pre-built map here.
Optional per-point gate, int32, length n. Points with mask 0 skip every geom kernel.
Skip the normal/closest computation (~2x faster) and return only signed distances.
Optional preallocated output; required shape n. Hot loops and CUDA-graph capture pass all out_* so no allocation happens per call.
Optional preallocated output, shape n.
Optional preallocated output, shape n.
Record the launches on an active wp.Tape; False keeps the query off the gradient.
Optional preallocated wp.mat33 output, one per point. Entry (i, j) is the derivative of normal component i with respect to point coordinate j. Mesh face normals have zero derivatives; voxel and primitive normals use analytical derivatives of the active query branch. Derivatives at cell, face, or closest-object switches are discontinuous.
Optional device bool array, one per point. True when every sensor map in the scene has observed the queried voxel; outside a sensor map or masked out is False. Meshes and analytical geometry leave this status unchanged. Unknown status never skips distance checks.
Flat (n,) views: signed_dists if distance_only, else (signed_dists, normals, closest_points). Points in an empty scene get MAX_DIST distance and zero normals.
Differentiable scene SDF query (per-point min over all attached geoms).
Query points, shape (n, 3), differentiable.
CSR boundaries into the points, length num_scenes+1.
Optional per-geom pose overrides, (count, 4, 4) tensors keyed by attached geom. Overridden geoms are queried on these poses and receive gradients; other geoms use their stored (non-differentiable) transforms.
Optional per-geom scale overrides, (count,) tensors keyed by attached geom. Same semantics as poses.
(signed_dists, normals, closest_points) torch tensors, shapes (n,), (n, 3), (n, 3). Gradients flow to query_points and to the poses/scales tensors of whichever geom is closest at each point.
N boxes: half_extents (N, 3), posed/rotated via poses.
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
Allocate the GPU arrays; called by WarpScene.add, or directly for scene-less query_sdf.
N spheres: radii (N,), centered via poses.
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
Allocate the GPU arrays; called by WarpScene.add, or directly for scene-less query_sdf.
N halfspaces (local z=0 planes, sdf = local z): count = scene_offsets[-1], orientation via poses.
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
Allocate the GPU arrays; called by WarpScene.add, or directly for scene-less query_sdf.
N capsules: radii (N,) + half_heights (N,), axis along local z via poses.
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
Allocate the GPU arrays; called by WarpScene.add, or directly for scene-less query_sdf.
N triangle meshes; enable_sdf bakes a disk-cached per-mesh SDF for far queries instead of the exact mesh.
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
meshes swaps the mesh ids + AABBs (and rebakes the SDF tier if enabled).
N pre-baked SdfVolume grids (NanoVDB trilinear sample; conservative extrapolation outside the AABB).
Revision of GPU resources referenced by captured graphs.
Query this geom alone (same semantics as WarpScene.query_sdf); call build first.
sdf_volumes swaps ids/AABBs/paddings.