gps-plus-slam-app-framework 1.0.7 → 1.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.
Files changed (167) hide show
  1. package/README.md +69 -15
  2. package/dist/{app-selectors-BeU0_ab8.d.ts → app-selectors-CR9OWodf.d.ts} +1 -1
  3. package/dist/ar/camera-blit-capture.d.ts +1 -1
  4. package/dist/ar/capability-checker.d.ts +2 -0
  5. package/dist/ar/capability-checker.js +25 -0
  6. package/dist/ar/capture-failure-tracker.d.ts +1 -1
  7. package/dist/ar/chromium-camera-access-workaround.d.ts +2 -2
  8. package/dist/ar/chromium-camera-access-workaround.js +197 -8
  9. package/dist/ar/depth-sampler.d.ts +2 -2
  10. package/dist/ar/enable-gps-ar.d.ts +2 -0
  11. package/dist/ar/enable-gps-ar.js +137 -0
  12. package/dist/ar/frame-loop.d.ts +1 -1
  13. package/dist/ar/frame-loop.js +24 -1
  14. package/dist/ar/image-capture.d.ts +1 -1
  15. package/dist/ar/index.d.ts +15 -11
  16. package/dist/ar/index.js +7 -3
  17. package/dist/ar/replay-scene.d.ts +1 -1
  18. package/dist/ar/scene-node-names.d.ts +1 -1
  19. package/dist/ar/webxr-session.d.ts +4 -4
  20. package/dist/ar/webxr-session.js +23 -38
  21. package/dist/ar/xr-error-handler.d.ts +1 -1
  22. package/dist/ar/xr-frame-loop.d.ts +2 -0
  23. package/dist/ar/xr-frame-loop.js +69 -0
  24. package/dist/ar-world-group-alignment-Dn4rQk_c.d.ts +43 -0
  25. package/dist/capability-checker-BTCmZRL4.d.ts +43 -0
  26. package/dist/chromium-camera-access-workaround-MifIwK9x.d.ts +137 -0
  27. package/dist/core/index.d.ts +1 -1
  28. package/dist/{create-slam-app-store-CNsZ3rcX.d.ts → create-slam-app-store-B76AGaI0.d.ts} +5 -5
  29. package/dist/{depth-sampler-xg8vna6c.d.ts → depth-sampler-CqrkRr2N.d.ts} +1 -1
  30. package/dist/enable-gps-ar-DNbO0zbg.d.ts +95 -0
  31. package/dist/{file-system-DTApEv_Q.d.ts → file-system-TIsDfamK.d.ts} +1 -1
  32. package/dist/frame-conversions-D2EYjeNa.d.ts +54 -0
  33. package/dist/{frame-loop-QJIxLin0.d.ts → frame-loop-BTeRpDm4.d.ts} +5 -0
  34. package/dist/{fused-path-CB4DwWOG.d.ts → fused-path-BdVHmDW9.d.ts} +1 -1
  35. package/dist/geo/h3-proximity.d.ts +1 -1
  36. package/dist/geo/index.d.ts +1 -1
  37. package/dist/{gps-anchor-CnWY61XK.d.ts → gps-anchor-CISLPQIb.d.ts} +12 -1
  38. package/dist/{gps-ar-pose-sampler-DsM1Kb2N.d.ts → gps-ar-pose-sampler-BypXZUqC.d.ts} +1 -1
  39. package/dist/{gps-event-coordinator-DBx9I1YX.d.ts → gps-event-coordinator-BKVZbS1M.d.ts} +3 -3
  40. package/dist/hit-test-reticle-BGXOxrUh.d.ts +45 -0
  41. package/dist/{image-capture-DZLxHDN9.d.ts → image-capture-BXZUmj7j.d.ts} +1 -1
  42. package/dist/index-22v8MXJX.d.ts +23 -0
  43. package/dist/index-BB2KEWbN2.d.ts +37 -0
  44. package/dist/index.d.ts +63 -57
  45. package/dist/index.js +14 -7
  46. package/dist/{leaflet-map-overlay-Cew7XAoO.d.ts → leaflet-map-overlay-jNt-kcUr.d.ts} +1 -1
  47. package/dist/{map-data-sih4g64v.d.ts → map-data-BGIBM5rv.d.ts} +1 -1
  48. package/dist/{map-overlay-draw-B3R1c9Xp.d.ts → map-overlay-draw-DcGs9UV3.d.ts} +1 -1
  49. package/dist/{null-storage-backend-BKOS7JpL.d.ts → null-storage-backend-BPQJSaMw.d.ts} +2 -2
  50. package/dist/{opfs-storage-backend-Cj_7PWoq.d.ts → opfs-storage-backend-u4QKvgvP.d.ts} +2 -2
  51. package/dist/{persistence-middleware-BkHIqvaA.d.ts → persistence-middleware-xB5sTllJ.d.ts} +1 -1
  52. package/dist/{recording-options-Dq6IsKAv.d.ts → recording-options-BSFpBSZH.d.ts} +10 -4
  53. package/dist/{recording-replayer-CmCIIZ02.d.ts → recording-replayer-CTL2cUE0.d.ts} +2 -2
  54. package/dist/{recording-slice-d6OtCrza.d.ts → recording-slice-Cb888P6d.d.ts} +2 -2
  55. package/dist/{replay-engine-BGBRQyXs.d.ts → replay-engine-B-5GIZtc.d.ts} +1 -1
  56. package/dist/{replay-scene-DpAGcAKY.d.ts → replay-scene-DkNfldPh.d.ts} +3 -3
  57. package/dist/sensors/gps-error-handler.d.ts +1 -1
  58. package/dist/sensors/gps.d.ts +1 -1
  59. package/dist/sensors/index.d.ts +3 -3
  60. package/dist/sensors/index.js +1 -1
  61. package/dist/sensors/permission-checker.d.ts +1 -1
  62. package/dist/session-disposers-M-oashRH.js +57 -0
  63. package/dist/state/app-selectors.d.ts +1 -1
  64. package/dist/state/combined-root-state.d.ts +1 -1
  65. package/dist/state/create-slam-app-store.d.ts +1 -1
  66. package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
  67. package/dist/state/gps-event-coordinator.d.ts +1 -1
  68. package/dist/state/index.d.ts +17 -17
  69. package/dist/state/index.js +2 -2
  70. package/dist/state/persistence-middleware.d.ts +1 -1
  71. package/dist/state/persistence-middleware.js +9 -3
  72. package/dist/state/recording-options.d.ts +1 -1
  73. package/dist/state/recording-replayer.d.ts +2 -2
  74. package/dist/state/recording-slice.d.ts +1 -1
  75. package/dist/state/replay-engine.d.ts +1 -1
  76. package/dist/state/store-subscribers.d.ts +2 -2
  77. package/dist/state/subscribe-to-selector.d.ts +1 -1
  78. package/dist/state/tracking-quality.d.ts +1 -1
  79. package/dist/state/tracking-slice.d.ts +1 -1
  80. package/dist/state-BkIfpiyA.js +87 -0
  81. package/dist/storage/file-system-utils.d.ts +1 -1
  82. package/dist/storage/file-system.d.ts +1 -1
  83. package/dist/storage/index.d.ts +8 -8
  84. package/dist/storage/null-storage-backend.d.ts +1 -1
  85. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  86. package/dist/storage/opfs-storage.d.ts +1 -1
  87. package/dist/storage/storage-backend.d.ts +1 -1
  88. package/dist/storage/zip-export.d.ts +1 -1
  89. package/dist/storage/zip-reader.d.ts +1 -1
  90. package/dist/{storage-backend-CT0Il_AB.d.ts → storage-backend-yDSKafAQ.d.ts} +1 -1
  91. package/dist/{store-subscribers-Dce_CoJF.d.ts → store-subscribers-swlbtg_z.d.ts} +2 -2
  92. package/dist/{subscribe-to-selector-DIHm3BRZ.d.ts → subscribe-to-selector--KQpgLXG.d.ts} +1 -1
  93. package/dist/test-utils/browser-mocks.d.ts +1 -1
  94. package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
  95. package/dist/{tracking-slice-utCNND8t.d.ts → tracking-slice-CDREeoZ_.d.ts} +1 -1
  96. package/dist/types/ar-types.d.ts +1 -1
  97. package/dist/types/geo-types.d.ts +1 -1
  98. package/dist/types/index.d.ts +2 -2
  99. package/dist/utils/concurrency.d.ts +1 -1
  100. package/dist/utils/failure-tracker.d.ts +1 -1
  101. package/dist/utils/format-file-size.d.ts +1 -1
  102. package/dist/utils/fused-path.d.ts +1 -1
  103. package/dist/utils/index.d.ts +6 -6
  104. package/dist/utils/list-formatter.d.ts +1 -1
  105. package/dist/utils/logger.d.ts +1 -1
  106. package/dist/visualization/accuracy-circles.d.ts +1 -1
  107. package/dist/visualization/alignment-lerper.d.ts +1 -1
  108. package/dist/visualization/ar-world-group-alignment.d.ts +2 -0
  109. package/dist/visualization/ar-world-group-alignment.js +51 -0
  110. package/dist/visualization/camera-follower.d.ts +1 -1
  111. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  112. package/dist/visualization/frame-conversions.d.ts +2 -0
  113. package/dist/visualization/frame-conversions.js +88 -0
  114. package/dist/visualization/frustum-visibility.d.ts +1 -1
  115. package/dist/visualization/gps-anchor.d.ts +1 -1
  116. package/dist/visualization/gps-anchor.js +216 -1
  117. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  118. package/dist/visualization/gps-event-markers.d.ts +1 -1
  119. package/dist/visualization/hit-test-reticle.d.ts +2 -0
  120. package/dist/visualization/hit-test-reticle.js +81 -0
  121. package/dist/visualization/index.d.ts +19 -17
  122. package/dist/visualization/index.js +5 -2
  123. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  124. package/dist/visualization/lerp-utils.d.ts +1 -1
  125. package/dist/visualization/map-data.d.ts +1 -1
  126. package/dist/visualization/map-overlay-draw.d.ts +1 -1
  127. package/dist/visualization/map-overlay.d.ts +1 -1
  128. package/dist/visualization/three-dispose.d.ts +1 -1
  129. package/dist/visualization/vis-colors.d.ts +1 -1
  130. package/dist/webxr-nue-basis-BbdqhqY6.js +54 -0
  131. package/dist/{webxr-session-DB5cIZnN.d.ts → webxr-session-BnArFCew.d.ts} +29 -8
  132. package/dist/xr-frame-loop-BKckC7xC.d.ts +70 -0
  133. package/package.json +1 -1
  134. package/dist/chromium-camera-access-workaround-NvChXsi8.d.ts +0 -61
  135. package/dist/gps-anchor-DjC_3MoT.js +0 -257
  136. package/dist/index-pOjUCKEP.d.ts +0 -24
  137. /package/dist/{accuracy-circles-CsxE_7x1.d.ts → accuracy-circles-DEKr0Hoh.d.ts} +0 -0
  138. /package/dist/{alignment-lerper-L1RbWHQ4.d.ts → alignment-lerper-CCZJf-Xb.d.ts} +0 -0
  139. /package/dist/{ar-types-Ck8LEq8k.d.ts → ar-types-isPsQptb.d.ts} +0 -0
  140. /package/dist/{camera-blit-capture-C1V9I1Z6.d.ts → camera-blit-capture-75WWa9Xb.d.ts} +0 -0
  141. /package/dist/{camera-follower-1k8mnw5J.d.ts → camera-follower-B-nS1sr6.d.ts} +0 -0
  142. /package/dist/{capture-failure-tracker-JKb1ST8E.d.ts → capture-failure-tracker-D4HYJNOj.d.ts} +0 -0
  143. /package/dist/{concurrency-CMw8pSaG.d.ts → concurrency-Bsmv53qw.d.ts} +0 -0
  144. /package/dist/{css3d-renderer-manager-CkjCb2HW.d.ts → css3d-renderer-manager-EDED3nvg.d.ts} +0 -0
  145. /package/dist/{failure-tracker-DnHXOIRa.d.ts → failure-tracker-D7ELffm0.d.ts} +0 -0
  146. /package/dist/{file-system-utils-CtKiiw27.d.ts → file-system-utils-BH6uIs2i.d.ts} +0 -0
  147. /package/dist/{format-file-size-BTS5H62-.d.ts → format-file-size-B7gJb3Md.d.ts} +0 -0
  148. /package/dist/{frustum-visibility-BHnFrSKQ.d.ts → frustum-visibility-DGnJqls0.d.ts} +0 -0
  149. /package/dist/{geo-types-CTuF23gG.d.ts → geo-types-clgzl8b5.d.ts} +0 -0
  150. /package/dist/{gps-DXoQb9Kf.d.ts → gps-B7AlMPz5.d.ts} +0 -0
  151. /package/dist/{gps-compass-cubes-CsLtFv4B.d.ts → gps-compass-cubes-Ys6Hf1nc.d.ts} +0 -0
  152. /package/dist/{gps-error-handler-Dg3ziRVY.d.ts → gps-error-handler-BLDhUlw5.d.ts} +0 -0
  153. /package/dist/{gps-event-markers-BGr-iLvi.d.ts → gps-event-markers-BlHq3jYV.d.ts} +0 -0
  154. /package/dist/{h3-proximity-BhfgNbdW.d.ts → h3-proximity-DJnghtir.d.ts} +0 -0
  155. /package/dist/{index-gzWJMVpo.d.ts → index--ldLph4V.d.ts} +0 -0
  156. /package/dist/{lerp-utils-B8MM8zCR.d.ts → lerp-utils-DNcSmKVX.d.ts} +0 -0
  157. /package/dist/{list-formatter-CNqi-E2j.d.ts → list-formatter-CsqcU4v5.d.ts} +0 -0
  158. /package/dist/{logger-C9vugiQb.d.ts → logger-BZ44Dhd3.d.ts} +0 -0
  159. /package/dist/{map-overlay-DAmreyA3.d.ts → map-overlay-yrFsUtGv.d.ts} +0 -0
  160. /package/dist/{opfs-storage-DOPkzgeT.d.ts → opfs-storage-LsLY6VZV.d.ts} +0 -0
  161. /package/dist/{permission-checker-DPJl_RU6.d.ts → permission-checker-CfV7INCa.d.ts} +0 -0
  162. /package/dist/{scene-node-names-6LBjPmwz.d.ts → scene-node-names-IHW7HR4S.d.ts} +0 -0
  163. /package/dist/{three-dispose-C2drkp6f.d.ts → three-dispose-WTBAfaWU.d.ts} +0 -0
  164. /package/dist/{vis-colors-CHQhjal3.d.ts → vis-colors-Djnyg_UH.d.ts} +0 -0
  165. /package/dist/{xr-error-handler-CDY5QxGb.d.ts → xr-error-handler-DcUFshNF.d.ts} +0 -0
  166. /package/dist/{zip-export-QO4iLIi7.d.ts → zip-export-C0_ErAqT.d.ts} +0 -0
  167. /package/dist/{zip-reader-D1105idz.d.ts → zip-reader-B2lzN8F5.d.ts} +0 -0
@@ -1,257 +0,0 @@
1
- import { registerFrameUpdate } from "./ar/frame-loop.js";
2
- import { isObjectInCameraFrustum } from "./visualization/frustum-visibility.js";
3
- import { calcRelativeCoordsInMeters } from "./core/index.js";
4
- import * as THREE from "three";
5
- //#region ../src/visualization/frame-conversions.ts
6
- /**
7
- * `frame-conversions` — small, pure coordinate-frame helpers for the AR scene
8
- * graph. Currently a single function, `nueToArLocal`, that converts a
9
- * GPS-world NUE point into the AR-odometry local frame of `arWorldGroup`.
10
- *
11
- * Background: the scene root is GPS-world NUE; `arWorldGroup.matrix` IS the
12
- * alignment matrix, which maps **AR-odometry NUE → GPS-world NUE**. So a
13
- * direct child of `arWorldGroup` whose WORLD position must equal a GPS-world
14
- * point `nue` has to store `alignment⁻¹ · nue` as its LOCAL position —
15
- * writing raw `nue` double-applies the alignment. Getting this wrong was the
16
- * alignment-frame bug
17
- * (gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-gps-anchor-alignment-frame-bug.md);
18
- * this helper centralises the conversion behind one tested, well-named seam.
19
- *
20
- * Design (see the plan
21
- * gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-nue-to-ar-local-helper-plan.md):
22
- * - **Takes the explicit alignment matrix array**, NOT `Object3D.worldToLocal`.
23
- * `worldToLocal` would read the live, mid-lerp `matrixWorld` and break
24
- * replay determinism; the explicit target matrix keeps the result a pure
25
- * function of its inputs. Full rationale in the review doc
26
- * (gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-worldtolocal-frame-helper-review.md).
27
- * - **Positions only.** No pose/quaternion variant exists until a caller
28
- * needs one (YAGNI). No caller currently sets a GPS-world rotation.
29
- */
30
- const scratchMatrix = new THREE.Matrix4();
31
- /**
32
- * Convert a GPS-world NUE point into the AR-local position to write into a
33
- * direct child of `arWorldGroup`, given the current alignment matrix.
34
- *
35
- * Computes `alignment⁻¹ · nue`. When the result is later composed back by the
36
- * group's matrix (the same `alignment`), the child's WORLD position equals
37
- * `nue` exactly.
38
- *
39
- * @param alignment - The alignment matrix as a 16-element **column-major**
40
- * array (AR-odometry NUE → GPS-world NUE), e.g. from `getAlignmentMatrix()`
41
- * or `THREE.Matrix4.toArray()`. Not mutated.
42
- * @param nue - The GPS-world NUE point `[north, up, east]` in metres. Not
43
- * mutated.
44
- * @param out - Optional target vector to write into and return (pass a reused
45
- * scratch to avoid allocation on hot paths). Defaults to a fresh
46
- * `THREE.Vector3`.
47
- * @returns `out`, set to the AR-local position.
48
- */
49
- function nueToArLocal(alignment, nue, out = new THREE.Vector3()) {
50
- scratchMatrix.fromArray(alignment).invert();
51
- return out.set(nue[0], nue[1], nue[2]).applyMatrix4(scratchMatrix);
52
- }
53
- //#endregion
54
- //#region ../src/visualization/gps-anchor.ts
55
- /**
56
- * `createGpsAnchor` — GPS-anchored placement of a single `THREE.Object3D`.
57
- *
58
- * See the colocated sidecar (`gps-anchor.ts.md`) and the port plan at
59
- * `gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-13-gps-anchor-port-plan.md`
60
- * for the full design, state machine, and test matrix.
61
- *
62
- * This file implements sub-steps 2 (bootstrap phase), 3 (steady-state
63
- * `'snap-every-tick'` + distance-scaled threshold gate), and 4
64
- * (`'snap-when-offscreen'` mode gate + alignment-matrix large-jump
65
- * bypass). Floor-Y correction is sub-step 6 and remains deferred.
66
- */
67
- /**
68
- * Module-level registry of objects currently owned by a `GpsAnchor`.
69
- * Used to detect nested anchors (parent + child both anchored) which
70
- * we explicitly forbid; mirrors the C# invariant.
71
- */
72
- const anchoredObjects = /* @__PURE__ */ new WeakSet();
73
- function isObjectInAnchoredChain(object) {
74
- let cursor = object;
75
- while (cursor) {
76
- if (anchoredObjects.has(cursor)) return true;
77
- cursor = cursor.parent;
78
- }
79
- return false;
80
- }
81
- function median(values) {
82
- const sorted = [...values].sort((a, b) => a - b);
83
- const mid = Math.floor(sorted.length / 2);
84
- if (sorted.length % 2 === 0) return (sorted[mid - 1] + sorted[mid]) / 2;
85
- return sorted[mid];
86
- }
87
- function medianPoint(samples) {
88
- const lat = median(samples.map((s) => s.lat));
89
- const lon = median(samples.map((s) => s.lon));
90
- const alts = samples.map((s) => "altitude" in s ? s.altitude : void 0).filter((a) => typeof a === "number");
91
- if (alts.length > 0) return {
92
- lat,
93
- lon,
94
- altitude: median(alts)
95
- };
96
- return {
97
- lat,
98
- lon
99
- };
100
- }
101
- function createGpsAnchor(options) {
102
- if (isObjectInAnchoredChain(options.object3D)) throw new Error("createGpsAnchor: nested GpsAnchors are not supported — the supplied object3D is already inside an anchored parent chain.");
103
- anchoredObjects.add(options.object3D);
104
- const sampleCount = options.secondsToAccumulateGpsPose ?? 7;
105
- if (sampleCount < 1) {
106
- anchoredObjects.delete(options.object3D);
107
- throw new Error("createGpsAnchor: secondsToAccumulateGpsPose must be >= 1 — use skipBootstrap:true to bypass the accumulation phase.");
108
- }
109
- const settlingSeconds = options.settlingSeconds ?? 0;
110
- const distanceThreshold = options.distanceThreshold ?? 2;
111
- options.angleThresholdInDegrees;
112
- const mode = options.mode ?? "snap-when-offscreen";
113
- const LARGE_JUMP_TRANSLATION_M = 4;
114
- const LARGE_JUMP_Y_M = 20;
115
- const LARGE_JUMP_ROTATION_DEG = 2;
116
- const scratchTarget = new THREE.Vector3();
117
- const scratchCamWorld = new THREE.Vector3();
118
- const scratchObjWorld = new THREE.Vector3();
119
- const scratchPrevMatrix = new THREE.Matrix4();
120
- const scratchCurrMatrix = new THREE.Matrix4();
121
- const scratchPrevTrans = new THREE.Vector3();
122
- const scratchCurrTrans = new THREE.Vector3();
123
- const scratchPrevQuat = new THREE.Quaternion();
124
- const scratchCurrQuat = new THREE.Quaternion();
125
- let phase = options.skipBootstrap === true ? "anchored" : "bootstrap";
126
- let isFullyAnchored = phase === "anchored";
127
- let gpsPoint = options.gpsPoint;
128
- let phaseEnteredAtElapsed = null;
129
- let lastSampleAtElapsed = null;
130
- const samples = [];
131
- /**
132
- * Snapshot of the previous tick's alignment matrix. `null` until the
133
- * first steady-state tick in which `getAlignmentMatrix()` returned a
134
- * non-null value. Used by the large-jump bypass to compare against
135
- * the current tick's matrix.
136
- */
137
- let prevAlignmentMatrix = null;
138
- /**
139
- * Returns true iff the alignment matrix has jumped by more than the
140
- * configured large-jump thresholds between `prev` and `curr`. A
141
- * `null` `prev` (first tick) is treated as "no jump".
142
- */
143
- const detectLargeAlignmentJump = (prev, curr) => {
144
- if (prev === null || curr === null) return false;
145
- scratchPrevMatrix.fromArray(prev);
146
- scratchCurrMatrix.fromArray(curr);
147
- scratchPrevTrans.setFromMatrixPosition(scratchPrevMatrix);
148
- scratchCurrTrans.setFromMatrixPosition(scratchCurrMatrix);
149
- const dTrans = scratchPrevTrans.distanceTo(scratchCurrTrans);
150
- const dY = Math.abs(scratchCurrTrans.y - scratchPrevTrans.y);
151
- scratchPrevQuat.setFromRotationMatrix(scratchPrevMatrix);
152
- scratchCurrQuat.setFromRotationMatrix(scratchCurrMatrix);
153
- const dRotDeg = scratchPrevQuat.angleTo(scratchCurrQuat) * 180 / Math.PI;
154
- return dTrans > LARGE_JUMP_TRANSLATION_M || dY > LARGE_JUMP_Y_M || dRotDeg > LARGE_JUMP_ROTATION_DEG;
155
- };
156
- const enterBootstrap = () => {
157
- phase = "bootstrap";
158
- isFullyAnchored = false;
159
- phaseEnteredAtElapsed = null;
160
- lastSampleAtElapsed = null;
161
- samples.length = 0;
162
- prevAlignmentMatrix = null;
163
- };
164
- const commitMedian = () => {
165
- gpsPoint = medianPoint(samples);
166
- phase = "anchored";
167
- isFullyAnchored = true;
168
- samples.length = 0;
169
- };
170
- /**
171
- * Steady-state: compute the GPS-world NUE target from the stored
172
- * `gpsPoint` and the current `zeroRef`, map it into `arWorldGroup`'s
173
- * AR-local frame via the inverse alignment matrix, and commit it to
174
- * `object3D.position` iff the (AR-local) position delta exceeds the
175
- * distance-scaled threshold AND the mode gate (with optional large-jump
176
- * bypass) allows it.
177
- *
178
- * Frame note: `arWorldGroup.matrix` IS the alignment matrix, which maps
179
- * **AR-odometry NUE → GPS-world NUE**. `object3D.position` is a *local*
180
- * transform in that AR-odometry frame. To make the object's *world*
181
- * position equal the GPS-world `nue`, the local target must be
182
- * `alignment⁻¹ · nue` — writing raw `nue` would double-apply the
183
- * alignment (world = `alignment · nue`). See
184
- * `gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-gps-anchor-alignment-frame-bug.md`.
185
- *
186
- * Returns silently on missing inputs (no `zeroRef`, or no alignment
187
- * matrix yet — an AR-local object cannot be placed without knowing the
188
- * AR↔NUE transform).
189
- */
190
- const maybeCommitSteadyState = () => {
191
- const zero = options.getGpsZeroRef();
192
- if (zero === null || zero === void 0) return;
193
- const currentAlignment = options.getAlignmentMatrix();
194
- const largeJump = detectLargeAlignmentJump(prevAlignmentMatrix, currentAlignment);
195
- prevAlignmentMatrix = currentAlignment;
196
- if (currentAlignment === null || currentAlignment === void 0) return;
197
- const targetAlt = "altitude" in gpsPoint && typeof gpsPoint.altitude === "number" ? gpsPoint.altitude : 0;
198
- const nue = calcRelativeCoordsInMeters(zero, gpsPoint, targetAlt, 0);
199
- nueToArLocal(currentAlignment, [
200
- nue[0],
201
- nue[1],
202
- nue[2]
203
- ], scratchTarget);
204
- options.camera.getWorldPosition(scratchCamWorld);
205
- options.object3D.getWorldPosition(scratchObjWorld);
206
- const scale = 1 + 10 * scratchCamWorld.distanceTo(scratchObjWorld) / 100;
207
- if (options.object3D.position.distanceTo(scratchTarget) < distanceThreshold * scale) return;
208
- if (mode === "snap-when-offscreen" && !largeJump) {
209
- if (isObjectInCameraFrustum(options.camera, options.object3D)) return;
210
- }
211
- options.object3D.position.copy(scratchTarget);
212
- };
213
- const tick = (_dt, elapsed) => {
214
- if (phase === "anchored") {
215
- maybeCommitSteadyState();
216
- return;
217
- }
218
- if (phaseEnteredAtElapsed === null) {
219
- phaseEnteredAtElapsed = elapsed;
220
- lastSampleAtElapsed = elapsed - 1;
221
- }
222
- if (elapsed - phaseEnteredAtElapsed < settlingSeconds) return;
223
- if (lastSampleAtElapsed !== null && elapsed - lastSampleAtElapsed < 1) return;
224
- const sample = options.getCurrentGpsPoint();
225
- if (sample === null || sample === void 0) return;
226
- samples.push(sample);
227
- lastSampleAtElapsed = elapsed;
228
- if (samples.length >= sampleCount) commitMedian();
229
- };
230
- const unregister = registerFrameUpdate(tick);
231
- return {
232
- get phase() {
233
- return phase;
234
- },
235
- get isFullyAnchored() {
236
- return isFullyAnchored;
237
- },
238
- get gpsPoint() {
239
- return gpsPoint;
240
- },
241
- markMovedExternally() {
242
- enterBootstrap();
243
- },
244
- setGpsPoint(point) {
245
- gpsPoint = point;
246
- },
247
- dispose() {
248
- unregister();
249
- anchoredObjects.delete(options.object3D);
250
- },
251
- __tickForTests(dt, elapsed) {
252
- tick(dt, elapsed);
253
- }
254
- };
255
- }
256
- //#endregion
257
- export { nueToArLocal as n, createGpsAnchor as t };
@@ -1,24 +0,0 @@
1
- import * as THREE from "three";
2
-
3
- //#region ../src/visualization/frame-conversions.d.ts
4
- /**
5
- * Convert a GPS-world NUE point into the AR-local position to write into a
6
- * direct child of `arWorldGroup`, given the current alignment matrix.
7
- *
8
- * Computes `alignment⁻¹ · nue`. When the result is later composed back by the
9
- * group's matrix (the same `alignment`), the child's WORLD position equals
10
- * `nue` exactly.
11
- *
12
- * @param alignment - The alignment matrix as a 16-element **column-major**
13
- * array (AR-odometry NUE → GPS-world NUE), e.g. from `getAlignmentMatrix()`
14
- * or `THREE.Matrix4.toArray()`. Not mutated.
15
- * @param nue - The GPS-world NUE point `[north, up, east]` in metres. Not
16
- * mutated.
17
- * @param out - Optional target vector to write into and return (pass a reused
18
- * scratch to avoid allocation on hot paths). Defaults to a fresh
19
- * `THREE.Vector3`.
20
- * @returns `out`, set to the AR-local position.
21
- */
22
- declare function nueToArLocal(alignment: readonly number[], nue: readonly [number, number, number], out?: THREE.Vector3): THREE.Vector3;
23
- //#endregion
24
- export { nueToArLocal as t };
File without changes