mujoco_worldgen/util/geometry.py (42 lines of code) (raw):
import numpy as np
from mujoco_py import functions
from ctypes import c_int, addressof
from math import sqrt
def raycast(sim, geom1_id=None, geom2_id=None, pt1=None, pt2=None, geom_group=None):
'''
Given a mujoco sim, from a geom to a geom, point to a point
Args:
sim: Mujoco sim object
geom1 (int), id of geom ray originates from
geom2 (int), id of geom ray points to
p1 (np.ndarray[3]): 3D point ray originates from
p2 (np.ndarray[3]): 3D point ray points to
geom_group: one-hot list determining which of the five geom groups
should be visible to the raycast
'''
assert (geom1_id is None) != (pt1 is None), "geom1_id or p1 must be specified"
assert (geom2_id is None) != (pt2 is None), "geom2_id or p2 must be specified"
if geom1_id is not None:
pt1 = sim.data.geom_xpos[geom1_id]
body1 = sim.model.geom_bodyid[geom1_id]
else:
# Don't exclude any bodies if we originate ray from a point
body1 = np.max(sim.model.geom_bodyid) + 1
if geom2_id is not None:
pt2 = sim.data.geom_xpos[geom2_id]
ray_direction = pt2 - pt1
ray_direction /= sqrt(ray_direction[0] ** 2 + ray_direction[1] ** 2 + ray_direction[2] ** 2)
if geom_group is not None:
geom_group = np.array(geom_group).astype(np.uint8)
else:
geom_group = np.array([1, 1, 1, 1, 1]).astype(np.uint8) # This is the default geom group
# Setup int array
c_arr = (c_int*1)(0)
dist = functions.mj_ray(sim.model,
sim.data,
pt1,
ray_direction,
geom_group,
np.array([[0]]).astype(np.uint8), # flg_static. TODO idk what this is
body1, # Bodyid to exclude
addressof(c_arr))
collision_geom = c_arr[0] if c_arr[0] != -1 else None
return dist, collision_geom