Source code for mani_skill.utils.building.mjcf_loader

from __future__ import annotations

from typing import TYPE_CHECKING, Any, TypedDict

from mani_skill.utils.building.actor_builder import ActorBuilder
from mani_skill.utils.building.articulation_builder import ArticulationBuilder
from mani_skill.utils.structs import Actor, Articulation

if TYPE_CHECKING:
    from mani_skill.envs.scene import ManiSkillScene

from ._mjcf_loader import MJCFLoader as SAPIENMJCFLoader


[docs]class ParsedMJCFData(TypedDict):
[docs] articulation_builders: list[ArticulationBuilder]
[docs] actor_builders: list[ActorBuilder]
[docs] cameras: list[Any]
[docs]class MJCFLoader(SAPIENMJCFLoader): """ Wrapper for the SAPIEN MJCF Loader to support easy parallelization """
[docs] scene: ManiSkillScene
[docs] name: str = None
[docs] disable_self_collisions: bool = False
[docs] def parse(self, mjcf_file, package_dir=None) -> ParsedMJCFData: articulation_builders, actor_builders, cameras = super().parse( mjcf_file, package_dir ) for i, a in enumerate(articulation_builders): if len(articulation_builders) > 1: a.set_name(f"{self.name}-articulation-{i}") else: a.set_name(f"{self.name}") if self.disable_self_collisions: for l in a.link_builders: # NOTE (stao): Currently this may not be working as intended l.collision_groups[2] |= 1 << 29 for i, b in enumerate(actor_builders): b.set_name(f"{self.name}-actor-{i}") return dict( articulation_builders=articulation_builders, actor_builders=actor_builders, cameras=cameras, )
[docs] def load( self, mjcf_file: str, package_dir=None, name=None, scene_idxs=None, ) -> Articulation: """ Args: urdf_file: filename for URDL file srdf_file: SRDF for urdf_file. If srdf_file is None, it defaults to the ".srdf" file with the same as the urdf file package_dir: base directory used to resolve asset files in the URDF file. If an asset path starts with "package://", "package://" is simply removed from the file name name (str): name of the created articulation scene_idxs (list[int]): the ids of the scenes to build the objects in Returns: returns a single Articulation loaded from the URDF file. It throws an error if multiple objects exists """ if name is not None: self.name = name _parsed_mjcf_data = self.parse(mjcf_file, package_dir) articulation_builders = _parsed_mjcf_data["articulation_builders"] _parsed_mjcf_data["actor_builders"] cameras = _parsed_mjcf_data["cameras"] articulations: list[Articulation] = [] for b in articulation_builders[:1]: b.set_scene_idxs(scene_idxs) b.disable_self_collisions = self.disable_self_collisions articulations.append(b.build()) actors: list[Actor] = [] # for b in actor_builders: # actors.append(b.build()) if len(cameras) > 0: name2entity = dict() for a in articulations: for sapien_articulation in a._objs: for l in sapien_articulation.links: name2entity[l.name] = l.entity for a in actors: name2entity[a.name] = a # TODO (stao): support extracting sensors # for scene_idx, scene in enumerate(self.scene.sub_scenes): # for cam in cameras: # cam_component = RenderCameraComponent(cam["width"], cam["height"]) # if cam["fovx"] is not None and cam["fovy"] is not None: # cam_component.set_fovx(cam["fovx"], False) # cam_component.set_fovy(cam["fovy"], False) # elif cam["fovy"] is None: # cam_component.set_fovx(cam["fovx"], True) # elif cam["fovx"] is None: # cam_component.set_fovy(cam["fovy"], True) # cam_component.near = cam["near"] # cam_component.far = cam["far"] # name2entity[f"scene-{scene_idx}_{cam['reference']}"].add_component( # cam_component # ) return articulations[0]