예제 #1
0
    def set_camera(self, camera_name, pos, quat, camera_attribs=None):
        """
        Sets a camera with @camera_name. If the camera already exists, then this overwrites its pos and quat values.

        Args:
            camera_name (str): Camera name to search for / create
            pos (3-array): (x,y,z) coordinates of camera in world frame
            quat (4-array): (w,x,y,z) quaternion of camera in world frame
            camera_attribs (dict): If specified, should be additional keyword-mapped attributes for this camera.
                See http://www.mujoco.org/book/XMLreference.html#camera for exact attribute specifications.
        """
        # Determine if camera already exists
        camera = find_elements(root=self.worldbody,
                               tags="camera",
                               attribs={"name": camera_name},
                               return_first=True)

        # Compose attributes
        if camera_attribs is None:
            camera_attribs = {}
        camera_attribs["pos"] = array_to_string(pos)
        camera_attribs["quat"] = array_to_string(quat)

        if camera is None:
            # If camera doesn't exist, then add a new camera with the specified attributes
            self.worldbody.append(
                new_element(tag="camera", name=camera_name, **camera_attribs))
        else:
            # Otherwise, we edit all specified attributes in that camera
            for attrib, value in camera_attribs.items():
                camera.set(attrib, value)
예제 #2
0
 def _get_collision(self, site=False, ob_type="box"):
     main_body = ET.Element("body")
     main_body.set("name", self.name)
     template = self.get_collision_attrib_template()
     template["name"] = self.name
     template["type"] = ob_type
     if self.material == "default":
         template["rgba"] = "0.5 0.5 0.5 1" # mujoco default
         template["material"] = "{}_mat".format(self.name)
     elif self.material is not None:
         template["material"] = self.material.mat_attrib["name"]
     else:
         template["rgba"] = array_to_string(self.rgba)
     template["size"] = array_to_string(self.size)
     template["density"] = str(self.density)
     template["friction"] = array_to_string(self.friction)
     template["solref"] = array_to_string(self.solref)
     template["solimp"] = array_to_string(self.solimp)
     main_body.append(ET.Element("geom", attrib=template))
     if site:
         # add a site as well
         template = self.get_site_attrib_template()
         template["name"] = self.name
         main_body.append(ET.Element("site", attrib=template))
     return main_body
예제 #3
0
    def place_objects(self):
        """Places objects randomly until no collisions or max iterations hit."""

        pos_arr, quat_arr = self.initializer.sample(self.push_object_idx)
        for i in range(len(self.xml_objects)):
            self.xml_objects[i].set("pos", array_to_string(pos_arr[i]))
            self.xml_objects[i].set("quat", array_to_string(quat_arr[i]))
예제 #4
0
    def configure_location(self):
        """Configures correct locations for this arena"""
        # Run superclass first
        super().configure_location()

        # Determine peg friction
        friction = max(0.001, np.random.normal(self.table_friction[0], self.table_friction_std))

        # Grab reference to the table body in the xml
        table_subtree = self.worldbody.find(".//body[@name='{}']".format("table"))

        # Define start position for drawing the line
        pos = self.sample_start_pos()

        # Define dirt material for markers
        tex_attrib = {
            "type": "cube",
        }
        mat_attrib = {
            "texrepeat": "1 1",
            "specular": "0.0",
            "shininess": "0.0",
        }
        dirt = CustomMaterial(
            texture="Dirt",
            tex_name="dirt",
            mat_name="dirt_mat",
            tex_attrib=tex_attrib,
            mat_attrib=mat_attrib,
        )

        # Define line(s) drawn on table
        for i in range(self.num_sensors):
            # If we're using two clusters, we resample the starting position and direction at the halfway point
            if self.two_clusters and i == int(np.floor(self.num_sensors / 2)):
                pos = self.sample_start_pos()
            square_name2 = 'contact_'+str(i)
            square2 = CylinderObject(
                name=square_name2,
                size=[self.line_width / 2, 0.001],
                rgba=[1, 1, 1, 1],
                density=1,
                material=dirt,
                friction=friction,
            )
            self.merge_asset(square2)
            visual_c = square2.get_visual(site=True)
            visual_c.set("pos", array_to_string([pos[0], pos[1], self.table_half_size[2]]))
            visual_c.find("site").set("pos", [0, 0, 0.005])
            visual_c.find("site").set("rgba", array_to_string([0, 0, 0, 0]))
            table_subtree.append(visual_c)

            sensor_name = square_name2 + "_sensor"
            sensor_site_name = square_name2
            self.sensor_names += [sensor_name]
            self.sensor_site_names[sensor_name] = sensor_site_name

            # Add to the current dirt path
            pos = self.sample_path_pos(pos)
예제 #5
0
    def place_objects_not_random(self):
        """Places objects randomly until no collisions or max iterations hit."""
        #pos_arr = [np.array([ 0.53522776, -0.0287869 ,  0.82162434])]
        #quat_arr = [[0.8775825618903728, 0, 0, 0.479425538604203]]

        pos_arr = self.box_pos_array
        quat_arr = self.box_quat_array

        for i in range(len(self.objects)):
            self.objects[i].set("pos", array_to_string(pos_arr[i]))
            self.objects[i].set("quat", array_to_string(quat_arr[i]))
예제 #6
0
    def place_objects_plus_fixed(self):
        """Places objects randomly until no collisions or max iterations hit. 
            and the object in use to a defined location
        """
        placed_objects = []
        index = 0

        # place objects by rejection sampling
        for _, obj_mjcf in self.mujoco_objects.items():
            horizontal_radius = obj_mjcf.get_horizontal_radius()
            bottom_offset = obj_mjcf.get_bottom_offset()
            success = False
            # Fixing position of defined object
            if index == self.obj_id:
                pos = self.obj_fixed_loc[0]
                placed_objects.append((pos, horizontal_radius))
                self.objects[index].set("pos", array_to_string(pos))
                quat = self.obj_fixed_loc[1]
                self.objects[index].set("quat", array_to_string(quat))
                success = True
                continue
            for _ in range(5000):  # 5000 retries
                bin_x_half = self.bin_size[0] / 2 - horizontal_radius - 0.05
                bin_y_half = self.bin_size[1] / 2 - horizontal_radius - 0.05
                object_x = np.random.uniform(high=bin_x_half, low=-bin_x_half)
                object_y = np.random.uniform(high=bin_y_half, low=-bin_y_half)

                # make sure objects do not overlap
                object_xy = np.array([object_x, object_y, 0])
                pos = self.bin_offset - bottom_offset + object_xy
                location_valid = True
                for pos2, r in placed_objects:
                    dist = np.linalg.norm(pos[:2] - pos2[:2], np.inf)
                    if dist <= r + horizontal_radius:
                        location_valid = False
                        break

                # place the object
                if location_valid:
                    # add object to the position
                    placed_objects.append((pos, horizontal_radius))
                    self.objects[index].set("pos", array_to_string(pos))
                    # random z-rotation
                    quat = self.sample_quat()
                    self.objects[index].set("quat", array_to_string(quat))
                    success = True
                    break

            # raise error if all objects cannot be placed after maximum retries
            if not success:
                raise RandomizationError("Cannot place all objects in the bins")
            index += 1
예제 #7
0
    def move_objects_random(self):
        """Places objects randomly until no collisions or max iterations hit."""
        placed_objects = []
        index = 0
        count = 0

        # place objects by rejection sampling
        for _, obj_mjcf in self.mujoco_objects.items():
            horizontal_radius = obj_mjcf.get_horizontal_radius()
            bottom_offset = obj_mjcf.get_bottom_offset()
            success = False

            for _ in range(5000):  # 5000 retries
                bin_x_half = 0.1 - horizontal_radius - 0.01
                bin_y_half = 0.15 - horizontal_radius - 0.01
                object_x = np.random.uniform(high=bin_x_half, low=-bin_x_half)
                object_y = np.random.uniform(high=bin_y_half, low=-bin_y_half)

                # make sure objects do not overlap
                object_xy = np.array([object_x, object_y, 0])
                pos = self.bin2_offset - bottom_offset + object_xy
                location_valid = True
                for pos2, r in placed_objects:
                    dist = np.linalg.norm(pos[:2] - pos2[:2], np.inf)
                    if dist <= r + horizontal_radius:
                        location_valid = False
                        break

                # place the object
                if location_valid:
                    # add object to the position
                    placed_objects.append((pos, horizontal_radius))
                    self.objects[index].set("pos", array_to_string(pos))
                    # random z-rotation
                    quat = self.sample_quat()
                    self.objects[index].set("quat", array_to_string(quat))
                    success = True
                    # time.sleep(1)
                    break

            if success:
                count += 1
            # raise error if all objects cannot be placed after maximum retries
            # if not success:
            #     raise RandomizationError("Cannot place all objects in the bins")
            index += 1

        print("Placed %d objects in bin" % count)
예제 #8
0
def drop_cube_on_body_demo():
    world = MujocoWorldBase()
    arena = EmptyArena()
    arena.set_origin([0, 0, 0])
    world.merge(arena)

    soft_torso = SoftTorsoObject()
    obj = soft_torso.get_collision()

    box = BoxObject()
    box_obj = box.get_collision()

    obj.append(new_joint(name='soft_torso_free_joint', type='free'))
    box_obj.append(new_joint(name='box_free_joint', type='free'))

    world.merge_asset(soft_torso)

    world.worldbody.append(obj)
    world.worldbody.append(box_obj)

    # Place torso on ground
    collision_soft_torso = world.worldbody.find("./body")
    collision_soft_torso.set("pos", array_to_string(np.array([-0.1, 0, 0.1])))

    model = world.get_model(mode="mujoco_py")
    sim = MjSim(model)
    viewer = MjViewer(sim)

    for _ in range(10000):

        sim.step()
        viewer.render()
예제 #9
0
    def place_visual(self):
        """Places visual objects randomly until no collisions or max iterations hit."""
        index = 0
        bin_pos = string_to_array(self.bin2_body.get("pos"))
        bin_size = self.bin_size

        for _, obj_mjcf in self.visual_objects:

            bin_x_low = bin_pos[0]
            bin_y_low = bin_pos[1]
            if index == 0 or index == 2:
                bin_x_low -= bin_size[0] / 2
            if index < 2:
                bin_y_low -= bin_size[1] / 2

            bin_x_high = bin_x_low + bin_size[0] / 2
            bin_y_high = bin_y_low + bin_size[1] / 2
            bottom_offset = obj_mjcf.get_bottom_offset()

            bin_range = [bin_x_low + bin_x_high, bin_y_low + bin_y_high, 2 * bin_pos[2]]
            bin_center = np.array(bin_range) / 2.0

            pos = bin_center - bottom_offset
            self.visual_obj_mjcf[index].set("pos", array_to_string(pos))
            index += 1
예제 #10
0
 def set_origin(self, offset):
     """Applies a constant offset to all objects."""
     offset = np.array(offset)
     for node in self.worldbody.findall("./*[@pos]"):
         cur_pos = string_to_array(node.get("pos"))
         new_pos = cur_pos + offset
         node.set("pos", array_to_string(new_pos))
예제 #11
0
    def add_mount(self, mount):
        """
        Mounts @mount to arm.

        Throws error if robot already has a mount or if mount type is incorrect.

        Args:
            mount (MountModel): mount MJCF model

        Raises:
            ValueError: [mount already added]
        """
        if self.mount is not None:
            raise ValueError("Mount already added for this robot!")

        # First adjust mount's base position
        offset = self.base_offset - mount.top_offset
        mount._elements["root_body"].set("pos", array_to_string(offset))

        self.merge(mount, merge_body=self.root_body)

        self.mount = mount

        # Update cameras in this model
        self.cameras = self.get_element_names(self.worldbody, "camera")
예제 #12
0
 def place_objects(self):
     """
     Places objects randomly on table until no collisions or max iterations hit.
     """
     pos_arr, _ = self.initializer.sample()
     for i in range(len(self.objects_on_table)):
         self.objects_on_table[i].set("pos", array_to_string(pos_arr[i]))
     return pos_arr
예제 #13
0
파일: cube_exp.py 프로젝트: itaicaspi/coach
    def _get_cube_material(self):
        from robosuite.utils.mjcf_utils import array_to_string
        rgba = (1, 0, 0, 1)
        cube_material = CustomMaterial(
            texture=rgba,
            tex_name="solid",
            mat_name="solid_mat",
        )
        cube_material.tex_attrib.pop('file')
        cube_material.tex_attrib["type"] = "cube"
        cube_material.tex_attrib["builtin"] = "flat"
        cube_material.tex_attrib["rgb1"] = array_to_string(rgba[:3])
        cube_material.tex_attrib["rgb2"] = array_to_string(rgba[:3])
        cube_material.tex_attrib["width"] = "100"
        cube_material.tex_attrib["height"] = "100"

        return cube_material
예제 #14
0
    def get_collision_attrib_template():
        """
        Generates template with collision attributes for a given geom

        Returns:
            dict: Initial template with `'pos'` and `'group'` already specified
        """
        return {"group": "0", "rgba": array_to_string(OBJECT_COLLISION_COLOR)}
예제 #15
0
 def set_joint_damping(self,
                       damping=np.array((0.1, 0.1, 0.1, 0.1, 0.1, 0.01))):
     """Set joint damping """
     body = self._base_body
     for i in range(len(self._link_body)):
         body = body.find("./body[@name='{}']".format(self._link_body[i]))
         joint = body.find("./joint[@name='{}']".format(self._joints[i]))
         joint.set("damping", array_to_string(np.array([damping[i]])))
예제 #16
0
 def set_joint_frictionloss(self,
                            friction=np.array(
                                (0.1, 0.1, 0.1, 0.1, 0.1, 0.01))):
     """Set joint friction loss (static friction)"""
     body = self._base_body
     for i in range(len(self._link_body)):
         body = body.find("./body[@name='{}']".format(self._link_body[i]))
         joint = body.find("./joint[@name='{}']".format(self._joints[i]))
         joint.set("frictionloss", array_to_string(np.array([friction[i]])))
예제 #17
0
    def set_base_xpos(self, pos):
        """
        Places the robot on position @pos.

        Args:
            pos (3-array): (x,y,z) position to place robot base
        """
        node = self.worldbody.find("./body[@name='{}']".format(self._root_))
        node.set("pos", array_to_string(pos - self.bottom_offset))
예제 #18
0
    def set_base_xpos(self, pos):
        """
        Places the robot on position @pos.

        Args:
            pos (3-array): (x,y,z) position to place robot base
        """
        self._elements["root_body"].set(
            "pos", array_to_string(pos - self.bottom_offset))
예제 #19
0
    def _append_object(self, root, obj, parent_name=None, pos=None, quat=None):
        """
        Helper function to add pre-generated object @obj to the body with name @parent_name

        Args:
            root (ET.Element): Top-level element to iteratively search through for @parent_name to add @obj to
            obj (MujocoObject): Object to append to the body specified by @parent_name
            parent_name (None or str): Body name to search for in @root to append @obj to.
                None defaults to "root" (top-level body)
            pos (None or 3-array): (x,y,z) relative offset from parent body when appending @obj.
                None defaults to (0,0,0)
            quat (None or 4-array) (w,x,y,z) relative quaternion rotation from parent body when appending @obj.
                None defaults to (1,0,0,0)
        """
        # Set defaults if any are None
        if parent_name is None:
            parent_name = "root"
        if pos is None:
            pos = np.zeros(3)
        if quat is None:
            quat = np.array([1, 0, 0, 0])
        # First, find parent body
        parent = find_elements(root=root,
                               tags="body",
                               attribs={"name": parent_name},
                               return_first=True)
        assert parent is not None, "Could not find parent body with name: {}".format(
            parent_name)
        # Get the object xml element tree, remove its top-level joints, and modify its top-level pos / quat
        child = obj.get_obj()
        self._remove_joints(child)
        child.set("pos", array_to_string(pos))
        child.set("quat", array_to_string(quat))
        # Add this object and its assets to this composite object
        self.merge_assets(other=obj)
        parent.append(child)
        # Update geometric properties for this composite object
        obj_abs_pos = self._object_absolute_positions[parent_name] + np.array(
            pos)
        self._object_absolute_positions[obj.root_body] = obj_abs_pos
        self._top = max(self._top, obj_abs_pos[2] + obj.top_offset[2])
        self._bottom = min(self._bottom, obj_abs_pos[2] + obj.bottom_offset[2])
        self._horizontal = max(self._horizontal,
                               max(obj_abs_pos[:2]) + obj.horizontal_radius)
예제 #20
0
    def set_base_ori(self, rot):
        """
        Rotates robot by rotation @rot from its original orientation.

        Args:
            rot (3-array): (r,p,y) euler angles specifying the orientation for the robot base
        """
        # xml quat assumes w,x,y,z so we need to convert to this format from outputted x,y,z,w format from fcn
        rot = mat2quat(euler2mat(rot))[[3, 0, 1, 2]]
        self._elements["root_body"].set("quat", array_to_string(rot))
예제 #21
0
    def set_base_ori(self, rot):
        """
        Rotates robot by rotation @rot from its original orientation.

        Args:
            rot (3-array): (r,p,y) euler angles specifying the orientation for the robot base
        """
        node = self.worldbody.find("./body[@name='{}']".format(self._root_))
        # xml quat assumes w,x,y,z so we need to convert to this format from outputted x,y,z,w format from fcn
        rot = mat2quat(euler2mat(rot))[[3, 0, 1, 2]]
        node.set("quat", array_to_string(rot))
예제 #22
0
    def configure_location(self):
        """Configures correct locations for this arena"""
        self.bottom_pos = np.array([0, 0, 0])
        self.floor.set("pos", array_to_string(self.bottom_pos))

        self.center_pos = self.bottom_pos + np.array(
            [0, 0, -self.table_half_size[2]]) + self.table_offset
        self.table_body.set("pos", array_to_string(self.center_pos))
        self.table_collision.set("size", array_to_string(self.table_half_size))
        self.table_collision.set("friction",
                                 array_to_string(self.table_friction))
        self.table_visual.set("size", array_to_string(self.table_half_size))

        self.table_top.set(
            "pos", array_to_string(np.array([0, 0, self.table_half_size[2]])))

        # If we're not using legs, set their size to 0
        if not self.has_legs:
            for leg in self.table_legs_visual:
                leg.set("rgba", array_to_string([1, 0, 0, 0]))
                leg.set("size", array_to_string([0.0001, 0.0001]))
        else:
            # Otherwise, set leg locations appropriately
            delta_x = [0.1, -0.1, -0.1, 0.1]
            delta_y = [0.1, 0.1, -0.1, -0.1]
            for leg, dx, dy in zip(self.table_legs_visual, delta_x, delta_y):
                # If x-length of table is less than a certain length, place leg in the middle between ends
                # Otherwise we place it near the edge
                x = 0
                if self.table_half_size[0] > abs(dx * 2.0):
                    x += np.sign(dx) * self.table_half_size[0] - dx
                # Repeat the same process for y
                y = 0
                if self.table_half_size[1] > abs(dy * 2.0):
                    y += np.sign(dy) * self.table_half_size[1] - dy
                # Get z value
                z = (self.table_offset[2] - self.table_half_size[2]) / 2.0
                # Set leg position
                leg.set("pos", array_to_string([x, y, -z]))
                # Set leg size
                leg.set("size", array_to_string([0.025, z]))
예제 #23
0
    def _get_object_subtree_(self, ob_type="box"):
        # Create element tree
        obj = new_body(name="main")

        # Get base element attributes
        element_attr = {
            "name": "g0",
            "type": ob_type,
            "size": array_to_string(self.size)
        }

        # Add collision geom if necessary
        if self.obj_type in {"collision", "all"}:
            col_element_attr = deepcopy(element_attr)
            col_element_attr.update(self.get_collision_attrib_template())
            col_element_attr["density"] = str(self.density)
            col_element_attr["friction"] = array_to_string(self.friction)
            col_element_attr["solref"] = array_to_string(self.solref)
            col_element_attr["solimp"] = array_to_string(self.solimp)
            obj.append(new_geom(**col_element_attr))
        # Add visual geom if necessary
        if self.obj_type in {"visual", "all"}:
            vis_element_attr = deepcopy(element_attr)
            vis_element_attr.update(self.get_visual_attrib_template())
            vis_element_attr["name"] += "_vis"
            if self.material == "default":
                vis_element_attr["rgba"] = "0.5 0.5 0.5 1"  # mujoco default
                vis_element_attr["material"] = "mat"
            elif self.material is not None:
                vis_element_attr["material"] = self.material.mat_attrib["name"]
            else:
                vis_element_attr["rgba"] = array_to_string(self.rgba)
            obj.append(new_geom(**vis_element_attr))
        # add joint(s)
        for joint_spec in self.joint_specs:
            obj.append(new_joint(**joint_spec))
        # add a site as well
        site_element_attr = self.get_site_attrib_template()
        site_element_attr["name"] = "default_site"
        obj.append(new_site(**site_element_attr))
        return obj
예제 #24
0
    def _set_door_damping(self, damping):
        """
        Helper function to override the door friction directly in the XML

        Args:
            damping (float): damping parameter to override the ones specified in the XML
        """
        collision = self.worldbody.find("./body/body[@name='collision']")
        node = collision.find("./body[@name='frame']")
        node = node.find("./body[@name='door']")
        hinge = node.find("./joint[@name='door_hinge']")
        hinge.set("damping", array_to_string(np.array([damping])))
예제 #25
0
    def _set_door_friction(self, friction):
        """
        Helper function to override the door friction directly in the XML

        Args:
            friction (3-tuple of float): friction parameters to override the ones specified in the XML
        """
        hinge = find_elements(root=self.worldbody,
                              tags="joint",
                              attribs={"name": self.hinge_joint},
                              return_first=True)
        hinge.set("frictionloss", array_to_string(np.array([friction])))
예제 #26
0
    def set_origin(self, offset):
        """
        Applies a constant offset to all objects.

        Args:
            offset (3-tuple): (x,y,z) offset to apply to all nodes in this XML
        """
        offset = np.array(offset)
        for node in self.worldbody.findall("./*[@pos]"):
            cur_pos = string_to_array(node.get("pos"))
            new_pos = cur_pos + offset
            node.set("pos", array_to_string(new_pos))
예제 #27
0
    def _set_door_damping(self, damping):
        """
        Helper function to override the door friction directly in the XML

        Args:
            damping (float): damping parameter to override the ones specified in the XML
        """
        hinge = find_elements(root=self.worldbody,
                              tags="joint",
                              attribs={"name": self.hinge_joint},
                              return_first=True)
        hinge.set("damping", array_to_string(np.array([damping])))
예제 #28
0
    def _set_door_friction(self, friction):
        """
        Helper function to override the door friction directly in the XML

        Args:
            friction (3-tuple of float): friction parameters to override the ones specified in the XML
        """
        collision = self.worldbody.find("./body/body[@name='collision']")
        node = collision.find("./body[@name='frame']")
        node = node.find("./body[@name='door']")
        hinge = node.find("./joint[@name='door_hinge']")
        hinge.set("frictionloss", array_to_string(np.array([friction])))
예제 #29
0
    def set_goal_xpos(self, x_delta, y_delta):
        """ Sets x,y position of goal site in door model with x and y offset from door center"""

        door_center_site = self.worldbody.find(
            "./body/body/body/site[@name='door_center']")
        door_center_pos = string_to_array(door_center_site.get("pos"))
        goal_site = self.worldbody.find("./body/body/body/site[@name='goal']")
        goal_site.set(
            "pos",
            array_to_string([
                door_center_pos[0] + x_delta, door_center_pos[1] + y_delta,
                -1.0
            ]))
    def set_stiffness(self, stiffness):
        """
        Helper function to override the soft body's stiffness directly in the XML
        Args:
            stiffness (float, must be greater than zero): stiffness parameter to override the ones specified in the XML
        """
        assert stiffness > 0, 'Damping must be greater than zero'

        composite = self._get_composite_element()
        solref_str = composite.get('solrefsmooth').split(' ')
        damping = float(solref_str[1])

        solref = np.array([-stiffness, damping])
        composite.set('solrefsmooth', array_to_string(solref))