gps-plus-slam-app-framework 1.0.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 (200) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +222 -0
  3. package/dist/alignment-lerper-D9BeDwZX.d.ts +29 -0
  4. package/dist/app-selectors-DyMzxCEC.d.ts +140 -0
  5. package/dist/ar/camera-blit-capture.d.ts +2 -0
  6. package/dist/ar/camera-blit-capture.js +253 -0
  7. package/dist/ar/capture-failure-tracker.d.ts +2 -0
  8. package/dist/ar/capture-failure-tracker.js +45 -0
  9. package/dist/ar/chromium-camera-access-workaround.d.ts +2 -0
  10. package/dist/ar/chromium-camera-access-workaround.js +32 -0
  11. package/dist/ar/depth-sampler.d.ts +3 -0
  12. package/dist/ar/depth-sampler.js +147 -0
  13. package/dist/ar/image-capture.d.ts +2 -0
  14. package/dist/ar/image-capture.js +152 -0
  15. package/dist/ar/index.d.ts +12 -0
  16. package/dist/ar/index.js +12 -0
  17. package/dist/ar/replay-scene.d.ts +2 -0
  18. package/dist/ar/replay-scene.js +325 -0
  19. package/dist/ar/scene-node-names.d.ts +2 -0
  20. package/dist/ar/scene-node-names.js +16 -0
  21. package/dist/ar/tracking-state.d.ts +2 -0
  22. package/dist/ar/tracking-state.js +164 -0
  23. package/dist/ar/webxr-session.d.ts +4 -0
  24. package/dist/ar/webxr-session.js +890 -0
  25. package/dist/ar/xr-camera-texture.d.ts +2 -0
  26. package/dist/ar/xr-camera-texture.js +39 -0
  27. package/dist/ar/xr-error-handler.d.ts +2 -0
  28. package/dist/ar/xr-error-handler.js +37 -0
  29. package/dist/ar-types-B-ORgk6Z.d.ts +82 -0
  30. package/dist/camera-blit-capture-DHuyrrxr.d.ts +108 -0
  31. package/dist/camera-follower-BMqPddxx.d.ts +29 -0
  32. package/dist/capture-failure-tracker-2Q6oI2uQ.d.ts +52 -0
  33. package/dist/chromium-camera-access-workaround-CU5zSKNr.d.ts +61 -0
  34. package/dist/community-license-key-ChZLCJyO.d.ts +21 -0
  35. package/dist/concurrency-p6gB30fT.d.ts +24 -0
  36. package/dist/css3d-renderer-manager-rgLMVAvd.d.ts +23 -0
  37. package/dist/depth-sampler-BNCtnEoP.d.ts +108 -0
  38. package/dist/failure-tracker-1sQ_Cgyw.d.ts +49 -0
  39. package/dist/file-system-BsQgYCU3.d.ts +128 -0
  40. package/dist/file-system-utils-5cWO8Xyv.d.ts +24 -0
  41. package/dist/format-file-size-onGq0k1Q.d.ts +24 -0
  42. package/dist/fused-path-DtqCSqJh.d.ts +25 -0
  43. package/dist/geo-types-Xx-LVcnw.d.ts +29 -0
  44. package/dist/gps-Ddzr2KlX.d.ts +54 -0
  45. package/dist/gps-compass-cubes-C-6JEnpR.d.ts +22 -0
  46. package/dist/gps-error-handler-VPuNOuf8.d.ts +40 -0
  47. package/dist/gps-event-markers-DpEy2qRd.d.ts +67 -0
  48. package/dist/h3-ref-point-CFhayNSZ.d.ts +59 -0
  49. package/dist/image-capture-2pKjYUS6.d.ts +130 -0
  50. package/dist/index.d.ts +56 -0
  51. package/dist/index.js +61 -0
  52. package/dist/leaflet-map-overlay-CvfQXTye.d.ts +114 -0
  53. package/dist/lerp-utils-87NWjUOD.d.ts +20 -0
  54. package/dist/licensing/community-license-key.d.ts +2 -0
  55. package/dist/licensing/community-license-key.js +21 -0
  56. package/dist/licensing/index.d.ts +2 -0
  57. package/dist/licensing/index.js +2 -0
  58. package/dist/list-formatter-DKQQVLcl.d.ts +14 -0
  59. package/dist/logger-B81iwxx0.d.ts +74 -0
  60. package/dist/map-overlay-DuiZuCTx.d.ts +153 -0
  61. package/dist/null-storage-backend-CsWvQwN8.d.ts +11 -0
  62. package/dist/opfs-storage-ChOzF_Wp.d.ts +181 -0
  63. package/dist/opfs-storage-backend-CVcmfJHN.d.ts +11 -0
  64. package/dist/permission-checker-jO2ziCWC.d.ts +146 -0
  65. package/dist/persistence-middleware-DrptY02i.d.ts +31 -0
  66. package/dist/recorder-slice-fcwAXrsh.d.ts +35 -0
  67. package/dist/recording-coordinator-DzflP07_.d.ts +81 -0
  68. package/dist/recording-options-BYUFX8iU.d.ts +166 -0
  69. package/dist/recording-replayer-oOzPITrd.d.ts +32 -0
  70. package/dist/ref-point-importer-B_wn5ABk.d.ts +62 -0
  71. package/dist/ref-point-loader-Pt1smgHS.d.ts +117 -0
  72. package/dist/ref-points/h3-ref-point.d.ts +2 -0
  73. package/dist/ref-points/h3-ref-point.js +74 -0
  74. package/dist/ref-points/index.d.ts +2 -0
  75. package/dist/ref-points/index.js +2 -0
  76. package/dist/ref-points-slice-tC-Wd6XJ.d.ts +48 -0
  77. package/dist/reference-points-CFWy8_wj.d.ts +68 -0
  78. package/dist/replay-engine-DuX316ae.d.ts +103 -0
  79. package/dist/replay-scene-DtUm6bsr.d.ts +109 -0
  80. package/dist/routing-slice-BlHTM8eh.d.ts +23 -0
  81. package/dist/scene-node-names-DPsaE2z3.d.ts +14 -0
  82. package/dist/sensors/gps-error-handler.d.ts +2 -0
  83. package/dist/sensors/gps-error-handler.js +53 -0
  84. package/dist/sensors/gps.d.ts +2 -0
  85. package/dist/sensors/gps.js +93 -0
  86. package/dist/sensors/index.d.ts +4 -0
  87. package/dist/sensors/index.js +4 -0
  88. package/dist/sensors/permission-checker.d.ts +2 -0
  89. package/dist/sensors/permission-checker.js +397 -0
  90. package/dist/state/app-selectors.d.ts +2 -0
  91. package/dist/state/app-selectors.js +35 -0
  92. package/dist/state/index.d.ts +17 -0
  93. package/dist/state/index.js +13 -0
  94. package/dist/state/persistence-middleware.d.ts +2 -0
  95. package/dist/state/persistence-middleware.js +71 -0
  96. package/dist/state/recorder-slice.d.ts +2 -0
  97. package/dist/state/recorder-slice.js +47 -0
  98. package/dist/state/recording-coordinator.d.ts +2 -0
  99. package/dist/state/recording-coordinator.js +150 -0
  100. package/dist/state/recording-options.d.ts +2 -0
  101. package/dist/state/recording-options.js +192 -0
  102. package/dist/state/recording-replayer.d.ts +2 -0
  103. package/dist/state/recording-replayer.js +39 -0
  104. package/dist/state/ref-points-slice.d.ts +2 -0
  105. package/dist/state/ref-points-slice.js +44 -0
  106. package/dist/state/replay-engine.d.ts +2 -0
  107. package/dist/state/replay-engine.js +230 -0
  108. package/dist/state/routing-slice.d.ts +2 -0
  109. package/dist/state/routing-slice.js +13 -0
  110. package/dist/state/store-subscribers.d.ts +3 -0
  111. package/dist/state/store-subscribers.js +97 -0
  112. package/dist/state/store.d.ts +9 -0
  113. package/dist/state/store.js +71 -0
  114. package/dist/state/subscribe-to-selector.d.ts +2 -0
  115. package/dist/state/subscribe-to-selector.js +26 -0
  116. package/dist/storage/file-system-utils.d.ts +2 -0
  117. package/dist/storage/file-system-utils.js +31 -0
  118. package/dist/storage/file-system.d.ts +2 -0
  119. package/dist/storage/file-system.js +229 -0
  120. package/dist/storage/index.d.ts +11 -0
  121. package/dist/storage/index.js +10 -0
  122. package/dist/storage/null-storage-backend.d.ts +2 -0
  123. package/dist/storage/null-storage-backend.js +8 -0
  124. package/dist/storage/opfs-storage-backend.d.ts +2 -0
  125. package/dist/storage/opfs-storage-backend.js +15 -0
  126. package/dist/storage/opfs-storage.d.ts +2 -0
  127. package/dist/storage/opfs-storage.js +242 -0
  128. package/dist/storage/ref-point-importer.d.ts +2 -0
  129. package/dist/storage/ref-point-importer.js +163 -0
  130. package/dist/storage/ref-point-loader.d.ts +2 -0
  131. package/dist/storage/ref-point-loader.js +248 -0
  132. package/dist/storage/ref-point-recovery.d.ts +28 -0
  133. package/dist/storage/ref-point-recovery.js +159 -0
  134. package/dist/storage/storage-backend.d.ts +2 -0
  135. package/dist/storage/storage-backend.js +1 -0
  136. package/dist/storage/zip-export.d.ts +2 -0
  137. package/dist/storage/zip-export.js +214 -0
  138. package/dist/storage/zip-reader.d.ts +2 -0
  139. package/dist/storage/zip-reader.js +190 -0
  140. package/dist/storage-backend-BcEItnFr.d.ts +20 -0
  141. package/dist/store-C7PKOj8S.d.ts +96 -0
  142. package/dist/store-subscribers-CuoIzB5T.d.ts +77 -0
  143. package/dist/subscribe-to-selector-UTZ0KkAc.d.ts +26 -0
  144. package/dist/test-utils/browser-mocks.d.ts +294 -0
  145. package/dist/test-utils/browser-mocks.js +568 -0
  146. package/dist/test-utils/zip-round-trip-helpers.d.ts +60 -0
  147. package/dist/test-utils/zip-round-trip-helpers.js +207 -0
  148. package/dist/three-dispose-CCBHjE_a.d.ts +30 -0
  149. package/dist/tracking-state-B9QfuZCg.d.ts +101 -0
  150. package/dist/types/ar-types.d.ts +2 -0
  151. package/dist/types/ar-types.js +1 -0
  152. package/dist/types/geo-types.d.ts +2 -0
  153. package/dist/types/geo-types.js +1 -0
  154. package/dist/types/index.d.ts +3 -0
  155. package/dist/types/index.js +1 -0
  156. package/dist/utils/concurrency.d.ts +2 -0
  157. package/dist/utils/concurrency.js +40 -0
  158. package/dist/utils/failure-tracker.d.ts +2 -0
  159. package/dist/utils/failure-tracker.js +48 -0
  160. package/dist/utils/format-file-size.d.ts +2 -0
  161. package/dist/utils/format-file-size.js +41 -0
  162. package/dist/utils/fused-path.d.ts +2 -0
  163. package/dist/utils/fused-path.js +44 -0
  164. package/dist/utils/index.d.ts +7 -0
  165. package/dist/utils/index.js +7 -0
  166. package/dist/utils/list-formatter.d.ts +2 -0
  167. package/dist/utils/list-formatter.js +17 -0
  168. package/dist/utils/logger.d.ts +2 -0
  169. package/dist/utils/logger.js +226 -0
  170. package/dist/vis-colors-Qi2vlRGt.d.ts +63 -0
  171. package/dist/visualization/alignment-lerper.d.ts +2 -0
  172. package/dist/visualization/alignment-lerper.js +68 -0
  173. package/dist/visualization/camera-follower.d.ts +2 -0
  174. package/dist/visualization/camera-follower.js +51 -0
  175. package/dist/visualization/css3d-renderer-manager.d.ts +2 -0
  176. package/dist/visualization/css3d-renderer-manager.js +41 -0
  177. package/dist/visualization/gps-compass-cubes.d.ts +2 -0
  178. package/dist/visualization/gps-compass-cubes.js +129 -0
  179. package/dist/visualization/gps-event-markers.d.ts +2 -0
  180. package/dist/visualization/gps-event-markers.js +159 -0
  181. package/dist/visualization/index.d.ts +12 -0
  182. package/dist/visualization/index.js +12 -0
  183. package/dist/visualization/leaflet-map-overlay.d.ts +2 -0
  184. package/dist/visualization/leaflet-map-overlay.js +313 -0
  185. package/dist/visualization/lerp-utils.d.ts +2 -0
  186. package/dist/visualization/lerp-utils.js +22 -0
  187. package/dist/visualization/map-overlay.d.ts +2 -0
  188. package/dist/visualization/map-overlay.js +241 -0
  189. package/dist/visualization/reference-points.d.ts +2 -0
  190. package/dist/visualization/reference-points.js +160 -0
  191. package/dist/visualization/three-dispose.d.ts +2 -0
  192. package/dist/visualization/three-dispose.js +55 -0
  193. package/dist/visualization/vis-colors.d.ts +2 -0
  194. package/dist/visualization/vis-colors.js +74 -0
  195. package/dist/webxr-session-COlSrXdL.d.ts +316 -0
  196. package/dist/xr-camera-texture-BbukNE79.d.ts +53 -0
  197. package/dist/xr-error-handler-DTHfmvrl.d.ts +24 -0
  198. package/dist/zip-export-Rtpi75JJ.d.ts +87 -0
  199. package/dist/zip-reader-D7pkpX8K.d.ts +97 -0
  200. package/package.json +104 -0
@@ -0,0 +1,128 @@
1
+ import { n as ArPoseTuples } from "./ar-types-B-ORgk6Z.js";
2
+ import { n as SessionMetadata } from "./opfs-storage-ChOzF_Wp.js";
3
+ import { LatLongAlt } from "gps-plus-slam-js";
4
+
5
+ //#region ../src/storage/file-system.d.ts
6
+ /**
7
+ * Reset module state - exported for testing only
8
+ * @internal
9
+ */
10
+ declare function resetStorageState(): void;
11
+ /**
12
+ * Reset session-level state for a new recording.
13
+ *
14
+ * Clears scenario/session names and OPFS session handles, but preserves
15
+ * `storageInitialized` and the OPFS root so `initStorage()` doesn't need
16
+ * to be called again.
17
+ *
18
+ * Used during soft reset for new recordings (Issue 4, 2026-02-06 user feedback).
19
+ */
20
+ declare function resetForNewSession(): void;
21
+ /**
22
+ * Result of write access verification.
23
+ */
24
+ interface WriteAccessResult {
25
+ /** Whether write access was successfully verified */
26
+ success: boolean;
27
+ /** Error message if write verification failed */
28
+ error?: string;
29
+ }
30
+ /**
31
+ * Verify that we have actual write access to a directory.
32
+ *
33
+ * This probes the directory by creating a test file, writing content,
34
+ * and cleaning up. This catches cases where showDirectoryPicker grants
35
+ * a handle but the underlying file system is read-only.
36
+ *
37
+ * User Feedback Issue #1: Even with mode: 'readwrite', Android can
38
+ * return a handle where getFileHandle({create: true}) succeeds but
39
+ * createWritable() fails with NoModificationAllowedError.
40
+ *
41
+ * @param dirHandle - Directory handle to verify
42
+ * @returns Success status and optional error message
43
+ */
44
+ declare function verifyWriteAccess(dirHandle: FileSystemDirectoryHandle): Promise<WriteAccessResult>;
45
+ /**
46
+ * Initialize storage using OPFS.
47
+ *
48
+ * This replaces the old showDirectoryPicker approach which failed on Android Chrome.
49
+ * OPFS is automatically available and doesn't require user folder selection.
50
+ *
51
+ * @returns List of existing scenario folder names
52
+ * @throws Error if OPFS is not supported
53
+ */
54
+ declare function initStorage(): Promise<string[]>;
55
+ /**
56
+ * Create or open a scenario folder, then create a new session folder.
57
+ *
58
+ * Now uses OPFS backend instead of showDirectoryPicker.
59
+ *
60
+ * @param scenarioName - Name of the scenario
61
+ */
62
+ declare function startSession(scenarioName: string): Promise<{
63
+ scenarioPath: string;
64
+ sessionPath: string;
65
+ }>;
66
+ /**
67
+ * Write a Redux action to OPFS as a JSON file.
68
+ */
69
+ declare function writeAction(action: unknown, index: number): Promise<void>;
70
+ /**
71
+ * Write a captured frame image to OPFS.
72
+ */
73
+ declare function writeFrame(blob: Blob, index: number): Promise<void>;
74
+ /**
75
+ * Write session metadata (session.json) to OPFS.
76
+ * Contains timing, counts, and user agent for the recording session.
77
+ */
78
+ declare function writeSessionMetadata(metadata: SessionMetadata): Promise<void>;
79
+ /**
80
+ * Shape of a parsed action file for type safety
81
+ */
82
+ interface ParsedRefPointAction {
83
+ type: string;
84
+ payload: {
85
+ id: string;
86
+ gpsPosition?: LatLongAlt;
87
+ arPose?: ArPoseTuples;
88
+ };
89
+ }
90
+ /**
91
+ * Type guard for reference point actions
92
+ * Exported for testing
93
+ */
94
+ declare function isRefPointAction(action: unknown): action is ParsedRefPointAction;
95
+ /**
96
+ * Load existing reference points from a scenario (across all sessions).
97
+ * Now uses OPFS storage backend.
98
+ */
99
+ declare function loadScenarioRefPoints(scenarioName: string): Promise<RefPointRecord[]>;
100
+ /**
101
+ * Get the current scenario handle (for loading prior sessions).
102
+ * Now delegates to OPFS storage backend.
103
+ */
104
+ declare function getCurrentScenarioHandle(): FileSystemDirectoryHandle | null;
105
+ /**
106
+ * Set the current scenario handle (when user selects a scenario).
107
+ * With OPFS, we just store the name - the actual handle is retrieved when needed.
108
+ */
109
+ declare function setCurrentScenario(scenarioName: string): Promise<FileSystemDirectoryHandle | null>;
110
+ /**
111
+ * Ensure a scenario directory exists in OPFS, creating it if necessary.
112
+ * Used during OPFS recovery when the scenario directory was lost but ZIP
113
+ * data is available for restoration.
114
+ *
115
+ * Unlike setCurrentScenario() which only reads, this creates on demand.
116
+ */
117
+ declare function ensureScenarioDirectory(scenarioName: string): Promise<FileSystemDirectoryHandle | null>;
118
+ /**
119
+ * Reference point record from prior sessions
120
+ */
121
+ interface RefPointRecord {
122
+ id: string;
123
+ sessionName: string;
124
+ gpsPosition?: LatLongAlt;
125
+ arPose?: ArPoseTuples;
126
+ }
127
+ //#endregion
128
+ export { initStorage as a, resetForNewSession as c, startSession as d, verifyWriteAccess as f, writeSessionMetadata as h, getCurrentScenarioHandle as i, resetStorageState as l, writeFrame as m, WriteAccessResult as n, isRefPointAction as o, writeAction as p, ensureScenarioDirectory as r, loadScenarioRefPoints as s, RefPointRecord as t, setCurrentScenario as u };
@@ -0,0 +1,24 @@
1
+ //#region ../src/storage/file-system-utils.d.ts
2
+ /**
3
+ * File System Utilities - Pure Functions
4
+ *
5
+ * These are extracted from file-system.ts so they can be tested
6
+ * without mocking browser APIs.
7
+ */
8
+ /**
9
+ * Format a Date as a timestamp string for folder names
10
+ * @example "2025-02-28_14-30-11utc"
11
+ */
12
+ declare function formatTimestamp(date: Date): string;
13
+ /**
14
+ * Format an action file index as a zero-padded filename
15
+ * @example 42 -> "000042.json"
16
+ */
17
+ declare function formatActionFilename(index: number): string;
18
+ /**
19
+ * Format a frame index as a zero-padded filename
20
+ * @example 42 -> "frame-000042.jpg"
21
+ */
22
+ declare function formatFrameFilename(index: number): string;
23
+ //#endregion
24
+ export { formatFrameFilename as n, formatTimestamp as r, formatActionFilename as t };
@@ -0,0 +1,24 @@
1
+ //#region ../src/utils/format-file-size.d.ts
2
+ /**
3
+ * Format File Size Utility
4
+ *
5
+ * Converts byte counts to human-readable file size strings (B, KB, MB, GB).
6
+ * Used by session summary to display ZIP file statistics.
7
+ *
8
+ * @see 2026-02-06 User Feedback Issue #3: ZIP stats on summary screen
9
+ */
10
+ /**
11
+ * Format a byte count into a human-readable string.
12
+ *
13
+ * @param bytes - Number of bytes (non-negative integer expected)
14
+ * @returns Formatted string like "512 B", "1.5 KB", "23.4 MB", "1.0 GB"
15
+ *
16
+ * @example
17
+ * formatFileSize(0) // "0 B"
18
+ * formatFileSize(512) // "512 B"
19
+ * formatFileSize(1048576) // "1.0 MB"
20
+ * formatFileSize(2500000000) // "2.3 GB"
21
+ */
22
+ declare function formatFileSize(bytes: number): string;
23
+ //#endregion
24
+ export { formatFileSize as t };
@@ -0,0 +1,25 @@
1
+ import { t as GpsCoord } from "./geo-types-Xx-LVcnw.js";
2
+ import { LatLong, Matrix4, Vector3, fusedGpsFromOdom } from "gps-plus-slam-js";
3
+
4
+ //#region ../src/utils/fused-path.d.ts
5
+ /** Input data for computing the fused path */
6
+ interface FusedPathInput {
7
+ /** Odometry positions in AR-local coordinates */
8
+ odometryPositions: ReadonlyArray<Vector3>;
9
+ /** Alignment matrix from the solver (null if not computed yet) */
10
+ alignmentMatrix: Matrix4 | null;
11
+ /** GPS origin for ENU conversion (null if no GPS data) */
12
+ zeroRef: LatLong | null;
13
+ }
14
+ /**
15
+ * Compute the fused GPS path from odometry positions using the alignment matrix.
16
+ *
17
+ * Each odometry position is transformed by the alignment matrix to get ENU
18
+ * coordinates (meters relative to zeroRef), then converted to GPS lat/lng.
19
+ *
20
+ * @param input - Odometry positions, alignment matrix, and GPS zero reference
21
+ * @returns Array of GPS coordinates suitable for Leaflet polyline
22
+ */
23
+ declare function computeFusedPath(input: FusedPathInput): GpsCoord[];
24
+ //#endregion
25
+ export { computeFusedPath as n, fusedGpsFromOdom as r, FusedPathInput as t };
@@ -0,0 +1,29 @@
1
+ //#region ../src/types/geo-types.d.ts
2
+ /**
3
+ * Shared Geo Types
4
+ *
5
+ * Canonical definitions for Leaflet-convention GPS coordinate types
6
+ * (uses `lng`, NOT `lon`). Consolidates formerly duplicated interfaces
7
+ * from fused-path.ts and summary-map.ts, and replaces inline
8
+ * `{ lat: number; lng: number }` shapes across the codebase.
9
+ *
10
+ * NOTE: The library (`gps-plus-slam-js`) exports `LatLong` which uses
11
+ * `lon` (not `lng`). These two types are intentionally distinct —
12
+ * `GpsCoord` uses Leaflet's `lng` convention for UI/map code.
13
+ *
14
+ * @see 2026-03-03-code-review-inline-type-duplication.md Finding #3
15
+ */
16
+ /** A GPS coordinate using the Leaflet convention (lat/lng). */
17
+ interface GpsCoord {
18
+ readonly lat: number;
19
+ readonly lng: number;
20
+ }
21
+ /**
22
+ * A reference point with GPS location and a human-readable name.
23
+ * Extends GpsCoord so it is usable wherever GpsCoord is expected.
24
+ */
25
+ interface RefPointMarker extends GpsCoord {
26
+ readonly name: string;
27
+ }
28
+ //#endregion
29
+ export { RefPointMarker as n, GpsCoord as t };
@@ -0,0 +1,54 @@
1
+ //#region ../src/sensors/gps.d.ts
2
+ /**
3
+ * GPS Module
4
+ *
5
+ * Handles Geolocation API access and device orientation/compass.
6
+ */
7
+ interface GpsPosition {
8
+ readonly lat: number;
9
+ readonly lon: number;
10
+ readonly altitude: number | null;
11
+ readonly accuracy: number;
12
+ readonly altitudeAccuracy: number | null;
13
+ readonly heading: number | null;
14
+ readonly speed: number | null;
15
+ readonly timestamp: number;
16
+ }
17
+ /**
18
+ * Raw device orientation from the browser's DeviceOrientationEvent API.
19
+ * Fields are nullable because sensors may be unavailable on some devices.
20
+ * See also: DeviceOrientation in ar/tracking-state.ts (resolved, non-nullable).
21
+ */
22
+ interface RawDeviceOrientation {
23
+ alpha: number | null;
24
+ beta: number | null;
25
+ gamma: number | null;
26
+ absolute: boolean;
27
+ }
28
+ type GpsCallback = (position: GpsPosition) => void;
29
+ type OrientationCallback = (orientation: RawDeviceOrientation) => void;
30
+ /**
31
+ * Start watching GPS position.
32
+ * Idempotent: clears any existing watch before starting a new one
33
+ * (Issue 4, 2026-02-27 user feedback — prevents watch leaks when
34
+ * transitioning from warm-up to recording watch).
35
+ */
36
+ declare function startGpsWatch(onPosition: GpsCallback, onError?: (error: GeolocationPositionError) => void): void;
37
+ /**
38
+ * Stop watching GPS position
39
+ */
40
+ declare function stopGpsWatch(): void;
41
+ /**
42
+ * Start listening for device orientation (compass)
43
+ */
44
+ declare function startOrientationWatch(onOrientation: OrientationCallback): void;
45
+ /**
46
+ * Stop listening for device orientation
47
+ */
48
+ declare function stopOrientationWatch(): void;
49
+ /**
50
+ * Request permission for device orientation (required on iOS 13+)
51
+ */
52
+ declare function requestOrientationPermission(): Promise<boolean>;
53
+ //#endregion
54
+ export { startOrientationWatch as a, startGpsWatch as i, RawDeviceOrientation as n, stopGpsWatch as o, requestOrientationPermission as r, stopOrientationWatch as s, GpsPosition as t };
@@ -0,0 +1,22 @@
1
+ import * as THREE from "three";
2
+
3
+ //#region ../src/visualization/gps-compass-cubes.d.ts
4
+ /** Side length of each compass cube in metres. */
5
+ declare const COMPASS_CUBE_SIZE = 0.1;
6
+ /** Distance from origin to each compass cube in metres. */
7
+ declare const COMPASS_CUBE_DISTANCE = 1;
8
+ interface GpsCompassCubes {
9
+ /** The container Group — add this (or its parent) to the scene. */
10
+ readonly group: THREE.Group;
11
+ /** Remove the group from its parent and dispose resources. */
12
+ dispose(): void;
13
+ }
14
+ /**
15
+ * Create compass cubes and attach them to a parent Object3D.
16
+ *
17
+ * @param parent The Object3D to anchor the compass group to
18
+ * (typically the CameraFollower).
19
+ */
20
+ declare function createGpsCompassCubes(parent: THREE.Object3D): GpsCompassCubes;
21
+ //#endregion
22
+ export { createGpsCompassCubes as i, COMPASS_CUBE_SIZE as n, GpsCompassCubes as r, COMPASS_CUBE_DISTANCE as t };
@@ -0,0 +1,40 @@
1
+ //#region ../src/sensors/gps-error-handler.d.ts
2
+ /**
3
+ * GPS Error Handler
4
+ *
5
+ * Provides user-facing error messages for GPS failures.
6
+ * Separates error handling logic from GPS module for testability.
7
+ */
8
+ /**
9
+ * GPS error codes from the Geolocation API.
10
+ * Duplicated here to avoid depending on browser types in tests.
11
+ */
12
+ declare const GPS_ERROR_CODES: {
13
+ readonly PERMISSION_DENIED: 1;
14
+ readonly POSITION_UNAVAILABLE: 2;
15
+ readonly TIMEOUT: 3;
16
+ };
17
+ /**
18
+ * User-friendly error messages for each GPS error type.
19
+ */
20
+ declare const GPS_ERROR_MESSAGES: Record<number, string>;
21
+ /**
22
+ * Default message for unknown error codes.
23
+ */
24
+ declare const GPS_ERROR_MESSAGE_UNKNOWN = "GPS error. Check your device settings.";
25
+ /**
26
+ * Get a user-friendly error message for a GPS error.
27
+ *
28
+ * @param error - The GeolocationPositionError from the browser API
29
+ * @returns A user-friendly error message
30
+ */
31
+ declare function getGpsErrorMessage(error: GeolocationPositionError): string;
32
+ /**
33
+ * Create a GPS error handler that logs and shows user-facing errors.
34
+ *
35
+ * @param showError - Function to display error to user (e.g., from hud.ts)
36
+ * @returns A function suitable for use as startGpsWatch's onError callback
37
+ */
38
+ declare function createGpsErrorHandler(showError: (message: string) => void): (error: GeolocationPositionError) => void;
39
+ //#endregion
40
+ export { getGpsErrorMessage as a, createGpsErrorHandler as i, GPS_ERROR_MESSAGES as n, GPS_ERROR_MESSAGE_UNKNOWN as r, GPS_ERROR_CODES as t };
@@ -0,0 +1,67 @@
1
+ import { LatLong, Vector3 } from "gps-plus-slam-js";
2
+
3
+ //#region ../src/visualization/gps-event-markers.d.ts
4
+ /**
5
+ * Manager for GPS event visualization
6
+ */
7
+ declare class GpsEventVisualizer {
8
+ private rawGpsMarkers;
9
+ private fusedMarkers;
10
+ private snapshotMarkers;
11
+ private zeroRef;
12
+ private eventCounter;
13
+ private snapshotCounter;
14
+ /**
15
+ * Set the GPS zero reference (origin for coordinate conversion).
16
+ * Must be called before adding GPS events.
17
+ *
18
+ * @param zero - GPS coordinates of the origin
19
+ */
20
+ setZeroRef(zero: LatLong): void;
21
+ /**
22
+ * Get the current zero reference
23
+ */
24
+ getZeroRef(): LatLong | null;
25
+ /**
26
+ * Add a GPS event to the visualization.
27
+ * Creates both a raw GPS marker and a fused alignment marker.
28
+ *
29
+ * @param gpsCoords - GPS position as [x, y, z] meters from zero reference
30
+ * @param odomPosition - AR odometry position at the time of GPS reading
31
+ */
32
+ addGpsEvent(gpsCoords: Vector3, odomPosition: Vector3): void;
33
+ /**
34
+ * Add an alignment snapshot marker at the given NUE position.
35
+ * Snapshots represent the system's best GPS estimate at each alignment update.
36
+ * Added to scene root (GPS world space), not arWorldGroup.
37
+ */
38
+ addAlignmentSnapshot(nuePosition: Vector3): void;
39
+ /**
40
+ * Get the NUE positions of all alignment snapshot markers.
41
+ * Used at session end to convert to GPS coordinates for the summary map.
42
+ */
43
+ getAlignmentSnapshotPositions(): Vector3[];
44
+ /**
45
+ * Create a sphere marker mesh with the given color and name.
46
+ */
47
+ private createMarkerMesh;
48
+ /**
49
+ * Clear all markers from the scene and reset state.
50
+ */
51
+ clearAll(): void;
52
+ /**
53
+ * Get count of visible markers.
54
+ */
55
+ getCounts(): {
56
+ raw: number;
57
+ fused: number;
58
+ snapshots: number;
59
+ };
60
+ }
61
+ /**
62
+ * Singleton instance for global use.
63
+ * Import this to visualize GPS events.
64
+ */
65
+ declare const gpsEventVisualizer: GpsEventVisualizer;
66
+ //#endregion
67
+ export { gpsEventVisualizer as n, GpsEventVisualizer as t };
@@ -0,0 +1,59 @@
1
+ //#region ../src/ref-points/h3-ref-point.d.ts
2
+ /**
3
+ * H3 Reference Point Matching
4
+ *
5
+ * Utility for matching GPS positions to known reference points using
6
+ * H3 hexagonal grid indices. Uses gridDisk(cell, 1) to create a ~65m
7
+ * safe zone that absorbs GPS jitter of 3-10m.
8
+ *
9
+ * @see docs/2026-03-08-ref-point-naming-investigation.md §6
10
+ */
11
+ /** H3 resolution 11: ~25m edge, ~65m gridDisk safe zone */
12
+ declare const H3_RESOLUTION = 11;
13
+ /**
14
+ * A known reference point with its H3 cell index and GPS coordinates,
15
+ * used for proximity matching. GPS coordinates are needed to rank
16
+ * multiple candidates by distance when their gridDisk zones overlap.
17
+ */
18
+ interface KnownRefPoint {
19
+ readonly h3Index: string;
20
+ readonly displayName?: string;
21
+ readonly lat: number;
22
+ readonly lon: number;
23
+ }
24
+ /**
25
+ * Compute the H3 resolution-11 index for a GPS position.
26
+ */
27
+ declare function gpsToH3(lat: number, lng: number): string;
28
+ /**
29
+ * Approximate distance in metres using equirectangular projection.
30
+ * Accurate to < 0.1% for distances under 1 km at mid-latitudes,
31
+ * which is sufficient for ranking ref point candidates within a
32
+ * gridDisk safe zone (~65–130 m).
33
+ */
34
+ declare function approxDistanceMetres(lat1: number, lon1: number, lat2: number, lon2: number): number;
35
+ /**
36
+ * Find the known reference point closest to the given GPS position,
37
+ * provided it falls within the gridDisk safe zone.
38
+ *
39
+ * The safe zone is the center cell plus its 6 neighbors (~65m radius),
40
+ * which absorbs GPS jitter of 3-10m while keeping ref points >130m apart
41
+ * distinguishable.
42
+ *
43
+ * When multiple ref points have overlapping safe zones (65–130 m apart),
44
+ * the closest one by equirectangular distance is returned.
45
+ */
46
+ declare function findNearbyRefPoint(lat: number, lng: number, knownRefPoints: readonly KnownRefPoint[]): KnownRefPoint | undefined;
47
+ /**
48
+ * Check whether two H3 indices refer to the same physical location
49
+ * (i.e., one falls within the other's gridDisk safe zone).
50
+ * This is the canonical cross-session matching check.
51
+ */
52
+ declare function h3RefsMatch(h3a: string, h3b: string): boolean;
53
+ /**
54
+ * Check whether a string looks like a valid H3 resolution-11 index.
55
+ * Used to distinguish H3 IDs from legacy user-typed string IDs.
56
+ */
57
+ declare function isH3Index(id: string): boolean;
58
+ //#endregion
59
+ export { gpsToH3 as a, findNearbyRefPoint as i, KnownRefPoint as n, h3RefsMatch as o, approxDistanceMetres as r, isH3Index as s, H3_RESOLUTION as t };
@@ -0,0 +1,130 @@
1
+ import { a as WebXRQuaternion, o as WebXRVec3, t as ARPose } from "./ar-types-B-ORgk6Z.js";
2
+
3
+ //#region ../src/ar/image-capture.d.ts
4
+ /**
5
+ * Minimum expected blob size in bytes for a valid JPEG image.
6
+ * A black/empty 1920x1080 JPEG still compresses to ~2-3KB due to headers.
7
+ * A real camera frame at 0.7 quality should be 50KB+.
8
+ * We use a conservative threshold to catch obviously broken captures.
9
+ */
10
+ declare const MIN_VALID_IMAGE_BYTES = 5000;
11
+ /**
12
+ * Configuration for image capture timing and quality
13
+ */
14
+ interface ImageCaptureConfig {
15
+ /** Minimum interval between captures in milliseconds (default: 2000) */
16
+ intervalMs: number;
17
+ /** JPEG quality 0.0-1.0 (default: 0.7) */
18
+ quality: number;
19
+ /** Safety timeout for captureInProgress flag in milliseconds (default: 5000).
20
+ * If a capture promise doesn't resolve within this duration, the flag is
21
+ * force-reset to prevent permanent pipeline deadlock. */
22
+ captureTimeoutMs: number;
23
+ }
24
+ /**
25
+ * Default capture configuration
26
+ */
27
+ declare const DEFAULT_CAPTURE_CONFIG: ImageCaptureConfig;
28
+ /**
29
+ * Data returned when an image is captured
30
+ */
31
+ interface CapturedImage {
32
+ /** The captured image as a Blob */
33
+ readonly blob: Blob;
34
+ /** Epoch milliseconds when captured */
35
+ readonly timestamp: number;
36
+ /** Frame index (0-based, increments each capture) */
37
+ readonly frameIndex: number;
38
+ /** Camera position when captured */
39
+ readonly position: WebXRVec3;
40
+ /** Camera rotation when captured */
41
+ readonly rotation: WebXRQuaternion;
42
+ /** Device screen orientation (0, 90, 180, 270) */
43
+ readonly screenRotation: number;
44
+ }
45
+ /**
46
+ * Callbacks for image capture integration
47
+ */
48
+ interface ImageCaptureCallbacks {
49
+ /** Get current AR pose (position + orientation) */
50
+ getCurrentPose: () => ARPose | null;
51
+ /** Get device screen rotation (0, 90, 180, 270) */
52
+ getScreenRotation: () => number;
53
+ /** Called when an image is successfully captured */
54
+ onCaptured: (image: CapturedImage) => void;
55
+ /** Called when image capture fails (e.g., toBlob returns null on low memory) */
56
+ onCaptureFailed?: () => void;
57
+ /**
58
+ * Called when a captured image appears suspicious (likely black/empty).
59
+ * This can happen on mobile devices when WebGL hasn't composited the frame yet.
60
+ * The image is still saved (for debugging) but this callback allows logging.
61
+ */
62
+ onSuspiciousImage?: (blobSize: number, frameIndex: number) => void;
63
+ /**
64
+ * Optional custom frame capture function.
65
+ * When provided, this is used instead of canvas.toBlob() for capturing frames.
66
+ * This enables the "blit" technique for WebXR opaque textures that cannot
67
+ * be read directly via canvas.toBlob() (which returns black pixels).
68
+ *
69
+ * @param quality - JPEG quality 0.0-1.0
70
+ * @returns Promise resolving to a JPEG Blob, or null if capture fails
71
+ * @see docs/2026-02-06-bug-camera-frames-black.md
72
+ */
73
+ captureFrame?: (quality: number) => Promise<Blob | null>;
74
+ }
75
+ /**
76
+ * Manages periodic image capture from a canvas.
77
+ *
78
+ * Usage:
79
+ * 1. Create with canvas and callbacks
80
+ * 2. Call start() when recording begins
81
+ * 3. Call onFrame(time) each XR frame
82
+ * 4. Call stop() when recording ends
83
+ */
84
+ declare class ImageCaptureManager {
85
+ private canvas;
86
+ private callbacks;
87
+ private config;
88
+ private capturing;
89
+ private lastCaptureTime;
90
+ private frameCount;
91
+ private captureInProgress;
92
+ private captureTimeoutId;
93
+ constructor(canvas: HTMLCanvasElement, callbacks: ImageCaptureCallbacks, config?: ImageCaptureConfig);
94
+ /**
95
+ * Start capturing images.
96
+ * Resets frame counter and last capture time.
97
+ */
98
+ start(): void;
99
+ /**
100
+ * Stop capturing images.
101
+ * Clears any pending safety timeout and resets in-flight capture state.
102
+ */
103
+ stop(): void;
104
+ /**
105
+ * Check if capture manager is active.
106
+ */
107
+ isCapturing(): boolean;
108
+ /**
109
+ * Get the current frame count.
110
+ */
111
+ getFrameCount(): number;
112
+ /**
113
+ * Called each XR frame to check if a capture is needed.
114
+ *
115
+ * @param time - Frame timestamp in milliseconds (from requestAnimationFrame)
116
+ */
117
+ onFrame(time: number): void;
118
+ /**
119
+ * Clear the safety timeout for captureInProgress.
120
+ * Called when capture completes (success or failure) before the timeout fires.
121
+ */
122
+ private clearCaptureTimeout;
123
+ /**
124
+ * Common handler for captured blobs (from either canvas.toBlob or captureFrame).
125
+ * Handles null blobs, suspicious image detection, and dispatching onCaptured.
126
+ */
127
+ private handleCapturedBlob;
128
+ }
129
+ //#endregion
130
+ export { ImageCaptureManager as a, ImageCaptureConfig as i, DEFAULT_CAPTURE_CONFIG as n, MIN_VALID_IMAGE_BYTES as o, ImageCaptureCallbacks as r, CapturedImage as t };