How to properly load a URDF file using urdf-loader in aframe?

I am trying to load a URDF file in aframe scene to visualize it on VR. The code for aframe component is:

<script type="importmap"> { "imports": {
                    "urdf-loader":  "https://cdn.jsdelivr.net/npm/urdf-loader@0.12.1/umd/URDFLoader.js",
                    "three": "https://unpkg.com/three@0.150.1/build/three.module.js",
                    "three/addons/": "https://unpkg.com/three@0.150.1/examples/jsm/"
                } }
    </script>
    <script type="module">
      import 'urdf-loader';
      import {
        STLLoader
      } from 'three/addons/loaders/STLLoader';
      import {
        WebGLRenderer,
        Mesh,
        MathUtils,
        Bone,
        Vector3
      } from 'three';
      AFRAME.registerComponent('load-panda-urdf', {
        init: function() {
          const manager = new THREE.LoadingManager();
          const loader = new URDFLoader(manager);
          loader.load('https://raw.githubusercontent.com/StanfordASL/PandaRobot.jl/master/deps/Panda/panda.urdf', // The path to the URDF within the package OR absolute
            robot => {
              // The robot is loaded!
              this.el.sceneEl.object3D.add(robot);
            });
        },
      })
    </script>

I get these warnings

URDFLoader: Could not load model at /Panda/meshes/collision/link0.obj.
No loader available

URDFLoader: Could not load model at /Panda/meshes/collision/link1.obj.

URDFLoader: Could not load model at /Panda/meshes/collision/link2.obj.

URDFLoader: Could not load model at /Panda/meshes/collision/link3.obj.

URDFLoader: Could not load model at /Panda/meshes/collision/link4.obj.

I went through the documentation of the urdf-loaders project on github but couldn’t find any fix for this. How do I fix this?

PS:

This is the jsfiddle to try the code

It says “no loader available” in the warnings but even afrer importing the OBJLoader from threejs I am not sure where to use it.

The reason it’s not working is because you’re missing some basic set up which is described and shown at the very top of the URDF Loader README.

  1. You need to list the directories for the ROS packages used in the URDF file so the loader knows where to resolve mesh paths to:
const loader = new URDFLoader( manager );
loader.packages = {
    packageName : './package/dir/'            // The equivalent of a (list of) ROS package(s):// directory
};
  1. By default only STL and DAE files are supported by the URDF loader since these are (were?) the most common formats used in the ecosystem. So as the error states, the OBJ files cannot be loaded and you need to provide a custom loadMeshCb to handle OBJ file extensions. You can see how here in the Custom Mesh Loading section of the docs. You’ll need to load OBJ instead of GLTF, though:
loader.loadMeshCb = function( path, manager, onComplete ) {

    const loader = new OBJLoader( manager );
    loader.load(
        path,
        result => {

            onComplete( result.scene );

        },
        undefined,
        err => {
        
            // try to load again, notify user, etc
        
            onComplete( null, err );
        
        }
    );

};

Hi @gkjohnson,

Do you mean something like this?


<script type="importmap">
                { "imports": {
                    "urdf-loader":  "https://cdn.jsdelivr.net/npm/urdf-loader@0.12.1/umd/URDFLoader.js",
                    "three": "https://unpkg.com/three@0.150.1/build/three.module.js",
    				"three/addons/": "https://unpkg.com/three@0.150.1/examples/jsm/"
                } }
    </script>

    <script type="module">

        import 'urdf-loader';
        import { OBJLoader } from 'three/addons/loaders/OBJLoader';
        import { WebGLRenderer, Mesh, MathUtils, Bone, Vector3 } from 'three';

        AFRAME.registerComponent('load-panda-urdf', {
            init: function () {
                const URDF_PATH = './assets/Panda/panda.urdf';
                const manager = new THREE.LoadingManager();
                const loader = new URDFLoader(manager);
                loader.packages = {
                    package1: './assets/Panda/meshes/collision/finger.obj',
                    package2: './assets/Panda/meshes/collision/hand.obj',
                    package3: './assets/Panda/meshes/collision/link0.obj',
                    package10: './assets/Panda/meshes/collision/link1.obj',
                    package5: './assets/Panda/meshes/collision/link2.obj',
                    package6: './assets/Panda/meshes/collision/link3.obj',
                    package7: './assets/Panda/meshes/collision/link4.obj',
                    package8: './assets/Panda/meshes/collision/link5.obj',
                    package9: './assets/Panda/meshes/collision/link6.obj',
                    package10: './assets/Panda/meshes/collision/link7.obj'
                }
                loader.loadMeshCb = function (URDF_PATH, manager, onComplete) {

                    const loader = new OBJLoader(manager);
                    loader.load(
                        URDF_PATH,
                        result => {

                            onComplete(result.scene);

                        },
                        undefined,
                        err => {

                            // try to load again, notify user, etc

                            onComplete(null, err);

                        }
                    );

                };
            },
        })

    </script>

My folder structure image

panda.urdf (8.1 KB)

A ROS package is the root directory where the package contents are. In the URDF and other ROS files this directory is referenced via the package:// protocol in the file. In this case it’s package://Panda so you’ll need to specify where the package://Panda directory is so the URDF loader can resolve the mesh file paths:

loader.packages = {
   Panda: 'https://raw.githubusercontent.com/StanfordASL/PandaRobot.jl/f891b31b5b83db6104b4dea820c3672e5387b902/deps/Panda/',
}