-
|
I really like the new functionality of self-collision detection, which really release my pressure in manually correct some dexterous hand with more than 20 links. Just a quick question, how to perform the self-collision check in the code: |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
What do you mean exactly? This is how this filtering is implemented: # Lazily compute geom vertices only for geoms that need neutral overlap checks
geoms_verts: dict[int, np.ndarray] = {}
if needs_neutral_check:
self_root_indices = np.where(valid & same_root)[0]
self_root_geom_idxs = np.unique(np.concatenate([row[self_root_indices], col[self_root_indices]]))
# Compute vertices only for geoms involved in self-collision pairs,
# shrunk by 0.1% to avoid false positive when detecting self-collision
for gi in self_root_geom_idxs:
verts = tensor_to_array(geoms[gi].get_verts())
verts = verts.reshape((-1, *verts.shape[-2:]))
centroid = verts.mean(axis=1, keepdims=True)
verts = centroid + (1.0 - 1e-3) * (verts - centroid)
geoms_verts[gi] = verts
if needs_self_check:
self_root_indices = np.where(valid & same_root)[0]
for idx in self_root_indices:
i_ga, i_gb = row[idx], col[idx]
link_ga = geoms[i_ga].link
link_gb = geoms[i_gb].link
# adjacent links
# FIXME: Links should be considered adjacent if connected by only fixed joints.
if not self._solver._enable_adjacent_collision:
is_adjacent = False
link_a_, link_b_ = (link_ga, link_gb) if link_ga.idx < link_gb.idx else (link_gb, link_ga)
while link_b_.parent_idx != -1:
if link_b_.parent_idx == link_a_.idx:
is_adjacent = True
break
if not all(joint.type is gs.JOINT_TYPE.FIXED for joint in link_b_.joints):
break
link_b_ = self._solver.links[link_b_.parent_idx]
if is_adjacent:
valid[idx] = False
continue
# active in neutral configuration (qpos0)
if needs_neutral_check:
verts_a = geoms_verts[i_ga][0]
mesh_a = trimesh.Trimesh(vertices=verts_a, faces=geoms[i_ga].init_faces, process=False)
verts_b = geoms_verts[i_gb][0]
mesh_b = trimesh.Trimesh(vertices=verts_b, faces=geoms[i_gb].init_faces, process=False)
bounds_a, bounds_b = mesh_a.bounds, mesh_b.bounds
if not ((bounds_a[1] < bounds_b[0]).any() or (bounds_b[1] < bounds_a[0]).any()):
voxels_a = mesh_a.voxelized(
pitch=min(NEUTRAL_COLLISION_RES_ABS, NEUTRAL_COLLISION_RES_REL * max(mesh_a.extents))
)
voxels_b = mesh_b.voxelized(
pitch=min(NEUTRAL_COLLISION_RES_ABS, NEUTRAL_COLLISION_RES_REL * max(mesh_b.extents))
)
coords_a = voxels_a.indices_to_points(np.argwhere(voxels_a.matrix))
coords_b = voxels_b.indices_to_points(np.argwhere(voxels_b.matrix))
if voxels_a.is_filled(coords_b).any() or voxels_b.is_filled(coords_a).any():
self_colliding_pairs.append((i_ga, i_gb))
valid[idx] = False
continue |
Beta Was this translation helpful? Give feedback.
What do you mean exactly? This is how this filtering is implemented: