@wemap/providers 4.0.4 → 4.0.6

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.
package/package.json CHANGED
@@ -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.4",
43
- "gitHead": "8cb2140ad039f1e12b9834effb7cef467ade7549"
42
+ "version": "4.0.6",
43
+ "gitHead": "e6f232b824b7c2caabf0aefd719855a75f94b702"
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';
@@ -45,6 +45,12 @@ class MapMatchingHandler extends Provider {
45
45
  /** @type {number} */
46
46
  static MIN_STEPS_FOR_ORIENTATION_MATCHING = 5;
47
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
+
48
54
  /** @type {MapMatching} */
49
55
  _mapMatching;
50
56
 
@@ -69,6 +75,10 @@ class MapMatchingHandler extends Provider {
69
75
  /** @type {number} */
70
76
  _countStepsFromLastMatching = 0;
71
77
 
78
+ /** @type {Projection[]} */
79
+ _lastProjections = [];
80
+
81
+
72
82
  constructor() {
73
83
  super();
74
84
 
@@ -288,6 +298,7 @@ class MapMatchingHandler extends Provider {
288
298
 
289
299
  if (TurnDectector.isTurning()) {
290
300
  this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
301
+ this._lastProjections = [];
291
302
  AbsolutePosition.notify(positionEvent);
292
303
  return;
293
304
  }
@@ -297,6 +308,10 @@ class MapMatchingHandler extends Provider {
297
308
 
298
309
  if (projection) {
299
310
  this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
311
+ this._lastProjections.push(projection);
312
+ if (this._lastProjections.length > MapMatchingHandler.LAST_PROJECTIONS_WINDOW_SIZE) {
313
+ this._lastProjections.shift();
314
+ }
300
315
 
301
316
  const thisWillBeAHugeJump = projection.distanceFromNearestElement > MapMatchingHandler.MM_HUGE_JUMP_DISTANCE;
302
317
 
@@ -312,6 +327,12 @@ class MapMatchingHandler extends Provider {
312
327
  return;
313
328
  }
314
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
+
315
336
  AbsolutePosition.notify(this.createEvent(
316
337
  EventType.AbsolutePosition,
317
338
  projection.projection,
@@ -335,6 +356,18 @@ class MapMatchingHandler extends Provider {
335
356
 
336
357
  this._projectionsWithAbsAndWithoutRelAttitudeInARow.push(projectionWithAbs);
337
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);
338
371
  return;
339
372
  }
340
373
 
@@ -350,6 +383,7 @@ class MapMatchingHandler extends Provider {
350
383
  }
351
384
 
352
385
  this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
386
+ this._lastProjections = [];
353
387
 
354
388
  // If no projection found with both projection methods, simply use the newPosition.
355
389
  AbsolutePosition.notify(positionEvent);
@@ -380,6 +414,19 @@ class MapMatchingHandler extends Provider {
380
414
  return false;
381
415
  }
382
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
+ }
383
430
 
384
431
  /**
385
432
  * @param {Projection} projection
@@ -418,7 +465,9 @@ class MapMatchingHandler extends Provider {
418
465
  // Math.min(Math.abs(matchingDirectionAngle1), Math.abs(matchingDirectionAngle2))
419
466
  );
420
467
 
421
- AbsoluteAttitude.feed(new ProviderEvent(EventType.AbsoluteHeading, matchedHeading));
468
+ AbsoluteAttitude._forceHeadingForRelative(
469
+ new ProviderEvent(EventType.AbsoluteHeading, matchedHeading)
470
+ );
422
471
 
423
472
  this._countStepsFromLastMatching = 0;
424
473
  }
@@ -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);