How to detect self collision in articulation like robotic arm?

  1. Using Isaac URDF Importer I imported usd file of robot arm with
    Case 1. self collision disabled
    Case 2. self collision enabled
    Note! in all cases instaceable is enabled
  2. I passed root_path and robot prim to be checked for collision(self, ground and with other colliders).
    by parsing the meshes and calling omni.physx.get_physx_scene_query_interface().overlap_mesh(path_id_0, path_id_1, self.on_hit, False) method for each meshes. as show in the snap code below
  3. When testing for case 1(i.e self collision disabled) it reports for self collision, i.e all the adjacent robot links are in collision
  4. 1 Then I enabled Collision Enabled properties for all the joints → nothing changed and the problem
  5. When testing for case 2(i.e self collision enabled) it detects collision with ground and other objects correctly but can’t report self collision correctly. as shown in a demo below.
    Recording 2023-02-06 at 14.11.37

sample code

    def check_collision(self, prim: Usd.Prim, target_path: str):
        Check for collision of given root prim for self-collision, collision with ground, collision with other collision objects
        in a world

            prim (Usd.Prim): Root prim for the collision check
            target_path (str): Path of the already placed xform prim where the asset is added

            bool[self-collision], bool[collision with ground], bool[collision with other objects], List[objects path in collision]
        self.self_collision, self.ground_collision, self.object_collision = \
            False, False, False
        self.overlaps = []
        self.collision_root_path = target_path
        prim =  prim
        import omni.physx
        interface = omni.physx.get_physx_scene_query_interface()
        meshes = []
        get_collision_check_meshes(prim, meshes)

        # Iterate on all meshes in the added prim
        for mesh_path in meshes:
            # Get the encoded path
            path_id_0, path_id_1 = PhysicsSchemaTools.encodeSdfPath(mesh_path)
            # Look for collisions. We cannot use the direct hit count beca>
            interface.overlap_mesh(path_id_0, path_id_1, self.on_hit, False)
            #if len(self.overlaps) > 0:
            #    prim.GetReferences().ClearReferences()
            #    break
        # Return detected overlaps
        return {"self collision": self.self_collision, "ground collision": self.ground_collision, "object collision": self.object_collision, "overlaps": self.overlaps}

    def on_hit(self, hit) -> bool:
        Callback method for checking a given mesh for collisions
            hit (SceneQueryHits): Structure containing information about collision hits
            bool: True to continue scanning for collisions
        # Check that we are not hitting the ground plane (this is normal), and not having self collision
        if ("ground_plane" in hit.rigid_body or "defaultGroundPlane"):
            self.ground_collision = True
        if(self.collision_root_path in hit.rigid_body):
            self.self_collision = True
        if (hit.rigid_body not in self.overlaps):
        return True

def get_collision_check_meshes(prim: Usd.Prim, meshes: List[str]) -> None:
    Get paths to children of a prim to which collision can be added. Temporarily removes instancing
    to find subprims that are meshes.
        prim (Usd.Prim): Root prim for the collision check
        meshes (List[str]): List of children that are UsdGeomMesh for collision check. Includes
                            subprims of instanceable prims.
    instanceables = []
    for child in prim.GetChildren():
        # If the prim is instanceable, temporarily make it not instanced to get subprims.
        if child.IsInstanceable():
        # Select only meshes
        if child.IsA(UsdGeom.Mesh):
        # Recursively call the method on subprims
        get_collision_check_meshes(child, meshes)
    for modified_prim in instanceables:

Thanks for your time:)

Are you saying this is or isn’t what you are expecting to happen? It’s very common for adjacent robot link meshes to overlap (and for these reason it’s common to turn off collisions between adjacent links when simulating physics.

Can you help me understand what “the problem” is? What is your expected behavior and what are you seeing instead?

Let’s start with a simple example that we can both reproduce. I have loaded a UR10 from the “Create” menu:

I can then run this little snippet from the “Script Editor”:

from pxr import PhysicsSchemaTools

mesh_path = "/UR10/wrist_2_link/collisions"

h0, h1 = PhysicsSchemaTools.encodeSdfPath(mesh_path)

interface = omni.physx.get_physx_scene_query_interface()

def on_hit(hit):
	print("collision with ", hit.collision)
	return True

num_hits = interface.overlap_mesh(h0, h1, on_hit, False)
print("number of hits: ", num_hits)

When the robot is not in collision, I get this output:

collision with  /UR10/wrist_1_link/collisions
collision with  /UR10/wrist_2_link/collisions
collision with  /UR10/wrist_3_link/collisions
number of hits:  3

If I move the robot so that the robot is clearly overlapping I get this output where there is now an (expected) collision with the upper arm:

collision with  /UR10/upper_arm_link/collisions
collision with  /UR10/wrist_1_link/collisions
collision with  /UR10/wrist_2_link/collisions
collision with  /UR10/wrist_3_link/collisions
number of hits:  4

1 Like

@amanuel.ergogo , hope the above messages answer your questions, if not then let us know.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.