three-usd-robot 0.3.0 → 0.5.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 +55 -9
- package/dist/AssetResolver-CpIJNgWZ.d.ts +29 -0
- package/dist/{ThreeUsdRobot-C6uqpNZA.d.ts → ThreeUsdRobot-D9AOUaVh.d.ts} +15 -1
- package/dist/ThreeUsdRobotLoader-BgsnuJWd.d.ts +61 -0
- package/dist/{buildKinematicTree-BJuC_-5_.d.ts → buildKinematicTree-3oKG00Sc.d.ts} +27 -1
- package/dist/{chunk-XH3L7XDJ.js → chunk-36T6YOEX.js} +2677 -2523
- package/dist/chunk-36T6YOEX.js.map +1 -0
- package/dist/chunk-OFUMT72H.js +7 -0
- package/dist/chunk-OFUMT72H.js.map +1 -0
- package/dist/chunk-Y3NXBSX3.js +841 -0
- package/dist/chunk-Y3NXBSX3.js.map +1 -0
- package/dist/core.d.ts +24 -31
- package/dist/core.js +2 -1
- package/dist/extras.d.ts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.d.ts +118 -80
- package/dist/index.js +3 -575
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +72 -0
- package/dist/react.js +92 -0
- package/dist/react.js.map +1 -0
- package/package.json +22 -1
- package/dist/chunk-XH3L7XDJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,15 +8,16 @@ Think of it as a **USD version of [`urdf-loader`](https://www.npmjs.com/package/
|
|
|
8
8
|
it reads the link / joint / xform / mesh structure out of `UsdPhysics` robot assets
|
|
9
9
|
and drives forward kinematics on a Three.js `Object3D` hierarchy.
|
|
10
10
|
|
|
11
|
-
> 🚧 **Status: v0.
|
|
12
|
-
> (crate)**, and **`.usdz`** robots — including multi-file assets via
|
|
13
|
-
> references/payloads/sublayers
|
|
14
|
-
>
|
|
15
|
-
> applies flat **`UsdShade`
|
|
16
|
-
>
|
|
17
|
-
>
|
|
18
|
-
>
|
|
19
|
-
> (
|
|
11
|
+
> 🚧 **Status: v0.3.** Loads **ASCII `.usda`**, **binary `.usdc` / `.usd`
|
|
12
|
+
> (crate)**, and **`.usdz`** robots — including **multi-file assets** via
|
|
13
|
+
> references / payloads / sublayers (resolved across `.usda` *and* binary layers,
|
|
14
|
+
> with relationship-path remapping), **variant selections**, and **instanceable**
|
|
15
|
+
> prims — drives forward kinematics with meshes, applies flat **`UsdShade`
|
|
16
|
+
> material colors** (UsdPreviewSurface / OmniPBR constants) and **diffuse
|
|
17
|
+
> textures** (`UsdUVTexture`), normalizes up-axis & units, seeds the initial
|
|
18
|
+
> pose, and **plays back time-sampled joint trajectories**. The crate reader is a
|
|
19
|
+
> from-scratch TypeScript implementation (no OpenUSD/WASM dependency). Not yet:
|
|
20
|
+
> time samples and variant *selection* stored inside binary crate.
|
|
20
21
|
|
|
21
22
|
```ts
|
|
22
23
|
// .usda / .usdc / binary .usd / .usdz are all auto-detected:
|
|
@@ -25,6 +26,8 @@ const robot = await new ThreeUsdRobotLoader().loadAsync("/assets/robot.usd");
|
|
|
25
26
|
const robot = await new ThreeUsdRobotLoader().parseCrate(usdcBytes);
|
|
26
27
|
```
|
|
27
28
|
|
|
29
|
+

|
|
30
|
+
|
|
28
31
|
## Install
|
|
29
32
|
|
|
30
33
|
```sh
|
|
@@ -76,6 +79,48 @@ createJointSliderPanel(robot, new GUI()); // one slider per articulated joint
|
|
|
76
79
|
The `extras` panel takes the GUI instance from you, so the library never bundles
|
|
77
80
|
`lil-gui`. See [`examples/`](./examples) for runnable Vite demos.
|
|
78
81
|
|
|
82
|
+
### Animation playback
|
|
83
|
+
|
|
84
|
+
If the asset has time-sampled joint trajectories (joint-state or drive-target
|
|
85
|
+
time samples), the robot plays them back:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
if (robot.hasAnimation()) {
|
|
89
|
+
const { start, end } = robot.getTimeRange()!;
|
|
90
|
+
const fps = robot.getTimeCodesPerSecond();
|
|
91
|
+
// in your render loop, advance a time code and sample:
|
|
92
|
+
robot.setTime(t); // interpolates every animated joint and updates FK
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### React Three Fiber
|
|
97
|
+
|
|
98
|
+
`three-usd-robot/react` provides a declarative `<UsdRobot>` for R3F (`react` and
|
|
99
|
+
`@react-three/fiber` are **optional** peer deps):
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { Canvas } from "@react-three/fiber";
|
|
103
|
+
import { Suspense } from "react";
|
|
104
|
+
import { UsdRobot } from "three-usd-robot/react";
|
|
105
|
+
|
|
106
|
+
<Canvas camera={{ position: [2, 2, 2] }}>
|
|
107
|
+
<Suspense fallback={null}>
|
|
108
|
+
<UsdRobot
|
|
109
|
+
url="/robot.usda"
|
|
110
|
+
jointValues={{ joint1: 0.4 }} // controlled
|
|
111
|
+
showJointAxes
|
|
112
|
+
animate // play time-sampled trajectories
|
|
113
|
+
onLoad={(robot) => console.log(robot.getJointNames())}
|
|
114
|
+
/>
|
|
115
|
+
</Suspense>
|
|
116
|
+
<ambientLight />
|
|
117
|
+
</Canvas>;
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Also exported: `useUsdRobot(url)` (Suspense loader), `useRobotAnimation(robot)`
|
|
121
|
+
(per-frame playback), `preloadUsdRobot`, `clearUsdRobotCache`. Pass a `ref` to
|
|
122
|
+
`<UsdRobot>` for the imperative `ThreeUsdRobot` API.
|
|
123
|
+
|
|
79
124
|
### Inspect without Three.js
|
|
80
125
|
|
|
81
126
|
```ts
|
|
@@ -93,6 +138,7 @@ console.log(desc.rootLink, Object.keys(desc.joints));
|
|
|
93
138
|
| `three-usd-robot/core` | Three.js-independent USDA parser, robot IR, forward-kinematics math |
|
|
94
139
|
| `three-usd-robot/helpers` | Viewer helpers (joint axes, link frames, joint limits) |
|
|
95
140
|
| `three-usd-robot/extras` | Heavier convenience utilities (e.g. joint slider panel) |
|
|
141
|
+
| `three-usd-robot/react` | React Three Fiber `<UsdRobot>` component + hooks (optional `react` / `@react-three/fiber` peers) |
|
|
96
142
|
|
|
97
143
|
## Development
|
|
98
144
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves USD asset paths (from references / payloads / sublayers) to URLs and
|
|
3
|
+
* fetches their text. Composition (`composition.ts`) is I/O-agnostic and goes
|
|
4
|
+
* through an {@link AssetResolver}, so the same engine works in the browser, in
|
|
5
|
+
* Node, or against an in-memory file map in tests.
|
|
6
|
+
*/
|
|
7
|
+
interface AssetResolver {
|
|
8
|
+
/** Resolve an authored asset path against the layer's base URL to an absolute key. */
|
|
9
|
+
resolve(assetPath: string, baseUrl: string): string;
|
|
10
|
+
/** Fetch the text of a resolved asset; rejects if it cannot be read. */
|
|
11
|
+
fetchText(url: string): Promise<string>;
|
|
12
|
+
/** Fetch the raw bytes of a resolved asset (for binary USDC / USDZ). Optional. */
|
|
13
|
+
fetchBytes?(url: string): Promise<Uint8Array>;
|
|
14
|
+
}
|
|
15
|
+
/** URL-based resolver using the global `fetch` (browser / Node 18+). */
|
|
16
|
+
declare class DefaultAssetResolver implements AssetResolver {
|
|
17
|
+
resolve(assetPath: string, baseUrl: string): string;
|
|
18
|
+
fetchText(url: string): Promise<string>;
|
|
19
|
+
fetchBytes(url: string): Promise<Uint8Array>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolver over an in-memory `{ path: contents }` map (text or bytes), with
|
|
23
|
+
* posix-style joins. Useful for tests and bundled assets.
|
|
24
|
+
*/
|
|
25
|
+
declare function createMemoryResolver(files: Record<string, string | Uint8Array>): AssetResolver;
|
|
26
|
+
/** Resolve `rel` against `baseUrl` using posix semantics, normalizing `.`/`..`. */
|
|
27
|
+
declare function joinPosix(baseUrl: string, rel: string): string;
|
|
28
|
+
|
|
29
|
+
export { type AssetResolver as A, DefaultAssetResolver as D, createMemoryResolver as c, joinPosix as j };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
import { J as JointType, A as Axis, a as JointDescription, L as LinkDescription, R as RobotDescription, K as KinematicTree } from './buildKinematicTree-
|
|
2
|
+
import { J as JointType, A as Axis, a as JointDescription, L as LinkDescription, R as RobotDescription, K as KinematicTree } from './buildKinematicTree-3oKG00Sc.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The articulated "motion" node of a joint, inserted between the joint's two
|
|
@@ -107,6 +107,20 @@ declare class ThreeUsdRobot extends THREE.Object3D {
|
|
|
107
107
|
getJointNames(): string[];
|
|
108
108
|
getLinkNames(): string[];
|
|
109
109
|
getKinematicTree(): KinematicTree;
|
|
110
|
+
/** Playback rate in time codes per second (from the stage; default 24). */
|
|
111
|
+
getTimeCodesPerSecond(): number;
|
|
112
|
+
/** Whether any joint has a time-sampled trajectory. */
|
|
113
|
+
hasAnimation(): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Animation range in time codes: the union of authored joint sample ranges,
|
|
116
|
+
* falling back to the stage `startTimeCode`/`endTimeCode`. `null` if neither.
|
|
117
|
+
*/
|
|
118
|
+
getTimeRange(): {
|
|
119
|
+
start: number;
|
|
120
|
+
end: number;
|
|
121
|
+
} | null;
|
|
122
|
+
/** Sample every animated joint at time code `t` and apply the values. */
|
|
123
|
+
setTime(t: number): void;
|
|
110
124
|
get showVisual(): boolean;
|
|
111
125
|
set showVisual(v: boolean);
|
|
112
126
|
get showCollision(): boolean;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { R as RobotDescription } from './buildKinematicTree-3oKG00Sc.js';
|
|
2
|
+
import { A as AssetResolver } from './AssetResolver-CpIJNgWZ.js';
|
|
3
|
+
import { T as ThreeUsdRobot } from './ThreeUsdRobot-D9AOUaVh.js';
|
|
4
|
+
|
|
5
|
+
type ThreeUsdRobotLoaderOptions = {
|
|
6
|
+
/** Resolver for references / payloads / sublayers (default {@link DefaultAssetResolver}). */
|
|
7
|
+
assetResolver?: AssetResolver;
|
|
8
|
+
/** Render visual meshes (M6). */
|
|
9
|
+
loadVisuals?: boolean;
|
|
10
|
+
/** Render collision meshes (M6). */
|
|
11
|
+
loadCollisions?: boolean;
|
|
12
|
+
/** Load diffuse textures referenced by materials (default `true`). */
|
|
13
|
+
loadTextures?: boolean;
|
|
14
|
+
/** Up-axis correction strategy (M9). */
|
|
15
|
+
upAxisConversion?: "auto" | "Y" | "Z" | "none";
|
|
16
|
+
/** Extra uniform scale multiplied with `metersPerUnit` (M9). */
|
|
17
|
+
unitScale?: number;
|
|
18
|
+
/** Clamp `setJointValue` to authored limits (default `true`). */
|
|
19
|
+
clampJointLimits?: boolean;
|
|
20
|
+
/** Seed joints from drive targets / joint state (M9). */
|
|
21
|
+
applyDriveTargetsAsInitialPose?: boolean;
|
|
22
|
+
/** Override the robot name. */
|
|
23
|
+
robotName?: string;
|
|
24
|
+
/** Receives non-fatal load diagnostics. */
|
|
25
|
+
onWarn?: (message: string) => void;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Loads Isaac Sim / OpenUSD robot assets into a controllable {@link ThreeUsdRobot}.
|
|
29
|
+
*
|
|
30
|
+
* Composition (references / payloads / sublayers, M8) is resolved through an
|
|
31
|
+
* {@link AssetResolver}. Mesh rendering is M6; unit / up-axis / initial-pose
|
|
32
|
+
* handling is M9; USDC and variants are M10.
|
|
33
|
+
*/
|
|
34
|
+
declare class ThreeUsdRobotLoader {
|
|
35
|
+
readonly options: ThreeUsdRobotLoaderOptions;
|
|
36
|
+
constructor(options?: ThreeUsdRobotLoaderOptions);
|
|
37
|
+
private get resolver();
|
|
38
|
+
/**
|
|
39
|
+
* Fetch an asset by URL and build the robot. `.usdz` packages are unzipped and
|
|
40
|
+
* composed from their entries; everything else is sniffed for the crate magic
|
|
41
|
+
* and parsed as binary USDC or USDA text.
|
|
42
|
+
*/
|
|
43
|
+
loadAsync(url: string): Promise<ThreeUsdRobot>;
|
|
44
|
+
private fetchRootBytes;
|
|
45
|
+
/** Build a robot (composed, with meshes) from USDA source text. */
|
|
46
|
+
parse(text: string, baseUrl?: string): Promise<ThreeUsdRobot>;
|
|
47
|
+
/** Build a robot from the bytes of a `.usdz` package. */
|
|
48
|
+
parseUsdz(bytes: Uint8Array): Promise<ThreeUsdRobot>;
|
|
49
|
+
/** Build a robot from the bytes of a binary crate (`.usdc` / binary `.usd`). */
|
|
50
|
+
parseCrate(bytes: Uint8Array, baseUrl?: string): Promise<ThreeUsdRobot>;
|
|
51
|
+
/** Parse + compose USDA source into the Three.js-independent robot IR. */
|
|
52
|
+
parseRobotDescription(text: string, baseUrl?: string): Promise<RobotDescription>;
|
|
53
|
+
private buildFromStage;
|
|
54
|
+
private composeStage;
|
|
55
|
+
/** Compose a layer from raw bytes, sniffing binary crate vs USDA text. */
|
|
56
|
+
private composeStageFromBytes;
|
|
57
|
+
private robotOptions;
|
|
58
|
+
private extractOptions;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { type ThreeUsdRobotLoaderOptions as T, ThreeUsdRobotLoader as a };
|
|
@@ -177,6 +177,25 @@ declare function fromUsdMatrix(m: UsdMatrix): Mat4;
|
|
|
177
177
|
/** Extract the translation component `[x, y, z]` from a {@link Mat4}. */
|
|
178
178
|
declare function getTranslation(m: Mat4): Vec3;
|
|
179
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Time-sample interpolation for animated values (e.g. joint trajectories).
|
|
182
|
+
*
|
|
183
|
+
* USD time samples are keyed by time code. We linearly interpolate between the
|
|
184
|
+
* two bracketing samples and hold the endpoints outside the authored range
|
|
185
|
+
* (matching USD's held extrapolation).
|
|
186
|
+
*/
|
|
187
|
+
/** A sorted time-sampled scalar channel. */
|
|
188
|
+
type SampleChannel = {
|
|
189
|
+
/** Sample times, ascending. */
|
|
190
|
+
times: number[];
|
|
191
|
+
/** Sample values, parallel to {@link times} (SI units). */
|
|
192
|
+
values: number[];
|
|
193
|
+
};
|
|
194
|
+
/** Linearly sample `channel` at time `t` (held outside the range). */
|
|
195
|
+
declare function interpolate(channel: SampleChannel, t: number): number;
|
|
196
|
+
/** Build a sorted {@link SampleChannel} from `(time → value)` pairs via `map`. */
|
|
197
|
+
declare function channelFromSamples(samples: Map<number, number>): SampleChannel;
|
|
198
|
+
|
|
180
199
|
/**
|
|
181
200
|
* Robot intermediate representation (IR) — Three.js-independent.
|
|
182
201
|
*
|
|
@@ -205,6 +224,11 @@ type RobotDescription = {
|
|
|
205
224
|
upAxis: "Y" | "Z";
|
|
206
225
|
/** Stage linear unit, for the M9 scale normalization. */
|
|
207
226
|
metersPerUnit: number;
|
|
227
|
+
/** Playback rate (time codes per second); defaults to 24 when unauthored. */
|
|
228
|
+
timeCodesPerSecond?: number;
|
|
229
|
+
/** Authored animation range (time codes), if any. */
|
|
230
|
+
startTimeCode?: number;
|
|
231
|
+
endTimeCode?: number;
|
|
208
232
|
/** Non-fatal extraction diagnostics. */
|
|
209
233
|
warnings?: string[];
|
|
210
234
|
};
|
|
@@ -237,6 +261,8 @@ type JointDescription = {
|
|
|
237
261
|
jointFrame1: Mat4;
|
|
238
262
|
/** Initial joint value (SI) from JointStateAPI or a drive target, if authored. */
|
|
239
263
|
initialValue?: number;
|
|
264
|
+
/** Time-sampled joint value trajectory (SI), if authored — drives playback. */
|
|
265
|
+
valueSamples?: SampleChannel;
|
|
240
266
|
drive?: JointDriveDescription;
|
|
241
267
|
};
|
|
242
268
|
/** Authored joint drive parameters (`UsdPhysicsDriveAPI`), as read in M3. */
|
|
@@ -293,4 +319,4 @@ type BuildTreeOptions = {
|
|
|
293
319
|
};
|
|
294
320
|
declare function buildKinematicTree(robot: RobotDescription, options?: BuildTreeOptions): KinematicTree;
|
|
295
321
|
|
|
296
|
-
export { type Axis as A, type BuildTreeOptions as B, type CompositionArc as C, DEG2RAD as D,
|
|
322
|
+
export { type Axis as A, type BuildTreeOptions as B, type CompositionArc as C, DEG2RAD as D, makeRotationFromQuat as E, makeRotationX as F, makeRotationY as G, makeRotationZ as H, makeScale as I, type JointType as J, type KinematicTree as K, type LinkDescription as L, type Mat4 as M, makeTranslation as N, multiply as O, type PrimSpec as P, Quat as Q, type RobotDescription as R, type SampleChannel as S, type TreeEdge as T, type UsdDictionary as U, type Vec2 as V, multiplyAll as W, type JointDescription as a, type Vec3 as b, AssetPath as c, type AttributeSpec as d, type JointDriveDescription as e, type KinematicNode as f, type ListOp as g, type MetadataMap as h, type PropertySpec as i, RAD2DEG as j, type RelationshipSpec as k, type SdfPath as l, type Specifier as m, UsdMatrix as n, type UsdValue as o, type UsdaFile as p, type Variability as q, type Vec4 as r, buildKinematicTree as s, channelFromSamples as t, fromUsdMatrix as u, getTranslation as v, identity4 as w, interpolate as x, invert as y, makeEuler as z };
|