@wemap/positioning 2.0.0 → 2.2.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 (99) hide show
  1. package/.eslintrc.json +4 -2
  2. package/debug/absolute-attitude.html +16 -0
  3. package/debug/arcore.html +16 -0
  4. package/debug/gnss-wifi-pdr.html +16 -0
  5. package/debug/gnss-wifi.html +16 -0
  6. package/debug/imu.html +16 -0
  7. package/debug/inclination.html +16 -0
  8. package/debug/pdr.html +16 -0
  9. package/debug/pose.html +16 -0
  10. package/debug/positioning.html +16 -0
  11. package/debug/relative-attitude.html +16 -0
  12. package/package.json +7 -4
  13. package/src/PositioningHandler.js +96 -34
  14. package/src/components/AbsoluteAttitudeComponent.jsx +104 -0
  15. package/src/components/ArCoreComponent.jsx +74 -0
  16. package/src/components/GnssWifiComponent.jsx +58 -0
  17. package/src/components/GnssWifiPdrComponent.jsx +94 -0
  18. package/src/components/ImuComponent.jsx +100 -0
  19. package/src/components/InclinationComponent.jsx +53 -0
  20. package/src/components/MapComponent.jsx +226 -0
  21. package/src/components/PdrComponent.jsx +97 -0
  22. package/src/components/PoseComponent.jsx +81 -0
  23. package/src/components/PositioningComponent.jsx +26 -0
  24. package/src/components/PositioningInclinationComponent.jsx +76 -0
  25. package/src/components/PositioningPoseComponent.jsx +120 -0
  26. package/src/components/RelativeAttitudeComponent.jsx +82 -0
  27. package/src/components/StartStopComponent.jsx +50 -0
  28. package/src/components/Utils.js +92 -0
  29. package/src/components/index.js +32 -0
  30. package/src/errors/AskImuOnDesktopError.js +9 -0
  31. package/src/errors/GeolocationApiMissingError.js +9 -0
  32. package/src/errors/GeolocationPermissionDeniedError.js +9 -0
  33. package/src/errors/GeolocationPositionUnavailableError.js +9 -0
  34. package/src/errors/IpResolveServerError.js +9 -0
  35. package/src/errors/MissingAccelerometerError.js +11 -0
  36. package/src/errors/MissingArCoreError.js +9 -0
  37. package/src/errors/MissingGyroscopeError.js +11 -0
  38. package/src/errors/MissingMagnetometerError.js +9 -0
  39. package/src/errors/MissingNativeInterfaceError.js +9 -0
  40. package/src/errors/MissingSensorError.js +14 -0
  41. package/src/events/EventType.js +20 -0
  42. package/src/events/ProviderError.js +52 -0
  43. package/src/events/ProviderEvent.js +35 -0
  44. package/src/index.js +2 -2
  45. package/src/providers/Constants.js +5 -0
  46. package/src/providers/FakeAbsolutePositionProvider.js +56 -0
  47. package/src/providers/Provider.js +230 -0
  48. package/src/providers/ProviderOptions.js +28 -0
  49. package/{src.old → src}/providers/ProvidersLogger.js +2 -2
  50. package/src/providers/attitude/AbsoluteAttitudeProvider.js +207 -0
  51. package/src/providers/attitude/RelativeAttitudeProvider.js +129 -0
  52. package/src/providers/others/ImuProvider.js +186 -0
  53. package/src/providers/others/InclinationProvider.js +107 -0
  54. package/{src.old/providers/LocationSource.js → src/providers/others/MapMatchingProvider.js} +5 -148
  55. package/src/providers/pose/ArCoreProvider.js +127 -0
  56. package/src/providers/pose/GnssWifiPdrProvider.js +233 -0
  57. package/src/providers/pose/PoseProvider.js +90 -0
  58. package/{src.old/providers/PdrLocationSource.js → src/providers/pose/pdr/PdrProvider.js} +145 -113
  59. package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/Smoother.js +1 -1
  60. package/src/providers/position/GnssWifiProvider.js +129 -0
  61. package/src/providers/position/IpProvider.js +75 -0
  62. package/webpack/webpack.common.js +1 -1
  63. package/webpack/webpack.dev.js +1 -1
  64. package/debug/index.html +0 -15
  65. package/debug/index.old.html +0 -37
  66. package/scripts/release-github.js +0 -216
  67. package/src/providers/FakeLocationSource.js +0 -36
  68. package/src.old/Constants.js +0 -11
  69. package/src.old/NavigationHandler.js +0 -244
  70. package/src.old/Pose.js +0 -8
  71. package/src.old/attitude/AttitudeHandler.js +0 -342
  72. package/src.old/components/AbsoluteAttitude.jsx +0 -136
  73. package/src.old/components/Imu.jsx +0 -89
  74. package/src.old/components/LocationSource.jsx +0 -434
  75. package/src.old/components/Logger.jsx +0 -113
  76. package/src.old/components/NavigationDebugApp.jsx +0 -106
  77. package/src.old/components/Others.jsx +0 -121
  78. package/src.old/components/RelativeAttitude.jsx +0 -104
  79. package/src.old/components/Utils.js +0 -35
  80. package/src.old/components/index.js +0 -13
  81. package/src.old/index.js +0 -7
  82. package/src.old/providers/FixedLocationImuLocationSource.js +0 -66
  83. package/src.old/providers/GnssLocationSource.js +0 -118
  84. package/src.old/providers/GnssPdrLocationSource.js +0 -182
  85. package/src.old/providers/IPLocationSource.js +0 -96
  86. package/src.old/sensors/SensorsCompatibility.js +0 -486
  87. package/src.old/sensors/SensorsCompatibility.spec.js +0 -270
  88. package/src.old/sensors/SensorsLogger.js +0 -94
  89. package/src.old/sensors/SensorsLoggerUtils.js +0 -35
  90. /package/{src.old → src/providers}/attitude/EkfAttitude.js +0 -0
  91. /package/{src.old → src/providers}/attitude/EkfAttitude.spec.js +0 -0
  92. /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/HeadingUnlocker.js +0 -0
  93. /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/HeadingUnlocker.spec.js +0 -0
  94. /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/Smoother.spec.js +0 -0
  95. /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/ThugDetector.js +0 -0
  96. /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetection.js +0 -0
  97. /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionLadetto.js +0 -0
  98. /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionMinMaxPeaks.js +0 -0
  99. /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionMinMaxPeaks2.js +0 -0
@@ -1,244 +0,0 @@
1
- import noop from 'lodash.noop';
2
-
3
- import { WGS84UserPosition, Itinerary } from '@wemap/geo';
4
-
5
- import LocationSource from './providers/LocationSource';
6
- import IPLocationSource from './providers/IPLocationSource';
7
- import GnssLocationSource from './providers/GnssLocationSource';
8
- import PdrLocationSource from './providers/PdrLocationSource';
9
- import GnssPdrLocationSource from './providers/GnssPdrLocationSource';
10
- import FixedLocationImuLocationSource from './providers/FixedLocationImuLocationSource';
11
- import SensorsLogger from './sensors/SensorsLogger';
12
-
13
- const DEFAULT_ALTITUDE = 1.6;
14
-
15
- /**
16
- * @private
17
- */
18
- class NavigationHandler {
19
-
20
- /**
21
- * Constructor of NavigationHandler
22
- * @param {Function} callbackOnStart callback when navigation starts
23
- * @param {Function} callbackOnStop callback when navigation stops
24
- * @param {Function} callbackOnNewPose callback on new pose
25
- * @public
26
- */
27
- constructor(callbackOnStart, callbackOnStop, callbackOnNewPose) {
28
- this.callback = this.callback.bind(this);
29
-
30
- this.callbackOnStart = callbackOnStart || noop;
31
- this.callbackOnStop = callbackOnStop || noop;
32
- this.callbackOnNewPose = callbackOnNewPose || noop;
33
- }
34
-
35
-
36
- /**
37
- * Starts navigation from an initial position an initial heading
38
- * @param {*} initialPosition initial position {lat: xx, lng: xx}
39
- * @param {Number} initialHeading initial heading in radians and clockwise: north: 0, east = PI/2
40
- * @param {Array} path an optional itinerary (list of 2D points [lng, lat])
41
- * @public
42
- */
43
- startRelative(initialPosition, initialHeading, path = null) {
44
-
45
- const initialPositionWgs84 = new WGS84UserPosition(
46
- initialPosition.lat,
47
- initialPosition.lng,
48
- initialPosition.alt || DEFAULT_ALTITUDE
49
- );
50
-
51
- // stop current location source if already started
52
- if (this.locationSource) {
53
- this.locationSource.stop();
54
- }
55
-
56
- this.locationSource = new PdrLocationSource(this.callback, {
57
- 'stepdetectionlocker': true,
58
- 'smoother': true
59
- });
60
- this.locationSource.setLogger(this.logger);
61
-
62
- if (path) {
63
- const itinerary = Itinerary.fromPoints(path);
64
- this.locationSource.enableMapMatching(itinerary);
65
- this.locationSource.setItinerary(itinerary);
66
- }
67
- this.locationSource.setLocation(initialPositionWgs84);
68
- this.locationSource.setHeading(initialHeading);
69
- const promise = this.locationSource.start();
70
-
71
- this.callbackOnStart();
72
- return promise;
73
- }
74
-
75
- /**
76
- * Starts navigation handler without any knowledge on starting point
77
- * @param {Array} path an optional itinerary (list of 2D points [lng, lat])
78
- * @public
79
- */
80
- startAbsolute(path) {
81
- // stop if already started
82
- if (this.locationSource) {
83
- this.locationSource.stop();
84
- }
85
-
86
- const itinerary = Itinerary.fromPoints(path);
87
- this.locationSource = new GnssPdrLocationSource(this.callback);
88
- this.locationSource.enableMapMatching(itinerary);
89
- this.locationSource.setItinerary(itinerary);
90
- this.locationSource.setLogger(this.logger);
91
-
92
- const promise = this.locationSource.start();
93
- this.callbackOnStart();
94
- return promise;
95
- }
96
-
97
- locateme(
98
- options = {
99
- ip: true,
100
- browser: true,
101
- attitude: true
102
- }
103
- ) {
104
- const useIPProvider = !options.hasOwnProperty('ip') || options.ip === true;
105
- const useBrowserProvider = !options.hasOwnProperty('browser') || options.browser === true;
106
- const useImu = !options.hasOwnProperty('attitude') || options.attitude === true;
107
-
108
- return new Promise((resolve, reject) => {
109
- const gnss = new GnssLocationSource(pose => {
110
- resolve(pose);
111
- this.callback(pose);
112
- }, useImu);
113
-
114
- const ip = new IPLocationSource(pose => {
115
- resolve(pose);
116
- this.callback(pose);
117
- }, useImu);
118
-
119
- if (
120
- this.locationSource
121
- && LocationSource.getMostAccurateLocationSource(this.locationSource, gnss) === this.locationSource
122
- ) {
123
- resolve(this.locationSource.getPose());
124
- } else {
125
- if (this.locationSource) {
126
- this.locationSource.stop();
127
- }
128
-
129
- if (useBrowserProvider) {
130
- this.locationSource = gnss;
131
- gnss.start().catch(e => {
132
- if (useIPProvider) {
133
- this.locationSource = ip;
134
- ip.start();
135
- return;
136
- }
137
- reject(e);
138
- });
139
- } else if (useIPProvider) {
140
- this.locationSource = ip;
141
- ip.start();
142
- }
143
- }
144
- });
145
- }
146
-
147
-
148
- /**
149
- * Stop relative, absolute or locateme navigation if started
150
- * @public
151
- */
152
- stop() {
153
- if (
154
- this.locationSource
155
- ) {
156
- this.locationSource.stop();
157
- this.locationSource = null;
158
- }
159
- this.callbackOnStop();
160
- }
161
-
162
-
163
- /**
164
- * @see LocationSource#getProjectionOnNetwork()
165
- * @public
166
- */
167
- getProjectionOnNetwork(location) {
168
- return this.locationSource.getProjectionOnNetwork(location);
169
- }
170
-
171
- /**
172
- * @see LocationSource#getItineraryInfo()
173
- * @public
174
- */
175
- getItineraryInfo(location) {
176
- return this.locationSource.getItineraryInfo(location);
177
- }
178
-
179
- forceUserLocation(location) {
180
- if (
181
- this.locationSource
182
- && (!(this.locationSource instanceof FixedLocationImuLocationSource) || !location)
183
- ) {
184
- this.locationSource.stop();
185
- }
186
-
187
- if (location) {
188
- if (
189
- !this.locationSource
190
- || !(this.locationSource instanceof FixedLocationImuLocationSource)
191
- ) {
192
- this.locationSource = new FixedLocationImuLocationSource(this.callback);
193
- this.locationSource.start(location);
194
- } else {
195
- this.locationSource.setLocation(location);
196
- }
197
- } else {
198
- this.locationSource = null;
199
- }
200
- }
201
-
202
- /**
203
- * @private
204
- */
205
- callback(pose) {
206
- this.callbackOnNewPose(pose);
207
- }
208
-
209
- /**
210
- * Assign a SensorsLogger to LocationSource and start recording.
211
- * This logger will be fed with sensors output.
212
- * Logger is not working on locateme()
213
- * @param {SensorsLogger} logger An instance of SensorsLogger.
214
- * @public
215
- */
216
- startLogger(logger) {
217
- if (!(logger instanceof SensorsLogger)) {
218
- throw new Error('logger is not an instance of SensorsLogger');
219
- }
220
-
221
- this.logger = logger;
222
-
223
- if (this.locationSource) {
224
- this.locationSource.setLogger(this.logger);
225
- }
226
- }
227
-
228
- /**
229
- * Stop recording sensors
230
- * @public
231
- */
232
- stopLogger() {
233
- this.logger = null;
234
- if (this.locationSource) {
235
- this.locationSource.setLogger(this.logger);
236
- }
237
- }
238
-
239
- static get DEFAULT_ALTITUDE() {
240
- return DEFAULT_ALTITUDE;
241
- }
242
- }
243
-
244
- export default NavigationHandler;
package/src.old/Pose.js DELETED
@@ -1,8 +0,0 @@
1
- class Pose {
2
-
3
- attitude = null;
4
- location = null;
5
-
6
- }
7
-
8
- export default Pose;
@@ -1,342 +0,0 @@
1
- import geomagnetism from 'geomagnetism';
2
-
3
- import { Attitude } from '@wemap/geo';
4
- import {
5
- deg2rad, Quaternion
6
- } from '@wemap/maths';
7
-
8
- import EkfAttitude from './EkfAttitude';
9
- import SensorsCompatibility from '../sensors/SensorsCompatibility';
10
-
11
-
12
- const RelativeMethod = {
13
- AUTOMATIC: 0,
14
- BROWSER: 1,
15
- INTERNAL_EKF: 2
16
- };
17
-
18
- const AbsoluteMethod = {
19
- AUTOMATIC: 0,
20
- BROWSER: 1,
21
- INTERNAL_EKF: 2,
22
- INTERNAL_CUSTOM: 3
23
- };
24
-
25
-
26
- class AttitudeHandler {
27
-
28
- isRelativeStarted = false;
29
-
30
- constructor() {
31
- this.sensorsCompatibility = new SensorsCompatibility();
32
- this.relativeOffsetQuaternion = [1, 0, 0, 0];
33
- this.ekfAttitude = new EkfAttitude();
34
- }
35
-
36
- static get RelativeMethod() {
37
- return RelativeMethod;
38
- }
39
-
40
- static get AbsoluteMethod() {
41
- return AbsoluteMethod;
42
- }
43
-
44
- setLogger(logger) {
45
- this.sensorsCompatibility.setLogger(logger);
46
- }
47
-
48
- startRelative(callback, method = RelativeMethod.INTERNAL_EKF) {
49
-
50
- if (method === RelativeMethod.AUTOMATIC) {
51
- throw new Error('Do not use automatic method for the moment');
52
- }
53
-
54
- let promise;
55
-
56
- this.relativeMethodAnswer = false;
57
-
58
- const fn = (quaternion, timestamp) => {
59
- if (quaternion) {
60
- callback(new Attitude(quaternion), timestamp);
61
- }
62
- };
63
-
64
- this.relativeMethod = method;
65
-
66
- if (method === RelativeMethod.AUTOMATIC) {
67
-
68
- promise = new Promise((resolve, reject) => {
69
- // Try internal EKF first
70
- this.startRelative(callback, RelativeMethod.INTERNAL_EKF)
71
- .then(resolve)
72
- .catch(() => {
73
- this.stopRelative();
74
- // If EKF did not work, try Browser method
75
- this.startRelative(callback, RelativeMethod.BROWSER)
76
- .then(resolve)
77
- .catch(() => {
78
- this.stopRelative();
79
- reject();
80
- });
81
- });
82
- });
83
-
84
- } else if (method === RelativeMethod.BROWSER) {
85
-
86
- promise = this.sensorsCompatibility.startRelativeOrientation((quaternion, timestamp) => {
87
- quaternion = Quaternion.multiply(this.relativeOffsetQuaternion, quaternion);
88
- fn(quaternion, timestamp);
89
- });
90
-
91
- } else if (method === RelativeMethod.INTERNAL_EKF) {
92
-
93
- let lastTimestamp = 0;
94
- promise = this.sensorsCompatibility.startImu(accGyrEvent => {
95
- const timestamp = accGyrEvent.timestamp;
96
- const acc = accGyrEvent.acc;
97
- const gyr = accGyrEvent.gyr;
98
-
99
- // Handle timestamps and dt
100
- if (lastTimestamp === 0) {
101
- lastTimestamp = timestamp;
102
- return;
103
- }
104
- const diffTime = timestamp - lastTimestamp;
105
- lastTimestamp = timestamp;
106
- const quaternion = this.ekfAttitude.update(diffTime, acc, gyr);
107
- fn(quaternion, timestamp);
108
- }, {
109
- accelerometer: true,
110
- gyroscope: true
111
- });
112
- } else {
113
- return Promise.reject();
114
- }
115
-
116
- this.isRelativeStarted = true;
117
-
118
- return promise;
119
- }
120
-
121
-
122
- stopRelative() {
123
- this.isRelativeStarted = false;
124
-
125
- if (this.relativeMethod === RelativeMethod.BROWSER) {
126
- this.sensorsCompatibility.stopRelativeOrientation();
127
- } else if (this.relativeMethod === RelativeMethod.INTERNAL_EKF) {
128
- this.sensorsCompatibility.stopImu();
129
- }
130
- this.relativeMethod = null;
131
- }
132
-
133
-
134
- /**
135
- *
136
- * Set yaw offset, this value will be used as the filter does not use magnetometer
137
- * @param {Number} heading heading offset in radians and clockwise
138
- */
139
- setRelativeHeading(heading) {
140
-
141
- // Minus before "heading" is here because ENU attitude is counter-clockwise whereas WGS84 heading is clockwise.
142
- heading = -heading;
143
-
144
- // Offset from window orientation
145
- heading += deg2rad(window.orientation || 0);
146
-
147
- // // We don't know the method used, so we set both
148
- this.relativeOffsetQuaternion = Quaternion.fromAxisAngle([0, 0, 1], heading);
149
-
150
- // We don't know the method used, so we set both
151
- this.ekfAttitude.setOrientationYaw(heading);
152
-
153
- if (this.relativeMethod === RelativeMethod.BROWSER && this.relativeMethodAnswer) {
154
- this.stopRelative();
155
- return this.startRelative(this.relativeCallback, RelativeMethod.BROWSER);
156
- }
157
-
158
- return Promise.resolve();
159
- }
160
-
161
-
162
- startAbsolute(callback, method = AbsoluteMethod.BROWSER) {
163
-
164
- if (method === AbsoluteMethod.AUTOMATIC) {
165
- throw new Error('Do not use automatic method for the moment');
166
- }
167
-
168
- let promise;
169
-
170
- this.absoluteMethodAnswer = false;
171
-
172
- const fn = (quaternion, timestamp, externalData) => {
173
- if (!quaternion || !this.declinationQuaternion) {
174
- return;
175
- }
176
- const trueQuaternion = Quaternion.multiply(this.declinationQuaternion, quaternion);
177
- callback(new Attitude(trueQuaternion), timestamp, externalData);
178
- };
179
-
180
- this.absoluteMethod = method;
181
-
182
- if (method === AbsoluteMethod.AUTOMATIC) {
183
-
184
- promise = new Promise((resolve, reject) => {
185
-
186
- // Try internal EKF first
187
- this.startAbsolute(callback, AbsoluteMethod.INTERNAL_EKF).catch(() => {
188
- this.stopAbsolute();
189
-
190
- // If EKF did not work, try internal custom method
191
- this.startAbsolute(callback, AbsoluteMethod.INTERNAL_CUSTOM).catch(() => {
192
- this.stopAbsolute();
193
-
194
- // If internal custom did not work, try Browser method
195
- this.startAbsolute(callback, AbsoluteMethod.BROWSER).catch(() => {
196
-
197
- this.stopAbsolute();
198
- reject();
199
-
200
- }).then(resolve);
201
-
202
- }).then(resolve);
203
-
204
- }).then(resolve);
205
- });
206
-
207
- } else if (method === AbsoluteMethod.INTERNAL_CUSTOM) {
208
-
209
- let lastAttitude;
210
- let isFirst = true;
211
-
212
- promise = new Promise((resolve, reject) => {
213
-
214
- const startRelativeFn = (heading) => {
215
- this.stopAbsolute();
216
-
217
- // Mandatory, otherwise this.absoluteMethod is null and cannot be stopped
218
- this.absoluteMethod = AbsoluteMethod.INTERNAL_CUSTOM;
219
-
220
- this.startRelative(callback)
221
- .then(resolve)
222
- .catch(() => {
223
- this.stopRelative();
224
- reject();
225
- });
226
- this.setRelativeHeading(heading);
227
- };
228
-
229
- const customCallback = (attitude, timestamp, externalData) => {
230
- lastAttitude = attitude;
231
-
232
- if (isFirst) {
233
- this.timeoutAbsoluteFirstMillis = setTimeout(() => {
234
- startRelativeFn(externalData && externalData.webkitCompassHeading
235
- ? deg2rad(externalData.webkitCompassHeading)
236
- : lastAttitude.heading);
237
- }, 300);
238
-
239
- isFirst = false;
240
- }
241
-
242
- };
243
-
244
- this.startAbsolute(customCallback, AbsoluteMethod.BROWSER)
245
- .catch(() => {
246
- this.stopAbsolute();
247
- reject();
248
- });
249
- });
250
-
251
- } else if (method === AbsoluteMethod.BROWSER) {
252
- promise = this.sensorsCompatibility.startAbsoluteOrientation((quaternion, timestamp, externalData) => {
253
- fn(quaternion, timestamp, externalData);
254
- });
255
-
256
- } else if (method === AbsoluteMethod.INTERNAL_EKF) {
257
- let lastTimestamp = 0;
258
- promise = this.sensorsCompatibility.startImu(accGyrMagEvent => {
259
- const timestamp = accGyrMagEvent.timestamp;
260
- const acc = accGyrMagEvent.acc;
261
- const gyr = accGyrMagEvent.gyr;
262
- const mag = accGyrMagEvent.mag;
263
-
264
- // Handle timestamps and dt
265
- if (lastTimestamp === 0) {
266
- lastTimestamp = timestamp;
267
- return;
268
- }
269
- const diffTime = timestamp - lastTimestamp;
270
- lastTimestamp = timestamp;
271
- const quaternion = this.ekfAttitude.update(diffTime, acc, gyr, mag);
272
- fn(quaternion, timestamp);
273
- });
274
- } else {
275
- promise = Promise.reject();
276
- }
277
-
278
- return promise;
279
- }
280
-
281
- stopAbsolute() {
282
- if (this.absoluteMethod === AbsoluteMethod.BROWSER) {
283
- this.sensorsCompatibility.stopAbsoluteOrientation();
284
- } else if (this.absoluteMethod === AbsoluteMethod.INTERNAL_EKF) {
285
- this.sensorsCompatibility.stopImu();
286
- } else if (this.absoluteMethod === AbsoluteMethod.INTERNAL_CUSTOM) {
287
- this.stopRelative();
288
- }
289
- if (this.timeoutAbsoluteFirstMillis) {
290
- clearTimeout(this.timeoutAbsoluteFirstMillis);
291
- this.timeoutAbsoluteFirstMillis = null;
292
- }
293
- this.absoluteMethod = null;
294
- }
295
-
296
- // This method should be theoretically called every time the user moves.
297
- // But in reality declination does not change as much.
298
- setUserLocationForAbsolute(userLocation) {
299
- const wmmResult = geomagnetism.model().point([userLocation.lat, userLocation.lng]);
300
- // Declination is given in NED frame and our code use ENU, that is why we have: "-decl"
301
- this.declinationQuaternion = Quaternion.fromAxisAngle([0, 0, 1], - deg2rad(wmmResult.decl));
302
- }
303
-
304
- startMonitoringInclination(callback) {
305
-
306
- this.sensorsCompatibilityInclination = new SensorsCompatibility();
307
-
308
- return this.sensorsCompatibility.startImu(({ acc }) => {
309
-
310
- const screenOrientation = window.orientation || 0;
311
-
312
- const sizeAcc = Math.sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
313
- const accNormalized = [acc[0] / sizeAcc, acc[1] / sizeAcc, acc[2] / sizeAcc];
314
-
315
- const q = [accNormalized[2] + 1, accNormalized[1], -accNormalized[0], 0];
316
- const qSize = Math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
317
- const qNormalized = [q[0] / qSize, q[1] / qSize, q[2] / qSize, 0];
318
-
319
- let inclination;
320
- if (screenOrientation === 0) {
321
- inclination = Math.asin(2 * qNormalized[1] * qNormalized[0]);
322
- } else if (screenOrientation === 90) {
323
- inclination = -Math.asin(2 * qNormalized[2] * qNormalized[0]);
324
- } else if (screenOrientation === -90) {
325
- inclination = Math.asin(2 * qNormalized[2] * qNormalized[0]);
326
- } else if (screenOrientation === 180) {
327
- inclination = -Math.asin(2 * qNormalized[1] * qNormalized[0]);
328
- }
329
-
330
- callback(inclination);
331
-
332
- }, { accelerometer: true });
333
- }
334
-
335
- stopMonitoringInclination() {
336
- if (this.sensorsCompatibilityInclination) {
337
- this.sensorsCompatibilityInclination.stopImu();
338
- }
339
- }
340
- }
341
-
342
- export default AttitudeHandler;