@wemap/providers 3.0.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.
- package/babel.config.js +11 -0
- package/config.json +4 -0
- package/debug/absolute-attitude.html +16 -0
- package/debug/absolute-position.html +16 -0
- package/debug/attitude.html +16 -0
- package/debug/components/AbsoluteAttitudeComponent.jsx +142 -0
- package/debug/components/AbsolutePositionComponent.jsx +79 -0
- package/debug/components/AttitudeComponent.jsx +40 -0
- package/debug/components/Common.css +27 -0
- package/debug/components/GnssWifiComponent.jsx +53 -0
- package/debug/components/ImuComponent.jsx +53 -0
- package/debug/components/InclinationComponent.jsx +68 -0
- package/debug/components/MapComponent.jsx +366 -0
- package/debug/components/NavigationConfig.js +112 -0
- package/debug/components/PoseComponent.jsx +168 -0
- package/debug/components/RelativeAttitudeComponent.jsx +85 -0
- package/debug/components/StartStopComponent.jsx +45 -0
- package/debug/components/StepDetectionComponent.jsx +39 -0
- package/debug/components/Utils.js +216 -0
- package/debug/components/index.js +30 -0
- package/debug/components/old/PositioningComponent.jsx +29 -0
- package/debug/components/old/PositioningInclinationComponent.jsx +82 -0
- package/debug/components/old/PositioningPoseComponent.jsx +117 -0
- package/debug/gnss-wifi.html +16 -0
- package/debug/imu.html +16 -0
- package/debug/inclination.html +16 -0
- package/debug/pose.html +16 -0
- package/debug/positioning-legacy.html +16 -0
- package/debug/relative-attitude.html +16 -0
- package/debug/step-detection.html +16 -0
- package/index.js +7 -0
- package/package.json +67 -0
- package/src/Providers.js +80 -0
- package/src/ProvidersInterface.js +125 -0
- package/src/ProvidersOptions.js +29 -0
- package/src/errors/AskImuOnDesktopError.js +9 -0
- package/src/errors/ContainsIgnoredProviderError.js +9 -0
- package/src/errors/GeolocationApiMissingError.js +9 -0
- package/src/errors/GeolocationPermissionDeniedError.js +9 -0
- package/src/errors/GeolocationPositionUnavailableError.js +9 -0
- package/src/errors/IpResolveServerError.js +9 -0
- package/src/errors/MissingAccelerometerError.js +11 -0
- package/src/errors/MissingArCoreError.js +9 -0
- package/src/errors/MissingGyroscopeError.js +11 -0
- package/src/errors/MissingMagnetometerError.js +9 -0
- package/src/errors/MissingNativeInterfaceError.js +9 -0
- package/src/errors/MissingSensorError.js +14 -0
- package/src/errors/NoProviderFoundError.js +9 -0
- package/src/events/Availability.js +44 -0
- package/src/events/EventType.js +33 -0
- package/src/events/ProviderEvent.js +32 -0
- package/src/events/ProvidersLogger.js +83 -0
- package/src/providers/Constants.js +5 -0
- package/src/providers/FakeProvider.spec.js +57 -0
- package/src/providers/MetaProvider.js +42 -0
- package/src/providers/Provider.js +314 -0
- package/src/providers/Provider.spec.js +136 -0
- package/src/providers/ProviderState.js +5 -0
- package/src/providers/attitude/AttitudeProvider.js +63 -0
- package/src/providers/attitude/EkfAttitude.js +224 -0
- package/src/providers/attitude/EkfAttitude.spec.js +114 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.js +224 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromRelAttProvider.js +134 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.js +143 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.js +89 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.js +114 -0
- package/src/providers/attitude/relative/RelativeAttitudeProvider.js +103 -0
- package/src/providers/imu/AccelerometerProvider.js +61 -0
- package/src/providers/imu/GyroscopeProvider.js +61 -0
- package/src/providers/imu/ImuProvider.js +122 -0
- package/src/providers/inclination/InclinationFromAccProvider.js +87 -0
- package/src/providers/inclination/InclinationFromAttitudeProvider.js +77 -0
- package/src/providers/inclination/InclinationProvider.js +69 -0
- package/src/providers/legacy/AbsolutePdrProvider.js +258 -0
- package/src/providers/legacy/ArCoreAbsoluteProvider.js +230 -0
- package/src/providers/legacy/GnssWifiPdrProvider.js +217 -0
- package/src/providers/legacy/MapMatchingProvider.js +65 -0
- package/src/providers/legacy/PdrProvider.old.js +300 -0
- package/src/providers/legacy/PoseProvider.js +68 -0
- package/src/providers/legacy/helpers/HeadingUnlocker.js +47 -0
- package/src/providers/legacy/helpers/HeadingUnlocker.spec.js +53 -0
- package/src/providers/legacy/helpers/Smoother.js +92 -0
- package/src/providers/legacy/helpers/Smoother.spec.js +426 -0
- package/src/providers/legacy/helpers/ThugDetector.js +37 -0
- package/src/providers/others/CameraNativeProvider.js +44 -0
- package/src/providers/position/absolute/AbsolutePositionFromRelProvider.js +109 -0
- package/src/providers/position/absolute/AbsolutePositionProvider.js +172 -0
- package/src/providers/position/absolute/GnssWifiProvider.js +122 -0
- package/src/providers/position/absolute/IpProvider.js +68 -0
- package/src/providers/position/relative/ArCoreProvider.js +197 -0
- package/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.js +85 -0
- package/src/providers/position/relative/GeoRelativePositionProvider.js +66 -0
- package/src/providers/position/relative/PdrProvider.js +132 -0
- package/src/providers/steps/StepDetectionLadetto.js +67 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks.js +80 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks2.js +108 -0
- package/src/providers/steps/StepDetectionProvider.js +100 -0
- package/src/smoothers/PositionSmoother.js +86 -0
- package/src/smoothers/PositionSmoother.spec.js +55 -0
- package/webpack/webpack.common.js +20 -0
- package/webpack/webpack.dev.js +24 -0
- package/webpack/webpack.prod.js +15 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
import {
|
|
3
|
+
Attitude, UserPosition
|
|
4
|
+
} from '@wemap/geo';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Quaternion, Vector3
|
|
8
|
+
} from '@wemap/maths';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import Availability from '../../events/Availability';
|
|
12
|
+
import EventType from '../../events/EventType';
|
|
13
|
+
import ArCoreProvider from '../position/relative/ArCoreProvider';
|
|
14
|
+
import ImuProvider from '../others/ImuProvider';
|
|
15
|
+
import MapMatchingProvider from './MapMatchingProvider';
|
|
16
|
+
import PdrProvider from './pdr/PdrProvider';
|
|
17
|
+
|
|
18
|
+
const MM_ARCORE_DIST = 5;
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ArCoreAbsoluteProvider extends MapMatchingProvider {
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @override
|
|
25
|
+
*/
|
|
26
|
+
constructor(onEvent, onError, options) {
|
|
27
|
+
super(onEvent, onError, options);
|
|
28
|
+
|
|
29
|
+
this.arCoreProvider = new ArCoreProvider(
|
|
30
|
+
e => this.onArCoreEvent(e),
|
|
31
|
+
onError,
|
|
32
|
+
options);
|
|
33
|
+
|
|
34
|
+
this.imuProvider = new ImuProvider(
|
|
35
|
+
this.onImuEvent,
|
|
36
|
+
onError,
|
|
37
|
+
Object.assign({}, options || {}, { require: [EventType.AngularRate] })
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (this.options.useMapMatching) {
|
|
41
|
+
this.enableMapMatching();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @override
|
|
47
|
+
*/
|
|
48
|
+
static get displayName() {
|
|
49
|
+
return 'ArCore absolute provider';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @override
|
|
54
|
+
*/
|
|
55
|
+
static get eventsType() {
|
|
56
|
+
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Return the list of required providers
|
|
61
|
+
*/
|
|
62
|
+
static get _availability() {
|
|
63
|
+
return Availability.union(
|
|
64
|
+
ArCoreProvider.availability,
|
|
65
|
+
ImuProvider.availability
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @override
|
|
71
|
+
*/
|
|
72
|
+
_start() {
|
|
73
|
+
this.arCoreProvider.start();
|
|
74
|
+
this.imuProvider.start();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @override
|
|
79
|
+
*/
|
|
80
|
+
_stop() {
|
|
81
|
+
this.arCoreProvider.stop();
|
|
82
|
+
this.imuProvider.stop();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onArCoreEvent = events => {
|
|
86
|
+
|
|
87
|
+
const eventsForNotification = [];
|
|
88
|
+
|
|
89
|
+
events.forEach(event => {
|
|
90
|
+
if (event.dataType === EventType.RelativeAttitude) {
|
|
91
|
+
|
|
92
|
+
// const previousAttitude = this.relativeAttitude;
|
|
93
|
+
this.relativeAttitude = event.data;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The two following blocks cannot be called in the same call because this.waitingForceHeading
|
|
97
|
+
* if exists, is called before the first this.relativeAttitude assigment. So, this.waitingForceHeading
|
|
98
|
+
* and previousAttitude should not be defined in the same time.
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
if (typeof this.waitingForceHeading !== 'undefined') {
|
|
102
|
+
/**
|
|
103
|
+
* waitingForceHeading is set by setHeading() if this.relativeAttitude does not exist
|
|
104
|
+
* At this moment, this.relativeAttitude is defined, so we can call setHeading again
|
|
105
|
+
*/
|
|
106
|
+
this.setHeading(this.waitingForceHeading);
|
|
107
|
+
delete this.waitingForceHeading;
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// if (previousAttitude && this.absoluteAttitude) {
|
|
112
|
+
// /**
|
|
113
|
+
// * Sometimes ArCore has "orientation jumps" around z-axis.
|
|
114
|
+
// * Here we try to detect and remove them.
|
|
115
|
+
// */
|
|
116
|
+
// const dist = Quaternion.distance(event.data.quaternion, previousAttitude.quaternion);
|
|
117
|
+
// if (typeof this.angularRate !== 'undefined') {
|
|
118
|
+
// const velocity = Vector3.norm(this.angularRate);
|
|
119
|
+
// if (dist > deg2rad(10) && velocity < deg2rad(4)) {
|
|
120
|
+
// this.setHeading(this.absoluteAttitude.heading);
|
|
121
|
+
// }
|
|
122
|
+
// }
|
|
123
|
+
// }
|
|
124
|
+
|
|
125
|
+
if (this.offsetQuat) {
|
|
126
|
+
const absoluteQuaternion = Quaternion.multiply(this.offsetQuat, this.relativeAttitude.quaternion);
|
|
127
|
+
this.absoluteAttitude = new Attitude(absoluteQuaternion);
|
|
128
|
+
eventsForNotification.push(this.createEvent(EventType.AbsoluteAttitude, this.absoluteAttitude, event.timestamp));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (event.dataType === EventType.RelativePosition) {
|
|
133
|
+
|
|
134
|
+
if (this.oldRelativePos && this.offsetAngle
|
|
135
|
+
&& !ArCoreAbsoluteProvider.positionEquals(this.oldRelativePos, event.data)) {
|
|
136
|
+
|
|
137
|
+
const diffPos = Vector3.subtract(event.data, this.oldRelativePos);
|
|
138
|
+
const dist = Math.sqrt(diffPos[0] ** 2 + diffPos[2] ** 2);
|
|
139
|
+
const bearing = Math.atan2(diffPos[0], -diffPos[2]) - this.offsetAngle;
|
|
140
|
+
this.position = this.position.destinationPoint(dist, bearing, diffPos[1]);
|
|
141
|
+
|
|
142
|
+
if (this.absoluteAttitude) {
|
|
143
|
+
this.position.bearing = this.absoluteAttitude.heading;
|
|
144
|
+
this.updatePositionWithMapMatching();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
eventsForNotification.push(this.createEvent(EventType.AbsolutePosition, this.position, event.timestamp));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.oldRelativePos = event.data;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (event.dataType === EventType.Barcode) {
|
|
154
|
+
eventsForNotification.push(event);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (eventsForNotification.length !== 0) {
|
|
158
|
+
this.notify(...eventsForNotification);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
static positionEquals(pos1, pos2) {
|
|
164
|
+
return pos1[0] === pos2[0] && pos1[1] === pos2[1] && pos1[2] === pos2[2];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
onImuEvent = events => {
|
|
168
|
+
this.angularRate = events[0].data;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
setHeading(heading) {
|
|
172
|
+
|
|
173
|
+
if (!this.relativeAttitude) {
|
|
174
|
+
this.waitingForceHeading = heading;
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this.offsetAngle = this.relativeAttitude.heading - heading;
|
|
179
|
+
this.offsetQuat = Quaternion.fromAxisAngle([0, 0, 1], this.offsetAngle);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
setPosition(position) {
|
|
183
|
+
this.position = UserPosition.fromCoordinates(position);
|
|
184
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, this.position));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @override
|
|
189
|
+
*/
|
|
190
|
+
static get useCameraNatively() {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* MapMatching
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
enableMapMatching(network, maxDistance, maxAngleBearing) {
|
|
200
|
+
super.enableMapMatching(
|
|
201
|
+
network,
|
|
202
|
+
maxDistance || MM_ARCORE_DIST,
|
|
203
|
+
maxAngleBearing || PdrProvider.MM_PDR_ANGLE
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
updatePositionWithMapMatching() {
|
|
208
|
+
if (!this.mapMatching) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const projection = this.mapMatching.getProjection(this.position, true, true);
|
|
212
|
+
if (projection) {
|
|
213
|
+
if (projection.distanceFromNearestElement > 1) {
|
|
214
|
+
this.position.lat = projection.projection.lat;
|
|
215
|
+
this.position.lng = projection.projection.lng;
|
|
216
|
+
}
|
|
217
|
+
this.position.level = projection.projection.level;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
enableBarcodeScanner() {
|
|
222
|
+
this.arCoreProvider.enableBarcodeScanner();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
disableBarcodeScanner() {
|
|
226
|
+
this.arCoreProvider.disableBarcodeScanner();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export default ArCoreAbsoluteProvider;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/* eslint max-statements: ["error", 40]*/
|
|
2
|
+
|
|
3
|
+
import { UserPosition } from '@wemap/geo';
|
|
4
|
+
import { deg2rad } from '@wemap/maths';
|
|
5
|
+
|
|
6
|
+
import MapMatchingProvider from './MapMatchingProvider';
|
|
7
|
+
import PdrProvider from './pdr/PdrProvider';
|
|
8
|
+
import GnssWifiProvider from '../position/GnssWifiProvider';
|
|
9
|
+
import Availability from '../../events/Availability';
|
|
10
|
+
import EventType from '../../events/EventType';
|
|
11
|
+
import AbsoluteAttitudeProvider from '../attitude/absolute/AbsoluteAttitudeProvider';
|
|
12
|
+
import Constants from '../Constants';
|
|
13
|
+
|
|
14
|
+
const GPF_ACCURACY = 25;
|
|
15
|
+
const GPF_DISTANCE = 25;
|
|
16
|
+
|
|
17
|
+
const MM_GNSS_DIST = 20;
|
|
18
|
+
const MM_GNSS_ANGLE = deg2rad(20);
|
|
19
|
+
|
|
20
|
+
class GnssWifiPdrProvider extends MapMatchingProvider {
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @override
|
|
24
|
+
*/
|
|
25
|
+
constructor(onEvent, onError, options) {
|
|
26
|
+
super(onEvent, onError, options);
|
|
27
|
+
|
|
28
|
+
this.pdrProvider = new PdrProvider(e => this.onPdrEvent(e), onError, options);
|
|
29
|
+
this.gnssWifiProvider = new GnssWifiProvider(e => this.onGnssWifiEvent(e), onError, options);
|
|
30
|
+
this.absoluteAttitudeProvider = new AbsoluteAttitudeProvider(
|
|
31
|
+
e => this.onAbsoluteAttitudeEvent(e),
|
|
32
|
+
onError,
|
|
33
|
+
options
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
this.gpsLastUpdate = 0;
|
|
37
|
+
this.isFirstGnssUpdate = true;
|
|
38
|
+
this.isFirstAttitudeUpdate = true;
|
|
39
|
+
|
|
40
|
+
if (this.options.useMapMatching) {
|
|
41
|
+
this.enableMapMatching();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @override
|
|
47
|
+
*/
|
|
48
|
+
static get displayName() {
|
|
49
|
+
return 'GnssWifiPdr';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @override
|
|
54
|
+
*/
|
|
55
|
+
static get eventsType() {
|
|
56
|
+
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @override
|
|
61
|
+
*/
|
|
62
|
+
static get _availability() {
|
|
63
|
+
return Availability.merge(
|
|
64
|
+
PdrProvider.availability,
|
|
65
|
+
GnssWifiProvider.availability,
|
|
66
|
+
AbsoluteAttitudeProvider.availability
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @override
|
|
73
|
+
*/
|
|
74
|
+
_start() {
|
|
75
|
+
this.pdrProvider.start();
|
|
76
|
+
this.gnssWifiProvider.start();
|
|
77
|
+
this.absoluteAttitudeProvider.start();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @override
|
|
82
|
+
*/
|
|
83
|
+
stop() {
|
|
84
|
+
this.pdrProvider.stop();
|
|
85
|
+
this.gnssWifiProvider.stop();
|
|
86
|
+
this.absoluteAttitudeProvider.stop();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
onPdrEvent(pdrEvent) {
|
|
93
|
+
pdrEvent.forEach(event => {
|
|
94
|
+
if (event.dataType === EventType.AbsolutePosition) {
|
|
95
|
+
this.position = event.data;
|
|
96
|
+
} else if (event.dataType === EventType.AbsoluteAttitude) {
|
|
97
|
+
this.attitude = event.data;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
this.notify(...pdrEvent);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
onGnssWifiEvent(events) {
|
|
107
|
+
|
|
108
|
+
const gnssWifiEvent = events[0];
|
|
109
|
+
const position = gnssWifiEvent.data;
|
|
110
|
+
|
|
111
|
+
// This should be called to update True North / Magnetic North declination
|
|
112
|
+
this.absoluteAttitudeProvider.setPosition(position);
|
|
113
|
+
|
|
114
|
+
if (position.accuracy > GPF_ACCURACY) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.gnssPosition = position.clone();
|
|
119
|
+
this.gnssPosition.alt = Constants.DEFAULT_ALTITUDE;
|
|
120
|
+
|
|
121
|
+
if (!this.position || this.position
|
|
122
|
+
&& this.position.distanceTo(this.gnssPosition) > GPF_DISTANCE) {
|
|
123
|
+
|
|
124
|
+
if (!this.mapMatching || !this.attitude) {
|
|
125
|
+
this.pdrProvider.setPosition(this.gnssPosition);
|
|
126
|
+
} else {
|
|
127
|
+
|
|
128
|
+
this.gnssPosition.bearing = this.attitude.heading;
|
|
129
|
+
const projection = this.mapMatching.getProjection(this.gnssPosition, true, true);
|
|
130
|
+
|
|
131
|
+
if (projection && projection.projection) {
|
|
132
|
+
|
|
133
|
+
// Create a new position from projection and new GNSS position.
|
|
134
|
+
this.gnssPosition.lat = projection.projection.lat;
|
|
135
|
+
this.gnssPosition.lng = projection.projection.lng;
|
|
136
|
+
|
|
137
|
+
// // If nearest element is an edge, use its orientation to set heading
|
|
138
|
+
// if (projection.nearestElement instanceof Edge) {
|
|
139
|
+
// const edgeBearing = projection.nearestElement.bearing;
|
|
140
|
+
// const diff1 = MathUtils.diffAngle(MathUtils.deg2rad(this.gnssPosition.bearing), edgeBearing);
|
|
141
|
+
// const diff2 = MathUtils.diffAngle(MathUtils.deg2rad(this.gnssPosition.bearing), edgeBearing + Math.PI);
|
|
142
|
+
// this.pdrProvider.setHeading(diff1 < diff2 ? edgeBearing : edgeBearing + Math.PI);
|
|
143
|
+
// }
|
|
144
|
+
|
|
145
|
+
if (this.lastAttitude) {
|
|
146
|
+
this.pdrProvider.setHeading(this.lastAttitude.heading);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
this.pdrProvider.setPosition(this.gnssPosition);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
onAbsoluteAttitudeEvent(events) {
|
|
157
|
+
|
|
158
|
+
const attitude = events[0].data;
|
|
159
|
+
|
|
160
|
+
if (this.isFirstAttitudeUpdate) {
|
|
161
|
+
this.pdrProvider.setHeading(attitude.heading);
|
|
162
|
+
this.isFirstAttitudeUpdate = false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
this.lastAttitude = attitude;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* MapMatching
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
enableMapMatching(network = null, maxDistance = MM_GNSS_DIST, maxAngleBearing = MM_GNSS_ANGLE) {
|
|
173
|
+
this.pdrProvider.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
174
|
+
super.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
setNetwork(network) {
|
|
179
|
+
this.pdrProvider.setNetwork(network);
|
|
180
|
+
super.setNetwork(network);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Itinerary
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
setItinerary(itinerary) {
|
|
188
|
+
|
|
189
|
+
const isFirstItinerary = !this.itinerary;
|
|
190
|
+
|
|
191
|
+
super.setItinerary(itinerary);
|
|
192
|
+
|
|
193
|
+
if (isFirstItinerary && itinerary.length > 0) {
|
|
194
|
+
|
|
195
|
+
// When the first itinerary is received, first or second node (depending on MM_GNSS_DIST) is used as a starting point. No map-matching is needed here as router already provide the projection in the itinerary (node2 is node1 projection on OSRM network).
|
|
196
|
+
|
|
197
|
+
if (!this.gnssPosition
|
|
198
|
+
|| itinerary.length < 2
|
|
199
|
+
|| !itinerary.points[0].equalsTo(this.gnssPosition)) {
|
|
200
|
+
console.warn('Itinerary has not been calculated from GnssWifiPdrProvider and these is not recommanded');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const startEdge = itinerary.getEdgeAt(MM_GNSS_DIST);
|
|
204
|
+
if (!startEdge) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const startPoint = UserPosition.fromCoordinates(startEdge.node1.coords);
|
|
208
|
+
startPoint.alt = Constants.DEFAULT_ALTITUDE;
|
|
209
|
+
this.pdrProvider.setPosition(startPoint);
|
|
210
|
+
this.pdrProvider.setStepDetectionLockerOrientation(startEdge.bearing);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export default GnssWifiPdrProvider;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import Provider from '../Provider';
|
|
2
|
+
import {
|
|
3
|
+
Itinerary, MapMatching, Network
|
|
4
|
+
} from '@wemap/graph';
|
|
5
|
+
|
|
6
|
+
class MapMatchingProvider extends Provider {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Enable mapmatching
|
|
10
|
+
* @param {*} network a network which will be used for map matching
|
|
11
|
+
* @param {*} maxDistance max distance between position and network to match. null disables maxDistance (default: null)
|
|
12
|
+
* @param {*} maxAngleBearing threshold to match a parallel segment for angle between position bearing and segment. null disables this threshold (default: null)
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
enableMapMatching(network, maxDistance, maxAngleBearing) {
|
|
16
|
+
this.mapMatching = new MapMatching();
|
|
17
|
+
this.mapMatching.maxDistance = maxDistance;
|
|
18
|
+
this.mapMatching.maxAngleBearing = maxAngleBearing;
|
|
19
|
+
|
|
20
|
+
if (network) {
|
|
21
|
+
this.setNetwork(network);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Update the network for mapmatching
|
|
27
|
+
* @param {Network} network a network instance
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
setNetwork(network) {
|
|
31
|
+
if (!this.mapMatching) {
|
|
32
|
+
throw new Error('MapMatching is not enabled');
|
|
33
|
+
}
|
|
34
|
+
this.mapMatching.network = network;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Is mapmatching activated?
|
|
39
|
+
* @returns is mapmatching activated
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
get hasMapMatching() {
|
|
43
|
+
return this.mapMatching !== null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Itinerary
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Update itinerary.
|
|
53
|
+
* Itinerary is different from network, it is not used for mapmatching. It can be used for others tricks like HeadingUnlocker
|
|
54
|
+
* @param {Itinerary} itinerary a given itinerary
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
setItinerary(itinerary) {
|
|
58
|
+
if (!(itinerary instanceof Itinerary)) {
|
|
59
|
+
throw new TypeError(itinerary + ' is not an instance of Itinerary');
|
|
60
|
+
}
|
|
61
|
+
this.itinerary = itinerary;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default MapMatchingProvider;
|