|
|
from typing import List, Tuple |
|
|
|
|
|
import mujoco |
|
|
|
|
|
from .sim_utils import get_body_geom_ids |
|
|
|
|
|
|
|
|
def check_contact( |
|
|
mj_model: mujoco.MjModel, |
|
|
mj_data: mujoco.MjData, |
|
|
bodies_1: List[str] | str, |
|
|
bodies_2: List[str] | str, |
|
|
return_all_contact_bodies: bool = False, |
|
|
) -> Tuple[bool, List[Tuple[str, str]]] | bool: |
|
|
""" |
|
|
Finds contact between two body groups. Any geom in the body is considered to be in contact. |
|
|
Args: |
|
|
mj_model (MujocoModel): Current simulation object |
|
|
mj_data (MjData): Current simulation data |
|
|
bodies_1 (str or list of int): an individual body name or list of body names. |
|
|
bodies_2 (str or list of int): another individual body name or list of body names. |
|
|
Returns: |
|
|
bool: True if any body in @bodies_1 is in contact with any body in @bodies_2. |
|
|
""" |
|
|
if isinstance(bodies_1, str): |
|
|
bodies_1 = [bodies_1] |
|
|
if isinstance(bodies_2, str): |
|
|
bodies_2 = [bodies_2] |
|
|
|
|
|
geoms_1 = [get_body_geom_ids(mj_model, mj_model.body(g).id) for g in bodies_1] |
|
|
geoms_1 = [g for geom_list in geoms_1 for g in geom_list] |
|
|
geoms_2 = [get_body_geom_ids(mj_model, mj_model.body(g).id) for g in bodies_2] |
|
|
geoms_2 = [g for geom_list in geoms_2 for g in geom_list] |
|
|
contact_bodies = [] |
|
|
for i in range(mj_data.ncon): |
|
|
contact = mj_data.contact[i] |
|
|
|
|
|
c1_in_g1 = contact.geom1 in geoms_1 |
|
|
c2_in_g2 = contact.geom2 in geoms_2 if geoms_2 is not None else True |
|
|
|
|
|
c2_in_g1 = contact.geom2 in geoms_1 |
|
|
c1_in_g2 = contact.geom1 in geoms_2 if geoms_2 is not None else True |
|
|
if (c1_in_g1 and c2_in_g2) or (c1_in_g2 and c2_in_g1): |
|
|
contact_bodies.append( |
|
|
( |
|
|
mj_model.body(mj_model.geom(contact.geom1).bodyid).name, |
|
|
mj_model.body(mj_model.geom(contact.geom2).bodyid).name, |
|
|
) |
|
|
) |
|
|
if not return_all_contact_bodies: |
|
|
break |
|
|
if return_all_contact_bodies: |
|
|
return len(contact_bodies) > 0, set(contact_bodies) |
|
|
else: |
|
|
return len(contact_bodies) > 0 |
|
|
|
|
|
|
|
|
def check_height( |
|
|
mj_model: mujoco.MjModel, |
|
|
mj_data: mujoco.MjData, |
|
|
geom_name: str, |
|
|
lower_bound: float = -float("inf"), |
|
|
upper_bound: float = float("inf"), |
|
|
): |
|
|
""" |
|
|
Checks if the height of a geom is greater than a given height. |
|
|
""" |
|
|
geom_id = mj_model.geom(geom_name).id |
|
|
return ( |
|
|
mj_data.geom_xpos[geom_id][2] < upper_bound and mj_data.geom_xpos[geom_id][2] > lower_bound |
|
|
) |
|
|
|