@pollen-robotics/reachy-mini-sdk 1.8.0 → 1.8.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/APP_CREATION_GUIDE.md +1795 -0
- package/README.md +2 -5
- package/dist/animation/distance.d.ts +87 -0
- package/dist/animation/distance.d.ts.map +1 -0
- package/dist/animation/distance.js +140 -0
- package/dist/animation/distance.js.map +1 -0
- package/dist/animation/index.d.ts +34 -0
- package/dist/animation/index.d.ts.map +1 -0
- package/dist/animation/index.js +33 -0
- package/dist/animation/index.js.map +1 -0
- package/dist/animation/pose.d.ts +40 -0
- package/dist/animation/pose.d.ts.map +1 -0
- package/dist/animation/pose.js +15 -0
- package/dist/animation/pose.js.map +1 -0
- package/dist/animation/presets.d.ts +85 -0
- package/dist/animation/presets.d.ts.map +1 -0
- package/dist/animation/presets.js +82 -0
- package/dist/animation/presets.js.map +1 -0
- package/dist/animation/safe-return.d.ts +90 -0
- package/dist/animation/safe-return.d.ts.map +1 -0
- package/dist/animation/safe-return.js +123 -0
- package/dist/animation/safe-return.js.map +1 -0
- package/dist/lib/reachy-mini.d.ts +99 -0
- package/dist/lib/reachy-mini.d.ts.map +1 -1
- package/dist/lib/reachy-mini.js +314 -9
- package/dist/lib/reachy-mini.js.map +1 -1
- package/dist/lib/types.d.ts +27 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/host/README.md +14 -12
- package/host/dist/ReachyHost.d.ts +2 -1
- package/host/dist/ReachyHost.d.ts.map +1 -1
- package/host/dist/chunks/index-lMs2sCXG.js +439 -0
- package/host/dist/chunks/{mountHost-D7cgkU9Q.js → mountHost-DjE5zE9R.js} +11142 -11014
- package/host/dist/chunks/{reachy-mini-B1hlBmDQ.js → reachy-mini-GHNS4GSp.js} +494 -307
- package/host/dist/components/PickerView.d.ts.map +1 -1
- package/host/dist/components/PostOAuthSplash.d.ts +25 -0
- package/host/dist/components/PostOAuthSplash.d.ts.map +1 -0
- package/host/dist/components/ReachyHostShell.d.ts.map +1 -1
- package/host/dist/components/TopBar.d.ts +8 -1
- package/host/dist/components/TopBar.d.ts.map +1 -1
- package/host/dist/components/WelcomeBackOverlay.d.ts.map +1 -1
- package/host/dist/embed/index.d.ts +3 -2
- package/host/dist/embed/index.d.ts.map +1 -1
- package/host/dist/entry/auto.js +2 -2
- package/host/dist/entry/embed.js +2 -2
- package/host/dist/hooks/useHostBridge.d.ts +6 -0
- package/host/dist/hooks/useHostBridge.d.ts.map +1 -1
- package/host/dist/hooks/useSdk.d.ts.map +1 -1
- package/host/dist/index.js +3 -3
- package/host/dist/lib/protocol.d.ts +17 -3
- package/host/dist/lib/protocol.d.ts.map +1 -1
- package/host/dist/lib/settings.d.ts +3 -2
- package/host/dist/lib/settings.d.ts.map +1 -1
- package/host/dist/mountHost.d.ts.map +1 -1
- package/host/dist/ui/design/IdentityChipBar.d.ts +46 -0
- package/host/dist/ui/design/IdentityChipBar.d.ts.map +1 -0
- package/host/dist/ui/design/LinkQualityBars.d.ts +32 -0
- package/host/dist/ui/design/LinkQualityBars.d.ts.map +1 -0
- package/host/dist/ui/design/MetaPill.d.ts +41 -0
- package/host/dist/ui/design/MetaPill.d.ts.map +1 -0
- package/host/dist/ui/design/TransportChip.d.ts +39 -0
- package/host/dist/ui/design/TransportChip.d.ts.map +1 -0
- package/package.json +7 -4
- package/CHANGELOG.md +0 -188
- package/host/APP_AUTHOR_GUIDE.md +0 -646
- package/host/SPEC.md +0 -618
- package/host/dist/chunks/index-CyLPysJS.js +0 -400
package/README.md
CHANGED
|
@@ -98,9 +98,8 @@ See the JSDoc header in [`reachy-mini-sdk.js`](./reachy-mini-sdk.js) for the ful
|
|
|
98
98
|
|
|
99
99
|
For Hugging Face Spaces apps that need OAuth + a robot picker + iframe lifecycle management:
|
|
100
100
|
|
|
101
|
-
- [`
|
|
102
|
-
- [`host/
|
|
103
|
-
- [`host/SPEC.md`](./host/SPEC.md) — host ↔ embed protocol spec
|
|
101
|
+
- **[`APP_CREATION_GUIDE.md`](./APP_CREATION_GUIDE.md)** — single source of truth for app authors (scaffold, `sdk: static` deploy, host ↔ embed contract, invariants). Today's SDK pin: `1.8.0`.
|
|
102
|
+
- [`host/README.md`](./host/README.md) — one-page tour of the host package layout
|
|
104
103
|
|
|
105
104
|
## Migration from `@pollen-robotics/reachy-mini-host`
|
|
106
105
|
|
|
@@ -122,8 +121,6 @@ You can drop `@pollen-robotics/reachy-mini-host` from your `package.json`. The h
|
|
|
122
121
|
|
|
123
122
|
The host bundles now import the SDK directly and assign it on `window.ReachyMini` at load time, so apps no longer need a second `<script type="module">` for the SDK alone.
|
|
124
123
|
|
|
125
|
-
See the [CHANGELOG](./CHANGELOG.md) for the full release history.
|
|
126
|
-
|
|
127
124
|
## License
|
|
128
125
|
|
|
129
126
|
Apache-2.0 — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pose distance + scaled duration math.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions, no SDK calls, no clock reads. The caller passes a
|
|
5
|
+
* `current` pose (typically from `reachy.robotState`) and a `target`
|
|
6
|
+
* pose; the helpers return per-channel distances and a "feels right"
|
|
7
|
+
* duration for `gotoTarget`.
|
|
8
|
+
*
|
|
9
|
+
* Mirror of the daemon's `utils/interpolation.distance_between_poses`
|
|
10
|
+
* (head magic-mm) + the scaled-duration algorithm used internally for
|
|
11
|
+
* `wake_up` / `goto_sleep`. Duplicated client-side so apps know the
|
|
12
|
+
* duration **synchronously** for audio sync, streamer scheduling, and
|
|
13
|
+
* live constant tuning.
|
|
14
|
+
*/
|
|
15
|
+
import type { PartialPose } from "./pose.js";
|
|
16
|
+
import { type ScaledDurationPreset } from "./presets.js";
|
|
17
|
+
/**
|
|
18
|
+
* Per-channel "raw" distance between two poses.
|
|
19
|
+
*
|
|
20
|
+
* Channels missing from either input are absent from the result (the
|
|
21
|
+
* caller's `current` and `target` may both be `PartialPose`).
|
|
22
|
+
*
|
|
23
|
+
* Units:
|
|
24
|
+
* - `head`: "magic-mm" — translation_mm + rotation_deg fused into one
|
|
25
|
+
* scalar. The Python SDK's `utils/interpolation.distance_between_poses`
|
|
26
|
+
* uses the same trick: two unrelated units summed into a single
|
|
27
|
+
* number that's monotonic with "how big does this motion feel".
|
|
28
|
+
* - `antennas.right` / `antennas.left`: `|Δ°|` per antenna.
|
|
29
|
+
* - `body_yaw`: `|Δ°|`.
|
|
30
|
+
*
|
|
31
|
+
* Useful in log lines:
|
|
32
|
+
* `head=3.2mm, antennaR=18°, body=14°, limiter=antennaR`
|
|
33
|
+
*/
|
|
34
|
+
export interface PoseDistance {
|
|
35
|
+
head?: number;
|
|
36
|
+
antennas?: {
|
|
37
|
+
right: number;
|
|
38
|
+
left: number;
|
|
39
|
+
};
|
|
40
|
+
body_yaw?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compute the per-channel distance between two poses.
|
|
44
|
+
*
|
|
45
|
+
* Pure function. Allocates only the output object.
|
|
46
|
+
*/
|
|
47
|
+
export declare function distanceBetweenPoses(current: PartialPose, target: PartialPose): PoseDistance;
|
|
48
|
+
/** Outcome of a scaled-duration calculation. */
|
|
49
|
+
export interface ScaledDurationResult {
|
|
50
|
+
/** Duration to pass to `gotoTarget`, clamped to the preset (sec). */
|
|
51
|
+
readonly duration: number;
|
|
52
|
+
/** Which channel was the slowest (i.e. dictated the duration).
|
|
53
|
+
* `null` when `current` and `target` had no overlapping channels. */
|
|
54
|
+
readonly limiter: "head" | "antennaR" | "antennaL" | "body_yaw" | null;
|
|
55
|
+
/** Per-channel un-clamped candidate durations (sec), for log lines
|
|
56
|
+
* and "why is this slow?" diagnostics. */
|
|
57
|
+
readonly perChannel: Readonly<{
|
|
58
|
+
head?: number;
|
|
59
|
+
antennaR?: number;
|
|
60
|
+
antennaL?: number;
|
|
61
|
+
body_yaw?: number;
|
|
62
|
+
}>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Pick a `goto` duration that "feels right" for the move from
|
|
66
|
+
* `current` to `target`.
|
|
67
|
+
*
|
|
68
|
+
* Algorithm: for each channel defined on both sides, compute its
|
|
69
|
+
* candidate duration as `channelDistance × channelCost`. Take the max
|
|
70
|
+
* (slowest channel limits). Clamp to
|
|
71
|
+
* `[preset.minDurationSec, preset.maxDurationSec]`.
|
|
72
|
+
*
|
|
73
|
+
* If no channel overlaps, returns `{ duration: minDurationSec,
|
|
74
|
+
* limiter: null, perChannel: {} }` — a safe fallback the caller can
|
|
75
|
+
* still pass to `gotoTarget` (the resulting move is a no-op held over
|
|
76
|
+
* the min duration).
|
|
77
|
+
*
|
|
78
|
+
* **Divergence from Rémi's `reachy-mini-js-practices` bench (intentional):**
|
|
79
|
+
* his version returns `max` in the no-overlap case. We return `min`
|
|
80
|
+
* instead — a no-op move doesn't need the maximum dwell time, and the
|
|
81
|
+
* minimum is the smallest legal duration the daemon accepts. Callers
|
|
82
|
+
* that need a longer dwell can pass an explicit duration.
|
|
83
|
+
*
|
|
84
|
+
* Pure function. No SDK reads, no clock reads.
|
|
85
|
+
*/
|
|
86
|
+
export declare function scaledDuration(current: PartialPose, target: PartialPose, preset?: ScaledDurationPreset): ScaledDurationResult;
|
|
87
|
+
//# sourceMappingURL=distance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distance.d.ts","sourceRoot":"","sources":["../../animation/distance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAEH,KAAK,oBAAoB,EAC5B,MAAM,cAAc,CAAC;AAItB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,WAAW,GACpB,YAAY,CA0Bd;AAgDD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;0EACsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC;IACvE;+CAC2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;QAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACN;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAC1B,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,WAAW,EACnB,MAAM,GAAE,oBAAqD,GAC9D,oBAAoB,CAwCtB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pose distance + scaled duration math.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions, no SDK calls, no clock reads. The caller passes a
|
|
5
|
+
* `current` pose (typically from `reachy.robotState`) and a `target`
|
|
6
|
+
* pose; the helpers return per-channel distances and a "feels right"
|
|
7
|
+
* duration for `gotoTarget`.
|
|
8
|
+
*
|
|
9
|
+
* Mirror of the daemon's `utils/interpolation.distance_between_poses`
|
|
10
|
+
* (head magic-mm) + the scaled-duration algorithm used internally for
|
|
11
|
+
* `wake_up` / `goto_sleep`. Duplicated client-side so apps know the
|
|
12
|
+
* duration **synchronously** for audio sync, streamer scheduling, and
|
|
13
|
+
* live constant tuning.
|
|
14
|
+
*/
|
|
15
|
+
import { radToDeg } from "../lib/math.js";
|
|
16
|
+
import { DEFAULT_SCALED_DURATION_PRESET, } from "./presets.js";
|
|
17
|
+
/**
|
|
18
|
+
* Compute the per-channel distance between two poses.
|
|
19
|
+
*
|
|
20
|
+
* Pure function. Allocates only the output object.
|
|
21
|
+
*/
|
|
22
|
+
export function distanceBetweenPoses(current, target) {
|
|
23
|
+
const out = {};
|
|
24
|
+
if (current.head !== undefined && target.head !== undefined) {
|
|
25
|
+
out.head = headDistanceMagicMm(current.head, target.head);
|
|
26
|
+
}
|
|
27
|
+
if (current.antennas !== undefined && target.antennas !== undefined) {
|
|
28
|
+
const curR = current.antennas[0] ?? 0;
|
|
29
|
+
const curL = current.antennas[1] ?? 0;
|
|
30
|
+
const tgtR = target.antennas[0] ?? 0;
|
|
31
|
+
const tgtL = target.antennas[1] ?? 0;
|
|
32
|
+
out.antennas = {
|
|
33
|
+
right: Math.abs(radToDeg(tgtR - curR)),
|
|
34
|
+
left: Math.abs(radToDeg(tgtL - curL)),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (typeof current.body_yaw === "number" &&
|
|
38
|
+
typeof target.body_yaw === "number") {
|
|
39
|
+
out.body_yaw = Math.abs(radToDeg(target.body_yaw - current.body_yaw));
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Fuse translation (mm) and rotation (deg) of a 4×4 head transform
|
|
45
|
+
* delta into a single "magic-mm" scalar.
|
|
46
|
+
*
|
|
47
|
+
* Mirrors Python `distance_between_poses`:
|
|
48
|
+
* - Translation distance = `|t_a - t_b|` (Euclidean, mm).
|
|
49
|
+
* - Rotation distance = `arccos((trace(R_a^T · R_b) - 1) / 2)` in
|
|
50
|
+
* degrees, robust to numerical drift via clamping.
|
|
51
|
+
* - Magic-mm = `translation_mm + rotation_deg`.
|
|
52
|
+
*
|
|
53
|
+
* Assumes incoming matrices use **metres** for the translation column
|
|
54
|
+
* (indices 3, 7, 11 in row-major), matching the daemon's wire format,
|
|
55
|
+
* and converts to millimetres internally.
|
|
56
|
+
*/
|
|
57
|
+
function headDistanceMagicMm(headA, headB) {
|
|
58
|
+
// Translation in metres at indices 3, 7, 11 (row-major).
|
|
59
|
+
const dxM = (headA[3] ?? 0) - (headB[3] ?? 0);
|
|
60
|
+
const dyM = (headA[7] ?? 0) - (headB[7] ?? 0);
|
|
61
|
+
const dzM = (headA[11] ?? 0) - (headB[11] ?? 0);
|
|
62
|
+
const translationMm = Math.sqrt(dxM * dxM + dyM * dyM + dzM * dzM) * 1000;
|
|
63
|
+
// Top-left 3×3 of each, row-major: trace(A^T · B) = Σ_ij A[i,j] * B[i,j]
|
|
64
|
+
const trace = (headA[0] ?? 0) * (headB[0] ?? 0) +
|
|
65
|
+
(headA[1] ?? 0) * (headB[1] ?? 0) +
|
|
66
|
+
(headA[2] ?? 0) * (headB[2] ?? 0) +
|
|
67
|
+
(headA[4] ?? 0) * (headB[4] ?? 0) +
|
|
68
|
+
(headA[5] ?? 0) * (headB[5] ?? 0) +
|
|
69
|
+
(headA[6] ?? 0) * (headB[6] ?? 0) +
|
|
70
|
+
(headA[8] ?? 0) * (headB[8] ?? 0) +
|
|
71
|
+
(headA[9] ?? 0) * (headB[9] ?? 0) +
|
|
72
|
+
(headA[10] ?? 0) * (headB[10] ?? 0);
|
|
73
|
+
// Clamp to [-1, 1] before arccos to absorb floating-point drift
|
|
74
|
+
// (matrices that should be orthonormal sometimes have trace numerically
|
|
75
|
+
// slightly outside the valid range).
|
|
76
|
+
let cosTheta = (trace - 1) / 2;
|
|
77
|
+
if (cosTheta > 1)
|
|
78
|
+
cosTheta = 1;
|
|
79
|
+
else if (cosTheta < -1)
|
|
80
|
+
cosTheta = -1;
|
|
81
|
+
const rotationDeg = radToDeg(Math.acos(cosTheta));
|
|
82
|
+
return translationMm + rotationDeg;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Pick a `goto` duration that "feels right" for the move from
|
|
86
|
+
* `current` to `target`.
|
|
87
|
+
*
|
|
88
|
+
* Algorithm: for each channel defined on both sides, compute its
|
|
89
|
+
* candidate duration as `channelDistance × channelCost`. Take the max
|
|
90
|
+
* (slowest channel limits). Clamp to
|
|
91
|
+
* `[preset.minDurationSec, preset.maxDurationSec]`.
|
|
92
|
+
*
|
|
93
|
+
* If no channel overlaps, returns `{ duration: minDurationSec,
|
|
94
|
+
* limiter: null, perChannel: {} }` — a safe fallback the caller can
|
|
95
|
+
* still pass to `gotoTarget` (the resulting move is a no-op held over
|
|
96
|
+
* the min duration).
|
|
97
|
+
*
|
|
98
|
+
* **Divergence from Rémi's `reachy-mini-js-practices` bench (intentional):**
|
|
99
|
+
* his version returns `max` in the no-overlap case. We return `min`
|
|
100
|
+
* instead — a no-op move doesn't need the maximum dwell time, and the
|
|
101
|
+
* minimum is the smallest legal duration the daemon accepts. Callers
|
|
102
|
+
* that need a longer dwell can pass an explicit duration.
|
|
103
|
+
*
|
|
104
|
+
* Pure function. No SDK reads, no clock reads.
|
|
105
|
+
*/
|
|
106
|
+
export function scaledDuration(current, target, preset = DEFAULT_SCALED_DURATION_PRESET) {
|
|
107
|
+
const dist = distanceBetweenPoses(current, target);
|
|
108
|
+
const perChannel = {};
|
|
109
|
+
if (dist.head !== undefined) {
|
|
110
|
+
perChannel.head = dist.head * preset.headSecPerMagicMm;
|
|
111
|
+
}
|
|
112
|
+
if (dist.antennas !== undefined) {
|
|
113
|
+
perChannel.antennaR = dist.antennas.right * preset.antennaSecPerDeg;
|
|
114
|
+
perChannel.antennaL = dist.antennas.left * preset.antennaSecPerDeg;
|
|
115
|
+
}
|
|
116
|
+
if (dist.body_yaw !== undefined) {
|
|
117
|
+
perChannel.body_yaw = dist.body_yaw * preset.bodyYawSecPerDeg;
|
|
118
|
+
}
|
|
119
|
+
let limiter = null;
|
|
120
|
+
// Sentinel: -1 means "no channel seen yet". Distinguishes "no
|
|
121
|
+
// overlap" (limiter stays null) from "overlap but zero motion"
|
|
122
|
+
// (limiter = first overlapping channel, raw = 0).
|
|
123
|
+
let rawDuration = -1;
|
|
124
|
+
for (const key of ["head", "antennaR", "antennaL", "body_yaw"]) {
|
|
125
|
+
const value = perChannel[key];
|
|
126
|
+
if (value === undefined)
|
|
127
|
+
continue;
|
|
128
|
+
if (value > rawDuration) {
|
|
129
|
+
rawDuration = value;
|
|
130
|
+
limiter = key;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
let duration = rawDuration < 0 ? 0 : rawDuration;
|
|
134
|
+
if (duration < preset.minDurationSec)
|
|
135
|
+
duration = preset.minDurationSec;
|
|
136
|
+
if (duration > preset.maxDurationSec)
|
|
137
|
+
duration = preset.maxDurationSec;
|
|
138
|
+
return { duration, limiter, perChannel };
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=distance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distance.js","sourceRoot":"","sources":["../../animation/distance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@pollen-robotics/reachy-mini-sdk/animation` — motion utilities.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 surface, split by concern:
|
|
5
|
+
*
|
|
6
|
+
* - **Types** (`Pose`, `PartialPose`): the wire format every SDK
|
|
7
|
+
* motion call already uses.
|
|
8
|
+
* - **Canonical pose** (`INIT_POSE` + sub-constants): the "safe
|
|
9
|
+
* rest" pose, mirror of the daemon's `Backend.INIT_HEAD_POSE` +
|
|
10
|
+
* `Backend.INIT_ANTENNAS_JOINT_POSITIONS`.
|
|
11
|
+
* - **Distance math** (`distanceBetweenPoses`, `scaledDuration`):
|
|
12
|
+
* "how big is this move" + "how long should it take", computed
|
|
13
|
+
* synchronously client-side so apps can sync audio / scheduling
|
|
14
|
+
* against it.
|
|
15
|
+
* - **Exit handlers** (`safelyReturnToPose`, `installShutdownHandler`):
|
|
16
|
+
* thin convenience wrappers around the three-call SDK sequence
|
|
17
|
+
* (`setMotorMode` + read state + `gotoTarget`) for `pagehide` /
|
|
18
|
+
* `onLeave` call sites.
|
|
19
|
+
*
|
|
20
|
+
* Pure-TS: this lib does not introduce any daemon-side primitive. All
|
|
21
|
+
* motion routes through existing data-channel commands. See
|
|
22
|
+
* `DESIGN.md` for the rationale.
|
|
23
|
+
*
|
|
24
|
+
* @see DESIGN.md
|
|
25
|
+
* @see APP_CREATION_GUIDE.md — "Robotics best practices" section
|
|
26
|
+
*/
|
|
27
|
+
export type { Pose, PartialPose } from "./pose.js";
|
|
28
|
+
export type { PoseDistance, ScaledDurationResult } from "./distance.js";
|
|
29
|
+
export type { ScaledDurationPreset } from "./presets.js";
|
|
30
|
+
export type { SafelyReturnOptions, InstallShutdownHandlerOptions, } from "./safe-return.js";
|
|
31
|
+
export { INIT_HEAD_POSE_FLAT, INIT_ANTENNAS_RAD, INIT_BODY_YAW_RAD, INIT_POSE, DEFAULT_SCALED_DURATION_PRESET, } from "./presets.js";
|
|
32
|
+
export { distanceBetweenPoses, scaledDuration } from "./distance.js";
|
|
33
|
+
export { safelyReturnToPose, installShutdownHandler } from "./safe-return.js";
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../animation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EACR,mBAAmB,EACnB,6BAA6B,GAChC,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACH,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,8BAA8B,GACjC,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@pollen-robotics/reachy-mini-sdk/animation` — motion utilities.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 surface, split by concern:
|
|
5
|
+
*
|
|
6
|
+
* - **Types** (`Pose`, `PartialPose`): the wire format every SDK
|
|
7
|
+
* motion call already uses.
|
|
8
|
+
* - **Canonical pose** (`INIT_POSE` + sub-constants): the "safe
|
|
9
|
+
* rest" pose, mirror of the daemon's `Backend.INIT_HEAD_POSE` +
|
|
10
|
+
* `Backend.INIT_ANTENNAS_JOINT_POSITIONS`.
|
|
11
|
+
* - **Distance math** (`distanceBetweenPoses`, `scaledDuration`):
|
|
12
|
+
* "how big is this move" + "how long should it take", computed
|
|
13
|
+
* synchronously client-side so apps can sync audio / scheduling
|
|
14
|
+
* against it.
|
|
15
|
+
* - **Exit handlers** (`safelyReturnToPose`, `installShutdownHandler`):
|
|
16
|
+
* thin convenience wrappers around the three-call SDK sequence
|
|
17
|
+
* (`setMotorMode` + read state + `gotoTarget`) for `pagehide` /
|
|
18
|
+
* `onLeave` call sites.
|
|
19
|
+
*
|
|
20
|
+
* Pure-TS: this lib does not introduce any daemon-side primitive. All
|
|
21
|
+
* motion routes through existing data-channel commands. See
|
|
22
|
+
* `DESIGN.md` for the rationale.
|
|
23
|
+
*
|
|
24
|
+
* @see DESIGN.md
|
|
25
|
+
* @see APP_CREATION_GUIDE.md — "Robotics best practices" section
|
|
26
|
+
*/
|
|
27
|
+
// Constants
|
|
28
|
+
export { INIT_HEAD_POSE_FLAT, INIT_ANTENNAS_RAD, INIT_BODY_YAW_RAD, INIT_POSE, DEFAULT_SCALED_DURATION_PRESET, } from "./presets.js";
|
|
29
|
+
// Distance + scaled duration
|
|
30
|
+
export { distanceBetweenPoses, scaledDuration } from "./distance.js";
|
|
31
|
+
// Exit-handler helpers
|
|
32
|
+
export { safelyReturnToPose, installShutdownHandler } from "./safe-return.js";
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../animation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAWH,YAAY;AACZ,OAAO,EACH,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,8BAA8B,GACjC,MAAM,cAAc,CAAC;AAEtB,6BAA6B;AAC7B,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAErE,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pose primitives.
|
|
3
|
+
*
|
|
4
|
+
* A `Pose` is the canonical "frame" the SDK sends and receives on the
|
|
5
|
+
* data channel. The shape mirrors `setTarget` / `gotoTarget` / the
|
|
6
|
+
* `state` event payload, named so it can be passed around without
|
|
7
|
+
* anonymous-object soup.
|
|
8
|
+
*
|
|
9
|
+
* Channel units (wire format):
|
|
10
|
+
* - `head` : flat 16-float row-major 4×4 homogeneous matrix.
|
|
11
|
+
* - `antennas` : [right, left] in **radians**.
|
|
12
|
+
* - `body_yaw` : scalar in **radians**.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Canonical pose carried over the data channel. All three channels
|
|
16
|
+
* required.
|
|
17
|
+
*/
|
|
18
|
+
export interface Pose {
|
|
19
|
+
/** Flat 16-float row-major 4×4 head pose. */
|
|
20
|
+
head: number[];
|
|
21
|
+
/** [right, left] in radians. */
|
|
22
|
+
antennas: [number, number];
|
|
23
|
+
/** Body yaw in radians. */
|
|
24
|
+
body_yaw: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Same shape as `Pose` but every channel is optional. Matches the
|
|
28
|
+
* partial-update semantics of `setTarget` / `gotoTarget`: only the
|
|
29
|
+
* channels you specify are commanded; the rest keep their previous
|
|
30
|
+
* target.
|
|
31
|
+
*
|
|
32
|
+
* Also the shape `reachy.robotState` actually carries — fields appear
|
|
33
|
+
* only once the daemon has emitted them.
|
|
34
|
+
*/
|
|
35
|
+
export interface PartialPose {
|
|
36
|
+
head?: number[];
|
|
37
|
+
antennas?: [number, number] | number[];
|
|
38
|
+
body_yaw?: number;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=pose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pose.d.ts","sourceRoot":"","sources":["../../animation/pose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;GAGG;AACH,MAAM,WAAW,IAAI;IACjB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,gCAAgC;IAChC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IACxB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pose primitives.
|
|
3
|
+
*
|
|
4
|
+
* A `Pose` is the canonical "frame" the SDK sends and receives on the
|
|
5
|
+
* data channel. The shape mirrors `setTarget` / `gotoTarget` / the
|
|
6
|
+
* `state` event payload, named so it can be passed around without
|
|
7
|
+
* anonymous-object soup.
|
|
8
|
+
*
|
|
9
|
+
* Channel units (wire format):
|
|
10
|
+
* - `head` : flat 16-float row-major 4×4 homogeneous matrix.
|
|
11
|
+
* - `antennas` : [right, left] in **radians**.
|
|
12
|
+
* - `body_yaw` : scalar in **radians**.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=pose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pose.js","sourceRoot":"","sources":["../../animation/pose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical safe-rest pose + scaled-duration preset.
|
|
3
|
+
*
|
|
4
|
+
* Both are mirrored from the daemon (Python). The constants live on
|
|
5
|
+
* both sides because apps need the values **synchronously** in JS:
|
|
6
|
+
*
|
|
7
|
+
* - `INIT_POSE`: the "home" pose for `safelyReturnToPose`'s default
|
|
8
|
+
* target. Mirror of `Backend.INIT_HEAD_POSE` + `Backend.INIT_ANTENNAS_JOINT_POSITIONS`
|
|
9
|
+
* in `src/reachy_mini/daemon/backend/abstract.py`.
|
|
10
|
+
* - `DEFAULT_SCALED_DURATION_PRESET`: the per-channel "magic-mm × cost"
|
|
11
|
+
* tuning. Mirror of the constants the daemon already uses for
|
|
12
|
+
* `wake_up()` / `goto_sleep()` durations.
|
|
13
|
+
*
|
|
14
|
+
* **If you change a value here**, update the matching constant in
|
|
15
|
+
* `src/reachy_mini/daemon/backend/abstract.py` in the same commit.
|
|
16
|
+
*/
|
|
17
|
+
import type { Pose } from "./pose.js";
|
|
18
|
+
/**
|
|
19
|
+
* Identity 4×4 head matrix, row-major, flattened.
|
|
20
|
+
*
|
|
21
|
+
* Mirror of `Backend.INIT_HEAD_POSE` (Python `np.eye(4)`) in
|
|
22
|
+
* `abstract.py`. Frozen so apps can't accidentally mutate the shared
|
|
23
|
+
* instance via `INIT_POSE.head[0] = 0`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const INIT_HEAD_POSE_FLAT: readonly number[];
|
|
26
|
+
/**
|
|
27
|
+
* Antennas at ~±10° outward (anti-resonance offset).
|
|
28
|
+
*
|
|
29
|
+
* Mirror of `Backend.INIT_ANTENNAS_JOINT_POSITIONS = [-0.1745, 0.1745]`
|
|
30
|
+
* (rounded to match Python bit-for-bit) in `abstract.py`. Background:
|
|
31
|
+
* straight-up (0°, 0°) antennas mechanically resonate with the
|
|
32
|
+
* head-motor cogging frequency; the ~10° symmetric outward tilt damps
|
|
33
|
+
* it. See [PR #952](https://github.com/pollen-robotics/reachy_mini/pull/952).
|
|
34
|
+
*/
|
|
35
|
+
export declare const INIT_ANTENNAS_RAD: readonly [number, number];
|
|
36
|
+
/** Body squared up: head and body share the world-frame yaw axis at rest. */
|
|
37
|
+
export declare const INIT_BODY_YAW_RAD: number;
|
|
38
|
+
/**
|
|
39
|
+
* Aggregate canonical "safe rest" pose.
|
|
40
|
+
*
|
|
41
|
+
* Default target for `safelyReturnToPose`. Deep-frozen, so spread it
|
|
42
|
+
* if you need a mutable copy:
|
|
43
|
+
* `{ ...INIT_POSE, head: INIT_POSE.head.slice() }`.
|
|
44
|
+
*/
|
|
45
|
+
export declare const INIT_POSE: Readonly<Pose>;
|
|
46
|
+
/**
|
|
47
|
+
* Tuning knobs for `scaledDuration` and friends.
|
|
48
|
+
*
|
|
49
|
+
* Each `*SecPer*` field is the per-unit cost of motion on that channel.
|
|
50
|
+
* A move's duration is `max(channelDistance × channelCost)` across all
|
|
51
|
+
* channels, clamped to `[minDurationSec, maxDurationSec]`. Slowest
|
|
52
|
+
* channel wins.
|
|
53
|
+
*/
|
|
54
|
+
export interface ScaledDurationPreset {
|
|
55
|
+
/** Head: `magicMm × this` = head channel candidate (sec). */
|
|
56
|
+
readonly headSecPerMagicMm: number;
|
|
57
|
+
/** Per antenna: `|Δ°| × this` = each antenna's candidate (sec). */
|
|
58
|
+
readonly antennaSecPerDeg: number;
|
|
59
|
+
/** Body yaw: `|Δ°| × this` = body channel candidate (sec). */
|
|
60
|
+
readonly bodyYawSecPerDeg: number;
|
|
61
|
+
/** Lower bound on the final duration (sec). */
|
|
62
|
+
readonly minDurationSec: number;
|
|
63
|
+
/** Upper bound on the final duration (sec). */
|
|
64
|
+
readonly maxDurationSec: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Default tuning, calibrated on a real Reachy Mini via the
|
|
68
|
+
* `reachy-mini-js-practices` bench (May 2026).
|
|
69
|
+
*
|
|
70
|
+
* Per-channel rationale:
|
|
71
|
+
* - **head**: 0.015 s per "magic-mm" (translation_mm + rotation_deg).
|
|
72
|
+
* 0.02 reads as noticeably slow on the head.
|
|
73
|
+
* - **antenna**: 0.005 s/°. Antennas are light, but the mechanical
|
|
74
|
+
* resonance window (~PR #952) penalises overly fast moves.
|
|
75
|
+
* - **body_yaw**: 0.015 s/°. Body sits between head (heavy) and
|
|
76
|
+
* antennas (light).
|
|
77
|
+
* - **min/max**: 0.01 / 1.5 s. The low floor matters for in-app
|
|
78
|
+
* interactions — at 0.2 s, every tiny correction takes 200 ms
|
|
79
|
+
* minimum and reads as sluggish.
|
|
80
|
+
*
|
|
81
|
+
* Frozen so apps can't mutate the shared instance. Spread to derive
|
|
82
|
+
* a custom preset: `{ ...DEFAULT_SCALED_DURATION_PRESET, headSecPerMagicMm: 0.03 }`.
|
|
83
|
+
*/
|
|
84
|
+
export declare const DEFAULT_SCALED_DURATION_PRESET: Readonly<ScaledDurationPreset>;
|
|
85
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../animation/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAItC;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAK/C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAEzB,CAAC;AAEhC,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,EAAE,MAAU,CAAC;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,IAAI,CAInC,CAAC;AAIH;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,oBAAoB,CAMxE,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical safe-rest pose + scaled-duration preset.
|
|
3
|
+
*
|
|
4
|
+
* Both are mirrored from the daemon (Python). The constants live on
|
|
5
|
+
* both sides because apps need the values **synchronously** in JS:
|
|
6
|
+
*
|
|
7
|
+
* - `INIT_POSE`: the "home" pose for `safelyReturnToPose`'s default
|
|
8
|
+
* target. Mirror of `Backend.INIT_HEAD_POSE` + `Backend.INIT_ANTENNAS_JOINT_POSITIONS`
|
|
9
|
+
* in `src/reachy_mini/daemon/backend/abstract.py`.
|
|
10
|
+
* - `DEFAULT_SCALED_DURATION_PRESET`: the per-channel "magic-mm × cost"
|
|
11
|
+
* tuning. Mirror of the constants the daemon already uses for
|
|
12
|
+
* `wake_up()` / `goto_sleep()` durations.
|
|
13
|
+
*
|
|
14
|
+
* **If you change a value here**, update the matching constant in
|
|
15
|
+
* `src/reachy_mini/daemon/backend/abstract.py` in the same commit.
|
|
16
|
+
*/
|
|
17
|
+
// ─── Canonical safe-rest pose ────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Identity 4×4 head matrix, row-major, flattened.
|
|
20
|
+
*
|
|
21
|
+
* Mirror of `Backend.INIT_HEAD_POSE` (Python `np.eye(4)`) in
|
|
22
|
+
* `abstract.py`. Frozen so apps can't accidentally mutate the shared
|
|
23
|
+
* instance via `INIT_POSE.head[0] = 0`.
|
|
24
|
+
*/
|
|
25
|
+
export const INIT_HEAD_POSE_FLAT = Object.freeze([
|
|
26
|
+
1, 0, 0, 0,
|
|
27
|
+
0, 1, 0, 0,
|
|
28
|
+
0, 0, 1, 0,
|
|
29
|
+
0, 0, 0, 1,
|
|
30
|
+
]);
|
|
31
|
+
/**
|
|
32
|
+
* Antennas at ~±10° outward (anti-resonance offset).
|
|
33
|
+
*
|
|
34
|
+
* Mirror of `Backend.INIT_ANTENNAS_JOINT_POSITIONS = [-0.1745, 0.1745]`
|
|
35
|
+
* (rounded to match Python bit-for-bit) in `abstract.py`. Background:
|
|
36
|
+
* straight-up (0°, 0°) antennas mechanically resonate with the
|
|
37
|
+
* head-motor cogging frequency; the ~10° symmetric outward tilt damps
|
|
38
|
+
* it. See [PR #952](https://github.com/pollen-robotics/reachy_mini/pull/952).
|
|
39
|
+
*/
|
|
40
|
+
export const INIT_ANTENNAS_RAD = Object.freeze([
|
|
41
|
+
-0.1745, 0.1745,
|
|
42
|
+
]);
|
|
43
|
+
/** Body squared up: head and body share the world-frame yaw axis at rest. */
|
|
44
|
+
export const INIT_BODY_YAW_RAD = 0;
|
|
45
|
+
/**
|
|
46
|
+
* Aggregate canonical "safe rest" pose.
|
|
47
|
+
*
|
|
48
|
+
* Default target for `safelyReturnToPose`. Deep-frozen, so spread it
|
|
49
|
+
* if you need a mutable copy:
|
|
50
|
+
* `{ ...INIT_POSE, head: INIT_POSE.head.slice() }`.
|
|
51
|
+
*/
|
|
52
|
+
export const INIT_POSE = Object.freeze({
|
|
53
|
+
head: INIT_HEAD_POSE_FLAT,
|
|
54
|
+
antennas: INIT_ANTENNAS_RAD,
|
|
55
|
+
body_yaw: INIT_BODY_YAW_RAD,
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* Default tuning, calibrated on a real Reachy Mini via the
|
|
59
|
+
* `reachy-mini-js-practices` bench (May 2026).
|
|
60
|
+
*
|
|
61
|
+
* Per-channel rationale:
|
|
62
|
+
* - **head**: 0.015 s per "magic-mm" (translation_mm + rotation_deg).
|
|
63
|
+
* 0.02 reads as noticeably slow on the head.
|
|
64
|
+
* - **antenna**: 0.005 s/°. Antennas are light, but the mechanical
|
|
65
|
+
* resonance window (~PR #952) penalises overly fast moves.
|
|
66
|
+
* - **body_yaw**: 0.015 s/°. Body sits between head (heavy) and
|
|
67
|
+
* antennas (light).
|
|
68
|
+
* - **min/max**: 0.01 / 1.5 s. The low floor matters for in-app
|
|
69
|
+
* interactions — at 0.2 s, every tiny correction takes 200 ms
|
|
70
|
+
* minimum and reads as sluggish.
|
|
71
|
+
*
|
|
72
|
+
* Frozen so apps can't mutate the shared instance. Spread to derive
|
|
73
|
+
* a custom preset: `{ ...DEFAULT_SCALED_DURATION_PRESET, headSecPerMagicMm: 0.03 }`.
|
|
74
|
+
*/
|
|
75
|
+
export const DEFAULT_SCALED_DURATION_PRESET = Object.freeze({
|
|
76
|
+
headSecPerMagicMm: 0.015,
|
|
77
|
+
antennaSecPerDeg: 0.005,
|
|
78
|
+
bodyYawSecPerDeg: 0.015,
|
|
79
|
+
minDurationSec: 0.01,
|
|
80
|
+
maxDurationSec: 1.5,
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../animation/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAChE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACV,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACV,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACV,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;CACb,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA8B,MAAM,CAAC,MAAM,CAAC;IACtE,CAAC,MAAM,EAAE,MAAM;CAClB,CAA8B,CAAC;AAEhC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAW,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAmB,MAAM,CAAC,MAAM,CAAC;IACnD,IAAI,EAAE,mBAAoD;IAC1D,QAAQ,EAAE,iBAAkE;IAC5E,QAAQ,EAAE,iBAAiB;CAC9B,CAAC,CAAC;AAyBH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAmC,MAAM,CAAC,MAAM,CAAC;IACxF,iBAAiB,EAAE,KAAK;IACxB,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,KAAK;IACvB,cAAc,EAAE,IAAI;IACpB,cAAc,EAAE,GAAG;CACtB,CAAC,CAAC"}
|