Source code for grutopia.core.util.omni_usd_util
import time
import typing
import carb
import numpy as np
import omni.usd
from pxr import Gf, Usd
[docs]def compute_path_bbox(prim_path: str) -> typing.Tuple[carb.Double3, carb.Double3]:
"""
Compute Bounding Box using omni.usd.UsdContext.compute_path_world_bounding_box
See https://docs.omniverse.nvidia.com/kit/docs/omni.usd/latest/omni.usd/omni.usd.UsdContext.html#\
omni.usd.UsdContext.compute_path_world_bounding_box
Args:
prim_path: A prim path to compute the bounding box.
Returns:
A range (i.e. bounding box) as a minimum point and maximum point.
"""
return omni.usd.get_context().compute_path_world_bounding_box(prim_path)
[docs]def get_pick_position(robot_base_position: np.ndarray, prim_path: str) -> np.ndarray:
"""Get the pick position for a manipulator robots to pick an objects at prim_path.
The pick position is simply the nearest top vertex of the objects's bounding box.
Args:
robot_base_position (np.ndarray): robots base position.
prim_path (str): prim path of objects to pick.
Returns:
np.ndarray: pick position.
"""
bbox_0, bbox_1 = compute_path_bbox(prim_path)
x1 = bbox_0[0]
x2 = bbox_1[0]
y1 = bbox_0[1]
y2 = bbox_1[1]
top_z = bbox_0[2] if bbox_0[2] > bbox_1[2] else bbox_1[2]
top_vertices = [
np.array([x1, y1, top_z]),
np.array([x1, y2, top_z]),
np.array([x2, y1, top_z]),
np.array([x2, y2, top_z]),
]
print('================================ Top vertices: ', top_vertices, ' ====================================')
pick_position = top_vertices[0]
for vertex in top_vertices:
if np.linalg.norm(robot_base_position - vertex) < np.linalg.norm(robot_base_position - pick_position):
pick_position = vertex
return pick_position
[docs]def get_grabbed_able_xform_paths(root_path: str, prim: Usd.Prim, depth: int = 3) -> typing.List[str]:
"""get all prim paths of Xform objects under specified prim.
Args:
root_path (str): root path of scenes.
prim (Usd.Prim): target prim.
depth (int, optional): expected depth of Xform objects relative to root_path. Defaults to 3.
Returns:
typing.List[str]: prim paths.
"""
paths = []
if prim is None:
return paths
print(f'get_grabbed_able_xform_paths: start to traverse {prim.GetPrimPath()}')
relative_prim_path = str(prim.GetPrimPath())[len(root_path):]
if relative_prim_path.count('/') <= depth:
for child in prim.GetChildren():
if child.GetTypeName() == 'Scope':
paths.extend(get_grabbed_able_xform_paths(root_path, child))
if child.GetTypeName() == 'Xform':
paths.append(str(child.GetPrimPath()))
return paths
[docs]def get_world_transform_xform(prim: Usd.Prim) -> typing.Tuple[Gf.Vec3d, Gf.Rotation, Gf.Vec3d]:
"""
Get the local transformation of a prim using omni.usd.get_world_transform_matrix().
See https://docs.omniverse.nvidia.com/kit/docs/omni.usd/latest/omni.usd/omni.usd.get_world_transform_matrix.html
Args:
prim: The prim to calculate the world transformation.
Returns:
A tuple of:
- Translation vector.
- Rotation quaternion, i.e. 3d vector plus angle.
- Scale vector.
"""
world_transform: Gf.Matrix4d = omni.usd.get_world_transform_matrix(prim)
translation: Gf.Vec3d = world_transform.ExtractTranslation()
rotation: Gf.Rotation = world_transform.ExtractRotation()
scale: Gf.Vec3d = Gf.Vec3d(*(v.GetLength() for v in world_transform.ExtractRotationMatrix()))
return translation, rotation, scale
[docs]def nearest_xform_from_position(stage: Usd.Stage,
xform_paths: typing.List[str],
position: np.ndarray,
threshold: float = 0) -> str:
"""get prim path of nearest Xform objects from the target position.
Args:
stage (Usd.Stage): usd stage.
xform_paths (typing.List[str]): full list of xforms paths.
position (np.ndarray): target position.
threshold (float, optional): max distance. Defaults to 0 (unlimited).
Returns:
str: prim path of the Xform objects, None if not found.
"""
start = time.time()
if threshold == 0:
threshold = 1000000.0
min_dist = threshold
nearest_prim_path = None
for path in xform_paths:
prim = stage.GetPrimAtPath(path)
if prim is not None and prim.IsValid():
pose = get_world_transform_xform(prim)
dist = np.linalg.norm(pose[0] - position)
if dist < min_dist:
min_dist = dist
nearest_prim_path = path
print(f'nearest_xform_from_position costs: {time.time() - start}')
return nearest_prim_path