Source code for mani_skill.utils.building.actors.common

"""
Common utilities for adding primitive prebuilt shapes to a scene
"""

from typing import Optional, Union

import numpy as np
import sapien
import sapien.render

from mani_skill.envs.scene import ManiSkillScene
from mani_skill.utils.building.actor_builder import ActorBuilder
from mani_skill.utils.structs.pose import Pose
from mani_skill.utils.structs.types import Array


[docs]def get_actor_builder( scene: ManiSkillScene, id: str, add_collision: bool = True, add_visual: bool = True ) -> ActorBuilder: """Returns an :py:class:`~mani_skill.utils.building.actor_builder.ActorBuilder` given an ID specifying which dataset/source and then the ID of the asset. Currently these IDs are hardcoded for a few datasets. We may add more actor datasets in the future for easy loading by users Args: scene: The ManiSkillScene. If building a custom task this is generally just self.scene id (str): The unique ID identifying the dataset and the ID of the actor in that dataset to build. The format should be "<dataset_id>:<actor_id_in_dataset>" add_collision (bool): Whether to include the collision shapes/meshes add_visual (bool): Whether to include visual shapes/meshes """ splits = id.split(":") dataset_source = splits[0] actor_id = ":".join(splits[1:]) if dataset_source == "ycb": from mani_skill.utils.building.actors.ycb import get_ycb_builder builder = get_ycb_builder( scene=scene, id=actor_id, add_collision=add_collision, add_visual=add_visual ) else: raise RuntimeError(f"No dataset with id {dataset_source} was found") return builder
[docs]def _build_by_type( builder: ActorBuilder, name, body_type, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): if scene_idxs is not None: builder.set_scene_idxs(scene_idxs) if initial_pose is not None: builder.set_initial_pose(initial_pose) if body_type == "dynamic": actor = builder.build(name=name) elif body_type == "static": actor = builder.build_static(name=name) elif body_type == "kinematic": actor = builder.build_kinematic(name=name) else: raise ValueError(f"Unknown body type {body_type}") return actor
# Primitive Shapes
[docs]def build_cube( scene: ManiSkillScene, half_size: float, color, name: str, body_type: str = "dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): builder = scene.create_actor_builder() if add_collision: builder.add_box_collision( half_size=[half_size] * 3, ) builder.add_box_visual( half_size=[half_size] * 3, material=sapien.render.RenderMaterial( base_color=color, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]def build_box( scene: ManiSkillScene, half_sizes, color, name: str, body_type: str = "dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): builder = scene.create_actor_builder() if add_collision: builder.add_box_collision( half_size=half_sizes, ) builder.add_box_visual( half_size=half_sizes, material=sapien.render.RenderMaterial( base_color=color, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]def build_cylinder( scene: ManiSkillScene, radius: float, half_length: float, color, name: str, body_type: str = "dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): builder = scene.create_actor_builder() if add_collision: builder.add_cylinder_collision( radius=radius, half_length=half_length, ) builder.add_cylinder_visual( radius=radius, half_length=half_length, material=sapien.render.RenderMaterial( base_color=color, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]def build_sphere( scene: ManiSkillScene, radius: float, color, name: str, body_type: str = "dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): builder = scene.create_actor_builder() if add_collision: builder.add_sphere_collision( radius=radius, ) builder.add_sphere_visual( radius=radius, material=sapien.render.RenderMaterial( base_color=color, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]def build_red_white_target( scene: ManiSkillScene, radius: float, thickness: float, name: str, body_type: str = "dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): TARGET_RED = np.array([194, 19, 22, 255]) / 255 builder = scene.create_actor_builder() builder.add_cylinder_visual( radius=radius, half_length=thickness / 2, material=sapien.render.RenderMaterial(base_color=TARGET_RED), ) builder.add_cylinder_visual( radius=radius * 4 / 5, half_length=thickness / 2 + 1e-5, material=sapien.render.RenderMaterial(base_color=[1, 1, 1, 1]), ) builder.add_cylinder_visual( radius=radius * 3 / 5, half_length=thickness / 2 + 2e-5, material=sapien.render.RenderMaterial(base_color=TARGET_RED), ) builder.add_cylinder_visual( radius=radius * 2 / 5, half_length=thickness / 2 + 3e-5, material=sapien.render.RenderMaterial(base_color=[1, 1, 1, 1]), ) builder.add_cylinder_visual( radius=radius * 1 / 5, half_length=thickness / 2 + 4e-5, material=sapien.render.RenderMaterial(base_color=TARGET_RED), ) if add_collision: builder.add_cylinder_collision( radius=radius, half_length=thickness / 2, ) builder.add_cylinder_collision( radius=radius * 4 / 5, half_length=thickness / 2 + 1e-5, ) builder.add_cylinder_collision( radius=radius * 3 / 5, half_length=thickness / 2 + 2e-5, ) builder.add_cylinder_collision( radius=radius * 2 / 5, half_length=thickness / 2 + 3e-5, ) builder.add_cylinder_collision( radius=radius * 1 / 5, half_length=thickness / 2 + 4e-5, ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]def build_twocolor_peg( scene: ManiSkillScene, length, width, color_1, color_2, name: str, body_type="dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): builder = scene.create_actor_builder() if add_collision: builder.add_box_collision( half_size=[length, width, width], ) builder.add_box_visual( pose=sapien.Pose(p=[-length / 2, 0, 0]), half_size=[length / 2, width, width], material=sapien.render.RenderMaterial( base_color=color_1, ), ) builder.add_box_visual( pose=sapien.Pose(p=[length / 2, 0, 0]), half_size=[length / 2, width, width], material=sapien.render.RenderMaterial( base_color=color_2, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]RED_COLOR = [220 / 255, 12 / 255, 12 / 255, 1]
[docs]BLUE_COLOR = [0 / 255, 44 / 255, 193 / 255, 1]
[docs]GREEN_COLOR = [17 / 255, 190 / 255, 70 / 255, 1]
[docs]def build_fourcolor_peg( scene: ManiSkillScene, length, width, name: str, color_1=RED_COLOR, color_2=BLUE_COLOR, color_3=GREEN_COLOR, color_4=[1, 1, 1, 1], body_type="dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): """ A peg with four sections and four different colors. Useful for visualizing every possible rotation without any symmetries """ builder = scene.create_actor_builder() if add_collision: builder.add_box_collision( half_size=[length, width, width], ) builder.add_box_visual( pose=sapien.Pose(p=[-length / 2, -width / 2, 0]), half_size=[length / 2, width / 2, width], material=sapien.render.RenderMaterial( base_color=color_1, ), ) builder.add_box_visual( pose=sapien.Pose(p=[length / 2, -width / 2, 0]), half_size=[length / 2, width / 2, width], material=sapien.render.RenderMaterial( base_color=color_2, ), ) builder.add_box_visual( pose=sapien.Pose(p=[-length / 2, width / 2, 0]), half_size=[length / 2, width / 2, width], material=sapien.render.RenderMaterial( base_color=color_3, ), ) builder.add_box_visual( pose=sapien.Pose(p=[length / 2, width / 2, 0]), half_size=[length / 2, width / 2, width], material=sapien.render.RenderMaterial( base_color=color_4, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)
[docs]def build_colorful_cube( scene: ManiSkillScene, half_size: float, color, name: str, body_type: str = "dynamic", add_collision: bool = True, scene_idxs: Optional[Array] = None, initial_pose: Optional[Union[Pose, sapien.Pose]] = None, ): builder = scene.create_actor_builder() if add_collision: builder._mass = 0.1 cube_material = sapien.pysapien.physx.PhysxMaterial( static_friction=5, dynamic_friction=3, restitution=0 ) builder.add_box_collision( half_size=[half_size] * 3, material=cube_material, ) builder.add_box_visual( half_size=[half_size] * 3, material=sapien.render.RenderMaterial( base_color=color, ), ) return _build_by_type(builder, name, body_type, scene_idxs, initial_pose)