@wemap/providers 4.0.3 → 4.0.5

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.
@@ -1,5 +1,6 @@
1
1
  import React from 'react'; // eslint-disable-line no-unused-vars
2
2
 
3
+ import { ItineraryInfo } from '@wemap/geo';
3
4
  import { rad2deg } from '@wemap/maths';
4
5
  import { OsrmUtils } from '@wemap/osm';
5
6
 
@@ -121,6 +122,9 @@ class Utils {
121
122
 
122
123
  }
123
124
 
125
+ /**
126
+ * @param {ItineraryInfo} info
127
+ */
124
128
  static renderItineraryInfo(info) {
125
129
 
126
130
  if (!info) {
package/package.json CHANGED
@@ -8,16 +8,16 @@
8
8
  "Guillaume Pannetier <guillaume.pannetier@getwemap.com>"
9
9
  ],
10
10
  "dependencies": {
11
- "@wemap/geo": "^4.0.3",
11
+ "@wemap/geo": "^4.0.4",
12
12
  "@wemap/geomagnetism": "^0.1.1",
13
13
  "@wemap/logger": "^4.0.0",
14
- "@wemap/map": "^4.0.3",
14
+ "@wemap/map": "^4.0.4",
15
15
  "@wemap/maths": "^4.0.3",
16
16
  "@wemap/utils": "^4.0.0"
17
17
  },
18
18
  "description": "A package using different geoloc systems",
19
19
  "devDependencies": {
20
- "@wemap/osm": "^4.0.3",
20
+ "@wemap/osm": "^4.0.4",
21
21
  "mapbox-gl": "^1.11.1"
22
22
  },
23
23
  "homepage": "https://github.com/wemap/wemap-modules-js#readme",
@@ -39,6 +39,6 @@
39
39
  "url": "git+https://github.com/wemap/wemap-modules-js.git"
40
40
  },
41
41
  "type": "module",
42
- "version": "4.0.3",
43
- "gitHead": "91a82028ddda32038999582da381d1d0d8acd091"
42
+ "version": "4.0.5",
43
+ "gitHead": "83de234c6e6e93200995545e5d4d523f40850ecd"
44
44
  }
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AbsoluteHeading, Edge, Itinerary, MapMatching, Network, Projection, UserPosition
4
4
  } from '@wemap/geo';
5
- import { deg2rad, diffAngle } from '@wemap/maths';
5
+ import { deg2rad, diffAngle, diffAngleLines } from '@wemap/maths';
6
6
  import { TimeUtils } from '@wemap/utils';
7
7
 
8
8
  import EventType from '../events/EventType.js';
@@ -42,6 +42,15 @@ class MapMatchingHandler extends Provider {
42
42
  /** @type {number} */
43
43
  static MIN_STEPS_BETWEEN_ORIENTATION_MATCHING = 3;
44
44
 
45
+ /** @type {number} */
46
+ static MIN_STEPS_FOR_ORIENTATION_MATCHING = 5;
47
+
48
+ /** @type {number} */
49
+ static LAST_PROJECTIONS_WINDOW_SIZE = 3;
50
+
51
+ /** @type {number} */
52
+ static LAST_PROJECTIONS_EDGE_ANGLE_THRESHOLD = deg2rad(3);
53
+
45
54
  /** @type {MapMatching} */
46
55
  _mapMatching;
47
56
 
@@ -66,6 +75,10 @@ class MapMatchingHandler extends Provider {
66
75
  /** @type {number} */
67
76
  _countStepsFromLastMatching = 0;
68
77
 
78
+ /** @type {Projection[]} */
79
+ _lastProjections = [];
80
+
81
+
69
82
  constructor() {
70
83
  super();
71
84
 
@@ -262,6 +275,11 @@ class MapMatchingHandler extends Provider {
262
275
  return;
263
276
  }
264
277
 
278
+ // Detector to avoid big jumps in the wrong direction
279
+ if (thisWillBeAHugeJump && this._detectWrongBigJump(projectionWithBearing)) {
280
+ return;
281
+ }
282
+
265
283
  AbsolutePosition.notify(this.createEvent(
266
284
  EventType.AbsolutePosition,
267
285
  projectionWithBearing.projection,
@@ -280,6 +298,7 @@ class MapMatchingHandler extends Provider {
280
298
 
281
299
  if (TurnDectector.isTurning()) {
282
300
  this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
301
+ this._lastProjections = [];
283
302
  AbsolutePosition.notify(positionEvent);
284
303
  return;
285
304
  }
@@ -289,6 +308,10 @@ class MapMatchingHandler extends Provider {
289
308
 
290
309
  if (projection) {
291
310
  this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
311
+ this._lastProjections.push(projection);
312
+ if (this._lastProjections.length > MapMatchingHandler.LAST_PROJECTIONS_WINDOW_SIZE) {
313
+ this._lastProjections.shift();
314
+ }
292
315
 
293
316
  const thisWillBeAHugeJump = projection.distanceFromNearestElement > MapMatchingHandler.MM_HUGE_JUMP_DISTANCE;
294
317
 
@@ -298,6 +321,18 @@ class MapMatchingHandler extends Provider {
298
321
  return;
299
322
  }
300
323
 
324
+ // Detector to avoid big jumps in the wrong direction
325
+ if (thisWillBeAHugeJump && this._detectWrongBigJump(projection)) {
326
+ AbsolutePosition.notify(positionEvent);
327
+ return;
328
+ }
329
+
330
+ // Do not use projection if the neareast element is not the same direction than previous
331
+ if (!this._areLastProjectionsInTheSameDirection()) {
332
+ AbsolutePosition.notify(positionEvent);
333
+ return;
334
+ }
335
+
301
336
  AbsolutePosition.notify(this.createEvent(
302
337
  EventType.AbsolutePosition,
303
338
  projection.projection,
@@ -321,6 +356,18 @@ class MapMatchingHandler extends Provider {
321
356
 
322
357
  this._projectionsWithAbsAndWithoutRelAttitudeInARow.push(projectionWithAbs);
323
358
  if (this._projectionsWithAbsAndWithoutRelAttitudeInARow.length < 3) {
359
+ AbsolutePosition.notify(positionEvent);
360
+ return;
361
+ }
362
+
363
+ this._lastProjections.push(projectionWithAbs);
364
+ if (this._lastProjections.length > MapMatchingHandler.LAST_PROJECTIONS_WINDOW_SIZE) {
365
+ this._lastProjections.shift();
366
+ }
367
+
368
+
369
+ if (!this._areLastProjectionsInTheSameDirection()) {
370
+ AbsolutePosition.notify(positionEvent);
324
371
  return;
325
372
  }
326
373
 
@@ -336,6 +383,7 @@ class MapMatchingHandler extends Provider {
336
383
  }
337
384
 
338
385
  this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
386
+ this._lastProjections = [];
339
387
 
340
388
  // If no projection found with both projection methods, simply use the newPosition.
341
389
  AbsolutePosition.notify(positionEvent);
@@ -343,6 +391,43 @@ class MapMatchingHandler extends Provider {
343
391
 
344
392
  }
345
393
 
394
+ /**
395
+ * @param {Projection} projection
396
+ */
397
+ _detectWrongBigJump(projection) {
398
+
399
+ if (this.network instanceof Itinerary && AbsolutePosition.lastEvent) {
400
+ const itinerary = this.network;
401
+ const infoPrevious = itinerary.getInfo(AbsolutePosition.lastEvent.data);
402
+ const infoProjection = itinerary.getInfo(projection.projection);
403
+ if (infoPrevious
404
+ && infoProjection
405
+ && infoPrevious.traveledDistance > infoProjection.traveledDistance
406
+ && (infoPrevious.traveledDistance - infoProjection.traveledDistance) > projection.origin.accuracy
407
+ && projection.distanceFromNearestElement > projection.origin.accuracy
408
+ && projection.origin.distanceTo(AbsolutePosition.lastEvent.data) < projection.origin.accuracy + AbsolutePosition.lastEvent.data.accuracy) {
409
+
410
+ return true;
411
+ }
412
+ }
413
+
414
+ return false;
415
+ }
416
+
417
+ _areLastProjectionsInTheSameDirection() {
418
+
419
+ if (this._lastProjections.length === 0) {
420
+ return false;
421
+ }
422
+
423
+ const firstProjection = this._lastProjections[0];
424
+ return !this._lastProjections.some(projection =>
425
+ !(projection.nearestElement instanceof Edge)
426
+ || (diffAngleLines(projection.nearestElement.bearing, firstProjection.nearestElement.bearing)
427
+ > MapMatchingHandler.LAST_PROJECTIONS_EDGE_ANGLE_THRESHOLD)
428
+ );
429
+ }
430
+
346
431
  /**
347
432
  * @param {Projection} projection
348
433
  */
@@ -353,7 +438,8 @@ class MapMatchingHandler extends Provider {
353
438
  }
354
439
 
355
440
  if (this.state !== ProviderState.STARTED
356
- || this._countStepsFromLastMatching < MapMatchingHandler.MIN_STEPS_BETWEEN_ORIENTATION_MATCHING) {
441
+ || this._countStepsFromLastMatching < MapMatchingHandler.MIN_STEPS_BETWEEN_ORIENTATION_MATCHING
442
+ || StraightLineDetector.numStepsDetectedFromLastTurn < MapMatchingHandler.MIN_STEPS_FOR_ORIENTATION_MATCHING) {
357
443
  return;
358
444
  }
359
445
 
@@ -9,7 +9,7 @@ class TurnDetector extends Provider {
9
9
  // in seconds
10
10
  static SLIDING_WINDOW_TIME = 0.3;
11
11
 
12
- static STD_THRESHOLD = 0.05;
12
+ static STD_THRESHOLD = 0.075;
13
13
 
14
14
  /** @type {number} in seconds */
15
15
  static CONSIDER_TURN_UNTIL = 1;
@@ -108,22 +108,43 @@ class AbsoluteAttitude extends Provider {
108
108
  /**
109
109
  * @param {ProviderEvent<Attitude|AbsoluteHeading>} absoluteHeadingEvent
110
110
  */
111
- _forceHeadingForRelative = (absoluteHeadingEvent, force = false) => {
111
+ _forceHeadingForRelative = (absoluteHeadingEvent) => {
112
112
 
113
- if (!force && this.lastEvent
114
- && absoluteHeadingEvent.data.accuracy > this.lastEvent.data.accuracy) {
113
+ if (this.lastEvent && absoluteHeadingEvent.data.accuracy > this.lastEvent.data.accuracy) {
115
114
  return;
116
115
  }
117
116
 
118
- const currentRelativeHeading = this._relativeAttitude ? this._relativeAttitude.heading : 0;
119
117
 
120
- this._relAbsQuat = Quaternion.fromAxisAngle(
121
- [0, 0, 1],
122
- currentRelativeHeading - absoluteHeadingEvent.data.heading
118
+ /**
119
+ * @param {Attitude} relativeAttitude
120
+ */
121
+ const calcForceHeading = (relativeAttitude) => {
122
+ const currentRelativeHeading = relativeAttitude.heading;
123
+
124
+ this._relAbsQuat = Quaternion.fromAxisAngle(
125
+ [0, 0, 1],
126
+ currentRelativeHeading - absoluteHeadingEvent.data.heading
127
+ );
128
+
129
+ this._relativeAccuracy = 0;
130
+ this._lastForcedHeadingEvent = absoluteHeadingEvent;
131
+ };
132
+
133
+ // If relativeAttitude does not exist yet, wait the next
134
+ if (this._relativeAttitude) {
135
+ calcForceHeading(this._relativeAttitude);
136
+ return;
137
+ }
138
+
139
+ // If this._relativeAttitude does not exist, wait the first value
140
+ // /!\ This works only if the relative attitude event is provided rapidly.
141
+ const providerId = RelativeAttitude.addEventListener(
142
+ events => {
143
+ calcForceHeading(events[0].data);
144
+ RelativeAttitude.removeEventListener(providerId);
145
+ }
123
146
  );
124
147
 
125
- this._relativeAccuracy = 0;
126
- this._lastForcedHeadingEvent = absoluteHeadingEvent;
127
148
  };
128
149
 
129
150
  /**
@@ -131,34 +152,41 @@ class AbsoluteAttitude extends Provider {
131
152
  */
132
153
  _onRelativeAttitudeEvent(event) {
133
154
 
134
- if (!this._lastForcedHeadingEvent) {
135
- return;
136
- }
137
-
138
155
  const { quaternion, accuracy, time } = event.data;
139
156
 
140
157
  // Calculate relative accuracy
141
158
  if (this._relativeAttitude) {
142
159
  this._relativeAccuracy += (time - this._relativeAttitude.time) * accuracy;
143
160
  }
161
+
144
162
  // Keep the relative attitude event for the calculation of relAbsQuat
163
+ // /!\ Keep this even if forced heading is not set /!\
145
164
  this._relativeAttitude = event.data;
146
165
 
166
+
167
+ if (!this._lastForcedHeadingEvent) {
168
+ return;
169
+ }
170
+
147
171
  const accuracyWithRelative = Math.min(
148
172
  this._lastForcedHeadingEvent.data.accuracy + this._relativeAccuracy,
149
173
  Math.PI
150
174
  );
151
- const accuracyWithAbsolute = this._eventFromBrowser.data.accuracy;
152
-
153
- let newAccuracy;
154
- let relAbsQuat;
155
- if (accuracyWithAbsolute < accuracyWithRelative) {
156
- const currentHeading = this._relativeAttitude ? this._relativeAttitude.heading : 0;
157
- newAccuracy = accuracyWithAbsolute;
158
- relAbsQuat = Quaternion.fromAxisAngle([0, 0, 1], currentHeading - this._eventFromBrowser.data.heading);
159
- } else {
160
- newAccuracy = accuracyWithRelative;
161
- relAbsQuat = this._relAbsQuat;
175
+
176
+ let newAccuracy = accuracyWithRelative;
177
+ let relAbsQuat = this._relAbsQuat;
178
+
179
+ if (this._eventFromBrowser) {
180
+
181
+ const {
182
+ accuracy: accuracyWithAbsolute,
183
+ heading: headingFromAbsolute
184
+ } = this._eventFromBrowser.data;
185
+
186
+ if (accuracyWithAbsolute < accuracyWithRelative) {
187
+ newAccuracy = accuracyWithAbsolute;
188
+ relAbsQuat = Quaternion.fromAxisAngle([0, 0, 1], event.data.heading - headingFromAbsolute);
189
+ }
162
190
  }
163
191
 
164
192
  const absoluteQuat = Quaternion.multiply(relAbsQuat, quaternion);
@@ -6,7 +6,7 @@ import EventType from '../../events/EventType.js';
6
6
  class StraightLineDetector extends Provider {
7
7
 
8
8
  /** @type {number} */
9
- static STEPS_CONSIDERED_FOR_STRAIGHT_LINE = 3;
9
+ static STEPS_CONSIDERED_FOR_STRAIGHT_LINE = 2;
10
10
 
11
11
  /** @type {number?} */
12
12
  _turnDetectorProviderId = null;
@@ -75,6 +75,10 @@ class StraightLineDetector extends Provider {
75
75
  isStraight() {
76
76
  return this._countSteps >= StraightLineDetector.STEPS_CONSIDERED_FOR_STRAIGHT_LINE;
77
77
  }
78
+
79
+ get numStepsDetectedFromLastTurn() {
80
+ return this._countSteps;
81
+ }
78
82
  }
79
83
 
80
84
  export default new StraightLineDetector();
@@ -5,7 +5,7 @@ import { deg2rad, diffAngle, Quaternion } from '@wemap/maths';
5
5
  class AttitudeSmoother {
6
6
 
7
7
  /** @type {number} in radians/s */
8
- static ROTATION_SPEED_JUMP_THRESHOLD = deg2rad(90);
8
+ static ROTATION_SPEED_JUMP_THRESHOLD = deg2rad(180);
9
9
 
10
10
  /** @type {number} in radians/s */
11
11
  static ROTATION_SPEED_CONVERGENCE = deg2rad(10);