@wemap/providers 3.1.17 → 3.1.19

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
@@ -8,11 +8,11 @@
8
8
  "Guillaume Pannetier <guillaume.pannetier@getwemap.com>"
9
9
  ],
10
10
  "dependencies": {
11
- "@wemap/geo": "^3.1.15",
12
- "@wemap/graph": "^3.1.15",
11
+ "@wemap/geo": "^3.1.19",
12
+ "@wemap/graph": "^3.1.19",
13
13
  "@wemap/logger": "^3.0.0",
14
14
  "@wemap/maths": "^3.1.15",
15
- "@wemap/osm": "^3.1.15",
15
+ "@wemap/osm": "^3.1.19",
16
16
  "@wemap/utils": "^3.1.5",
17
17
  "geomagnetism": "^0.1.0",
18
18
  "lodash.isempty": "^4.4.0",
@@ -65,6 +65,6 @@
65
65
  "lint": "eslint --ext .js,.jsx --quiet src",
66
66
  "test": "mocha -r esm \"src/**/*.spec.js\""
67
67
  },
68
- "version": "3.1.17",
69
- "gitHead": "86f10be874c865261ae07521d64c31d7db1445f4"
68
+ "version": "3.1.19",
69
+ "gitHead": "4a4167fd2159c856b90e6a566595ae5945f92d2e"
70
70
  }
@@ -19,13 +19,14 @@ import ProvidersOptions from '../../../ProvidersOptions';
19
19
  const ACCURACY_NEW_POS_EPS_RATIO = 1.5;
20
20
  const ACCURACY_RELOC_RATIO = 2;
21
21
  const MM_MAX_ANGLE = deg2rad(20);
22
- const MM_MAX_DIST = 15;
23
- const MM_MIN_DIST = 1;
22
+ const MM_MAX_DIST = 30;
23
+ const MM_MIN_DIST = 0;
24
24
  const MM_MIN_TIME = 0.4;
25
25
 
26
26
  class AbsolutePositionProvider extends MetaProvider {
27
27
 
28
28
  lastMMAttempt = -Infinity;
29
+ lastEventBearing = null;
29
30
 
30
31
  constructor() {
31
32
  super();
@@ -94,22 +95,47 @@ class AbsolutePositionProvider extends MetaProvider {
94
95
  }
95
96
 
96
97
  onAbsolutePosition(newPositionEvent, canContainLevel = true) {
97
- if (this.lastEvent) {
98
+ let newPosition = newPositionEvent.data;
98
99
 
99
- const newPosition = newPositionEvent.data;
100
- const lastPosition = this.lastEvent.data;
100
+ if (!this._useNewAbsolutePosition(newPosition)) {
101
+ return;
102
+ }
103
+
104
+ if (this.lastEvent && !canContainLevel) {
105
+ newPosition.level = this.lastEvent.data.level;
106
+ }
107
+
108
+ if (this.lastEventBearing !== null) {
109
+ newPosition.bearing = this.lastEventBearing;
110
+ }
111
+
112
+ if (this._shouldHandleMapMatching()) {
113
+
114
+ let projectedPosition = null;
101
115
 
102
- if (newPosition.distanceTo(lastPosition) < newPosition.accuracy * ACCURACY_NEW_POS_EPS_RATIO
103
- && newPosition.accuracy > lastPosition.accuracy / ACCURACY_RELOC_RATIO) {
104
- return;
116
+ // Firstly, if lastEvent bearing is known, try to use map-matching with bearing
117
+ if (newPosition.bearing !== null) {
118
+ projectedPosition = this._calcMapMatchingPosition(newPosition, true);
105
119
  }
106
120
 
107
- if (!canContainLevel) {
108
- newPosition.level = lastPosition.level;
121
+ // Secondly, if map-matching with bearing did not work, try MM on nodes (without bearing).
122
+ if (!projectedPosition) {
123
+ projectedPosition = this._calcMapMatchingPosition(newPosition, false);
109
124
  }
125
+
126
+ if (projectedPosition) {
127
+ newPosition = projectedPosition;
128
+ }
129
+ } else {
130
+ newPosition = newPosition.clone();
110
131
  }
111
132
 
112
- this.notify(newPositionEvent.clone());
133
+ this.notify(this.createEvent(
134
+ EventType.AbsolutePosition,
135
+ newPosition,
136
+ newPositionEvent
137
+ ));
138
+
113
139
  }
114
140
 
115
141
  /**
@@ -117,43 +143,76 @@ class AbsolutePositionProvider extends MetaProvider {
117
143
  */
118
144
  onAbsolutePositionFromRel(newPositionEvent) {
119
145
 
120
- /**
121
- * If map matching is not used or not set, raw position is returned
122
- */
123
- if (!ProvidersOptions.useMapMatching
124
- || !this.mapMatching.network
125
- || newPositionEvent.data.time - this.lastMMAttempt < MM_MIN_TIME) {
126
- this.notify(newPositionEvent.clone());
127
- return;
128
- }
129
- this.lastMMAttempt = newPositionEvent.data.time;
146
+ let newPosition = newPositionEvent.data;
130
147
 
131
- const newPosition = newPositionEvent.data;
132
- const projection = this.mapMatching.getProjection(newPosition, true, true);
133
- if (!projection || !projection.projection) {
134
- // If no projection has been found, returns the position without map-matching
135
- this.notify(newPositionEvent.clone());
136
- return;
137
- }
148
+ this.lastEventBearing = newPosition.bearing;
138
149
 
139
- const projectedPosition = newPosition.clone();
150
+ if (this._shouldHandleMapMatching()
151
+ && newPositionEvent.data.time - this.lastMMAttempt > MM_MIN_TIME) {
140
152
 
141
- // Anyway, the projected level is used for new position
142
- projectedPosition.level = projection.projection.level;
153
+ // Firstly, try map matching with bearing
154
+ const projectedPosition = this._calcMapMatchingPosition(newPosition, true);
155
+ if (projectedPosition) {
156
+ newPosition = projectedPosition;
157
+ }
158
+ // map matching without bearing is not used to allow user to leave the network.
143
159
 
144
- // Do not use projection if it too close from itinerary,
145
- // this allows left/right movements (ie with ArCore)
146
- if (projection.distanceFromNearestElement > this._mapMatchingMinDistance) {
147
- projectedPosition.lat = projection.projection.lat;
148
- projectedPosition.lng = projection.projection.lng;
160
+ this.lastMMAttempt = newPositionEvent.data.time;
161
+ } else {
162
+ newPosition = newPosition.clone();
149
163
  }
150
164
 
151
165
  this.notify(this.createEvent(
152
166
  EventType.AbsolutePosition,
153
- projectedPosition,
167
+ newPosition,
154
168
  newPositionEvent
155
169
  ));
170
+ }
171
+
172
+ _useNewAbsolutePosition(newPosition) {
156
173
 
174
+ if (!this.lastEvent) {
175
+ return true;
176
+ }
177
+
178
+ const lastPosition = this.lastEvent.data;
179
+
180
+ if (newPosition.accuracy <= newPosition.distanceTo(lastPosition) / ACCURACY_NEW_POS_EPS_RATIO) {
181
+ return true;
182
+ }
183
+
184
+ if (newPosition.accuracy <= lastPosition.accuracy / ACCURACY_RELOC_RATIO) {
185
+ return true;
186
+ }
187
+
188
+ return false;
189
+
190
+ }
191
+
192
+ _shouldHandleMapMatching() {
193
+ return ProvidersOptions.useMapMatching && this.mapMatching.network;
194
+ }
195
+
196
+ _calcMapMatchingPosition(position, useBearing = true) {
197
+
198
+ const projection = this.mapMatching.getProjection(position, true, useBearing);
199
+ if (!projection || !projection.projection) {
200
+ return null;
201
+ }
202
+
203
+ // Do not use projection if it too close from itinerary,
204
+ // this allows left/right movements (ie with ArCore)
205
+ if (projection.distanceFromNearestElement < this._mapMatchingMinDistance) {
206
+ return null;
207
+ }
208
+
209
+ // Do not user projection.projection directly, because position has some specific properties like bearing
210
+ const projectedPosition = position.clone();
211
+ projectedPosition.lat = projection.projection.lat;
212
+ projectedPosition.lng = projection.projection.lng;
213
+ projectedPosition.level = projection.projection.level;
214
+
215
+ return projectedPosition;
157
216
  }
158
217
 
159
218
  /**
@@ -175,6 +234,31 @@ class AbsolutePositionProvider extends MetaProvider {
175
234
  ));
176
235
  } else if (data instanceof Network || eventType === EventType.Network) {
177
236
  this.mapMatching.network = data;
237
+
238
+ if (this._shouldHandleMapMatching() && this.lastEvent) {
239
+
240
+ const position = this.lastEvent.data;
241
+ let projectedPosition = null;
242
+
243
+ // Firstly, if lastEvent bearing is known, try to use map-matching with bearing
244
+ if (position.bearing !== null) {
245
+ projectedPosition = this._calcMapMatchingPosition(position, true);
246
+ }
247
+
248
+ // Secondly, if map-matching with bearing did not work, try MM on nodes (without bearing).
249
+ if (!projectedPosition) {
250
+ projectedPosition = this._calcMapMatchingPosition(position, false);
251
+ }
252
+
253
+ if (projectedPosition) {
254
+ this.notify(this.createEvent(
255
+ EventType.AbsolutePosition,
256
+ projectedPosition,
257
+ this.lastEvent
258
+ ));
259
+ }
260
+ }
261
+
178
262
  } else {
179
263
  throw new Error('Unknown feed object');
180
264
  }