Skip to content

draped

Draped

Bases: RelativeObjectState, KinematicsMixin, BooleanStateMixin, ClothStateMixin

Source code in omnigibson/object_states/draped.py
class Draped(RelativeObjectState, KinematicsMixin, BooleanStateMixin, ClothStateMixin):
    @classmethod
    def get_dependencies(cls):
        deps = super().get_dependencies()
        deps.add(ContactBodies)
        return deps

    def _set_value(self, other, new_value):
        if not new_value:
            raise NotImplementedError("DrapedOver does not support set_value(False)")

        if not (self.obj.prim_type == PrimType.CLOTH and other.prim_type == PrimType.RIGID):
            raise ValueError("DrapedOver state requires obj1 is cloth and obj2 is rigid.")

        state = og.sim.dump_state(serialized=False)

        if sample_cloth_on_rigid(self.obj, other, randomize_xy=True) and self.get_value(other):
            return True
        else:
            og.sim.load_state(state, serialized=False)

        return False

    def _get_value(self, other):
        """
        Check whether the (cloth) object is draped on the other (rigid) object.
        The cloth object should touch the rigid object and its CoM should be below the average position of the contact points.
        """
        if not (self.obj.prim_type == PrimType.CLOTH and other.prim_type == PrimType.RIGID):
            raise ValueError("Draped state requires obj1 is cloth and obj2 is rigid.")

        # Find the links of @other that are in contact with @self.obj
        contact_links = self.obj.states[ContactBodies].get_value() & set(other.links.values())
        if len(contact_links) == 0:
            return False
        contact_link_prim_paths = {contact_link.prim_path for contact_link in contact_links}

        # Filter the contact points to only include the ones that are on the contact links
        contact_positions = []
        for contact in self.obj.contact_list():
            if len({contact.body0, contact.body1} & contact_link_prim_paths) > 0:
                contact_positions.append(contact.position)

        # The center of mass of the cloth needs to be below the average position of the contact points
        mean_contact_position = np.mean(contact_positions, axis=0)
        center_of_mass = np.mean(self.obj.root_link.keypoint_particle_positions, axis=0)
        return center_of_mass[2] < mean_contact_position[2]