@wemap/providers 12.10.8 → 12.10.9

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 (146) hide show
  1. package/dist/helpers/CustomMapProvider.d.ts +10 -0
  2. package/{index.ts → dist/index.d.ts} +0 -14
  3. package/dist/index.js +1 -3446
  4. package/dist/index.js.map +1 -1
  5. package/{src/ProvidersOptions.ts → dist/src/ProvidersOptions.d.ts} +7 -16
  6. package/dist/src/errors/AskImuOnDesktopError.d.ts +5 -0
  7. package/dist/src/errors/ContainsIgnoredProviderError.d.ts +5 -0
  8. package/dist/src/errors/GeolocationApiMissingError.d.ts +5 -0
  9. package/dist/src/errors/GeolocationPermissionDeniedError.d.ts +5 -0
  10. package/dist/src/errors/GeolocationPositionUnavailableError.d.ts +5 -0
  11. package/dist/src/errors/IpResolveServerError.d.ts +5 -0
  12. package/dist/src/errors/MissingAccelerometerError.d.ts +6 -0
  13. package/dist/src/errors/MissingArCoreError.d.ts +5 -0
  14. package/dist/src/errors/MissingGyroscopeError.d.ts +6 -0
  15. package/dist/src/errors/MissingMagnetometerError.d.ts +5 -0
  16. package/dist/src/errors/MissingNativeInterfaceError.d.ts +5 -0
  17. package/dist/src/errors/MissingPoleStarError.d.ts +5 -0
  18. package/dist/src/errors/MissingSensorError.d.ts +6 -0
  19. package/dist/src/errors/NoProviderFoundError.d.ts +5 -0
  20. package/dist/src/events/AvailabilityHelper.d.ts +5 -0
  21. package/dist/src/events/ProvidersLoggerOld.d.ts +24 -0
  22. package/dist/src/events/Types.d.ts +34 -0
  23. package/dist/src/mapmatching/MapMatchingHandler.d.ts +93 -0
  24. package/dist/src/providers/Constants.d.ts +4 -0
  25. package/{src/providers/NativeProviders.ts → dist/src/providers/NativeProviders.d.ts} +2 -23
  26. package/dist/src/providers/Provider.d.ts +64 -0
  27. package/dist/src/providers/attitude/EkfAttitude.d.ts +41 -0
  28. package/dist/src/providers/attitude/TurnProvider.d.ts +17 -0
  29. package/dist/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.d.ts +60 -0
  30. package/dist/src/providers/attitude/absolute/AbsoluteAttitudeProvider.d.ts +44 -0
  31. package/dist/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.d.ts +31 -0
  32. package/dist/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.d.ts +26 -0
  33. package/dist/src/providers/attitude/relative/RelativeAttitudeFromInertialProvider.d.ts +18 -0
  34. package/dist/src/providers/attitude/relative/RelativeAttitudeProvider.d.ts +25 -0
  35. package/dist/src/providers/imu/AccelerometerProvider.d.ts +11 -0
  36. package/dist/src/providers/imu/GyroscopeProvider.d.ts +11 -0
  37. package/dist/src/providers/imu/HighRotationsProvider.d.ts +15 -0
  38. package/dist/src/providers/imu/ImuProvider.d.ts +34 -0
  39. package/dist/src/providers/imu/MagnetometerCalibrationProvider.d.ts +11 -0
  40. package/dist/src/providers/inclination/InclinationFromAccProvider.d.ts +18 -0
  41. package/dist/src/providers/inclination/InclinationFromRelativeAttitudeProvider.d.ts +19 -0
  42. package/dist/src/providers/inclination/InclinationProvider.d.ts +18 -0
  43. package/dist/src/providers/legacy/helpers/HeadingUnlocker.d.ts +12 -0
  44. package/dist/src/providers/legacy/helpers/ThugDetector.d.ts +8 -0
  45. package/dist/src/providers/others/CameraNativeProvider.d.ts +11 -0
  46. package/dist/src/providers/others/CameraProjectionMatrixProvider.d.ts +11 -0
  47. package/dist/src/providers/position/absolute/AbsolutePositionProvider.d.ts +35 -0
  48. package/dist/src/providers/position/absolute/GnssWifiProvider.d.ts +28 -0
  49. package/dist/src/providers/position/absolute/IpProvider.d.ts +16 -0
  50. package/dist/src/providers/position/absolute/PoleStarProvider.d.ts +14 -0
  51. package/dist/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.d.ts +17 -0
  52. package/dist/src/providers/position/relative/GeoRelativePositionProvider.d.ts +12 -0
  53. package/dist/src/providers/position/relative/PdrProvider.d.ts +15 -0
  54. package/dist/src/providers/steps/StepDetectionLadetto.d.ts +15 -0
  55. package/dist/src/providers/steps/StepDetectionMinMaxPeaks.d.ts +19 -0
  56. package/dist/src/providers/steps/StepDetectionMinMaxPeaks2.d.ts +27 -0
  57. package/dist/src/providers/steps/StepDetectionMinMaxPeaks3.d.ts +24 -0
  58. package/dist/src/providers/steps/StepProvider.d.ts +36 -0
  59. package/dist/src/providers/steps/StraightLineProvider.d.ts +21 -0
  60. package/dist/src/providers/vision/ArCoreProvider.d.ts +50 -0
  61. package/dist/src/providers/vision/BarcodeProvider.d.ts +11 -0
  62. package/dist/src/providers/vision/vps/ImageRelocalization.d.ts +11 -0
  63. package/dist/src/providers/vision/vps/RelativeRotationCalc.d.ts +10 -0
  64. package/dist/src/providers/vision/vps/VpsMetadata.d.ts +33 -0
  65. package/dist/src/providers/vision/vps/VpsProvider.d.ts +45 -0
  66. package/dist/src/providers/vision/vps/VpsRequest.d.ts +18 -0
  67. package/dist/src/providers/vision/vps/VpsResponse.d.ts +15 -0
  68. package/dist/src/smoothers/AttitudeSmoother.d.ts +23 -0
  69. package/dist/src/smoothers/PositionSmoother.d.ts +21 -0
  70. package/package.json +16 -12
  71. package/src/errors/AskImuOnDesktopError.ts +0 -10
  72. package/src/errors/ContainsIgnoredProviderError.ts +0 -10
  73. package/src/errors/GeolocationApiMissingError.ts +0 -10
  74. package/src/errors/GeolocationPermissionDeniedError.ts +0 -10
  75. package/src/errors/GeolocationPositionUnavailableError.ts +0 -10
  76. package/src/errors/IpResolveServerError.ts +0 -10
  77. package/src/errors/MissingAccelerometerError.ts +0 -11
  78. package/src/errors/MissingArCoreError.ts +0 -10
  79. package/src/errors/MissingGyroscopeError.ts +0 -11
  80. package/src/errors/MissingMagnetometerError.ts +0 -9
  81. package/src/errors/MissingNativeInterfaceError.ts +0 -11
  82. package/src/errors/MissingPoleStarError.ts +0 -10
  83. package/src/errors/MissingSensorError.ts +0 -15
  84. package/src/errors/NoProviderFoundError.ts +0 -10
  85. package/src/events/AvailabilityHelper.spec.ts +0 -30
  86. package/src/events/AvailabilityHelper.ts +0 -28
  87. package/src/events/ProvidersLoggerOld.ts +0 -87
  88. package/src/events/Types.ts +0 -18
  89. package/src/mapmatching/MapMatchingHandler.spec.ts +0 -142
  90. package/src/mapmatching/MapMatchingHandler.ts +0 -540
  91. package/src/providers/Constants.ts +0 -5
  92. package/src/providers/FakeProvider.spec.ts +0 -49
  93. package/src/providers/Provider.spec.ts +0 -113
  94. package/src/providers/Provider.ts +0 -244
  95. package/src/providers/attitude/EkfAttitude.spec.ts +0 -115
  96. package/src/providers/attitude/EkfAttitude.ts +0 -233
  97. package/src/providers/attitude/TurnProvider.ts +0 -58
  98. package/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.ts +0 -267
  99. package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.ts +0 -268
  100. package/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.ts +0 -84
  101. package/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.ts +0 -89
  102. package/src/providers/attitude/relative/RelativeAttitudeFromInertialProvider.ts +0 -66
  103. package/src/providers/attitude/relative/RelativeAttitudeProvider.ts +0 -70
  104. package/src/providers/imu/AccelerometerProvider.ts +0 -28
  105. package/src/providers/imu/GyroscopeProvider.ts +0 -27
  106. package/src/providers/imu/HighRotationsProvider.ts +0 -49
  107. package/src/providers/imu/ImuProvider.ts +0 -110
  108. package/src/providers/imu/MagnetometerCalibrationProvider.ts +0 -21
  109. package/src/providers/inclination/InclinationFromAccProvider.ts +0 -57
  110. package/src/providers/inclination/InclinationFromRelativeAttitudeProvider.ts +0 -51
  111. package/src/providers/inclination/InclinationProvider.ts +0 -59
  112. package/src/providers/legacy/helpers/HeadingUnlocker.spec.ts +0 -53
  113. package/src/providers/legacy/helpers/HeadingUnlocker.ts +0 -44
  114. package/src/providers/legacy/helpers/ThugDetector.ts +0 -30
  115. package/src/providers/others/CameraNativeProvider.ts +0 -29
  116. package/src/providers/others/CameraProjectionMatrixProvider.ts +0 -25
  117. package/src/providers/position/absolute/AbsolutePositionProvider.spec.ts +0 -31
  118. package/src/providers/position/absolute/AbsolutePositionProvider.ts +0 -277
  119. package/src/providers/position/absolute/GnssWifiProvider.ts +0 -126
  120. package/src/providers/position/absolute/GnssWifiProviders.spec.ts +0 -90
  121. package/src/providers/position/absolute/IpProvider.ts +0 -47
  122. package/src/providers/position/absolute/PoleStarProvider.ts +0 -88
  123. package/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.ts +0 -82
  124. package/src/providers/position/relative/GeoRelativePositionProvider.ts +0 -35
  125. package/src/providers/position/relative/PdrProvider.ts +0 -107
  126. package/src/providers/steps/StepDetectionLadetto.ts +0 -67
  127. package/src/providers/steps/StepDetectionMinMaxPeaks.ts +0 -70
  128. package/src/providers/steps/StepDetectionMinMaxPeaks2.ts +0 -99
  129. package/src/providers/steps/StepDetectionMinMaxPeaks3.ts +0 -192
  130. package/src/providers/steps/StepProvider.ts +0 -151
  131. package/src/providers/steps/StraightLineProvider.ts +0 -69
  132. package/src/providers/vision/ArCoreProvider.ts +0 -184
  133. package/src/providers/vision/BarcodeProvider.ts +0 -28
  134. package/src/providers/vision/vps/ImageRelocalization.ts +0 -98
  135. package/src/providers/vision/vps/RelativeRotationCalc.ts +0 -58
  136. package/src/providers/vision/vps/VpsMetadata.ts +0 -63
  137. package/src/providers/vision/vps/VpsProvider.ts +0 -251
  138. package/src/providers/vision/vps/VpsRequest.ts +0 -29
  139. package/src/providers/vision/vps/VpsResponse.ts +0 -43
  140. package/src/providers/vision/vps/VpsSchema.json +0 -90
  141. package/src/smoothers/AttitudeSmoother.ts +0 -110
  142. package/src/smoothers/PositionSmoother.spec.ts +0 -53
  143. package/src/smoothers/PositionSmoother.ts +0 -96
  144. package/tsconfig.json +0 -3
  145. package/vite.config.ts +0 -4
  146. /package/{src/providers/ProviderState.ts → dist/src/providers/ProviderState.d.ts} +0 -0
@@ -1,233 +0,0 @@
1
- import { Matrix_t } from '@wemap/maths';
2
- import {
3
- Matrix, Matrix3, Matrix3_t, Matrix4, Matrix4_t,
4
- Quaternion, Quaternion_t, Vector, Vector3, Vector3_t,
5
- Vector4_t
6
- } from '@wemap/maths';
7
-
8
- type RelativeNoises = { acc: number, gyr: number };
9
- type AbsoluteNoises = { acc: number, gyr: number, yc: number };
10
-
11
- type RelativeNoisesMat = { acc: Matrix3_t, gyr: Matrix3_t };
12
- type AbsoluteNoisesMat = { acc: Matrix3_t, gyr: Matrix3_t, yc: Matrix3_t };
13
-
14
- const DEFAULT_RELATIVE_NOISES = {
15
- acc: 0.5,
16
- gyr: 0.3
17
- };
18
-
19
- const DEFAULT_ABSOLUTE_NOISES = {
20
- acc: 0.5,
21
- gyr: 0.3,
22
- yc: 2
23
- };
24
-
25
- class EkfAttitude {
26
- P: Matrix4_t;
27
- accRef: Vector3_t;
28
- cRef: Vector3_t;
29
- noises!: { relative: RelativeNoisesMat, absolute: AbsoluteNoisesMat };
30
- quaternion: Quaternion_t | null;
31
-
32
- constructor(accRef: Vector3_t = [0, 0, 1], ycRef: Vector3_t = [-1, 0, 0]) {
33
-
34
- this.accRef = accRef;
35
- this.cRef = ycRef;
36
-
37
- this.P = Matrix4.fromDiagVector(Array(4).fill(0.1 ** 2) as Vector4_t);
38
-
39
- this.quaternion = null;
40
-
41
- this.noises = {} as never;
42
- this.setRelativeNoises(DEFAULT_RELATIVE_NOISES);
43
- this.setAbsoluteNoises(DEFAULT_ABSOLUTE_NOISES);
44
- }
45
-
46
- setRelativeNoises(relativeNoises: RelativeNoises) {
47
- this.noises.relative = {
48
- acc: Matrix3.diag(Array(3).fill(relativeNoises.acc ** 2) as Vector3_t),
49
- gyr: Matrix3.diag(Array(3).fill(relativeNoises.gyr ** 2) as Vector3_t)
50
- };
51
- }
52
-
53
-
54
- setAbsoluteNoises(absoluteNoises: AbsoluteNoises) {
55
- this.noises.absolute = {
56
- acc: Matrix3.diag(Array(3).fill(absoluteNoises.acc ** 2) as Vector3_t),
57
- gyr: Matrix3.diag(Array(3).fill(absoluteNoises.gyr ** 2) as Vector3_t),
58
- yc: Matrix3.diag(Array(3).fill(absoluteNoises.yc ** 2) as Vector3_t)
59
- };
60
- }
61
-
62
- /**
63
- * Try to initialize filter.
64
- * To initialize, we need at least current acceleration (acc)
65
- */
66
- tryInitialize(acc: Vector3_t, mag?: Vector3_t) {
67
-
68
- const accNormalized = Vector3.normalize(acc);
69
-
70
- if (mag) {
71
- const magNormalized = Vector3.normalize(mag);
72
-
73
- const H = Vector3.normalize(Vector3.cross(magNormalized, accNormalized));
74
- const M = Vector3.cross(accNormalized, H);
75
-
76
- const R: Matrix3_t = [
77
- [H[0], M[0], accNormalized[0]],
78
- [H[1], M[1], accNormalized[1]],
79
- [H[2], M[2], accNormalized[2]]
80
- ];
81
-
82
- this.quaternion = Quaternion.fromMatrix3Matlab(R);
83
-
84
- } else {
85
-
86
- const r = Vector3.dot(accNormalized, this.accRef) + 1;
87
- const v = Vector3.cross(accNormalized, this.accRef);
88
-
89
- let quaternion: Quaternion_t = [r, v[0], v[1], v[2]];
90
- quaternion = Quaternion.normalize(quaternion);
91
-
92
- this.quaternion = quaternion;
93
- }
94
-
95
- return this.quaternion;
96
- }
97
-
98
- update(diffTime: number, acc: Vector3_t, gyr: Vector3_t, mag?: Vector3_t) {
99
-
100
- if (!this.quaternion) {
101
- return this.tryInitialize(acc, mag);
102
- }
103
-
104
- let q = this.quaternion;
105
-
106
- /* ------------
107
- * ESTIMATION
108
- * ------------*/
109
-
110
- const qArray = q;
111
- const gyrInt = Vector3.multiplyScalar(gyr, 0.5 * diffTime);
112
- const F = this.computeC([1, gyrInt[0], gyrInt[1], gyrInt[2]]);
113
- const qAPriori = Matrix4.multiplyVector(F, q);
114
- const E1 = Matrix3.diag([qArray[0], qArray[0], qArray[0]]);
115
- const eSkew = Matrix3.skew([qArray[1], qArray[2], qArray[3]]);
116
-
117
- const qPart = [-1 * qArray[1], -1 * qArray[2], -1 * qArray[3]];
118
- const E = Matrix.concatRow([qPart], Matrix3.sum(eSkew, E1));
119
-
120
- const Qk = Matrix4.multiplyScalar(
121
- Matrix.multiply(
122
- Matrix.multiply(E, this.noises[mag ? 'absolute' : 'relative'].gyr),
123
- Matrix.transpose(E)
124
- ) as Matrix4_t,
125
- (diffTime / 2) ** 2
126
- );
127
-
128
- const pAPriori = Matrix4.sum(
129
- Matrix4.multiply(
130
- Matrix4.multiply(F, this.P),
131
- Matrix4.transpose(F)
132
- ),
133
- Qk
134
- );
135
-
136
- /* ------------
137
- * CORRECTION
138
- * ------------*/
139
-
140
- const accNormalized = Vector3.normalize(acc);
141
- let dz, K: Matrix_t, H;
142
-
143
- if (mag) {
144
-
145
- const magNormalized = Vector3.normalize(mag);
146
- const yc = Vector3.cross(accNormalized, magNormalized);
147
- const ycNormalized = Vector3.normalize(yc);
148
-
149
- const dzYc = Vector3.subtract(ycNormalized, Quaternion.rotateMatlab(qAPriori, this.cRef));
150
- const dzAcc = Vector3.subtract(accNormalized, Quaternion.rotateMatlab(qAPriori, this.accRef));
151
- dz = Vector.concat(dzYc, dzAcc);
152
-
153
- const HYc = this.jacobianES(qAPriori, this.cRef);
154
- const HAcc = this.jacobianES(qAPriori, this.accRef);
155
- H = Matrix.concatRow(HYc, HAcc);
156
-
157
- const RYc = Matrix.concatLine(this.noises.absolute.yc, Matrix3.zeros);
158
- const RAcc = Matrix.concatLine(Matrix3.zeros, this.noises.absolute.acc);
159
- const R = Matrix.concatRow(RYc, RAcc);
160
-
161
- K = Matrix.multiply(
162
- Matrix.multiply(pAPriori, Matrix.transpose(H)),
163
- Matrix.inverse(
164
- Matrix.sum(
165
- Matrix.multiply(
166
- Matrix.multiply(H, pAPriori),
167
- Matrix.transpose(H)
168
- ),
169
- R
170
- )
171
- ) as Matrix_t
172
- );
173
- } else {
174
- dz = Vector3.subtract(accNormalized, Quaternion.rotateMatlab(qAPriori, this.accRef));
175
- H = this.jacobianES(qAPriori, this.accRef);
176
- const R = this.noises.relative.acc;
177
-
178
- K = Matrix.multiply(
179
- Matrix.multiply(pAPriori, Matrix.transpose(H)),
180
- Matrix3.inverse(
181
- Matrix3.sum(
182
- Matrix.multiply(
183
- Matrix.multiply(H, pAPriori),
184
- Matrix.transpose(H)
185
- ) as Matrix3_t,
186
- R
187
- )
188
- ) as Matrix_t
189
- );
190
- }
191
-
192
- q = Quaternion.sum(
193
- qAPriori,
194
- Matrix.multiplyVector(K, dz) as Quaternion_t
195
- );
196
- const P = Matrix4.multiply(
197
- Matrix4.subtract(
198
- Matrix4.identity,
199
- Matrix.multiply(K, H) as Matrix4_t
200
- ),
201
- pAPriori
202
- );
203
-
204
- q = Quaternion.normalize(q);
205
- this.quaternion = q;
206
- this.P = P;
207
-
208
- return q;
209
- }
210
-
211
- computeC(b: Vector4_t): Matrix4_t {
212
- return [
213
- [b[0], -b[1], -b[2], -b[3]],
214
- [b[1], b[0], b[3], -b[2]],
215
- [b[2], -b[3], b[0], b[1]],
216
- [b[3], b[2], -b[1], b[0]]
217
- ];
218
- }
219
-
220
- jacobianES(q: Quaternion_t, v: Vector3_t) {
221
-
222
- const [qw, qx, qy, qz] = q;
223
- const [vx, vy, vz] = v;
224
-
225
- return [
226
- [2 * qz * vy - 2 * qy * vz, 2 * qy * vy + 2 * qz * vz, 2 * qx * vy - 2 * qw * vz - 4 * qy * vx, 2 * qw * vy + 2 * qx * vz - 4 * qz * vx],
227
- [2 * qx * vz - 2 * qz * vx, 2 * qw * vz - 4 * qx * vy + 2 * qy * vx, 2 * qx * vx + 2 * qz * vz, 2 * qy * vz - 2 * qw * vx - 4 * qz * vy],
228
- [2 * qy * vx - 2 * qx * vy, 2 * qz * vx - 4 * qx * vz - 2 * qw * vy, 2 * qw * vx - 4 * qy * vz + 2 * qz * vy, 2 * qx * vx + 2 * qy * vy]
229
- ];
230
- }
231
- }
232
-
233
- export default EkfAttitude;
@@ -1,58 +0,0 @@
1
- import { std } from '@wemap/maths';
2
-
3
- import Provider from '../Provider.js';
4
- import RelativeAttitudeProvider from './relative/RelativeAttitudeProvider.js';
5
- import { RelativeAttitude, Turn } from '../../events/Types.js';
6
-
7
- class TurnProvider extends Provider<Turn> {
8
-
9
- static SLIDING_WINDOW_TIME = 0.3; // in seconds
10
- static STD_THRESHOLD = 0.075;
11
- static CONSIDER_TURN_UNTIL = 1; // in seconds
12
-
13
- providerId?: number;
14
-
15
- slidingWindow: [number, number][] = [];
16
-
17
- getName = () => 'Turn';
18
-
19
- availability = () => RelativeAttitudeProvider.getAvailability();
20
-
21
- start() {
22
- this.providerId = RelativeAttitudeProvider.addEventListener(
23
- this._parseRelativeAttitude,
24
- this.notifyError
25
- );
26
- }
27
-
28
- stop() {
29
- RelativeAttitudeProvider.removeEventListener(this.providerId);
30
- }
31
-
32
- isTurning() {
33
- if (!this.lastEvent || !RelativeAttitudeProvider.lastEvent) {
34
- return false;
35
- }
36
-
37
- const diffTime = RelativeAttitudeProvider.lastEvent.time as number - this.lastEvent.timestamp;
38
- return diffTime < TurnProvider.CONSIDER_TURN_UNTIL;
39
- }
40
-
41
-
42
- private _parseRelativeAttitude = (relativeAttitudeEvent: RelativeAttitude) => {
43
-
44
- const { heading } = relativeAttitudeEvent;
45
- const timestamp = relativeAttitudeEvent.time as number;
46
-
47
- this.slidingWindow = this.slidingWindow.filter(item => item[0] >= timestamp - TurnProvider.SLIDING_WINDOW_TIME);
48
- this.slidingWindow.push([timestamp, heading]);
49
-
50
- const stdVal = std(this.slidingWindow.map(item => item[1]));
51
- if (stdVal > TurnProvider.STD_THRESHOLD) {
52
- this.notify({ timestamp });
53
- }
54
-
55
- }
56
- }
57
-
58
- export default new TurnProvider();
@@ -1,267 +0,0 @@
1
- import * as geomag from 'geomag';
2
-
3
- import { deg2rad, rad2deg, Quaternion, Rotations, Quaternion_t } from '@wemap/maths';
4
- import { Browser, BrowserUtils } from '@wemap/utils';
5
-
6
- import Provider from '../../Provider.js';
7
- import AskImuOnDesktopError from '../../../errors/AskImuOnDesktopError.js';
8
- import MissingMagnetometerError from '../../../errors/MissingMagnetometerError.js';
9
- import MissingSensorError from '../../../errors/MissingSensorError.js';
10
- import AbsolutePositionProvider from '../../position/absolute/AbsolutePositionProvider.js';
11
- import { AbsoluteAttitude, AbsolutePosition } from '../../../events/Types.js';
12
-
13
-
14
- // https://stackoverflow.com/a/73369838/2239938
15
- export interface DeviceOrientationEventiOS extends DeviceOrientationEvent {
16
- webkitCompassHeading: number | null;
17
- webkitCompassAccuracy: number | null;
18
- requestPermission?: () => Promise<'granted' | 'denied'>;
19
- }
20
-
21
-
22
-
23
- declare global {
24
- interface Window {
25
- addEventListener(evtName: 'deviceorientationabsolute', cb: (evt: DeviceOrientationEvent) => void, options?: boolean): void;
26
- addEventListener(evtName: 'deviceorientation', cb: (evt: DeviceOrientationEventiOS) => void, options?: boolean): void;
27
- removeEventListener(evtName: 'deviceorientationabsolute', cb: (evt: DeviceOrientationEvent) => void, options?: boolean): void;
28
- removeEventListener(evtName: 'deviceorientation', cb: (evt: DeviceOrientationEventiOS) => void, options?: boolean): void;
29
- }
30
- }
31
-
32
-
33
-
34
- /**
35
- * Absolute attitude provider gives the device attitude in East-North-Up (ENU) frame using
36
- * browser deviceorientation or deviceorientationabsolute
37
- * The provider does not work until an AbsolutePosition is given. This is necessary to
38
- * calculate declination.
39
- *
40
- * -----------------------------------
41
- * Overview of compatibilities:
42
- * -----------------------------------
43
- *
44
- * Chrome Android (v72.0.3626): YES (via deviceorientationabsolute)
45
- * Safari iOS (v12.0): YES (via deviceorientation and event.webkitCompassHeading)
46
- * Opera Android (v50.2.2426): NO {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/ondeviceorientation}
47
- * Firefox Android (v65.0.1): NO {@link https://www.fxsitecompat.com/en-CA/docs/2018/various-device-sensor-apis-are-now-deprecated/}
48
- *
49
- * -----------------------------------
50
- */
51
- class AbsoluteAttitudeFromBrowser extends Provider<AbsoluteAttitude> {
52
-
53
- // from http://tyrex.inria.fr/mobile/benchmarks-attitude/
54
- DEFAULT_ACCURACY = deg2rad(15);
55
-
56
- absolutePositionProviderId?: number;
57
- absolutePositionEvent?: AbsolutePosition;
58
-
59
- declinationQuaternion?: Quaternion_t;
60
- magQuaternion?: Quaternion_t;
61
- magQuaternionTimestamp?: number;
62
-
63
- iosPreviousQuat?: Quaternion_t;
64
- iosIsSkyMode: boolean | null = null;
65
-
66
-
67
- getName = () => 'AbsoluteAttitudeFromBrowser';
68
-
69
- availability() {
70
- return BrowserUtils.isMobile
71
- ? Promise.resolve()
72
- : Promise.resolve(new AskImuOnDesktopError());
73
- }
74
-
75
- start() {
76
-
77
-
78
- const subscribe = () => {
79
- switch (BrowserUtils.getName()) {
80
- case Browser.CHROME:
81
- window.addEventListener('deviceorientationabsolute',
82
- this.onDeviceOrientationChromeEvent, true);
83
- break;
84
-
85
- case Browser.SAFARI:
86
- case Browser.IOS_WEBVIEW:
87
- window.addEventListener('deviceorientation',
88
- this.onDeviceOrientationSafariEvent, true);
89
- break;
90
- }
91
- };
92
-
93
- const requestPermission = (DeviceOrientationEvent as unknown as DeviceOrientationEventiOS).requestPermission || undefined;
94
-
95
- if (requestPermission) {
96
- requestPermission()
97
- .then(response => {
98
- if (response !== 'granted') {
99
- throw new Error('Permission not granted');
100
- }
101
- subscribe();
102
- })
103
- .catch(this.notifyError);
104
- } else {
105
- subscribe();
106
- }
107
-
108
-
109
- const lastAbsolutePosition = AbsolutePositionProvider.lastEvent;
110
- if (lastAbsolutePosition) {
111
- this.onAbsolutePositionEvent(lastAbsolutePosition);
112
- } else {
113
- this.absolutePositionProviderId = AbsolutePositionProvider.addEventListener(
114
- this.onAbsolutePositionEvent,
115
- this.notifyError,
116
- false
117
- );
118
- }
119
-
120
- }
121
-
122
- stop() {
123
- switch (BrowserUtils.getName()) {
124
- case Browser.CHROME:
125
- window.removeEventListener('deviceorientationabsolute',
126
- this.onDeviceOrientationChromeEvent, true);
127
- break;
128
-
129
- case Browser.SAFARI:
130
- case Browser.IOS_WEBVIEW:
131
- window.removeEventListener('deviceorientation',
132
- this.onDeviceOrientationSafariEvent, true);
133
- break;
134
- }
135
-
136
- AbsolutePositionProvider.removeEventListener(this.absolutePositionProviderId);
137
- }
138
-
139
-
140
- onDeviceOrientationChromeEvent = (e: DeviceOrientationEvent) => {
141
-
142
- this.magQuaternionTimestamp = e.timeStamp / 1e3;
143
-
144
- if (typeof e.alpha !== 'number' || typeof e.beta !== 'number' || typeof e.gamma !== 'number') {
145
- this.notifyError(new MissingSensorError().from('deviceorientationabsolute'));
146
- return;
147
- }
148
-
149
- this.magQuaternion = Rotations.eulerToQuaternionZXYDegrees(
150
- [e.alpha, e.beta, e.gamma]);
151
-
152
- this.compute();
153
- };
154
-
155
-
156
- onDeviceOrientationSafariEvent = (e: DeviceOrientationEventiOS) => {
157
-
158
- this.magQuaternionTimestamp = e.timeStamp / 1e3;
159
-
160
- if (typeof e.beta !== 'number' || typeof e.gamma !== 'number') {
161
- this.notifyError(new MissingSensorError().from('deviceorientation'));
162
- return;
163
- }
164
-
165
- if (typeof e.webkitCompassHeading !== 'number') {
166
- this.notifyError(new MissingMagnetometerError().from('deviceorientation'));
167
- return;
168
- }
169
-
170
- /**
171
- * Trying the best to retrieve a good quaternion from devicemotion event.
172
- */
173
-
174
- let alpha;
175
- const [qw, qx, qy, qz] = Rotations.eulerToQuaternionZXYDegrees([e.webkitCompassHeading, e.beta, e.gamma]);
176
- const groundAngle = rad2deg(Math.acos(qw ** 2 - qx ** 2 - qy ** 2 + qz ** 2));
177
-
178
- let isSkyMode = null;
179
- if (groundAngle > 136) {
180
- isSkyMode = true;
181
- } else if (groundAngle < 134) {
182
- isSkyMode = false;
183
- } else if (this.iosPreviousQuat && this.iosIsSkyMode !== null) {
184
- /**
185
- * This condition is true only if :
186
- * - we are in the [134°; 136°] ground angle range
187
- * - we know the previous quaternion
188
- * - one of the both previous condition has been reached during this session
189
- *
190
- * In this case, we define a threshold to detect if there is a "jump" in the quaternion calculation,
191
- * then, the mode is switched.
192
- */
193
- isSkyMode = Quaternion.distance([qw, qx, qy, qz], this.iosPreviousQuat) < 0.5
194
- ? this.iosIsSkyMode
195
- : !this.iosIsSkyMode;
196
- }
197
- this.iosPreviousQuat = [qw, qx, qy, qz];
198
- this.iosIsSkyMode = isSkyMode;
199
-
200
- if (typeof (isSkyMode) === 'undefined') {
201
- // Algorithm uncertainity
202
- return;
203
- }
204
-
205
- if (isSkyMode) {
206
- alpha = 180 - e.webkitCompassHeading;
207
- } else {
208
- alpha = AbsoluteAttitudeFromBrowser.webkitCompassToHeading(
209
- e.webkitCompassHeading, e.beta, e.gamma);
210
- }
211
-
212
- this.magQuaternion = Rotations.eulerToQuaternionZXYDegrees([alpha, e.beta, e.gamma]);
213
-
214
- this.compute();
215
- };
216
-
217
-
218
- compute() {
219
-
220
- if (!this.declinationQuaternion || !this.magQuaternion || !this.absolutePositionEvent) {
221
- return;
222
- }
223
-
224
- const trueQuaternion = Quaternion.multiply(this.declinationQuaternion, this.magQuaternion);
225
- const attitude = new AbsoluteAttitude(trueQuaternion, this.magQuaternionTimestamp, this.DEFAULT_ACCURACY);
226
- this.notify(attitude);
227
- }
228
-
229
- /**
230
- * Initialized declination quaternion using current position.
231
- * This method should be theoretically called every time the user moves.
232
- * But in reality declination does not change as much.
233
- */
234
- onAbsolutePositionEvent = (position: AbsolutePosition) => {
235
-
236
- this.absolutePositionEvent = position;
237
-
238
- const wmmResult = geomag.field(position.lat, position.lng);
239
-
240
- // Declination is given in NED frame and our code use ENU, that is why we have: "-declination"
241
- this.declinationQuaternion = Quaternion.fromAxisAngle([0, 0, 1], - deg2rad(wmmResult.declination));
242
-
243
- AbsolutePositionProvider.removeEventListener(this.absolutePositionProviderId);
244
- delete this.absolutePositionProviderId;
245
- this.compute();
246
- }
247
-
248
- static webkitCompassToHeading(_webkitCompassHeading: number, _beta: number, _gamma: number) {
249
- const webkitCompassHeading = deg2rad(_webkitCompassHeading);
250
- const beta = deg2rad(_beta);
251
- const gamma = deg2rad(_gamma);
252
-
253
- const c1 = Math.cos(webkitCompassHeading / 2);
254
- const c2 = Math.cos(beta / 2);
255
- const c3 = Math.cos(gamma / 2);
256
- const s1 = Math.sin(webkitCompassHeading / 2);
257
- const s2 = Math.sin(beta / 2);
258
- const s3 = Math.sin(gamma / 2);
259
-
260
- const qw = c1 * c2 * c3 - s1 * s2 * s3;
261
- const qz = s1 * c2 * c3 + c1 * s2 * s3;
262
-
263
- return rad2deg(-2 * Math.atan(qz / qw));
264
- }
265
- }
266
-
267
- export default new AbsoluteAttitudeFromBrowser();