@wemap/positioning 2.1.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 (53) hide show
  1. package/debug/arcore.html +16 -0
  2. package/package.json +2 -1
  3. package/src/components/ArCoreComponent.jsx +74 -0
  4. package/src/components/GnssWifiComponent.jsx +14 -2
  5. package/src/components/GnssWifiPdrComponent.jsx +9 -0
  6. package/src/components/MapComponent.jsx +226 -0
  7. package/src/components/PdrComponent.jsx +9 -0
  8. package/src/components/PoseComponent.jsx +7 -0
  9. package/src/components/PositioningPoseComponent.jsx +9 -0
  10. package/src/components/Utils.js +18 -0
  11. package/src/components/index.js +2 -0
  12. package/src/errors/MissingArCoreError.js +9 -0
  13. package/src/errors/MissingNativeInterfaceError.js +9 -0
  14. package/src/providers/Provider.js +15 -3
  15. package/src/providers/pose/ArCoreProvider.js +127 -0
  16. package/src/providers/pose/pdr/PdrProvider.js +1 -1
  17. package/webpack/webpack.common.js +1 -1
  18. package/src.old/Constants.js +0 -11
  19. package/src.old/NavigationHandler.js +0 -244
  20. package/src.old/Pose.js +0 -8
  21. package/src.old/attitude/AttitudeHandler.js +0 -342
  22. package/src.old/attitude/EkfAttitude.js +0 -238
  23. package/src.old/attitude/EkfAttitude.spec.js +0 -116
  24. package/src.old/components/AbsoluteAttitude.jsx +0 -136
  25. package/src.old/components/Imu.jsx +0 -89
  26. package/src.old/components/LocationSource.jsx +0 -434
  27. package/src.old/components/Logger.jsx +0 -113
  28. package/src.old/components/NavigationDebugApp.jsx +0 -106
  29. package/src.old/components/Others.jsx +0 -121
  30. package/src.old/components/RelativeAttitude.jsx +0 -104
  31. package/src.old/components/Utils.js +0 -35
  32. package/src.old/components/index.js +0 -13
  33. package/src.old/index.js +0 -7
  34. package/src.old/providers/FixedLocationImuLocationSource.js +0 -66
  35. package/src.old/providers/GnssLocationSource.js +0 -118
  36. package/src.old/providers/GnssPdrLocationSource.js +0 -182
  37. package/src.old/providers/IPLocationSource.js +0 -96
  38. package/src.old/providers/LocationSource.js +0 -290
  39. package/src.old/providers/PdrLocationSource.js +0 -320
  40. package/src.old/providers/ProvidersLogger.js +0 -77
  41. package/src.old/providers/pdr/HeadingUnlocker.js +0 -41
  42. package/src.old/providers/pdr/HeadingUnlocker.spec.js +0 -26
  43. package/src.old/providers/pdr/Smoother.js +0 -90
  44. package/src.old/providers/pdr/Smoother.spec.js +0 -424
  45. package/src.old/providers/pdr/ThugDetector.js +0 -37
  46. package/src.old/providers/steps/StepDetection.js +0 -7
  47. package/src.old/providers/steps/StepDetectionLadetto.js +0 -67
  48. package/src.old/providers/steps/StepDetectionMinMaxPeaks.js +0 -80
  49. package/src.old/providers/steps/StepDetectionMinMaxPeaks2.js +0 -108
  50. package/src.old/sensors/SensorsCompatibility.js +0 -486
  51. package/src.old/sensors/SensorsCompatibility.spec.js +0 -270
  52. package/src.old/sensors/SensorsLogger.js +0 -94
  53. package/src.old/sensors/SensorsLoggerUtils.js +0 -35
@@ -1,320 +0,0 @@
1
- import noop from 'lodash.noop';
2
-
3
- import {
4
- Constants as GeoConstants, Itinerary, WGS84UserPosition
5
- } from '@wemap/geo';
6
- import {
7
- rad2deg, Quaternion
8
- } from '@wemap/maths';
9
-
10
- import LocationSource from './LocationSource';
11
- import AttitudeHandler from '../attitude/AttitudeHandler';
12
- import Constants from '../Constants';
13
- import SensorsLogger from '../sensors/SensorsLogger';
14
- import SensorsCompatibility from '../sensors/SensorsCompatibility';
15
- import StepDetection from './steps/StepDetection';
16
- import HeadingUnlocker from './pdr/HeadingUnlocker';
17
- import ThugDetector from './pdr/ThugDetector';
18
- import Smoother from './pdr/Smoother';
19
-
20
-
21
- const MM_PDR_ANGLE = 20;
22
- const MM_PDR_DIST = 15;
23
- const MM_CONV_SPEED = 0.7;
24
-
25
- const LO_SEGMENT_SIZE = 1.5;
26
-
27
- const DEFAULT_OPTIONS = {
28
- stepdetectionlocker: true,
29
- smoother: true,
30
- onThugEvent: noop
31
- };
32
-
33
- class PdrLocationSource extends LocationSource {
34
-
35
- // pdrLocation can be different from this.pose.location
36
- // pdrLocation is raw location calculated by PdrLocationSource where
37
- // this.pose.location is smoothed location.
38
- pdrLocation = null;
39
-
40
- constructor(callback, options = DEFAULT_OPTIONS) {
41
- super(callback);
42
-
43
- // Assign params
44
- this.callback = callback;
45
- this.stepDetectionLockerEnabled = options.stepdetectionlocker !== null ? options.stepdetectionlocker : DEFAULT_OPTIONS.stepdetectionlocker;
46
- this.smootherEnabled = options.smoother !== null ? options.smoother : DEFAULT_OPTIONS.smoother;
47
- this.onThugEvent = options.onThugEvent !== null ? options.onThugEvent : DEFAULT_OPTIONS.onThugEvent;
48
-
49
- // Input data providers
50
- this.attitudeHandler = new AttitudeHandler();
51
- this.sensorsCompatibility = new SensorsCompatibility();
52
-
53
- // Helpers for PDR
54
- this.stepDetection = new StepDetection();
55
- this.stepDetectionLocker = new HeadingUnlocker();
56
- this.smoother = new Smoother();
57
- this.thugDetector = new ThugDetector();
58
- }
59
-
60
- /**
61
- * Start the location source algorithm
62
- * @override
63
- */
64
- start() {
65
- super.start();
66
-
67
- return Promise.all([
68
- this.sensorsCompatibility.startImu(this.onNewMotion, {
69
- accelerometer: true,
70
- gyroscope: true
71
- }),
72
- this.attitudeHandler.startRelative(this.onNewAttitude, AttitudeHandler.RelativeMethod.INTERNAL_EKF)
73
- ]);
74
- }
75
-
76
- /**
77
- * Stop the location source algorithm
78
- * @override
79
- */
80
- stop() {
81
- super.stop();
82
-
83
- this.attitudeHandler.stopRelative();
84
- this.sensorsCompatibility.stopImu();
85
- }
86
-
87
- /**
88
- * Get provider name
89
- * @override
90
- */
91
- get providerNameWithOptions() {
92
- let name = this.providerName;
93
- name += ' (locker: ';
94
- name += this.stepDetectionLockerEnabled ? 'Y' : 'N';
95
- name += ', ';
96
- name += 'smoo: ';
97
- name += this.smootherEnabled ? 'Y' : 'N';
98
- name += ', ';
99
- name += 'mm: ';
100
- name += this.mapMatching ? 'Y' : 'N';
101
- name += ')';
102
- return name;
103
- }
104
-
105
- /**
106
- * Get provider name
107
- * @override
108
- */
109
- static get providerName() {
110
- return Constants.LOCATION_SOURCE_PROVIDERS.PDR;
111
- }
112
-
113
- /**
114
- * @override
115
- */
116
- notify() {
117
- if (!this.pose.attitude) {
118
- return;
119
- }
120
- super.notify();
121
- }
122
-
123
- setLogger(logger) {
124
- super.setLogger(logger);
125
- this.sensorsCompatibility.setLogger(logger);
126
- this.attitudeHandler.setLogger(logger);
127
- }
128
-
129
- setHeading(heading) {
130
- this.attitudeHandler.setRelativeHeading(heading);
131
- if (this.logger) {
132
- this.logger.feedWithCurrentTime(SensorsLogger.DataType.USER_INPUT_HEADING, heading);
133
- }
134
- }
135
-
136
- setLocation(location) {
137
- this.pdrLocation = location;
138
-
139
- if (this.smootherEnabled) {
140
- this.smoother.generateNextLocations(location, true);
141
- // this.smoother.pullLocation(location.time) should never return null
142
- this.pose.location = this.smoother.pullLocation(location.time);
143
- } else {
144
- this.pose.location = location;
145
- }
146
-
147
- this.notify();
148
-
149
- if (this.logger) {
150
- const data = [location.lat, location.lng];
151
- if (location.altitude) {
152
- data.push(location.altitude);
153
- }
154
- this.logger.feedWithCurrentTime(SensorsLogger.DataType.USER_INPUT_POSITION, data);
155
- }
156
- }
157
-
158
- onNewAttitude = (attitude) => {
159
- this.pose.attitude = attitude;
160
- }
161
-
162
- onNewMotion = (motionEvent) => {
163
-
164
- if (!this.pose.attitude) {
165
- // We should wait attitude for stepDetectionLocker and linear acceleration
166
- return;
167
- }
168
-
169
- if (!this.pdrLocation) {
170
- // We should wait at least an input location for PDR
171
- return;
172
- }
173
-
174
- if (this.stepDetectionLockerEnabled
175
- && this.stepDetectionLocker.locked
176
- && this.stepDetectionLocker.feedHeading(this.pose.attitude.heading)) {
177
- // Step detection is locked by stepDetectionLocker
178
- // We still need to notify for attitude
179
- this.notify();
180
- return;
181
- }
182
-
183
- const timestamp = motionEvent.timestamp;
184
- const heading = this.pose.attitude.heading;
185
- const acceleration = motionEvent.acc;
186
-
187
- if (this.onThugEvent && this.thugDetector.compute(timestamp, acceleration)) {
188
- this.onThugEvent();
189
- }
190
-
191
- /**
192
- * Step Detection and Step Size Detection
193
- */
194
- const linearAcc = PdrLocationSource.computeLinearAcceleration(
195
- this.pose.attitude.quaternion, acceleration);
196
- const stepDetected = this.stepDetection.compute(timestamp, linearAcc, motionEvent.gyr);
197
-
198
- if (stepDetected) {
199
-
200
- this.pdrLocation = this.calculateNewLocation(this.pdrLocation, timestamp,
201
- heading, this.stepDetection.lastStepSize);
202
-
203
- if (this.smootherEnabled) {
204
- this.smoother.generateNextLocations(this.pdrLocation);
205
- }
206
-
207
- /**
208
- * Update current_position
209
- */
210
- this.pose.location = this.smootherEnabled
211
- ? this.smoother.pullLocation(timestamp)
212
- : this.pdrLocation;
213
-
214
- } else if (this.smootherEnabled) {
215
- // If no step is detected, we pull last known location from smoother until now (timestamp).
216
- const smoothedLocation = this.smoother.pullLocation(timestamp);
217
- if (smoothedLocation) {
218
- this.pose.location = smoothedLocation;
219
- }
220
- }
221
-
222
- this.notify();
223
- }
224
-
225
- calculateNewLocation(previousLocation, timestamp, heading, stepSize) {
226
-
227
- /**
228
- * Compute new_position
229
- */
230
- const newLocationWithoutMM = previousLocation.clone();
231
- newLocationWithoutMM.move(stepSize, heading);
232
- newLocationWithoutMM.bearing = rad2deg(heading);
233
- newLocationWithoutMM.time = timestamp;
234
-
235
- if (!this.mapMatching) {
236
- return newLocationWithoutMM;
237
- }
238
-
239
- const projection = this.mapMatching.getProjection(newLocationWithoutMM);
240
-
241
- if (!projection || !projection.projection) {
242
- return newLocationWithoutMM;
243
- }
244
-
245
- if (projection.distanceFromNearestElement < stepSize) {
246
- return WGS84UserPosition.fromWGS84(projection.projection, newLocationWithoutMM);
247
- }
248
-
249
- /**
250
- * Update new_position
251
- */
252
- const smoothedDistance = projection.distanceFromNearestElement * MM_CONV_SPEED;
253
- const smoothedBearing = previousLocation.bearingTo(projection.projection);
254
- const smoothedLocation = previousLocation.clone();
255
- smoothedLocation.move(smoothedDistance, smoothedBearing);
256
-
257
- return WGS84UserPosition.fromWGS84(smoothedLocation, newLocationWithoutMM);
258
- }
259
-
260
-
261
- /**
262
- * MapMatching
263
- */
264
-
265
- enableMapMatching(network = [], maxDistance = MM_PDR_DIST, maxAngleBearing = MM_PDR_ANGLE) {
266
- super.enableMapMatching(network, maxDistance, maxAngleBearing);
267
- }
268
-
269
-
270
- /**
271
- * Itinerary and PDR Locker
272
- */
273
-
274
- setItinerary(itinerary) {
275
- super.setItinerary(itinerary);
276
-
277
- if (this.stepDetectionLockerEnabled) {
278
- this.stepDetectionLocker.setWaitingOrientation(
279
- PdrLocationSource.retrieveWaitingOrientationFromItinerary(itinerary)
280
- );
281
- }
282
- }
283
-
284
- static retrieveWaitingOrientationFromItinerary(itinerary) {
285
-
286
- if (!itinerary) {
287
- throw new Error('Empty itinerary');
288
- }
289
-
290
- if (!(itinerary instanceof Itinerary)) {
291
- throw new TypeError(itinerary + ' is not an instance of itinerary');
292
- }
293
-
294
- if (itinerary.length < 1) {
295
- throw new Error('Empty itinerary');
296
- }
297
-
298
- if (itinerary.firstEdge.getLength() > LO_SEGMENT_SIZE) {
299
- return itinerary.firstEdge.getBearing();
300
- }
301
-
302
- if (itinerary.length < 2) {
303
- throw new Error('Itinerary is too short');
304
- }
305
- return itinerary.secondEdge.getBearing();
306
- }
307
-
308
- setStepDetectionLockerOrientation(orientation) {
309
- this.stepDetectionLocker.setWaitingOrientation(orientation);
310
- }
311
-
312
- // Linear acceleration in ENU
313
- static computeLinearAcceleration(quaternion, acc) {
314
- const linearAcc = Quaternion.rotate(Quaternion.inverse(quaternion), acc);
315
- linearAcc[2] -= GeoConstants.EARTH_GRAVITY;
316
- return linearAcc;
317
- }
318
- }
319
-
320
- export default PdrLocationSource;
@@ -1,77 +0,0 @@
1
- import Logger from '@wemap/logger';
2
-
3
- let currentId = 0;
4
- const objectsIdMap = new WeakMap();
5
-
6
- let pushEvents = {};
7
- let pushEventsRef = {};
8
-
9
- let interval;
10
- let initDate;
11
-
12
- class ProvidersLogger {
13
-
14
- static initializeInterval() {
15
-
16
- if (interval) {
17
- return;
18
- }
19
-
20
- interval = setInterval(() => {
21
-
22
- for (const [key, value] of Object.entries(pushEvents)) {
23
- Logger.debug('Received ' + value + ' values from ' + pushEventsRef[key].constructor.name + ' last second');
24
- }
25
-
26
- pushEvents = {};
27
- pushEventsRef = {};
28
- }, 1000);
29
- }
30
-
31
- static getObjectId(object) {
32
- if (!objectsIdMap.has(object)) {
33
- objectsIdMap.set(object, ++currentId);
34
- }
35
- return objectsIdMap.get(object);
36
- }
37
-
38
- static addEvent(object, method) {
39
-
40
- if (!ProvidersLogger.enabled) {
41
- return;
42
- }
43
-
44
- if (!initDate) {
45
- initDate = Date.now();
46
- }
47
-
48
- ProvidersLogger.initializeInterval();
49
-
50
- const objectId = ProvidersLogger.getObjectId(object);
51
- const objectClassName = object.constructor.name;
52
-
53
- Logger.debug(objectClassName + '[' + objectId + '].' + method);
54
- }
55
-
56
- static addPushEvent(object) {
57
-
58
- if (!ProvidersLogger.enabled) {
59
- return;
60
- }
61
-
62
- const objectId = ProvidersLogger.getObjectId(object);
63
-
64
- let counter = pushEvents[objectId];
65
- if (!counter) {
66
- counter = 0;
67
- pushEventsRef[objectId] = object;
68
- }
69
- pushEvents[objectId] = counter + 1;
70
- }
71
-
72
- static get enabled() {
73
- return Logger.LOG_LEVEL === Logger.DEBUG;
74
- }
75
-
76
- }
77
- export default ProvidersLogger;
@@ -1,41 +0,0 @@
1
- import isnumber from 'lodash.isnumber';
2
-
3
- import { diffAngle } from '@wemap/maths';
4
-
5
- const LO_ANGLE = 15 * Math.PI / 180;
6
-
7
- /**
8
- * HeadingUnlocker is designed to block Pdr Step Detection until user is aiming in the right direction
9
- */
10
- class HeadingUnlocker {
11
-
12
- constructor() {
13
- // HeadingUnlocker status, by default it is unlocked
14
- this.locked = false;
15
- }
16
-
17
- setWaitingOrientation(waitingOrientation) {
18
- this.waitingOrientation = waitingOrientation;
19
- this.locked = true;
20
- }
21
-
22
- feedHeading(heading) {
23
-
24
- if (!isnumber(this.waitingOrientation)) {
25
- throw new Error('HeadingUnlocker has not been initialized by setWaitingOrientation');
26
- }
27
-
28
- if (!this.locked) {
29
- throw new Error('HeadingUnlocker is already unlocked');
30
- }
31
-
32
- if (Math.abs(diffAngle(heading, this.waitingOrientation)) < LO_ANGLE) {
33
- this.locked = false;
34
- }
35
-
36
- return this.locked;
37
- }
38
-
39
- }
40
-
41
- export default HeadingUnlocker;
@@ -1,26 +0,0 @@
1
- import chai from 'chai';
2
- import chaiAlmost from 'chai-almost';
3
-
4
- import HeadingUnlocker from './HeadingUnlocker';
5
-
6
- const expect = chai.expect;
7
- chai.use(chaiAlmost());
8
-
9
- describe('HeadingUnlocker test short first edge', () => {
10
-
11
- it('Should return the good value', () => {
12
-
13
- const headingUnlocker = new HeadingUnlocker();
14
- headingUnlocker.setWaitingOrientation(102 * Math.PI / 180);
15
-
16
- headingUnlocker.feedHeading(0 * Math.PI / 180);
17
- expect(headingUnlocker.locked).to.be.true;
18
-
19
- headingUnlocker.feedHeading(130 * Math.PI / 180);
20
- expect(headingUnlocker.locked).to.be.true;
21
-
22
- headingUnlocker.feedHeading(100 * Math.PI / 180);
23
- expect(headingUnlocker.locked).to.be.false;
24
-
25
- });
26
- });
@@ -1,90 +0,0 @@
1
- /* eslint max-statements: ["error", 27]*/
2
- import {WGS84UserPosition} from '@wemap/geo';
3
-
4
- // Generated locations by second
5
- const GEN_FREQUENCY = 60;
6
-
7
- // Min and max time for flyby (in second)
8
- const MIN_FLYBY_TIME = 0.25;
9
- const MAX_FLYBY_TIME = 1;
10
-
11
- class Smoother {
12
-
13
- constructor() {
14
- this.locationsQueue = [];
15
- }
16
-
17
- /**
18
- * Calculate smoothed positions for the next milliseconds given a new location
19
- */
20
- generateNextLocations(_newLocation, flyby = false) {
21
-
22
- if (!(_newLocation instanceof WGS84UserPosition)) {
23
- throw new TypeError('newLocation is not instance of WGS84UserPosition');
24
- }
25
-
26
- const newLocation = _newLocation.clone();
27
- if (!newLocation.hasOwnProperty('time')) {
28
- throw new Error('newLocation does not have time property');
29
- }
30
-
31
- if (!this.previousLocation) {
32
- this.previousLocation = newLocation;
33
- this.locationsQueue.push(this.previousLocation);
34
- return;
35
- }
36
-
37
- const distance = this.previousLocation.distanceTo(newLocation);
38
- const azimuth = this.previousLocation.bearingTo(newLocation);
39
-
40
- let refTimestamp = newLocation.time;
41
-
42
- const queueLength = this.locationsQueue.length;
43
- if (queueLength) {
44
- refTimestamp = Math.max(refTimestamp, this.locationsQueue[queueLength - 1].time);
45
- }
46
-
47
- let diffTime = newLocation.time - this.previousLocation.time;
48
-
49
- if (flyby) {
50
- diffTime = MAX_FLYBY_TIME;
51
- }
52
-
53
- const nSamples = GEN_FREQUENCY * Math.min(Math.max(MIN_FLYBY_TIME, diffTime), MAX_FLYBY_TIME);
54
-
55
- let i = 1;
56
- while (i < nSamples + 1) {
57
- i = Math.min(i, nSamples);
58
- const smoothedLocation = this.previousLocation.destinationPoint(distance * i / nSamples, azimuth);
59
- smoothedLocation.time = refTimestamp + (i - 1) / GEN_FREQUENCY;
60
- this.locationsQueue.push(smoothedLocation);
61
- i++;
62
- }
63
-
64
- this.previousLocation = newLocation;
65
- }
66
-
67
- /**
68
- * Pull locations until timestamp and return the last one.
69
- * @param {*} timestamp location returned is the last before this timestamp
70
- * @returns last known location before timestamp, undefined otherwise
71
- */
72
- pullLocation(timestamp) {
73
-
74
- if ((typeof timestamp === 'undefined' || !timestamp)
75
- && this.locationsQueue.length > 0) {
76
- const output = this.locationsQueue[this.locationsQueue.length - 1];
77
- this.locationsQueue = [];
78
- return output;
79
- }
80
-
81
- let location;
82
- while (this.locationsQueue.length && this.locationsQueue[0].time <= timestamp) {
83
- location = this.locationsQueue.shift();
84
- }
85
- return location;
86
- }
87
-
88
- }
89
-
90
- export default Smoother;