Failed to import URDF file

Hi all,
I’m trying to import my robot to appear in the screen through the hello_world tutorial program. When I import my robot from the GUI everything works fine, but when I try to write a code to import I get this error:

2022-02-27 17:56:14 [180,538ms] [Error] [omni.isaac.urdf] Failed to parse URDF file '0720_Model_Update.urdf'
2022-02-27 17:56:14 [180,539ms] [Error] [asyncio] [/home/USER/.local/share/ov/pkg/isaac_sim-2021.2.1/kit/python/lib/python3.7/asyncio/base_events.py:1619] Task exception was never retrieved
future: <Task finished coro=<BaseSampleExtension._on_load_world.<locals>._on_load_world_async() done, defined at /home/USER/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/base_sample/base_sample_extension.py:161> exception=Exception('object type is not supported yet')>
Traceback (most recent call last):
  File "/home/USER/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/base_sample/base_sample_extension.py", line 162, in _on_load_world_async
    await self._sample.load_world_async()
  File "/home/USER/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/base_sample/base_sample.py", line 44, in load_world_async
    self.setup_scene()
  File "/home/USER/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/user_examples/hello_world.py", line 20, in setup_scene
    ai_link = world.scene.add(imported_robot)
  File "/home/USER/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.core/omni/isaac/core/scenes/scene.py", line 81, in add
    raise Exception("object type is not supported yet")
Exception: object type is not supported yet

For now, I just want to make the robot appear on the simulation; nothing fancy. Here’s the code in hello_world.py:

from omni.isaac.examples.base_sample import BaseSample
from omni.isaac.core import World
# from omni.isaac.urdf.scripts.samples.common import import_robot
from omni.isaac.urdf import _urdf


class HelloWorld(BaseSample):
    def __init__(self) -> None:
        super().__init__()
        return

    def setup_scene(self):
        world = World.instance()
        world.scene.add_default_ground_plane()
        urdf_interface = _urdf.acquire_urdf_interface()
        import_config = _urdf.ImportConfig()
        root_path = '~/Downloads/0720_Model_Update/urdf/'
        file_name = '0720_Model_Update.urdf'
        imported_robot =  urdf_interface.parse_urdf(root_path, file_name, import_config)
        ai_link = world.scene.add(imported_robot)
        return 

Please let me know what I am doing wrong.
Thanks!

Hi @OM_Metab

The scene.add method expects an instance of RigidPrim, GeometryPrim, Robot, Articulation or XFormPrim (Core [omni.isaac.core] — isaac_sim 2021.2.0-beta.121 documentation). However, imported_robot is a omni.isaac.urdf._urdf.UrdfRobot instance.

In order to add your robot to the scene, you need to import it and create one of the supported instances such as Robot as shown in the code below

from omni.isaac.examples.base_sample import BaseSample
from omni.isaac.core import World
# from omni.isaac.urdf.scripts.samples.common import import_robot
from omni.isaac.urdf import _urdf
# ++++++++++++++++++++++++++++++++++++++
from omni.isaac.core.robots.robot import Robot
# --------------------------------------

class HelloWorld(BaseSample):
    def __init__(self) -> None:
        super().__init__()
        return

    def setup_scene(self):
        world = World.instance()
        world.scene.add_default_ground_plane()
        urdf_interface = _urdf.acquire_urdf_interface()
        import_config = _urdf.ImportConfig()
        root_path = '~/Downloads/0720_Model_Update/urdf/'
        file_name = '0720_Model_Update.urdf'
        imported_robot =  urdf_interface.parse_urdf(root_path, file_name, import_config)
        # ++++++++++++++++++++++++++++++++++++++
        prim_path = urdf_interface.import_robot(root_path, file_name, imported_robot, import_config, "my_robot")
        robot = Robot(prim_path)
        ai_link = world.scene.add(robot)
        # --------------------------------------
        return 

HI toni, thanks for your answer. I tried your code and I get a different error:

*** Failed to load '~/Downloads/0720_Model_Update/urdf//0720_Model_Update.urdf'2022-03-01 18:36:56 [175,422,794ms] [Error] [omni.isaac.urdf] Failed to parse URDF file '0720_Model_Update.urdf'
2022-03-01 18:36:56 [175,422,794ms] [Error] [asyncio] [/home/omer/.local/share/ov/pkg/isaac_sim-2021.2.1/kit/python/lib/python3.7/asyncio/base_events.py:1619] Task exception was never retrieved
future: <Task finished coro=<BaseSampleExtension._on_load_world.<locals>._on_load_world_async() done, defined at /home/omer/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/base_sample/base_sample_extension.py:161> exception=TypeError("import_robot(): incompatible function arguments. The following argument types are supported:\n    1. (self: omni.isaac.urdf._urdf.Urdf, arg0: str, arg1: str, arg2: omni.isaac.urdf._urdf.UrdfRobot, arg3: omni.isaac.urdf._urdf.ImportConfig, arg4: str) -> str\n\nInvoked with: <omni.isaac.urdf._urdf.Urdf object at 0x7f1a1a77dc70>, '~/Downloads/0720_Model_Update/urdf/', '0720_Model_Update.urdf', <omni.isaac.urdf._urdf.UrdfRobot object at 0x7f19c40e5ab0>, <omni.isaac.urdf._urdf.ImportConfig object at 0x7f19c40e59f0>")>
Traceback (most recent call last):
  File "/home/omer/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/base_sample/base_sample_extension.py", line 162, in _on_load_world_async
    await self._sample.load_world_async()
  File "/home/omer/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/base_sample/base_sample.py", line 44, in load_world_async
    self.setup_scene()
  File "/home/omer/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.examples/omni/isaac/examples/user_examples/hello_world.py", line 23, in setup_scene
    prim_path = urdf_interface.import_robot(root_path, file_name, imported_robot, import_config)
TypeError: import_robot(): incompatible function arguments. The following argument types are supported:
    1. (self: omni.isaac.urdf._urdf.Urdf, arg0: str, arg1: str, arg2: omni.isaac.urdf._urdf.UrdfRobot, arg3: omni.isaac.urdf._urdf.ImportConfig, arg4: str) -> str

Invoked with: <omni.isaac.urdf._urdf.Urdf object at 0x7f1a1a77dc70>, '~/Downloads/0720_Model_Update/urdf/', '0720_Model_Update.urdf', <omni.isaac.urdf._urdf.UrdfRobot object at 0x7f19c40e5ab0>, <omni.isaac.urdf._urdf.ImportConfig object at 0x7f19c40e59f0>

Hi.

The method import_robot expects an additional last argument (arg4: str) as shown in the code I posted above. This argument is not currently described in the documentation… and I have no clear idea of its role (even an empty string "" works) 😅

2 Likes

It works actually! The reason that it didn’t work before was because I did not passed the absolute path as root path 🤦‍♂️

changing:

root_path = '~/Downloads/0720_Model_Update/urdf/'

to

root_path = '/home/user/Downloads/0720_Model_Update/urdf/'

fixed it…

Hi, @toni.sm and @OM_Metab ,

Thanks for your discussion. It seems that the return value “prim_path” is always the urdf file name. Do you guys know how to import urdf to a predefined prim path.

prim_path = urdf_interface.import_robot(root_path, file_name, imported_robot, import_config, "my_robot")

Hi @Raincold23

You can use the omni.isaac.core extension API to do it…

from omni.isaac.core.utils.prims import move_prim, define_prim
...
path_from = urdf_interface.import_robot(root_path, file_name, imported_robot, import_config, "")
...
path_to = "/World/robots"
define_prim(path_to, "Xform")
move_prim(path_from, path_to + "/my_robot")

Hi @toni.sm ,

Thanks so much for your reply.

I find another problem. I use the following code to print some info of robot object:

robot.initialize()
print("Num of Joints: ", robot.num_dof)
print("Joint Info: ", robot.get_joints_state())

And I get the following error:

Num of Joints:  0
File "/home/**/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.core/omni/isaac/core/articulations/articulation.py", line 347, in get_joints_state
    positions=self.get_joint_positions(),
  File "/home/**/.local/share/ov/pkg/isaac_sim-2021.2.1/exts/omni.isaac.core/omni/isaac/core/articulations/articulation.py", line 286, in get_joint_positions
    joint_positions = [joint_positions[i][0] for i in range(len(joint_positions))]
TypeError: object of type 'NoneType' has no len()

The robot object knows nothing about urdf joint info. The urdf imported is the Kaya.urdf in isaac assets.

Hi @Raincold23

It seems that you need to initialize the robot after the scene is loaded and in play, e.g., in the setup_post_load method

    def setup_scene(self):
        world = World.instance()
        ...
        robot = Robot(path_from)
        self.robot = self.world.scene.add(robot)
        
    async def setup_post_load(self):
        self.robot.initialize()
        print("Num of Joints: ", self.robot.num_dof)
        print("Joint Info: ", self.robot.get_joints_state())

Hi, @toni.sm,

I think I have initialized the robot in my code:

# Setting up import configuration:
status, import_config = omni.kit.commands.execute("URDFCreateImportConfig")
import_config.merge_fixed_joints = False
import_config.convex_decomp = False
import_config.import_inertia_tensor = True
import_config.fix_base = False
import_config.distance_scale = 0.01

# Get path to extension data:
extension_path = get_extension_path_from_name("omni.isaac.urdf")
urdf_interface = _urdf.acquire_urdf_interface()
imported_robot = urdf_interface.parse_urdf(extension_path + "/data/urdf/robots/kaya/urdf", "kaya.urdf", import_config)
prim_path = urdf_interface.import_robot(extension_path + "/data/urdf/robots/kaya/urdf", "kaya.urdf", imported_robot, import_config, "my_robot")
# init robot object
robot = Robot(prim_path)
# Get stage handle
stage = omni.usd.get_context().get_stage()
robot.initialize()
print("Num of Joints: ", robot.num_dof)
print("Joint Info: ", robot.get_joints_state())

That is why I can get Num of Joints: 0. Otherwise, the num of joints will be None.

Ok, @toni.sm I have found the reason.

The robot object can return joint info only if the simulation is running.

Thanks a lot for your help!

Thanks, it worked for me!
The tutorial has to be updated, does anyone know who I can send a message to?
(this one - 8. Import URDF — Omniverse Robotics documentation)

If anyone is stuck there - add “” as an argument to the function urdf_interface.import_robot:

    prim_path = urdf_interface.import_robot(root_path, file_name, imported_robot, import_config,"")