urdf-loader-babylonjs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,592 @@
1
+ # urdf-loader-babylonjs
2
+
3
+ Utilities for loading URDF files into Babylon.js and a Web Component that loads and renders the model.
4
+
5
+ Based on [urdf-loaders](https://github.com/gkjohnson/urdf-loaders) by gkjohnson, ported from Three.js to Babylon.js.
6
+
7
+ ![Example](/javascript/docs/javascript-example.gif)
8
+
9
+ # Installation
10
+
11
+ ```bash
12
+ npm install urdf-loader-babylonjs @babylonjs/core @babylonjs/loaders
13
+ ```
14
+
15
+ # Use
16
+
17
+ #### Basic Use
18
+
19
+ Loading a URDF file from a server.
20
+
21
+ ```js
22
+ import { Engine, Scene } from '@babylonjs/core';
23
+ import URDFLoader from 'urdf-loader-babylonjs';
24
+
25
+ // ...init Babylon.js scene...
26
+
27
+ const loader = new URDFLoader( scene );
28
+ loader.packages = {
29
+ packageName : './package/dir/' // The equivalent of a (list of) ROS package(s):// directory
30
+ };
31
+ loader.load(
32
+ 'T12/urdf/T12.URDF', // The path to the URDF within the package OR absolute
33
+ robot => {
34
+
35
+ // The robot is loaded!
36
+ robot.parent = scene.getTransformNodeByName('rootNode');
37
+
38
+ }
39
+ );
40
+ ```
41
+
42
+ #### Custom Mesh Loader & Error Handling
43
+
44
+ Implementing custom error handling and / or adding a custom loader for meshes can be done using the [loadMeshCb](#loadMeshCb) callback.
45
+
46
+ ```js
47
+ import { SceneLoader, Mesh } from '@babylonjs/core';
48
+ import '@babylonjs/loaders/glTF';
49
+ import URDFLoader from 'urdf-loader-babylonjs';
50
+
51
+ // ...init Babylon.js scene...
52
+
53
+ const loader = new URDFLoader( scene );
54
+ loader.loadMeshCb = function( path, scene, onComplete ) {
55
+
56
+ const rootUrl = path.substring(0, path.lastIndexOf('/') + 1);
57
+ const fileName = path.substring(path.lastIndexOf('/') + 1);
58
+
59
+ SceneLoader.ImportMesh('', rootUrl, fileName, scene, (meshes) => {
60
+
61
+ if (meshes.length === 1) onComplete(meshes[0]);
62
+ else {
63
+ const parent = new Mesh('root', scene);
64
+ meshes.forEach(m => { m.parent = parent; });
65
+ onComplete(parent);
66
+ }
67
+
68
+ }, null, (scene, message, err) => {
69
+
70
+ // try to load again, notify user, etc
71
+ onComplete( null, err || new Error(message) );
72
+
73
+ });
74
+
75
+ };
76
+ loader.load( 'T12/urdf/T12.URDF', robot => {
77
+
78
+ // The robot is loaded!
79
+ robot.parent = someParentNode;
80
+
81
+ } );
82
+
83
+ ```
84
+
85
+ #### From Xacro
86
+
87
+ Using [XacroParser](https://github.com/gkjohnson/xacro-parser) to process a Xacro URDF file and then parse it.
88
+
89
+ ```js
90
+ import { XacroLoader } from 'xacro-parser';
91
+ import URDFLoader from 'urdf-loader-babylonjs';
92
+
93
+ // ...init Babylon.js scene...
94
+
95
+ const url = './path/to/file.xacro';
96
+ const xacroLoader = new XacroLoader();
97
+ xacroLoader.load( url, xml => {
98
+
99
+ const urdfLoader = new URDFLoader( scene );
100
+ urdfLoader.workingPath = url.substring(0, url.lastIndexOf('/') + 1);
101
+
102
+ const robot = urdfLoader.parse( xml );
103
+ robot.parent = someParentNode;
104
+
105
+ } );
106
+ ```
107
+
108
+ ### Adjusting Joint Angles
109
+
110
+ ```js
111
+ robot.setJointValue( jointName, jointAngle );
112
+
113
+ // or
114
+
115
+ robot.joints[ jointName ].setJointValue( jointAngle );
116
+ ```
117
+
118
+ ### Coordinate System
119
+
120
+ URDF/ROS uses a right-handed coordinate system while Babylon.js uses a left-handed system. When using the `<urdf-viewer>` web component, this is handled automatically via a root transform. When using `URDFLoader.parse()` directly, you may need to apply a root transform yourself (e.g., `robot.scaling = new Vector3(1, 1, -1)` or rotate to match your scene's conventions).
121
+
122
+ ### DAE/COLLADA Support
123
+
124
+ DAE (COLLADA) files are not supported in the Babylon.js port. If your URDF references `.dae` meshes, convert them to glTF/GLB format. STL and glTF/GLB are fully supported.
125
+
126
+ # API
127
+
128
+ ## URDFOptions
129
+
130
+ List of options available on the URDFLoader class.
131
+
132
+ ### .packages
133
+
134
+ ```js
135
+ packages = '' : String | Object | ( pkg : String ) => String
136
+ ```
137
+
138
+ The path representing the `package://` directory(s) to load `package://` relative files.
139
+
140
+ If the argument is a string, then it is used to replace the `package://` prefix when loading geometry.
141
+
142
+ To specify multiple packages an object syntax is used defining the package name to the package path:
143
+ ```js
144
+ {
145
+ "package1": "./path/to/package1",
146
+ "package2": "./path/to/package2",
147
+ ...
148
+ }
149
+ ```
150
+
151
+ If the setting is set to a function then it takes the package name and is expected to return the package path.
152
+
153
+ ### .loadMeshCb
154
+
155
+ ```js
156
+ loadMeshCb = null :
157
+ (
158
+ pathToModel : string,
159
+ scene : Scene,
160
+ onComplete : ( obj : TransformNode, err ?: Error ) => void
161
+ ) => void
162
+ ```
163
+
164
+ An optional function that can be used to override the default mesh loading functionality. The default loader is specified at `URDFLoader.defaultMeshLoader`.
165
+
166
+ `pathToModel` is the url to load the model from.
167
+
168
+ `scene` is the Babylon.js `Scene` instance.
169
+
170
+ `onComplete` is called with the mesh once the geometry has been loaded.
171
+
172
+ ### .fetchOptions
173
+
174
+ ```js
175
+ fetchOptions = null : Object
176
+ ```
177
+
178
+ An optional object with the set of options to pass to the `fetch` function call used to load the URDF file.
179
+
180
+ ### .workingPath
181
+
182
+ ```js
183
+ workingPath = '' : string
184
+ ```
185
+
186
+ The path to load geometry relative to.
187
+
188
+ Defaults to the path relative to the loaded URDF file.
189
+
190
+ ### .parseVisual
191
+
192
+ ```js
193
+ parseVisual = true : boolean
194
+ ```
195
+
196
+ An optional value that can be used to enable / disable loading meshes for links from the `visual` nodes. Defaults to true.
197
+
198
+ ### .parseCollision
199
+
200
+ ```js
201
+ parseCollision = false : boolean
202
+ ```
203
+
204
+ An optional value that can be used to enable / disable loading meshes for links from the `collision` nodes. Defaults to false.
205
+
206
+ ## URDFLoader
207
+
208
+ ### .constructor
209
+
210
+ ```js
211
+ constructor( scene : Scene )
212
+ ```
213
+
214
+ Constructor. Scene is the Babylon.js scene that nodes will be created in.
215
+
216
+ ### .load
217
+
218
+ ```js
219
+ load(
220
+ urdfpath : string,
221
+ onComplete : (robot : URDFRobot) => void,
222
+ onProgress? : () => void,
223
+ onError? : (error : Error) => void
224
+ ) : void
225
+ ```
226
+
227
+ Loads and builds the specified URDF robot in Babylon.js.
228
+
229
+ Takes a path to load the urdf file from, a func to call when the robot has loaded, and a set of options.
230
+
231
+ ### .loadAsync
232
+
233
+ ```js
234
+ loadAsync( urdfpath : string ) : Promise<URDFRobot>
235
+ ```
236
+
237
+ Promise-wrapped version of `load`.
238
+
239
+ ### .parse
240
+
241
+ ```js
242
+ parse( urdfContent : string | Document | Element ) : URDFRobot
243
+ ```
244
+
245
+ Parses URDF content and returns the robot model. Takes an XML string to parse and a set of options.
246
+
247
+ If the XML document has already been parsed using `DOMParser` then either the returned `Document` or root `Element` can be passed into this function in place of the string, as well.
248
+
249
+ Note that geometry will not necessarily be loaded when the robot is returned.
250
+
251
+ ## URDFJoint
252
+
253
+ _extends TransformNode_
254
+
255
+ An object representing a robot joint.
256
+
257
+ ### .name
258
+
259
+ ```js
260
+ name : string
261
+ ```
262
+
263
+ The name of the joint.
264
+
265
+ ### .jointType
266
+
267
+ ```js
268
+ .jointType : string
269
+ ```
270
+
271
+ The type of joint. Can only be the URDF types of joints.
272
+
273
+ ### .limit
274
+
275
+ ```js
276
+ .limit : { lower : number, upper : number }
277
+ ```
278
+
279
+ An object containing the `lower` and `upper` constraints for the joint.
280
+
281
+ ### .axis
282
+
283
+ ```js
284
+ axis : Vector3
285
+ ```
286
+
287
+ The axis described for the joint.
288
+
289
+ ### .angle
290
+
291
+ _readonly_
292
+
293
+ ```js
294
+ angle : number
295
+ ```
296
+
297
+ The current position or angle for joint.
298
+
299
+ ### .ignoreLimits
300
+
301
+ ```js
302
+ ignoreLimits : boolean
303
+ ```
304
+
305
+ Whether or not to ignore the joint limits when setting a the joint position.
306
+
307
+ ### .mimicJoints
308
+
309
+ ```js
310
+ mimicJoints : URDFMimicJoints[]
311
+ ```
312
+
313
+ A list of joints which mimic this joint. These joints are updated whenever this joint is.
314
+
315
+ ### .setJointValue
316
+
317
+ ```js
318
+ setJointValue( ...jointValues : (number | null)[] ) : Boolean
319
+ ```
320
+
321
+ Sets the joint value(s) for the given joint. The interpretation of the value depends on the joint type. If the joint value specifies an angle it must be in radians. If the value specifies a distance, it must be in meters. Passing null for any component of the value will skip updating that particular component.
322
+
323
+ Returns true if the joint or any of its mimicking joints changed.
324
+
325
+ ## URDFMimicJoint
326
+
327
+ _extends URDFJoint_
328
+
329
+ An object representing a robot joint which mimics another existing joint. The value of this joint can be computed as `value = multiplier * other_joint_value + offset`.
330
+
331
+ ### .mimicJoint
332
+
333
+ ```js
334
+ mimicJoint : String
335
+ ```
336
+
337
+ The name of the joint which this joint mimics.
338
+
339
+ ### .offset
340
+
341
+ ```js
342
+ offset : Number
343
+ ```
344
+
345
+ Specifies the offset to add in the formula above. Defaults to 0 (radians for revolute joints, meters for prismatic joints).
346
+
347
+ ### .multiplier
348
+
349
+ ```js
350
+ multiplier : Number
351
+ ```
352
+
353
+ Specifies the multiplicative factor in the formula above. Defaults to 1.0.
354
+
355
+ ## URDFLink
356
+
357
+ _extends TransformNode_
358
+
359
+ ### .name
360
+
361
+ ```js
362
+ name : string
363
+ ```
364
+
365
+ The name of the link.
366
+
367
+ ## URDFRobot
368
+
369
+ _extends [URDFLink](#URDFLink)_
370
+
371
+ Object that describes the URDF Robot.
372
+
373
+ ### .robotName
374
+
375
+ ```js
376
+ robotName : string
377
+ ```
378
+
379
+ The name of the robot described in the `<robot>` tag.
380
+
381
+ ### .links
382
+
383
+ ```js
384
+ links : { [key] : URDFLink }
385
+ ```
386
+
387
+ A dictionary of `linkName : URDFLink` with all links in the robot.
388
+
389
+ ### .joints
390
+
391
+ ```js
392
+ joints : { [key] : URDFJoint }
393
+ ```
394
+
395
+ A dictionary of `jointName : URDFJoint` with all joints in the robot.
396
+
397
+ ### .colliders
398
+
399
+ ```js
400
+ colliders : { [key] : TransformNode }
401
+ ```
402
+
403
+ A dictionary of `colliderName : TransformNode` with all collision nodes in the robot.
404
+
405
+ ### .visual
406
+
407
+ ```js
408
+ visual : { [key] : TransformNode }
409
+ ```
410
+
411
+ A dictionary of `visualName : TransformNode` with all visual nodes in the robot.
412
+
413
+ ### .frames
414
+
415
+ ```js
416
+ frames : { [key] : TransformNode }
417
+ ```
418
+
419
+ A dictionary of all the named frames in the robot including links, joints, colliders, and visual.
420
+
421
+ ### .setJointValue
422
+
423
+ ```js
424
+ setJointValue( name : String, value : Number ) : Boolean
425
+ ```
426
+
427
+ Sets the joint value of the joint with the given name. Returns true if the joint changed.
428
+
429
+ ### .setJointValues
430
+
431
+ ```js
432
+ setJointValues( jointValueDictionary : Object ) : Boolean
433
+ ```
434
+
435
+ Sets the joint values for all the joints in the dictionary indexed by joint name. Returns true if a joint changed.
436
+
437
+ ## urdf-viewer Element
438
+ ```html
439
+ <!-- Register the Element -->
440
+ <script href=".../urdf-viewer-element.js"></script>
441
+ <script>customElements.define('urdf-viewer', URDFViewer)</script>
442
+
443
+ <body>
444
+ <urdf-viewer package=".../package/dir/" urdf="T12/urdf/T12.URDF" up="Z+" display-shadow ambient-color="red"></urdf-viewer>
445
+ </body>
446
+ ```
447
+
448
+ ### Attributes
449
+
450
+ #### package
451
+
452
+ Corresponds to the `package` parameter in `URDFLoader.load`. Supported are:
453
+
454
+ 1. Single package:
455
+
456
+ ```html
457
+ <!-- 1. Example for single package named `default_package` -->
458
+ <urdf-viewer package=".../path/to/default_package" ...></urdf-viewer>
459
+ ```
460
+
461
+ Fallback within 1: If the target package within the `package://` relative files do not match the default path it is assumed that the default path is the parent folder that contains the target package(s).
462
+
463
+ ```html
464
+ <!-- 1. Example for single package named `default_package` with fallback: -->
465
+ <urdf-viewer package=".../path/to/parent" ...></urdf-viewer>
466
+ <!-- since `parent` does not match `default_package`
467
+ the path ".../path/to/parent/default_package" is assumed -->
468
+ ```
469
+
470
+ 2. Serialized package map:
471
+
472
+ E.g. if the meshes of a URDF are distributed over mutliple packages.
473
+
474
+ ```html
475
+ <!-- 2. Example for serialized package map that contains `package1` and `package2` -->
476
+ <urdf-viewer package="package1:.../path/to/package1, package2:.../path/to/package1" ...></urdf-viewer>
477
+ ```
478
+
479
+ #### urdf
480
+
481
+ Corresponds to the `urdfpath` parameter in `URDFLoader.load`.
482
+
483
+ The element uses fetch options `{ mode: 'cors', credentials: 'same-origin' }` to load the urdf file.
484
+
485
+ #### ignore-limits
486
+
487
+ Whether or not the display should ignore the joint limits specified in the model when updating angles.
488
+
489
+ #### up
490
+
491
+ The axis to associate with "up" in Babylon.js. Values can be [+-][XYZ].
492
+
493
+ #### display-shadow
494
+
495
+ Whether or not the render the shadow under the robot.
496
+
497
+ #### ambient-color
498
+
499
+ The color of the ambient light specified with css colors.
500
+
501
+ #### auto-redraw
502
+
503
+ Automatically redraw the model every frame instead of waiting to be dirtied.
504
+
505
+ #### no-auto-recenter
506
+
507
+ Recenter the camera only after loading the model.
508
+
509
+ ### Properties
510
+
511
+ All of the above attributes have corresponding camel case properties.
512
+
513
+ #### .jointValues
514
+
515
+ ```js
516
+ jointValues : Object
517
+ ```
518
+
519
+ Sets or gets the jointValues of the robot as a dictionary of `joint-name` to `radian` pairs.
520
+
521
+ ### Functions
522
+
523
+ #### .setJointValue
524
+
525
+ ```js
526
+ setJointValue( jointName : String, ...jointValues : (number | null)[] ) : void
527
+ ```
528
+
529
+ Sets the given joint to the provided value(s). See URDFJoint.setJointValue.
530
+
531
+ #### .setJointValues
532
+
533
+ ```js
534
+ setJointValues( jointValueDictionary : Object ) : void
535
+ ```
536
+
537
+ Sets all joint names specified as keys to radian angle value.
538
+
539
+ #### .redraw
540
+
541
+ ```js
542
+ redraw() : void
543
+ ```
544
+
545
+ Dirty the renderer so the element will redraw next frame.
546
+
547
+ #### .recenter
548
+
549
+ ```js
550
+ recenter() : void
551
+ ```
552
+
553
+ Recenter the camera to the model and redraw.
554
+
555
+ ### Events
556
+
557
+ #### 'urdf-change'
558
+
559
+ Fires when the URDF has changed and a new one is starting to load.
560
+
561
+ #### 'ignore-limits-change'
562
+
563
+ Fires when the `ignore-limits` attribute changes.
564
+
565
+ #### 'urdf-processed'
566
+
567
+ Fires when the URDF has finished loading and getting processed.
568
+
569
+ #### 'geometry-loaded'
570
+
571
+ Fires when all the geometry has been fully loaded.
572
+
573
+ # Running the Example
574
+
575
+ Install Node.js and NPM.
576
+
577
+ Run `npm install`.
578
+
579
+ Run `npm start`.
580
+
581
+ Visit `localhost:9080/javascript/example/dev-bundle/` to view the page.
582
+
583
+ # LICENSE
584
+
585
+ The software is available under the [Apache V2.0 license](../LICENSE).
586
+
587
+ Copyright © 2020 California Institute of Technology. ALL RIGHTS
588
+ RESERVED. United States Government Sponsorship Acknowledged.
589
+ Neither the name of Caltech nor its operating division, the
590
+ Jet Propulsion Laboratory, nor the names of its contributors may be
591
+ used to endorse or promote products derived from this software
592
+ without specific prior written permission.
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "urdf-loader-babylonjs",
3
+ "version": "0.1.0",
4
+ "description": "URDF Loader for Babylon.js and webcomponent viewer",
5
+ "main": "src/URDFLoader.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "start": "concurrently \"rollup -w -c\" \"vite --config ./vite.config.js\"",
9
+ "build": "rollup -c",
10
+ "build-examples": "vite build --config ./vite.config.js",
11
+ "test": "vitest run",
12
+ "lint": "eslint \"./src/*.js\" \"./test/*.js\" && tsc -p tsconfig.json --noEmit",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "files": [
16
+ "src/*",
17
+ "umd/*"
18
+ ],
19
+ "license": "Apache-2.0",
20
+ "keywords": [
21
+ "javascript",
22
+ "babylonjs",
23
+ "babylon.js",
24
+ "graphics",
25
+ "ros",
26
+ "robotics",
27
+ "urdf",
28
+ "urdf-models",
29
+ "webcomponents"
30
+ ],
31
+ "peerDependencies": {
32
+ "@babylonjs/core": ">=6.0.0",
33
+ "@babylonjs/loaders": ">=6.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@babylonjs/core": "^7.0.0",
37
+ "@babylonjs/loaders": "^7.0.0",
38
+ "@eslint/js": "^9.19.0",
39
+ "@rollup/plugin-node-resolve": "^16.0.0",
40
+ "@vitest/eslint-plugin": "^1.1.25",
41
+ "@webcomponents/webcomponentsjs": "^2.4.4",
42
+ "concurrently": "^6.2.1",
43
+ "eslint": "^9.19.0",
44
+ "globals": "^15.14.0",
45
+ "jsdom": "^17.0.0",
46
+ "node-fetch": "^3.0.0",
47
+ "vite": "^6.2.2",
48
+ "rollup": "^4.32.0",
49
+ "typescript": "^5.7.3",
50
+ "vitest": "^3.0.4"
51
+ },
52
+ "dependencies": {}
53
+ }
@@ -0,0 +1,80 @@
1
+ import { TransformNode, Vector3, Scene, Nullable, Node } from '@babylonjs/core';
2
+
3
+ declare class URDFBase extends TransformNode {
4
+
5
+ urdfNode: Element | null;
6
+ urdfName: string;
7
+
8
+ constructor(name?: string, scene?: Scene | null);
9
+ traverse(callback: (node: URDFBase) => void): void;
10
+ copy(source: URDFBase, recursive?: boolean): this;
11
+ clone(name: string, newParent: Nullable<Node>, doNotCloneChildren?: boolean): Nullable<TransformNode>;
12
+
13
+ }
14
+
15
+ export class URDFCollider extends URDFBase {
16
+
17
+ isURDFCollider: true;
18
+
19
+ }
20
+
21
+ export class URDFVisual extends URDFBase {
22
+
23
+ isURDFVisual: true;
24
+
25
+ }
26
+
27
+ export class URDFLink extends URDFBase {
28
+
29
+ isURDFLink: true;
30
+
31
+ }
32
+
33
+ export class URDFJoint extends URDFBase {
34
+
35
+ isURDFJoint: true;
36
+
37
+ urdfNode: Element | null;
38
+ axis: Vector3;
39
+ jointType: 'fixed' | 'continuous' | 'revolute' | 'planar' | 'prismatic' | 'floating';
40
+ angle: number;
41
+ jointValue: number[];
42
+ limit: { lower: number, upper: number };
43
+ ignoreLimits: boolean;
44
+ mimicJoints: URDFMimicJoint[];
45
+
46
+ origPosition: Vector3 | null;
47
+ origQuaternion: import('@babylonjs/core').Quaternion | null;
48
+
49
+ setJointValue(...values: (number | null)[]): boolean;
50
+
51
+ }
52
+
53
+ export class URDFMimicJoint extends URDFJoint {
54
+
55
+ mimicJoint: string;
56
+ offset: number;
57
+ multiplier: number;
58
+
59
+ updateFromMimickedJoint(...values: number[]): boolean;
60
+
61
+ }
62
+
63
+ export class URDFRobot extends URDFLink {
64
+
65
+ isURDFRobot: true;
66
+
67
+ urdfRobotNode: Element | null;
68
+ robotName: string;
69
+
70
+ links: { [ key: string ]: URDFLink };
71
+ joints: { [ key: string ]: URDFJoint };
72
+ colliders: { [ key: string ]: URDFCollider };
73
+ visual: { [ key: string ]: URDFVisual };
74
+ frames: { [ key: string ]: TransformNode };
75
+
76
+ setJointValue(jointName: string, ...values: number[]): boolean;
77
+ setJointValues(values: { [ key: string ]: number | number[] }): boolean;
78
+ getFrame(name: string): TransformNode;
79
+
80
+ }