Bases: RelativeObjectState, KinematicsMixin, BooleanStateMixin, ClothStateMixin
Source code in OmniGibson/omnigibson/object_states/draped.py
| class Draped(RelativeObjectState, KinematicsMixin, BooleanStateMixin, ClothStateMixin):
@classmethod
def get_dependencies(cls):
deps = super().get_dependencies()
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.")
# Cloth contact is only available through cloth's get_contacts() method.
contact_link_prim_paths = set(other.link_prim_paths)
contact_positions = []
for contact_prim_path, contact_position in self.obj.root_link.get_contacts():
if contact_prim_path in contact_link_prim_paths:
contact_positions.append(contact_position)
if len(contact_positions) == 0:
return False
# The center of mass of the cloth needs to be below the average position of the contact points
mean_contact_position = th.mean(th.stack(contact_positions), dim=0)
center_of_mass = th.mean(self.obj.root_link.keypoint_particle_positions, dim=0)
return center_of_mass[2] < mean_contact_position[2]
|