Skip to content

Commit

Permalink
Version 1.12.2
Browse files Browse the repository at this point in the history
  • Loading branch information
clemense committed Jan 11, 2025
1 parent 829e30d commit 49f82d7
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 54 deletions.
28 changes: 18 additions & 10 deletions src/scene_synthesizer/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1818,51 +1818,59 @@ def __init__(self, mesh, **kwargs):


class BoxAsset(TrimeshAsset):
def __init__(self, extents, **kwargs):
def __init__(self, extents, transform=None, **kwargs):
"""A box primitive.
Args:
extents (list[float]): 3D extents of the box.
transform (np.ndarray, optional): 4x4 homogeneous transformation matrix for box center. Defaults to None.
"""
super().__init__(mesh=trimesh.primitives.Box(extents=extents), **kwargs)
super().__init__(mesh=trimesh.primitives.Box(extents=extents, transform=transform), **kwargs)

class BoxMeshAsset(TrimeshAsset):
def __init__(self, extents, **kwargs):
def __init__(self, extents, transform=None, **kwargs):
"""A triangular mesh in the shape of a box.
Args:
extents (list[float]): 3D extents of the box.
transform (np.ndarray, optional): 4x4 homogeneous transformation matrix for box center. Defaults to None.
"""
super().__init__(mesh=trimesh.creation.box(extents=extents), **kwargs)
super().__init__(mesh=trimesh.creation.box(extents=extents, transform=transform), **kwargs)

class CylinderAsset(TrimeshAsset):
def __init__(self, radius, height, **kwargs):
def __init__(self, radius, height, transform=None, sections=32, **kwargs):
"""A cylinder primitive.
Args:
radius (float): Radius of cylinder.
height (float): Height of cylinder.
transform (np.ndarray, optional): 4x4 homogeneous transformation matrix for cylinder center. Defaults to None.
sections (int, optional): Number of facets in circle. Defaults to 32.
"""
super().__init__(mesh=trimesh.primitives.Cylinder(radius=radius, height=height), **kwargs)
super().__init__(mesh=trimesh.primitives.Cylinder(radius=radius, height=height, transform=transform, sections=sections), **kwargs)

class SphereAsset(TrimeshAsset):
def __init__(self, radius, **kwargs):
def __init__(self, radius, transform=None, subdivisions=3, **kwargs):
"""A sphere primitive.
Args:
radius (float): Radius of sphere.
transform (np.ndarray, optional): 4x4 homogeneous transformation matrix for sphere center. Defaults to None.
subdivisions (int, optional): Number of subdivisions for icosphere. Defaults to 3.
"""
super().__init__(mesh=trimesh.primitives.Sphere(radius=radius), **kwargs)
super().__init__(mesh=trimesh.primitives.Sphere(radius=radius, transform=transform, subdivisions=subdivisions), **kwargs)

class CapsuleAsset(TrimeshAsset):
def __init__(self, radius, height, **kwargs):
def __init__(self, radius, height, transform=None, sections=32, **kwargs):
"""A capsule primitive.
Args:
radius (float): Radius of cylindrical part (and spherical end parts).
height (float): Height of cylindrical part. Total height of capsule will be height + 2*radius.
transform (np.ndarray, optional): 4x4 homogeneous transformation matrix for capsule center. Defaults to None.
sections (int, optional): Number of facets in circle. Defaults to 32.
"""
super().__init__(mesh=trimesh.primitives.Capsule(radius=radius, height=height), **kwargs)
super().__init__(mesh=trimesh.primitives.Capsule(radius=radius, height=height, transform=transform, sections=sections), **kwargs)


class TrimeshSceneAsset(Asset):
Expand Down
107 changes: 63 additions & 44 deletions src/scene_synthesizer/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,64 +1005,86 @@ def add_walls(
dimensions,
thickness=0.15,
overhang=0.0,
offset=0.0,
hole_extents=(0, 0),
hole_offset=(0, 0),
use_primitives=True,
object_ids=None,
use_collision_geometry=True,
joint_type=None,
):
"""Add walls/box assets to any combination of the six faces of the scene volume.
Args:
dimensions (list[str]): In which dimension to add a wall. Any subset of ['x', '-x', 'y', '-y', 'z', '-z'].
thickness (float, optional): Thickness of the wall. Defaults to 0.15.
overhang (float, optional): The amount of overhang of the wall. Can be a single scalar, a 3-dim list or a 6-dim list. Defaults to 0.0.
overhang (float, optional): The amount of overhang of the wall. Can be a single scalar or a len(dimensions)-dim list. Defaults to 0.0.
offset (float, optional): The distance between wall and closest scene geometry. Can be a single scalar or a len(dimensions)-dim list. Defaults to 0.0.
hole_extents (list[float], optional): 2-dim extents of the hole in the wall. Defaults to (0, 0).
hole_offset (tuple[float], optional): 2-dim position offset of the hole in the wall. Defaults to (0, 0).
use_primitives (bool, optional): Whether to create a mesh or use a primitive. Defaults to True.
object_ids (list[str], optional): A list of object names used for adding walls, needs to have same length as dimensions. If None, names will be "wall_{dim}". Defaults to None
use_collision_geometry (bool, optional): Defaults to True.
joint_type (str, optional): Defaults to None.
Raises:
ValueError: If overhang is not a float, or a list of length 3 or 6.
ValueError: If overhang is not a float, or a list of length len(dimensions).
ValueError: If object_ids is not None and len(object_ids) != len(dimensions).
"""
overhangs = None
offsets = None
dim_to_index = {'x': 0, '-x': 1, 'y': 2, '-y': 3, 'z': 4, '-z': 5}

if isinstance(overhang, float):
overhangs = [overhang] * 6
elif isinstance(overhang, list):
if len(overhang) == 3:
overhangs = [
overhang[0],
overhang[0],
overhang[1],
overhang[1],
overhang[2],
overhang[2],
]
elif len(overhang) == 6:
overhangs = overhang
elif isinstance(overhang, list) and len(overhang) == len(dimensions):
overhangs = [0.0] * 6
for i, d in enumerate(dimensions):
overhangs[dim_to_index[d]] = overhang[i]

if overhangs is None:
raise ValueError("Overhang needs to be a float or a list with 3 or 6 floats.")
raise ValueError("Overhang needs to be a float or a list with len(dimensions) floats.")

if isinstance(offset, float):
offsets = [offset] * 6
elif isinstance(offset, list) and len(offset) == len(dimensions):
offsets = [0.0] * 6
for i, d in enumerate(dimensions):
offsets[dim_to_index[d]] = offset[i]

if offsets is None:
raise ValueError("Offset needs to be a float or a list with len(dimensions) floats.")
offsets = np.array(offsets)

if object_ids is not None and len(object_ids) != len(dimensions):
raise ValueError("If object_ids is set it needs to have as many elements as dimensions.")

scene_bounds = self.get_bounds()
scene_extents = self.get_extents()

scene_bounds[0] -= offsets[1::2]
scene_bounds[1] += offsets[0::2]

scene_extents += (offsets[1::2] + offsets[0::2])

extents = {
"x": [
thickness,
self._scene.extents[1] + overhangs[2] + overhangs[3],
self._scene.extents[2] + overhangs[4] + overhangs[5],
scene_extents[1] + overhangs[2] + overhangs[3],
scene_extents[2] + overhangs[4] + overhangs[5],
],
"y": [
self._scene.extents[0] + overhangs[0] + overhangs[1],
scene_extents[0] + overhangs[0] + overhangs[1],
thickness,
self._scene.extents[2] + overhangs[4] + overhangs[5],
scene_extents[2] + overhangs[4] + overhangs[5],
],
"z": [
self._scene.extents[0] + overhangs[0] + overhangs[1],
self._scene.extents[1] + overhangs[2] + overhangs[3],
scene_extents[0] + overhangs[0] + overhangs[1],
scene_extents[1] + overhangs[2] + overhangs[3],
thickness,
],
}

if all(hole_extents): # check if hole is not zero
hole_extents_per_dim = {
"x": [None, hole_extents[0], hole_extents[1]],
Expand All @@ -1075,23 +1097,6 @@ def add_walls(
if all(hole_extents):
hole_extents_per_dim[f"-{k}"] = hole_extents_per_dim[k]

parent_achors = {
"x": ("top", "center", "center"),
"-x": ("bottom", "center", "center"),
"y": ("center", "top", "center"),
"-y": ("center", "bottom", "center"),
"z": ("center", "center", "top"),
"-z": ("center", "center", "bottom"),
}
obj_anchors = {
"x": ("bottom", "center", "center"),
"-x": ("top", "center", "center"),
"y": ("center", "bottom", "center"),
"-y": ("center", "top", "center"),
"z": ("center", "center", "bottom"),
"-z": ("center", "center", "top"),
}

if object_ids is None:
object_ids = [f"wall_{dim}" for dim in dimensions]

Expand All @@ -1104,16 +1109,30 @@ def add_walls(
use_primitives=use_primitives,
)
else:
wall = BoxAsset(extents=extents[dim]) if use_primitives else BoxMeshAsset(extents=extents[dim])
if use_primitives:
wall = BoxAsset(extents=extents[dim])
else:
wall = BoxMeshAsset(extents=extents[dim])

if dim == 'x':
transform = tra.translation_matrix(scene_bounds[1] * np.array([1.0, 0.0, 0.0]) + [thickness/2.0, 0, 0] + (scene_bounds[1] + scene_bounds[0]) * np.array([0, 0.5, 0.5]))
elif dim == '-x':
transform = tra.translation_matrix(scene_bounds[0] * np.array([1.0, 0.0, 0.0]) - [thickness/2.0, 0, 0] + (scene_bounds[1] + scene_bounds[0]) * np.array([0, 0.5, 0.5]))
elif dim == 'y':
transform = tra.translation_matrix(scene_bounds[1] * np.array([0.0, 1.0, 0.0]) + [0, thickness/2.0, 0] + (scene_bounds[1] + scene_bounds[0]) * np.array([0.5, 0, 0.5]))
elif dim == '-y':
transform = tra.translation_matrix(scene_bounds[0] * np.array([0.0, 1.0, 0.0]) - [0, thickness/2.0, 0] + (scene_bounds[1] + scene_bounds[0]) * np.array([0.5, 0, 0.5]))
elif dim == 'z':
transform = tra.translation_matrix(scene_bounds[1] * np.array([0.0, 0.0, 1.0]) + [0, 0, thickness/2.0] + (scene_bounds[1] + scene_bounds[0]) * np.array([0.5, 0.5, 0]))
elif dim == '-z':
transform = tra.translation_matrix(scene_bounds[0] * np.array([0.0, 0.0, 1.0]) - [0, 0, thickness/2.0] + (scene_bounds[1] + scene_bounds[0]) * np.array([0.5, 0.5, 0]))

self.add_object(
wall,
obj_id,
connect_parent_id=self._scene.graph.base_frame,
connect_parent_anchor=parent_achors[dim],
connect_obj_anchor=obj_anchors[dim],
use_collision_geometry=True,
joint_type=None,
transform=transform,
use_collision_geometry=use_collision_geometry,
joint_type=joint_type,
)

def distance_matrix_geometry(self, nodes_geometry=None, return_names=False):
Expand Down

0 comments on commit 49f82d7

Please sign in to comment.