xfu314's picture
Add phantom project with submodules and dependencies
96da58e
from copy import deepcopy
from robosuite.models.objects import MujocoObject
from robosuite.models.robots import RobotModel
from robosuite.models.world import MujocoWorldBase
from robosuite.utils.mjcf_utils import get_ids
class Task(MujocoWorldBase):
"""
Creates MJCF model for a task performed.
A task consists of one or more robots interacting with a variable number of
objects. This class combines the robot(s), the arena, and the objects
into a single MJCF model.
Args:
mujoco_arena (Arena): MJCF model of robot workspace
mujoco_robots (RobotModel or list of RobotModel): MJCF model of robot model(s) (list)
mujoco_objects (None or MujocoObject or list of MujocoObject): a list of MJCF models of physical objects
Raises:
AssertionError: [Invalid input object type]
"""
def __init__(
self,
mujoco_arena,
mujoco_robots,
mujoco_objects=None,
):
super().__init__()
# Store references to all models
self.mujoco_arena = mujoco_arena
self.mujoco_robots = [mujoco_robots] if isinstance(mujoco_robots, RobotModel) else mujoco_robots
if mujoco_objects is None:
self.mujoco_objects = []
else:
self.mujoco_objects = [mujoco_objects] if isinstance(mujoco_objects, MujocoObject) else mujoco_objects
# Merge all models
self.merge_arena(self.mujoco_arena)
for mujoco_robot in self.mujoco_robots:
self.merge_robot(mujoco_robot)
self.merge_objects(self.mujoco_objects)
self._instances_to_ids = None
self._geom_ids_to_instances = None
self._site_ids_to_instances = None
self._classes_to_ids = None
self._geom_ids_to_classes = None
self._site_ids_to_classes = None
def merge_robot(self, mujoco_robot):
"""
Adds robot model to the MJCF model.
Args:
mujoco_robot (RobotModel): robot to merge into this MJCF model
"""
self.merge(mujoco_robot)
def merge_arena(self, mujoco_arena):
"""
Adds arena model to the MJCF model.
Args:
mujoco_arena (Arena): arena to merge into this MJCF model
"""
self.merge(mujoco_arena)
def merge_objects(self, mujoco_objects):
"""
Adds object models to the MJCF model.
Args:
mujoco_objects (list of MujocoObject): objects to merge into this MJCF model
"""
for mujoco_obj in mujoco_objects:
# Make sure we actually got a MujocoObject
assert isinstance(mujoco_obj, MujocoObject), "Tried to merge non-MujocoObject! Got type: {}".format(
type(mujoco_obj)
)
# Merge this object
self.merge_assets(mujoco_obj)
self.worldbody.append(mujoco_obj.get_obj())
def generate_id_mappings(self, sim):
"""
Generates IDs mapping class instances to set of (visual) geom IDs corresponding to that class instance
Args:
sim (MjSim): Current active mujoco simulation object
"""
self._instances_to_ids = {}
self._geom_ids_to_instances = {}
self._site_ids_to_instances = {}
self._classes_to_ids = {}
self._geom_ids_to_classes = {}
self._site_ids_to_classes = {}
models = [model for model in self.mujoco_objects]
for robot in self.mujoco_robots:
models += [robot] + robot.models
# Parse all mujoco models from robots and objects
for model in models:
# Grab model class name and visual IDs
cls = str(type(model)).split("'")[1].split(".")[-1]
inst = model.name
id_groups = [
get_ids(sim=sim, elements=model.visual_geoms + model.contact_geoms, element_type="geom"),
get_ids(sim=sim, elements=model.sites, element_type="site"),
]
group_types = ("geom", "site")
ids_to_instances = (self._geom_ids_to_instances, self._site_ids_to_instances)
ids_to_classes = (self._geom_ids_to_classes, self._site_ids_to_classes)
# Add entry to mapping dicts
# Instances should be unique
assert inst not in self._instances_to_ids, f"Instance {inst} already registered; should be unique"
self._instances_to_ids[inst] = {}
# Classes may not be unique
if cls not in self._classes_to_ids:
self._classes_to_ids[cls] = {group_type: [] for group_type in group_types}
for ids, group_type, ids_to_inst, ids_to_cls in zip(
id_groups, group_types, ids_to_instances, ids_to_classes
):
# Add geom, site ids
self._instances_to_ids[inst][group_type] = ids
self._classes_to_ids[cls][group_type] += ids
# Add reverse mappings as well
for idn in ids:
assert idn not in ids_to_inst, f"ID {idn} already registered; should be unique"
ids_to_inst[idn] = inst
ids_to_cls[idn] = cls
@property
def geom_ids_to_instances(self):
"""
Returns:
dict: Mapping from geom IDs in sim to specific class instance names
"""
return deepcopy(self._geom_ids_to_instances)
@property
def site_ids_to_instances(self):
"""
Returns:
dict: Mapping from site IDs in sim to specific class instance names
"""
return deepcopy(self._site_ids_to_instances)
@property
def instances_to_ids(self):
"""
Returns:
dict: Mapping from specific class instance names to {geom, site} IDs in sim
"""
return deepcopy(self._instances_to_ids)
@property
def geom_ids_to_classes(self):
"""
Returns:
dict: Mapping from geom IDs in sim to specific classes
"""
return deepcopy(self._geom_ids_to_classes)
@property
def site_ids_to_classes(self):
"""
Returns:
dict: Mapping from site IDs in sim to specific classes
"""
return deepcopy(self._site_ids_to_classes)
@property
def classes_to_ids(self):
"""
Returns:
dict: Mapping from specific classes to {geom, site} IDs in sim
"""
return deepcopy(self._classes_to_ids)