three-usd-robot 0.12.0 → 0.13.1
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 +31 -320
- package/dist/{MeshBinding-DQKXuYNr.d.ts → MeshBinding-B_8RhuQE.d.ts} +2 -2
- package/dist/{ThreeUsdRobot-C3N6-XBJ.d.ts → ThreeUsdRobot-X1zbpRZo.d.ts} +38 -8
- package/dist/{ThreeUsdRobotLoader-D2fEo9_p.d.ts → ThreeUsdRobotLoader-u3d1yoLM.d.ts} +3 -3
- package/dist/{buildKinematicTree-iFqaw0Jl.d.ts → buildKinematicTree-Q9JOjAjM.d.ts} +17 -3
- package/dist/{chunk-7GGSIA6M.js → chunk-5C3VTA56.js} +4 -4
- package/dist/{chunk-7GGSIA6M.js.map → chunk-5C3VTA56.js.map} +1 -1
- package/dist/{chunk-6W4LQVEQ.js → chunk-J6ZQWQ2C.js} +96 -5
- package/dist/chunk-J6ZQWQ2C.js.map +1 -0
- package/dist/{chunk-KYBHWDX5.js → chunk-JN2QPDB3.js} +100 -13
- package/dist/chunk-JN2QPDB3.js.map +1 -0
- package/dist/{chunk-CK5MTMYR.js → chunk-ZHUNBTUV.js} +78 -5
- package/dist/chunk-ZHUNBTUV.js.map +1 -0
- package/dist/core.d.ts +4 -4
- package/dist/core.js +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +1 -1
- package/dist/index.d.ts +17 -7
- package/dist/index.js +31 -7
- package/dist/index.js.map +1 -1
- package/dist/nodes.d.ts +3 -3
- package/dist/react.d.ts +4 -4
- package/dist/react.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-6W4LQVEQ.js.map +0 -1
- package/dist/chunk-CK5MTMYR.js.map +0 -1
- package/dist/chunk-KYBHWDX5.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,14 +22,12 @@ exported back to `.usda` / `.usdz` in the browser.
|
|
|
22
22
|
Multi-file assets (references / payloads / sublayers), variant selections and
|
|
23
23
|
instanceable prims are composed for you.
|
|
24
24
|
- **Robots** — links, joints (fixed / revolute / continuous / prismatic), limits,
|
|
25
|
-
drives and the initial pose become
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
and units normalized automatically. Articulation-free stages load as
|
|
32
|
-
static scenes.
|
|
25
|
+
drives, mimic couplings (gripper finger linkages) and the initial pose become
|
|
26
|
+
a `setJointValue`-able hierarchy.
|
|
27
|
+
- **Rendering** — meshes, solid gprims, point clouds and curves with `UsdShade`
|
|
28
|
+
materials (UsdPreviewSurface / Omniverse MDL / MaterialX, plus optional TSL
|
|
29
|
+
graph execution on WebGPU) and textures; up-axis and units normalized
|
|
30
|
+
automatically. Articulation-free stages load as static scenes.
|
|
33
31
|
- **Animation** — plays back time-sampled joint trajectories, and replays
|
|
34
32
|
baked body-transform recordings through `setLinkTransforms` with
|
|
35
33
|
constraint diagnostics.
|
|
@@ -55,71 +53,6 @@ The CDN is public and CORS-enabled, so this works in the browser too. Try
|
|
|
55
53
|
FK check, and a re-export to one self-contained file), or open the Vite example
|
|
56
54
|
and pick a robot from the preset list.
|
|
57
55
|
|
|
58
|
-
Materials target **UsdPreviewSurface fidelity plus Omniverse MDL and MaterialX mappings**:
|
|
59
|
-
constant and textured inputs, faceVarying / indexed UVs, multiple UV sets,
|
|
60
|
-
per-vertex display colors, physical extensions (`ior` / `clearcoat` /
|
|
61
|
-
specular workflow → `MeshPhysicalMaterial`), packed ORM maps,
|
|
62
|
-
`sourceColorSpace`, and purpose/strength-aware bindings. MDL shaders are
|
|
63
|
-
identified by `info:mdl:sourceAsset` and mapped **by family** — no shader
|
|
64
|
-
execution — and referenced `.mdl` modules are fetched and parsed for their
|
|
65
|
-
declaration values, so wrapper materials
|
|
66
|
-
(`export material X(*) = OmniPBR(…)`) render correctly even when the USD
|
|
67
|
-
shader authors no inputs at all. Value priority: authored USD inputs >
|
|
68
|
-
wrapper arguments > declaration defaults.
|
|
69
|
-
|
|
70
|
-
| MDL family | three.js mapping |
|
|
71
|
-
| --- | --- |
|
|
72
|
-
| `OmniPBR` (and derivatives, e.g. `OmniPBR_Opacity`) | color / metalness / roughness / emissive (`emissive_intensity`), per-channel texture maps and packed `ORM_texture`, opacity, normal map, `texture_translate/rotate/scale` |
|
|
73
|
-
| `OmniPBR_ClearCoat` | the OmniPBR mapping plus `clearcoat` / `clearcoatRoughness` / `clearcoatNormalMap` |
|
|
74
|
-
| `OmniGlass` | `MeshPhysicalMaterial` with `transmission` / `ior` (default 1.491) / `roughness` / `thickness`, glass color + texture |
|
|
75
|
-
| `OmniSurface(Lite)` | constants subset: diffuse color / metalness / roughness / IOR / coat / emission / opacity |
|
|
76
|
-
|
|
77
|
-
MaterialX networks authored natively in UsdShade (`outputs:mtlx:surface` +
|
|
78
|
-
`ND_*` shaders) resolve the same way — by parameter mapping, without graph
|
|
79
|
-
execution. `ND_standard_surface_surfaceshader` maps `base × base_color` /
|
|
80
|
-
`metalness` / `specular_roughness` / `specular_IOR` / `coat(_roughness)` /
|
|
81
|
-
`transmission` / `emission (× emission_color)` / `opacity` / `normal` onto
|
|
82
|
-
the standard (or, when coat / transmission / IOR are authored, physical)
|
|
83
|
-
three material; the `ND_Usd*` compatibility nodes delegate to the
|
|
84
|
-
UsdPreviewSurface readers. Image and UV nodes are supported
|
|
85
|
-
(`ND_image_*` address modes, `ND_tiledimage_*` uvtiling/uvoffset,
|
|
86
|
-
`ND_texcoord_*` UV-channel index, `ND_geompropvalue_*` primvar name,
|
|
87
|
-
`ND_normalmap`), and constant-only `ND_multiply_* / ND_mix_* / ND_convert_*`
|
|
88
|
-
(plus `ND_constant_*` / `ND_dot_*`) fold into values. Anything that needs
|
|
89
|
-
real evaluation (noise, ramps, …) skips just that channel with a warning —
|
|
90
|
-
the rest of the material still renders — unless you opt into the TSL entry
|
|
91
|
-
below. External `.mtlx` file references (UsdMtlx) are not parsed; load them
|
|
92
|
-
with `loadMaterialXDocument` (a thin wrapper over three's official
|
|
93
|
-
`MaterialXLoader`) from `three-usd-robot/nodes`.
|
|
94
|
-
|
|
95
|
-
**Executing MaterialX graphs (optional, WebGPU)** — the separate
|
|
96
|
-
`three-usd-robot/nodes` entry converts `ND_*` graphs (noise, ramps, math,
|
|
97
|
-
images, procedural UV warps — a ~45-node practical subset) into three.js TSL
|
|
98
|
-
`MeshPhysicalNodeMaterial`s and plugs in through the loader's
|
|
99
|
-
`materialFactory` hook:
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
import { ThreeUsdRobotLoader } from "three-usd-robot";
|
|
103
|
-
import { createMaterialXNodeFactory } from "three-usd-robot/nodes";
|
|
104
|
-
|
|
105
|
-
const loader = new ThreeUsdRobotLoader({
|
|
106
|
-
materialFactory: createMaterialXNodeFactory({ onWarn: console.warn }),
|
|
107
|
-
});
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Requires `WebGPURenderer` (it falls back to WebGL2 internally). Graphs with
|
|
111
|
-
nodes outside the conversion table fall back to the parameter mapping with a
|
|
112
|
-
warning, and the WebGL core bundles never import `three/webgpu` / `three/tsl`
|
|
113
|
-
(verified at build time). See `examples/vite-webgpu-nodes` for a procedural
|
|
114
|
-
marble / worley / lava demo.
|
|
115
|
-
|
|
116
|
-
Executing MDL remains out of scope (a language, not a graph — it would need
|
|
117
|
-
an MDL SDK-class compiler); unknown MDL materials fall back to the OmniPBR
|
|
118
|
-
mapping (and unknown `ND_*` surface shaders to the UsdPreviewSurface reads)
|
|
119
|
-
with a warning. Not yet supported: collection-based material bindings, and
|
|
120
|
-
the exotic curve schemas (`NurbsCurves`, `HermiteCurves`, `NurbsPatch`)
|
|
121
|
-
which load with a warning and are skipped.
|
|
122
|
-
|
|
123
56
|
## Install
|
|
124
57
|
|
|
125
58
|
```sh
|
|
@@ -144,221 +77,33 @@ robot.setJointValues({ joint1: 0.4, joint2: -0.2 });
|
|
|
144
77
|
const handMatrix = robot.getLinkWorldMatrix("tool0"); // THREE.Matrix4
|
|
145
78
|
const handPos = robot.getLinkWorldPosition("tool0"); // THREE.Vector3
|
|
146
79
|
|
|
147
|
-
robot.getJointNames(); //
|
|
80
|
+
robot.getJointNames(); // commandable joints
|
|
148
81
|
robot.getKinematicTree(); // root, ordering, loop joints, ...
|
|
149
82
|
```
|
|
150
83
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const loader = new ThreeUsdRobotLoader();
|
|
157
|
-
await loader.parse(usdaText); // USDA source string
|
|
158
|
-
await loader.parse(file); // File / Blob from drag & drop or <input type="file">
|
|
159
|
-
await loader.parse(await res.arrayBuffer()); // a fetch you did yourself
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
`parseUsdz(data)` / `parseCrate(data, baseUrl)` stay as explicit-format entries,
|
|
163
|
-
and `parseRobotDescription(data)` returns the Three.js-independent IR. Pass a
|
|
164
|
-
`baseUrl` as the second `parse` argument if the layer has relative references
|
|
165
|
-
or texture paths to resolve.
|
|
166
|
-
|
|
167
|
-
### World up-axis & units
|
|
168
|
-
|
|
169
|
-
Stages load normalized: `metersPerUnit` scales the root, and the authored
|
|
170
|
-
`upAxis` (`"Y"` or `"Z"`) is rotated into your world convention via `worldUp`:
|
|
171
|
-
|
|
172
|
-
```ts
|
|
173
|
-
new ThreeUsdRobotLoader(); // default: "Y" — upright in a stock three.js scene
|
|
174
|
-
new ThreeUsdRobotLoader({ worldUp: "Z" }); // robotics-style Z-up world
|
|
175
|
-
new ThreeUsdRobotLoader({ worldUp: "keep" }); // leave the authored orientation
|
|
176
|
-
|
|
177
|
-
robot.upAxis; // authored stage value ("Y" | "Z"), independent of normalization
|
|
178
|
-
robot.metersPerUnit; // authored stage scale (already applied to the root)
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Isaac Sim assets are Z-up, so the default makes them stand upright in a plain
|
|
182
|
-
three.js scene; a Z-up app (ROS-style) passes `worldUp: "Z"` once instead of
|
|
183
|
-
counter-rotating per asset. The M9 option `upAxisConversion` remains as a
|
|
184
|
-
deprecated alias (`"auto"` ≡ `worldUp: "Y"`, `"none"` ≡ `"keep"`).
|
|
185
|
-
|
|
186
|
-
### Stable addressing (naming contract)
|
|
187
|
-
|
|
188
|
-
Joints and links are keyed by their prim's **leaf name** while it is unique
|
|
189
|
-
across the robot; on a collision (say, two arms each with a `seg` link) the
|
|
190
|
-
colliding entries are keyed by their **full prim path** instead —
|
|
191
|
-
deterministically. Every accessor also takes the full prim path directly, so
|
|
192
|
-
tooling can pin exact prims no matter how the asset is named:
|
|
193
|
-
|
|
194
|
-
```ts
|
|
195
|
-
robot.setJointValue("/World/armL/j1", 0.4); // same joint as its key
|
|
196
|
-
robot.getLinkWorldMatrix("/World/armL/seg");
|
|
197
|
-
robot.getLinkObjectsByPath(); // Map<primPath, LinkObject>
|
|
198
|
-
robot.getJointObjectsByPath(); // Map<primPath, JointObject>
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
`LinkObject.primPath` / `JointObject.primPath` carry the reverse direction.
|
|
202
|
-
|
|
203
|
-
### Viewer toggles & helpers
|
|
204
|
-
|
|
205
|
-
```ts
|
|
206
|
-
robot.showVisual = true;
|
|
207
|
-
robot.showCollision = false;
|
|
208
|
-
robot.showJointAxes = true; // built-in axes gizmos on each joint
|
|
209
|
-
robot.showLinkFrames = false;
|
|
210
|
-
|
|
211
|
-
import { addJointLimitHelpers } from "three-usd-robot/helpers";
|
|
212
|
-
addJointLimitHelpers(robot); // arc (revolute) / segment (prismatic) per joint
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Link highlighting & ghosts
|
|
216
|
-
|
|
217
|
-
Per-link appearance helpers cover the common viewer chores — flagging
|
|
218
|
-
colliding links, material swaps, and translucent "ghost" pose previews:
|
|
219
|
-
|
|
220
|
-
```ts
|
|
221
|
-
import {
|
|
222
|
-
createGhostRobot,
|
|
223
|
-
highlightLink,
|
|
224
|
-
restoreLinkMaterials,
|
|
225
|
-
setLinkMaterial,
|
|
226
|
-
} from "three-usd-robot/helpers";
|
|
227
|
-
|
|
228
|
-
highlightLink(robot, "link1"); // emissive red tint; maps/colors kept
|
|
229
|
-
highlightLink(robot, "/World/armL/seg", { color: 0xffaa00, opacity: 0.6 });
|
|
230
|
-
setLinkMaterial(robot, "link2", new THREE.MeshBasicMaterial({ wireframe: true }));
|
|
231
|
-
restoreLinkMaterials(robot, "link1"); // exact original materials back
|
|
232
|
-
|
|
233
|
-
const ghost = createGhostRobot(robot, { jointValues: { joint1: 1.2 } });
|
|
234
|
-
scene.add(ghost); // translucent copy previewing the target pose
|
|
235
|
-
ghost.setJointValues(ikSolution); // a full ThreeUsdRobot, driveable like the source
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Highlights never stack (each call re-tints from the originals), and ghosts
|
|
239
|
-
share the source's geometry — cloning is cheap enough for onion-skinning.
|
|
84
|
+
`parse` also takes in-memory content (USDA text, an `ArrayBuffer` / typed
|
|
85
|
+
array / `Blob` — the format is sniffed, so a dropped `File` works as-is), and
|
|
86
|
+
the loader normalizes units and up-axis for you: Isaac's Z-up assets stand
|
|
87
|
+
upright in a Y-up three.js scene by default, or pass `worldUp: "Z"` for a
|
|
88
|
+
robotics-style Z-up world. Details in the [runtime guide](./docs/runtime.md).
|
|
240
89
|
|
|
241
|
-
|
|
242
|
-
`{ loadSceneGeometry: true }` to the loader to draw the static environment
|
|
243
|
-
(floor, guarding, racking, …) around the machines. A stage with **no
|
|
244
|
-
articulation at all** — a plain static USD scene — is detected and rendered as
|
|
245
|
-
scene geometry automatically, with the same unit / up-axis normalization; pass
|
|
246
|
-
`loadSceneGeometry: false` to opt out.
|
|
90
|
+
## Documentation
|
|
247
91
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
createJointSliderPanel(robot, new GUI()); // one slider per articulated joint
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
The panel takes the GUI instance from you, so the library never bundles
|
|
258
|
-
`lil-gui`.
|
|
259
|
-
|
|
260
|
-
### Animation playback
|
|
261
|
-
|
|
262
|
-
If the asset has time-sampled joint trajectories, the robot plays them back:
|
|
263
|
-
|
|
264
|
-
```ts
|
|
265
|
-
const range = robot.getTimeRange();
|
|
266
|
-
if (range) {
|
|
267
|
-
// in your render loop, advance a time code between range.start and range.end:
|
|
268
|
-
robot.setTime(t); // interpolates every animated joint and updates FK
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### Baked link transforms (recorded playback)
|
|
273
|
-
|
|
274
|
-
Recordings baked as **body transforms** (Isaac Sim stage-recorder output,
|
|
275
|
-
maximal-coordinate solver playback) can drive link poses directly, bypassing
|
|
276
|
-
the joints — usdview-style display semantics:
|
|
277
|
-
|
|
278
|
-
```ts
|
|
279
|
-
// A world-pose track keyed by prim path (or link key), quaternion in [x, y, z, w]:
|
|
280
|
-
robot.setLinkTransforms({
|
|
281
|
-
"/World/link1": { position: [0, 0, 1], quaternion: [0, 0, 0, 1] },
|
|
282
|
-
"/World/link2": { position: [0.3, 0, 2], quaternion: [0, 0, 0, 1] },
|
|
283
|
-
}); // batched — one matrix update; unlisted links keep their current world pose
|
|
284
|
-
|
|
285
|
-
robot.displayMode; // "baked": joint values are untouched and no longer place links
|
|
286
|
-
robot.setJointValues(liveValues); // recompute all links from joint values → "fk"
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
Poses are read in the **three.js scene world after `worldUp` normalization** —
|
|
290
|
-
pair a Z-up meter track (Isaac / ROS convention) with `worldUp: "Z"`; feeding
|
|
291
|
-
it into the default Y-up normalization lays the robot on its side. Transforms
|
|
292
|
-
on the `robot` object itself (placement, uniform scaling) are accounted for,
|
|
293
|
-
and `{ space: "stage" }` reads authored stage coordinates instead.
|
|
294
|
-
|
|
295
|
-
Constraint deviations — a recording from a different model version, solver
|
|
296
|
-
drift, a coordinate-convention bug — are shown, never silently corrected.
|
|
297
|
-
Measure them, or project onto the joints instead:
|
|
298
|
-
|
|
299
|
-
```ts
|
|
300
|
-
robot.validateLinkTransforms(poses);
|
|
301
|
-
// { "/World/joint1": { anchorError /* m */, axisError /* rad */, q, limitExceeded }, … }
|
|
302
|
-
// covers every joint: fixed joints, loop joints dropped from the FK tree,
|
|
303
|
-
// and the world-fixed root attachment
|
|
304
|
-
|
|
305
|
-
const { values, residuals } = robot.jointValuesFromLinkTransforms(poses, {
|
|
306
|
-
previous: lastValues, // ±π branch continuity, frame to frame
|
|
307
|
-
});
|
|
308
|
-
robot.setJointValues(values); // constraint-respecting playback of the same track
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
`new ThreeUsdRobotLoader({ debugBakedTransforms: true })` warns once per baked
|
|
312
|
-
session when poses deviate beyond 1 mm / 0.01 rad.
|
|
313
|
-
|
|
314
|
-
### React Three Fiber
|
|
315
|
-
|
|
316
|
-
`three-usd-robot/react` provides a declarative `<UsdRobot>` (`react` and
|
|
317
|
-
`@react-three/fiber` are **optional** peer deps):
|
|
318
|
-
|
|
319
|
-
```tsx
|
|
320
|
-
import { Canvas } from "@react-three/fiber";
|
|
321
|
-
import { Suspense } from "react";
|
|
322
|
-
import { UsdRobot } from "three-usd-robot/react";
|
|
323
|
-
|
|
324
|
-
<Canvas camera={{ position: [2, 2, 2] }}>
|
|
325
|
-
<Suspense fallback={null}>
|
|
326
|
-
<UsdRobot
|
|
327
|
-
url="/robot.usda"
|
|
328
|
-
jointValues={{ joint1: 0.4 }} // controlled
|
|
329
|
-
showJointAxes
|
|
330
|
-
animate // play time-sampled trajectories
|
|
331
|
-
onLoad={(robot) => console.log(robot.getJointNames())}
|
|
332
|
-
/>
|
|
333
|
-
</Suspense>
|
|
334
|
-
<ambientLight />
|
|
335
|
-
</Canvas>;
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
Also exported: `useUsdRobot(url)` (Suspense loader), `useRobotAnimation(robot)`,
|
|
339
|
-
`preloadUsdRobot`, `clearUsdRobotCache`. Pass a `ref` to `<UsdRobot>` for the
|
|
340
|
-
imperative API.
|
|
92
|
+
| Doc | Contents |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| [Runtime guide](./docs/runtime.md) | Input sources, up-axis & units, naming contract, mimic joints, viewer helpers & ghosts, static scenes, joint sliders, React Three Fiber, using the core without Three.js |
|
|
95
|
+
| [Materials](./docs/materials.md) | UsdPreviewSurface fidelity, Omniverse MDL family mappings, MaterialX, optional TSL graph execution (WebGPU) |
|
|
96
|
+
| [Animation & recorded playback](./docs/recorded-playback.md) | Time-sampled trajectories, baked body-transform recordings, constraint diagnostics & joint projection |
|
|
97
|
+
| [Exporting USD](./docs/export.md) | Re-export, `RobotBuilder` authoring, simulation-ready assets (mass / collision / Isaac Robot Schema), USDZ packaging |
|
|
341
98
|
|
|
342
99
|
## Export USD
|
|
343
100
|
|
|
344
|
-
The loader's inverse
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-

|
|
101
|
+
The loader's inverse — author a robot from Three.js meshes and open it in
|
|
102
|
+
Isaac Sim:
|
|
348
103
|
|
|
349
104
|
```ts
|
|
350
|
-
import {
|
|
351
|
-
|
|
352
|
-
RobotBuilder,
|
|
353
|
-
serializeUsda,
|
|
354
|
-
writeUsdz,
|
|
355
|
-
} from "three-usd-robot";
|
|
356
|
-
|
|
357
|
-
// Re-export a loaded robot (meshes harvested from the Three.js scene):
|
|
358
|
-
const usda = serializeUsda(exportThreeUsdRobot(robot));
|
|
359
|
-
|
|
360
|
-
// …or build one from Three.js meshes. Z-up and metres by default; each joint
|
|
361
|
-
// takes ONE world-space frame, and the build-time arrangement is the zero pose.
|
|
105
|
+
import { RobotBuilder, serializeUsda } from "three-usd-robot";
|
|
106
|
+
|
|
362
107
|
const builder = new RobotBuilder({ name: "my_robot" });
|
|
363
108
|
builder.addLink({ name: "base", visuals: [baseMesh] });
|
|
364
109
|
builder.addLink({ name: "arm", frame: armFrame, visuals: [armMesh] });
|
|
@@ -367,46 +112,11 @@ builder.addRevoluteJoint({
|
|
|
367
112
|
name: "j1", parent: "base", child: "arm",
|
|
368
113
|
frame: jointFrame, axis: "Z", lower: -Math.PI, upper: Math.PI,
|
|
369
114
|
});
|
|
370
|
-
|
|
371
|
-
const file = builder.toUsda();
|
|
372
|
-
writeFileSync("robot.usda", serializeUsda(file));
|
|
373
|
-
writeFileSync("robot.usdz", writeUsdz({ "robot.usda": serializeUsda(file) }));
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
Joints export as `UsdPhysics` prims with their limits, drives and initial pose.
|
|
377
|
-
For a simulation-ready asset, links also take mass properties, and collision
|
|
378
|
-
meshes take physics materials and a collision approximation:
|
|
379
|
-
|
|
380
|
-
```ts
|
|
381
|
-
builder.addLink({
|
|
382
|
-
name: "arm",
|
|
383
|
-
visuals: [armMesh],
|
|
384
|
-
collisions: [armCollisionMesh],
|
|
385
|
-
inertial: { mass: 2.5, centerOfMass: [0, 0, 0.2], diagonalInertia: [0.02, 0.02, 0.004] },
|
|
386
|
-
collisionApproximation: "convexHull",
|
|
387
|
-
physicsMaterial: { name: "steel", staticFriction: 0.6, dynamicFriction: 0.5 },
|
|
388
|
-
});
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
Both screenshots above come from `npx tsx scripts/demo-factory.ts`, which
|
|
392
|
-
authors a complete robot cell — a 7-DOF arm with a gripper, a conveyor, a
|
|
393
|
-
turntable and the surrounding scenery — and exports it to
|
|
394
|
-
`out/factory.usda` / `.usdz`.
|
|
395
|
-
|
|
396
|
-
## Use it without Three.js
|
|
397
|
-
|
|
398
|
-
`three-usd-robot/core` is a standalone USD parser, writer and robot IR — handy
|
|
399
|
-
for server-side validation or asset tooling:
|
|
400
|
-
|
|
401
|
-
```ts
|
|
402
|
-
import { parseUsda, Stage, extractRobotDescription } from "three-usd-robot/core";
|
|
403
|
-
|
|
404
|
-
const desc = extractRobotDescription(Stage.OpenFromString(usdaText));
|
|
405
|
-
console.log(desc.rootLink, Object.keys(desc.joints));
|
|
115
|
+
writeFileSync("robot.usda", serializeUsda(builder.toUsda()));
|
|
406
116
|
```
|
|
407
117
|
|
|
408
|
-
|
|
409
|
-
|
|
118
|
+
Limits, drives, mimic couplings, the initial pose, mass properties and
|
|
119
|
+
collision setup all serialize — see [Exporting USD](./docs/export.md).
|
|
410
120
|
|
|
411
121
|
## Examples
|
|
412
122
|
|
|
@@ -417,10 +127,11 @@ and `.usdz` packages to ASCII USDA.
|
|
|
417
127
|
(prim tree + attribute inspector), a transform gizmo, joint sliders,
|
|
418
128
|
animation playback and USD export.
|
|
419
129
|
- **`vite-basic-viewer`** — the same thing through React Three Fiber.
|
|
130
|
+
- **`vite-webgpu-nodes`** — MaterialX graph execution (TSL) on `WebGPURenderer`.
|
|
420
131
|
|
|
421
|
-
|
|
422
|
-
one straight from NVIDIA's CDN. `npm run demo:build` generates the
|
|
423
|
-
and builds the deployable site.
|
|
132
|
+
The viewers take `?asset=<url>` for any asset, or `?isaac=<path under Isaac/>`
|
|
133
|
+
to pull one straight from NVIDIA's CDN. `npm run demo:build` generates the
|
|
134
|
+
factory cell and builds the deployable site.
|
|
424
135
|
|
|
425
136
|
## Package entry points
|
|
426
137
|
|
|
@@ -428,7 +139,7 @@ and builds the deployable site.
|
|
|
428
139
|
| --- | --- |
|
|
429
140
|
| `three-usd-robot` | Three.js runtime — `ThreeUsdRobotLoader`, `ThreeUsdRobot`, `RobotBuilder`, export helpers |
|
|
430
141
|
| `three-usd-robot/core` | Three.js-independent USD parser & writer, robot IR, forward-kinematics math |
|
|
431
|
-
| `three-usd-robot/helpers` | Viewer helpers (joint axes, link frames, joint limits) |
|
|
142
|
+
| `three-usd-robot/helpers` | Viewer helpers (joint axes, link frames, joint limits, highlights, ghosts) |
|
|
432
143
|
| `three-usd-robot/extras` | Joint slider panel (bring your own `lil-gui`) |
|
|
433
144
|
| `three-usd-robot/nodes` | Optional MaterialX → TSL execution (`three/webgpu`) — `createMaterialXNodeFactory`, `loadMaterialXDocument` |
|
|
434
145
|
| `three-usd-robot/react` | React Three Fiber `<UsdRobot>` component + hooks |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
import {
|
|
2
|
+
import { y as Vec2, z as Vec3, S as Stage, P as Prim, R as RobotDescription } from './buildKinematicTree-Q9JOjAjM.js';
|
|
3
3
|
import { b as MdlModuleProvider, A as AssetResolver } from './parseMdl-vfzBGoMr.js';
|
|
4
|
-
import { T as ThreeUsdRobot } from './ThreeUsdRobot-
|
|
4
|
+
import { T as ThreeUsdRobot } from './ThreeUsdRobot-X1zbpRZo.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Resolves `UsdShade` material bindings to flat PBR parameters.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
import {
|
|
2
|
+
import { g as JointType, A as Axis, f as JointMimicDescription, e as JointDescription, j as LinkDescription, R as RobotDescription, K as KinematicTree, S as Stage } from './buildKinematicTree-Q9JOjAjM.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The articulated "motion" node of a joint, inserted between the joint's two
|
|
@@ -17,6 +17,8 @@ declare class JointObject extends THREE.Object3D {
|
|
|
17
17
|
readonly axis: THREE.Vector3;
|
|
18
18
|
readonly lower: number | undefined;
|
|
19
19
|
readonly upper: number | undefined;
|
|
20
|
+
/** Mimic constraint this joint follows, if any (see {@link JointMimicDescription}). */
|
|
21
|
+
readonly mimic: JointMimicDescription | undefined;
|
|
20
22
|
private _value;
|
|
21
23
|
constructor(joint: JointDescription);
|
|
22
24
|
get value(): number;
|
|
@@ -156,6 +158,10 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
156
158
|
private readonly jointObjects;
|
|
157
159
|
private readonly linkKeyByPath;
|
|
158
160
|
private readonly jointKeyByPath;
|
|
161
|
+
/** Mimic edges among realized joints: leader key → followers. */
|
|
162
|
+
private readonly mimicFollowers;
|
|
163
|
+
private readonly mimicLeaderByFollower;
|
|
164
|
+
private warnedMimicDrive;
|
|
159
165
|
private dirty;
|
|
160
166
|
/** Constructed (fk rest) local matrix of every link, for baked→fk restore. */
|
|
161
167
|
private readonly restLocal;
|
|
@@ -180,6 +186,17 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
180
186
|
private applyStageNormalization;
|
|
181
187
|
/** Apply each joint's authored initial value, if any. */
|
|
182
188
|
private applyInitialPose;
|
|
189
|
+
/** Index the mimic edges realized in the tree (leader and follower both driven). */
|
|
190
|
+
private registerMimicFollowers;
|
|
191
|
+
/** Drive the followers of `leaderKey` from its current value (recursive, cycle-safe). */
|
|
192
|
+
private propagateMimic;
|
|
193
|
+
/** Re-derive every follower from its chain's top-most leader. */
|
|
194
|
+
private propagateAllMimic;
|
|
195
|
+
/** Whether the joint (key or prim path) is a mimic follower, driven by its leader. */
|
|
196
|
+
isMimicFollower(name: string): boolean;
|
|
197
|
+
/** Keys of the mimic-follower joints (excluded from {@link getJointNames}). */
|
|
198
|
+
getMimicJointNames(): string[];
|
|
199
|
+
private warnMimicDriveOnce;
|
|
183
200
|
private attachRoot;
|
|
184
201
|
private attachTreeEdges;
|
|
185
202
|
/** Build `parent → frame0 → motion → frame1⁻¹ → child` for one joint. */
|
|
@@ -191,12 +208,15 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
191
208
|
private jointKey;
|
|
192
209
|
/**
|
|
193
210
|
* Set one joint value, addressed by key or full prim path. Unknown joints
|
|
194
|
-
* are ignored
|
|
211
|
+
* are ignored, and so are mimic followers (their value derives from the
|
|
212
|
+
* leader; a warning is logged once). Driving a leader also updates its
|
|
213
|
+
* followers. Returns whether it applied. Always restores `"fk"` display
|
|
195
214
|
* mode first (see {@link setLinkTransforms}).
|
|
196
215
|
*/
|
|
197
216
|
setJointValue(name: string, value: number): boolean;
|
|
198
217
|
/**
|
|
199
|
-
* Set several joint values at once (matrix update is coalesced).
|
|
218
|
+
* Set several joint values at once (matrix update is coalesced). Mimic
|
|
219
|
+
* followers in the batch are skipped like in {@link setJointValue}. Always
|
|
200
220
|
* restores `"fk"` display mode first, recomputing every link purely from
|
|
201
221
|
* joint values — even an empty batch returns from baked playback (see
|
|
202
222
|
* {@link setLinkTransforms}).
|
|
@@ -250,9 +270,11 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
250
270
|
/**
|
|
251
271
|
* Project a link-pose batch onto the joint manifold: the closed-form 1-DOF
|
|
252
272
|
* joint values that best reproduce it, plus the same residuals as
|
|
253
|
-
* {@link validateLinkTransforms}. `values` covers the
|
|
254
|
-
*
|
|
255
|
-
*
|
|
273
|
+
* {@link validateLinkTransforms}. `values` covers the commandable
|
|
274
|
+
* articulated tree joints (mimic followers excluded — their leaders
|
|
275
|
+
* re-derive them), keyed by joint prim path, and feeds
|
|
276
|
+
* {@link setJointValues} directly — the constraint-respecting playback of
|
|
277
|
+
* the same track:
|
|
256
278
|
*
|
|
257
279
|
* ```ts
|
|
258
280
|
* robot.setJointValues(robot.jointValuesFromLinkTransforms(poses, { previous }).values);
|
|
@@ -311,7 +333,11 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
311
333
|
getJointObjectsByPath(): Map<string, JointObject>;
|
|
312
334
|
getJoints(): JointDescription[];
|
|
313
335
|
getLinks(): LinkDescription[];
|
|
314
|
-
/**
|
|
336
|
+
/**
|
|
337
|
+
* Names of the commandable joints — articulated tree joints minus mimic
|
|
338
|
+
* followers, whose values derive from their leader
|
|
339
|
+
* (see {@link getMimicJointNames}).
|
|
340
|
+
*/
|
|
315
341
|
getJointNames(): string[];
|
|
316
342
|
getLinkNames(): string[];
|
|
317
343
|
getKinematicTree(): KinematicTree;
|
|
@@ -331,7 +357,11 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
331
357
|
start: number;
|
|
332
358
|
end: number;
|
|
333
359
|
} | null;
|
|
334
|
-
/**
|
|
360
|
+
/**
|
|
361
|
+
* Sample every animated joint at time code `t` and apply the values (an fk
|
|
362
|
+
* drive — leaves baked mode). Samples on mimic followers are ignored; the
|
|
363
|
+
* constraint re-derives them from their leader.
|
|
364
|
+
*/
|
|
335
365
|
setTime(t: number): void;
|
|
336
366
|
get showVisual(): boolean;
|
|
337
367
|
set showVisual(v: boolean);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { R as RobotDescription } from './buildKinematicTree-
|
|
1
|
+
import { R as RobotDescription } from './buildKinematicTree-Q9JOjAjM.js';
|
|
2
2
|
import { A as AssetResolver } from './parseMdl-vfzBGoMr.js';
|
|
3
3
|
import { U as UsdSource, B as BinarySource } from './bytes-CxGRGry_.js';
|
|
4
|
-
import { M as MaterialFactory } from './MeshBinding-
|
|
5
|
-
import { W as WorldUpAxis, a as ThreeUsdRobotOptions, T as ThreeUsdRobot } from './ThreeUsdRobot-
|
|
4
|
+
import { M as MaterialFactory } from './MeshBinding-B_8RhuQE.js';
|
|
5
|
+
import { W as WorldUpAxis, a as ThreeUsdRobotOptions, T as ThreeUsdRobot } from './ThreeUsdRobot-X1zbpRZo.js';
|
|
6
6
|
|
|
7
7
|
type ThreeUsdRobotLoaderOptions = {
|
|
8
8
|
/** Resolver for references / payloads / sublayers (default {@link DefaultAssetResolver}). */
|
|
@@ -223,8 +223,6 @@ declare function decomposeRigid(m: Mat4): {
|
|
|
223
223
|
* {@link RobotDescription}; the kinematics builder (M4) trees it; the Three.js
|
|
224
224
|
* runtime (M5) realizes it as an `Object3D` hierarchy. Keeping the IR free of
|
|
225
225
|
* Three.js lets the same data drive tooling, validation, and (later) IK.
|
|
226
|
-
*
|
|
227
|
-
* See concept.md §9 for the rationale behind each field.
|
|
228
226
|
*/
|
|
229
227
|
|
|
230
228
|
type JointType = "fixed" | "revolute" | "continuous" | "prismatic";
|
|
@@ -306,6 +304,22 @@ type JointDescription = {
|
|
|
306
304
|
/** Time-sampled joint value trajectory (SI), if authored — drives playback. */
|
|
307
305
|
valueSamples?: SampleChannel;
|
|
308
306
|
drive?: JointDriveDescription;
|
|
307
|
+
/** Mimic constraint: this joint follows another joint's value. */
|
|
308
|
+
mimic?: JointMimicDescription;
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* A mimic constraint — `follower = multiplier · leader + offset` (URDF
|
|
312
|
+
* convention, SI units) — read from `NewtonMimicAPI` (Isaac Sim 6 / Newton
|
|
313
|
+
* authoring) or the legacy PhysX `PhysxMimicJointAPI`. Leader and follower
|
|
314
|
+
* must share the motion kind (angular ↔ angular, linear ↔ linear).
|
|
315
|
+
*/
|
|
316
|
+
type JointMimicDescription = {
|
|
317
|
+
/** Leader joint key (same key space as {@link RobotDescription.joints}). */
|
|
318
|
+
joint: string;
|
|
319
|
+
/** Scale on the leader value (dimensionless between same-type joints). */
|
|
320
|
+
multiplier: number;
|
|
321
|
+
/** Offset added after scaling, in SI (radians / stage linear units). */
|
|
322
|
+
offset: number;
|
|
309
323
|
};
|
|
310
324
|
/** Authored joint drive parameters (`UsdPhysicsDriveAPI`), as read in M3. */
|
|
311
325
|
type JointDriveDescription = {
|
|
@@ -528,4 +542,4 @@ type BuildTreeOptions = {
|
|
|
528
542
|
};
|
|
529
543
|
declare function buildKinematicTree(robot: RobotDescription, options?: BuildTreeOptions): KinematicTree;
|
|
530
544
|
|
|
531
|
-
export {
|
|
545
|
+
export { makeRotationY as $, type Axis as A, type BuildTreeOptions as B, type CompositionArc as C, DEFAULT_METERS_PER_UNIT as D, type Vec4 as E, buildKinematicTree as F, channelFromSamples as G, decomposeRigid as H, fromUsdMatrix as I, type JointDriveDescription as J, type KinematicTree as K, type LinkInertialDescription as L, type Mat4 as M, getTranslation as N, identity4 as O, Prim as P, Quat as Q, type RobotDescription as R, Stage as S, type TreeEdge as T, type UsdaFile as U, type Variability as V, interpolate as W, invert as X, makeEuler as Y, makeRotationFromQuat as Z, makeRotationX as _, AssetPath as a, makeRotationZ as a0, makeScale as a1, makeTranslation as a2, multiply as a3, multiplyAll as a4, toUsdMatrix as a5, Attribute as b, type AttributeSpec as c, DEG2RAD as d, type JointDescription as e, type JointMimicDescription as f, type JointType as g, type KinematicNode as h, Layer as i, type LinkDescription as j, type ListOp as k, type MetadataMap as l, type PrimSpec as m, type PropertySpec as n, RAD2DEG as o, Relationship as p, type RelationshipSpec as q, type SampleChannel as r, type SdfPath as s, type Specifier as t, type UpAxis as u, type UsdDictionary as v, UsdMatrix as w, type UsdValue as x, type Vec2 as y, type Vec3 as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getMaterialSubsets, isRenderableGprim, COLLISION_API, isNonVisualPurpose, computeLocalTransform, toBytes, extractRobotDescription, isZip, CrateReader, openUsdz, buildKinematicTree, loadMdlModules, isUnsupportedGprim, Stage, composeLayer, composeFile, crateToUsdaFile } from './chunk-
|
|
2
|
-
import { ThreeUsdRobot } from './chunk-
|
|
1
|
+
import { getMaterialSubsets, isRenderableGprim, COLLISION_API, isNonVisualPurpose, computeLocalTransform, toBytes, extractRobotDescription, isZip, CrateReader, openUsdz, buildKinematicTree, loadMdlModules, isUnsupportedGprim, Stage, composeLayer, composeFile, crateToUsdaFile } from './chunk-J6ZQWQ2C.js';
|
|
2
|
+
import { ThreeUsdRobot } from './chunk-JN2QPDB3.js';
|
|
3
3
|
import { identity4, multiply } from './chunk-YGJ23CG3.js';
|
|
4
4
|
import { resolveBoundMaterial, DefaultAssetResolver } from './chunk-PPPRB6KE.js';
|
|
5
5
|
import * as THREE from 'three';
|
|
@@ -969,5 +969,5 @@ var ThreeUsdRobotLoader = class {
|
|
|
969
969
|
};
|
|
970
970
|
|
|
971
971
|
export { ThreeUsdRobotLoader, bindRobotMeshes, bindSceneMeshes, buildGprimGeometry, buildGprimObject, buildMeshGeometry, buildMeshMaterial, createTextureProvider };
|
|
972
|
-
//# sourceMappingURL=chunk-
|
|
973
|
-
//# sourceMappingURL=chunk-
|
|
972
|
+
//# sourceMappingURL=chunk-5C3VTA56.js.map
|
|
973
|
+
//# sourceMappingURL=chunk-5C3VTA56.js.map
|