Unexpected bug/change in ArticulationView of Isaac2023.1.1

I have just upgraded to Isaac 2023.1.1 from the 2023.1.0-bugfix version-
What I am seeing is a probable issue with ArticulationView, and I didn’t see anything in the release notes associated to this, so I assume this is not an expected behavior.
The following is a simple example script I have put up to reproduce the issue. The script works flawlessly in Isaac2023.1.0-bugfix, while it throws the error

2023-12-26 17:13:51 [16,525ms] [Error] [omni.physx.tensors.plugin] Pattern '/World/envs/env_*/panda' did not match any articulations

when running on Isaac2023.1.1 .

# Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#

from omni.isaac.kit import SimulationApp

simulation_app = SimulationApp({"headless": False})

import numpy as np
from omni.isaac.core import World
from omni.isaac.core.articulations import ArticulationView

from omni.importer.urdf import _urdf

# urdf import config
import_config = _urdf.ImportConfig()
import_config.merge_fixed_joints = True 
import_config.import_inertia_tensor = True
import_config.fix_base = True
import_config.self_collision = False

my_world = World(stage_units_in_meters=1.0)
my_world.scene.add_default_ground_plane()

# create initial robot
import omni.isaac.core.utils.prims as prim_utils

# create GridCloner instance
env_ns = "/World/envs"
template_env_ns = env_ns + "/env" # a single env. may contain multiple robots
base_env = template_env_ns + "_0"
base_robot_path = base_env + "/panda"

# get path to resource
from omni.isaac.core.utils.extensions import get_extension_path_from_name
extension_path = get_extension_path_from_name("omni.importer.urdf")

# import URDF at default prim path
import omni.kit
success, robot_prim_path_default = omni.kit.commands.execute(
    "URDFParseAndImportFile",
    urdf_path=extension_path + "/data/urdf/robots/franka_description/robots/panda_arm.urdf",
    import_config=import_config, 
)

# moving default prim to base prim path (for potential cloning)
from omni.isaac.core.utils.prims import move_prim
prim_utils.define_prim(base_env)
move_prim(robot_prim_path_default, # from
        base_robot_path) # to

# cloning
from omni.isaac.cloner import GridCloner

cloner = GridCloner(spacing=2)
num_envs = 4
target_paths = cloner.generate_paths(template_env_ns, num_envs)

position_offsets = np.array([[0, 0, 1]] * num_envs)
cloner.clone(
    source_prim_path=base_env,
    prim_paths=target_paths,
    position_offsets=position_offsets,
    replicate_physics=True,
    base_env_path=env_ns,
)

# Prim paths structure:
# World/envs/env_0/panda/panda_link0/...

# this works in both
# art_view = ArticulationView(name = "Panda" + "ArtView",
#                         prim_paths_expr = env_ns + "/env_.*"+ "/panda/panda_link0", 
#                         reset_xform_properties=False # required as per doc. when cloning
#                         )

# this only in 2023.1.0
art_view = ArticulationView(name = "Panda" + "ArtView",
                        prim_paths_expr = env_ns + "/env_.*"+ "/panda", 
                        reset_xform_properties=False # required as per doc. when cloning
                        )

# moreover, robots are not cloned at different locations
my_world.scene.add(art_view)

print("Extension path: " + str(extension_path))
print("Prim paths: " + str(art_view.prim_paths))

my_world.reset()
for i in range(0, 100000):
    print(art_view.get_world_poses())
    my_world.step()
simulation_app.close()

Here I am simply importing a Panda robot from urdf, moving it to a base prim path and then cloning it with the GridCloner. After that, I create a view of the Panda robot across all environments.
What happens is that, when the world.reset() is called, all the articulation views in the scene are initialized, and this steps fails for some reason.
I am able to run if, instead of providing the env_ns + “/env_."+ “/panda” path to the ArticulationView, I give it the first link of the arm, i.e. env_ns + "/env_.”+ “/panda/panda_link0”.
Something is probably wrong or, at least, an undocumented change happened there.
Also, another thing that I noticed is that the grid cloner is spawning all the robots at the same location in Isaac2023.1.1, while in 2023.1.0-bugfix the spacing works.
Can someone reproduce the issue with my script? Any fixes/explanation for this behavior?

2 Likes

I’m having a similar problem, also in 2023.1.1. I’m also importing the robot from a urdf file.

When I print the prims paths, I can see that the paths looks right:

/World
/World/envs
/World/envs/env_0
/World/envs/env_0/ur5e
/World/envs/env_0/ur5e/base_link
/World/envs/env_0/ur5e/base_link/visuals
/World/envs/env_0/ur5e/base_link/collisions
/World/envs/env_0/ur5e/base_link/base_link_base_fixed_joint
/World/envs/env_0/ur5e/base_link/shoulder_pan_joint
/World/envs/env_0/ur5e/root_joint
/World/envs/env_0/ur5e/base

But I’m having errors that prevent the training to start:

2023-12-28 12:45:42 [14,893ms] [Warning] [omni.hydra.scene_delegate.plugin] Calling getBypassRenderSkelMeshProcessing for prim /World/envs/env_0/ur5e/wrist_3_link/visuals.proto_mesh_0_id0 that has not been populated
2023-12-28 12:45:43 [15,891ms] [Warning] [omni.physx.plugin] PhysicsUSD: CreateJoint - found a joint with disjointed body transforms, the simulation will most likely snap objects together: /World/envs/env_0/ur5e/root_joint
2023-12-28 12:45:43 [15,891ms] [Warning] [omni.physx.plugin] PhysicsUSD: CreateJoint - found a joint with disjointed body transforms, the simulation will most likely snap objects together: /World/envs/env_1/ur5e/root_joint

2023-12-28 12:45:43 [15,946ms] [Warning] [omni.physx.tensors.plugin] Failed to find articulation at '/World/envs/env_0/ur5e'
2023-12-28 12:45:43 [15,946ms] [Warning] [omni.physx.tensors.plugin] Failed to find articulation at '/World/envs/env_1/ur5e'
2023-12-28 12:45:43 [15,946ms] [Error] [omni.physx.tensors.plugin] Pattern '/World/envs/*/ur5e' did not match any articulations

Everything was working fine in isaac 2023.1.0 and 2023.1.0-hotfix.1. I have updated the default asset root path as instructed here

3 Likes

@kellyg, @rgasoto, @rthaker, @Milad-Rakhsha, @AlesBorovicka, any feedback on this?

2 Likes

Hi, @AndrePatri @edsonbffilho !
I am facing the same problem. Have you found a solution?

One curious point is that I didn’t encounter this error when using the Franka’s USD provided by the official sources. However, errors occurred when I used USD files created by myself using the URDF Importer.

1 Like

I haven’t found a solution for that. I reverted to use 2023.1.0- for now…

I see. Got it!
I wish there was a way to fix it… I’ll look into it a bit more.
Thank you!

@edsonbffilho @AndrePatri
I haven’t thoroughly verified it, so it’s not a definite solution, but I was able to load the USD files, which were converted using the URDF Importer in IsaacSim2022.2.1, without encountering any of the above errors in the IsaacSim2023.1.1 environment.

Therefore, it might be a good idea to first convert the URDF files to USD files using the URDF Importer in IsaacSim2022.2.1 and then load them with scripts in IsaacSim2023.1.1. I suspect there was a bug in the URDF Importer of IsaacSim2022.2.1, so I’m not sure if the robots spawned in this manner will function correctly.

1 Like

That worked! Thanks!

I had tried that with the 2023.1.0 but not in the 2022.

I had to use the URDF importer GUI in Isaac 2022.2.1 instead of the script:

# Copyright (c) 2018-2022, NVIDIA Corporation
# Copyright (c) 2022-2023, Johnson Sun
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Ref: https://docs.omniverse.nvidia.com/isaacsim/latest/advanced_tutorials/tutorial_advanced_import_urdf.html#importing-urdf-using-python

import os

import omni.kit.commands
import omni.usd
from omni.importer.urdf import _urdf
from omni.isaac.core.utils.extensions import get_extension_path_from_name
from pxr import Sdf, UsdGeom
import getpass

def create_usd_from_urdf(urdf_path, usd_path, mesh_usd_path, instanceable_usd_path):
    print("Creating USDs from urdf")
    # Set the settings in the import config
    import_config = _urdf.ImportConfig()
    import_config.merge_fixed_joints = False
    import_config.convex_decomp = False
    import_config.import_inertia_tensor = False
    import_config.fix_base = True
    import_config.make_default_prim = True
    import_config.self_collision = False
    import_config.create_physics_scene = True
    # The two values below follows the suggestion from Step 2 in
    # `5.1.3. Using the URDF Importer Extension Window`.
    # Ref: https://docs.omniverse.nvidia.com/isaacsim/latest/advanced_tutorials/tutorial_advanced_import_urdf.html#using-the-urdf-importer-extension-window
    # However, we found that the drive strength is too large, so we reduced it to the same value as drive damping.
    import_config.default_drive_strength = 100000.0 # 10000000.0
    import_config.default_position_drive_damping = 100000.0
    # import_config.default_drive_type = _urdf.UrdfJointTargetType.JOINT_DRIVE_POSITION
    import_config.default_drive_type = _urdf.UrdfJointTargetType.JOINT_DRIVE_VELOCITY
    import_config.distance_scale = 1
    import_config.density = 0.0
    # Finally import the robot & save it as USD
    result, prim_path = omni.kit.commands.execute(
        "URDFParseAndImportFile", urdf_path=urdf_path,
        import_config=import_config, dest_path=usd_path,
    )
    import_config.make_instanceable=True
    import_config.instanceable_usd_path=mesh_usd_path
    # Finally import the robot & save it as instanceable USD
    result, prim_path = omni.kit.commands.execute(
        "URDFParseAndImportFile", urdf_path=urdf_path,
        import_config=import_config, dest_path=instanceable_usd_path,
    )

if __name__ == '__main__':

    print("Started")

    username = getpass.getuser()
    urdf_path = f"/home/{username}/omniverse-playground/nucleus/UR5e/ur5e.urdf"
    usd_path = f"/home/{username}/omniverse-playground/nucleus/UR5e/ur5e.usd"
    mesh_usd_path = f"/home/{username}/omniverse-playground/nucleus/UR5e/ur5e_inst_meshes.usd"
    inst_usd_path = f"/home/{username}/omniverse-playground/nucleus/UR5e/ur5e_inst.usd"

    print("Paths acquired")
    
    create_usd_from_urdf(urdf_path, usd_path, mesh_usd_path, inst_usd_path)
    # create_block_indicator()
    print("Done!")

This script works on 2023 but gives me the error “No module named ‘omni.importer’” in 2022.2.1

1 Like

Same here @makoto.sato385, I am using the previous version. In my case I need the urdf importer at runtime to configure the simulation, so for now I’ll stick with the old version.

1 Like

I hope this will help:

1 Like