@wemap/positioning 2.7.13 → 14.0.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/README.md +51 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16582 -0
- package/dist/qr-scanner-worker.min-CdBZO1_x.js +2 -0
- package/dist/src/ILocationSource.d.ts +104 -0
- package/dist/src/ILocationSource.d.ts.map +1 -0
- package/dist/src/MapMatching.d.ts +83 -0
- package/dist/src/MapMatching.d.ts.map +1 -0
- package/dist/src/location-sources/GnssWifiLocationSource.d.ts +79 -0
- package/dist/src/location-sources/GnssWifiLocationSource.d.ts.map +1 -0
- package/dist/src/location-sources/LocationSource.d.ts +102 -0
- package/dist/src/location-sources/LocationSource.d.ts.map +1 -0
- package/dist/src/location-sources/VPSLocationSource.d.ts +107 -0
- package/dist/src/location-sources/VPSLocationSource.d.ts.map +1 -0
- package/dist/src/types.d.ts +65 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils/permissions.d.ts +29 -0
- package/dist/src/utils/permissions.d.ts.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/package.json +23 -59
- package/babel.config.js +0 -11
- package/config.json +0 -4
- package/debug/absolute-attitude.html +0 -16
- package/debug/arcore-absolute.html +0 -16
- package/debug/arcore.html +0 -16
- package/debug/components/AbsoluteAttitudeComponent.jsx +0 -100
- package/debug/components/ArCoreAbsoluteComponent.jsx +0 -104
- package/debug/components/ArCoreComponent.jsx +0 -69
- package/debug/components/GnssWifiComponent.jsx +0 -56
- package/debug/components/GnssWifiPdrComponent.jsx +0 -76
- package/debug/components/ImuComponent.jsx +0 -95
- package/debug/components/InclinationComponent.jsx +0 -52
- package/debug/components/MapComponent.jsx +0 -228
- package/debug/components/NavigationConfig.js +0 -92
- package/debug/components/PdrComponent.jsx +0 -75
- package/debug/components/PoseComponent.jsx +0 -77
- package/debug/components/PositioningComponent.jsx +0 -29
- package/debug/components/PositioningInclinationComponent.jsx +0 -82
- package/debug/components/PositioningPoseComponent.jsx +0 -117
- package/debug/components/RelativeAttitudeComponent.jsx +0 -82
- package/debug/components/StartStopComponent.jsx +0 -50
- package/debug/components/Utils.js +0 -128
- package/debug/components/index.js +0 -34
- package/debug/gnss-wifi-pdr.html +0 -16
- package/debug/gnss-wifi.html +0 -16
- package/debug/imu.html +0 -16
- package/debug/inclination.html +0 -16
- package/debug/pdr.html +0 -16
- package/debug/pose.html +0 -16
- package/debug/positioning.html +0 -16
- package/debug/relative-attitude.html +0 -16
- package/dist/wemap-positioning.min.js +0 -1
- package/index.js +0 -8
- package/src/PositioningHandler.js +0 -237
- package/src/PositioningHandler.spec.js +0 -294
- package/src/PositioningOptions.js +0 -34
- package/src/errors/AskImuOnDesktopError.js +0 -9
- package/src/errors/ContainsIgnoredProviderError.js +0 -9
- package/src/errors/GeolocationApiMissingError.js +0 -9
- package/src/errors/GeolocationPermissionDeniedError.js +0 -9
- package/src/errors/GeolocationPositionUnavailableError.js +0 -9
- package/src/errors/IpResolveServerError.js +0 -9
- package/src/errors/MissingAccelerometerError.js +0 -11
- package/src/errors/MissingArCoreError.js +0 -9
- package/src/errors/MissingGyroscopeError.js +0 -11
- package/src/errors/MissingMagnetometerError.js +0 -9
- package/src/errors/MissingNativeInterfaceError.js +0 -9
- package/src/errors/MissingSensorError.js +0 -14
- package/src/errors/NoProviderFoundError.js +0 -9
- package/src/events/Availability.js +0 -30
- package/src/events/EventType.js +0 -22
- package/src/events/ProviderEvent.js +0 -35
- package/src/providers/Constants.js +0 -5
- package/src/providers/Provider.js +0 -247
- package/src/providers/ProvidersList.js +0 -44
- package/src/providers/ProvidersLogger.js +0 -75
- package/src/providers/attitude/AbsoluteAttitudeProvider.js +0 -199
- package/src/providers/attitude/EkfAttitude.js +0 -238
- package/src/providers/attitude/EkfAttitude.spec.js +0 -116
- package/src/providers/attitude/RelativeAttitudeProvider.js +0 -121
- package/src/providers/others/ImuProvider.js +0 -179
- package/src/providers/others/InclinationProvider.js +0 -99
- package/src/providers/others/MapMatchingProvider.js +0 -65
- package/src/providers/pose/ArCoreAbsoluteProvider.js +0 -235
- package/src/providers/pose/ArCoreProvider.js +0 -191
- package/src/providers/pose/GnssWifiPdrProvider.js +0 -219
- package/src/providers/pose/PoseProvider.js +0 -71
- package/src/providers/pose/pdr/PdrProvider.js +0 -364
- package/src/providers/pose/pdr/helpers/HeadingUnlocker.js +0 -41
- package/src/providers/pose/pdr/helpers/HeadingUnlocker.spec.js +0 -26
- package/src/providers/pose/pdr/helpers/Smoother.js +0 -92
- package/src/providers/pose/pdr/helpers/Smoother.spec.js +0 -426
- package/src/providers/pose/pdr/helpers/ThugDetector.js +0 -37
- package/src/providers/pose/pdr/steps/StepDetection.js +0 -7
- package/src/providers/pose/pdr/steps/StepDetectionLadetto.js +0 -67
- package/src/providers/pose/pdr/steps/StepDetectionMinMaxPeaks.js +0 -80
- package/src/providers/pose/pdr/steps/StepDetectionMinMaxPeaks2.js +0 -108
- package/src/providers/position/GnssWifiProvider.js +0 -130
- package/src/providers/position/IpProvider.js +0 -74
- package/webpack/webpack.common.js +0 -20
- package/webpack/webpack.dev.js +0 -24
- package/webpack/webpack.prod.js +0 -15
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/* eslint max-statements: ["error", 40]*/
|
|
2
|
-
|
|
3
|
-
import { WGS84UserPosition } from '@wemap/geo';
|
|
4
|
-
import { deg2rad } from '@wemap/maths';
|
|
5
|
-
|
|
6
|
-
import MapMatchingProvider from '../others/MapMatchingProvider';
|
|
7
|
-
import PdrProvider from './pdr/PdrProvider';
|
|
8
|
-
import GnssWifiProvider from '../position/GnssWifiProvider';
|
|
9
|
-
import EventType from '../../events/EventType';
|
|
10
|
-
import AbsoluteAttitudeProvider from '../attitude/AbsoluteAttitudeProvider';
|
|
11
|
-
import Constants from '../Constants';
|
|
12
|
-
|
|
13
|
-
const GPF_ACCURACY = 25;
|
|
14
|
-
const GPF_DISTANCE = 25;
|
|
15
|
-
|
|
16
|
-
const MM_GNSS_DIST = 20;
|
|
17
|
-
const MM_GNSS_ANGLE = deg2rad(20);
|
|
18
|
-
|
|
19
|
-
class GnssWifiPdrProvider extends MapMatchingProvider {
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @override
|
|
23
|
-
*/
|
|
24
|
-
constructor(onEvent, onError, options) {
|
|
25
|
-
super(onEvent, onError, options);
|
|
26
|
-
|
|
27
|
-
this.pdrProvider = new PdrProvider(e => this.onPdrEvent(e), onError, options);
|
|
28
|
-
this.gnssWifiProvider = new GnssWifiProvider(e => this.onGnssWifiEvent(e), onError, options);
|
|
29
|
-
this.absoluteAttitudeProvider = new AbsoluteAttitudeProvider(
|
|
30
|
-
e => this.onAbsoluteAttitudeEvent(e),
|
|
31
|
-
onError,
|
|
32
|
-
options
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
this.gpsLastUpdate = 0;
|
|
36
|
-
this.isFirstGnssUpdate = true;
|
|
37
|
-
this.isFirstAttitudeUpdate = true;
|
|
38
|
-
|
|
39
|
-
if (this.options.useMapMatching) {
|
|
40
|
-
this.enableMapMatching();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @override
|
|
46
|
-
*/
|
|
47
|
-
static get name() {
|
|
48
|
-
return 'GnssWifi';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @override
|
|
53
|
-
*/
|
|
54
|
-
static get displayName() {
|
|
55
|
-
return 'GnssWifiPdr';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @override
|
|
60
|
-
*/
|
|
61
|
-
static get eventsType() {
|
|
62
|
-
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @override
|
|
67
|
-
*/
|
|
68
|
-
static getRequiredProviders() {
|
|
69
|
-
return [PdrProvider, GnssWifiProvider, AbsoluteAttitudeProvider];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @override
|
|
75
|
-
*/
|
|
76
|
-
startInternal() {
|
|
77
|
-
this.pdrProvider.start();
|
|
78
|
-
this.gnssWifiProvider.start();
|
|
79
|
-
this.absoluteAttitudeProvider.start();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @override
|
|
84
|
-
*/
|
|
85
|
-
stop() {
|
|
86
|
-
this.pdrProvider.stop();
|
|
87
|
-
this.gnssWifiProvider.stop();
|
|
88
|
-
this.absoluteAttitudeProvider.stop();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @private
|
|
93
|
-
*/
|
|
94
|
-
onPdrEvent(pdrEvent) {
|
|
95
|
-
pdrEvent.forEach(event => {
|
|
96
|
-
if (event.dataType === EventType.AbsolutePosition) {
|
|
97
|
-
this.position = event.data;
|
|
98
|
-
} else if (event.dataType === EventType.AbsoluteAttitude) {
|
|
99
|
-
this.attitude = event.data;
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
this.notify(...pdrEvent);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @private
|
|
107
|
-
*/
|
|
108
|
-
onGnssWifiEvent(events) {
|
|
109
|
-
|
|
110
|
-
const gnssWifiEvent = events[0];
|
|
111
|
-
const position = gnssWifiEvent.data;
|
|
112
|
-
|
|
113
|
-
// This should be called to update True North / Magnetic North declination
|
|
114
|
-
this.absoluteAttitudeProvider.setPosition(position);
|
|
115
|
-
|
|
116
|
-
if (position.accuracy > GPF_ACCURACY) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
this.gnssPosition = position.clone();
|
|
121
|
-
this.gnssPosition.alt = Constants.DEFAULT_ALTITUDE;
|
|
122
|
-
|
|
123
|
-
if (!this.position || this.position
|
|
124
|
-
&& this.position.distanceTo(this.gnssPosition) > GPF_DISTANCE) {
|
|
125
|
-
|
|
126
|
-
if (!this.mapMatching || !this.attitude) {
|
|
127
|
-
this.pdrProvider.setPosition(this.gnssPosition);
|
|
128
|
-
} else {
|
|
129
|
-
|
|
130
|
-
this.gnssPosition.bearing = this.attitude.heading;
|
|
131
|
-
const projection = this.mapMatching.getProjection(this.gnssPosition, true, true);
|
|
132
|
-
|
|
133
|
-
if (projection && projection.projection) {
|
|
134
|
-
|
|
135
|
-
// Create a new position from projection and new GNSS position.
|
|
136
|
-
this.gnssPosition.lat = projection.projection.lat;
|
|
137
|
-
this.gnssPosition.lng = projection.projection.lng;
|
|
138
|
-
|
|
139
|
-
// // If nearest element is an edge, use its orientation to set heading
|
|
140
|
-
// if (projection.nearestElement instanceof Edge) {
|
|
141
|
-
// const edgeBearing = projection.nearestElement.bearing;
|
|
142
|
-
// const diff1 = MathUtils.diffAngle(MathUtils.deg2rad(this.gnssPosition.bearing), edgeBearing);
|
|
143
|
-
// const diff2 = MathUtils.diffAngle(MathUtils.deg2rad(this.gnssPosition.bearing), edgeBearing + Math.PI);
|
|
144
|
-
// this.pdrProvider.setHeading(diff1 < diff2 ? edgeBearing : edgeBearing + Math.PI);
|
|
145
|
-
// }
|
|
146
|
-
|
|
147
|
-
if (this.lastAttitude) {
|
|
148
|
-
this.pdrProvider.setHeading(this.lastAttitude.heading);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
this.pdrProvider.setPosition(this.gnssPosition);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
onAbsoluteAttitudeEvent(events) {
|
|
159
|
-
|
|
160
|
-
const attitude = events[0].data;
|
|
161
|
-
|
|
162
|
-
if (this.isFirstAttitudeUpdate) {
|
|
163
|
-
this.pdrProvider.setHeading(attitude.heading);
|
|
164
|
-
this.isFirstAttitudeUpdate = false;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
this.lastAttitude = attitude;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* MapMatching
|
|
172
|
-
*/
|
|
173
|
-
|
|
174
|
-
enableMapMatching(network = null, maxDistance = MM_GNSS_DIST, maxAngleBearing = MM_GNSS_ANGLE) {
|
|
175
|
-
this.pdrProvider.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
176
|
-
super.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
setNetwork(network) {
|
|
181
|
-
this.pdrProvider.setNetwork(network);
|
|
182
|
-
super.setNetwork(network);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Itinerary
|
|
187
|
-
*/
|
|
188
|
-
|
|
189
|
-
setItinerary(itinerary) {
|
|
190
|
-
|
|
191
|
-
const isFirstItinerary = !this.itinerary;
|
|
192
|
-
|
|
193
|
-
super.setItinerary(itinerary);
|
|
194
|
-
|
|
195
|
-
if (isFirstItinerary && itinerary.length > 0) {
|
|
196
|
-
|
|
197
|
-
// 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).
|
|
198
|
-
|
|
199
|
-
if (!this.gnssPosition
|
|
200
|
-
|| itinerary.length < 2
|
|
201
|
-
|| !itinerary.points[0].equalsTo(this.gnssPosition)) {
|
|
202
|
-
console.warn('Itinerary has not been calculated from GnssWifiPdrProvider and these is not recommanded');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const startEdge = itinerary.getEdgeAt(MM_GNSS_DIST);
|
|
206
|
-
if (!startEdge) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
const startPoint = WGS84UserPosition.fromWGS84(startEdge.node1.coords);
|
|
210
|
-
startPoint.alt = Constants.DEFAULT_ALTITUDE;
|
|
211
|
-
this.pdrProvider.setPosition(startPoint);
|
|
212
|
-
this.pdrProvider.setStepDetectionLockerOrientation(startEdge.bearing);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export default GnssWifiPdrProvider;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import Provider from '../Provider';
|
|
2
|
-
import EventType from '../../events/EventType';
|
|
3
|
-
|
|
4
|
-
import GnssWifiProvider from '../position/GnssWifiProvider';
|
|
5
|
-
import AbsoluteAttitudeProvider from '../attitude/AbsoluteAttitudeProvider';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Pose provider is the provider used by the PositioningHandler. It uses the best fusion
|
|
9
|
-
* of what he can and provides an AbsoluteAttitude and an AbsolutePosition as an output.
|
|
10
|
-
*/
|
|
11
|
-
class PoseProvider extends Provider {
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @override
|
|
15
|
-
*/
|
|
16
|
-
constructor(onEvent, onError, options) {
|
|
17
|
-
super(onEvent, onError, options);
|
|
18
|
-
|
|
19
|
-
this.absoluteAttitudeProvider = new AbsoluteAttitudeProvider(onEvent, onError);
|
|
20
|
-
this.gnssWifiProvider = new GnssWifiProvider((events) => {
|
|
21
|
-
this.absoluteAttitudeProvider.setPosition(events[0].data);
|
|
22
|
-
onEvent(events);
|
|
23
|
-
}, onError);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @override
|
|
28
|
-
*/
|
|
29
|
-
static get name() {
|
|
30
|
-
return 'Pose';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @override
|
|
35
|
-
*/
|
|
36
|
-
static get displayName() {
|
|
37
|
-
return 'Pose provider';
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @override
|
|
42
|
-
*/
|
|
43
|
-
static get eventsType() {
|
|
44
|
-
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Return the list of required providers
|
|
49
|
-
*/
|
|
50
|
-
static getRequiredProviders() {
|
|
51
|
-
return [AbsoluteAttitudeProvider, GnssWifiProvider];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @override
|
|
56
|
-
*/
|
|
57
|
-
startInternal() {
|
|
58
|
-
this.absoluteAttitudeProvider.start();
|
|
59
|
-
this.gnssWifiProvider.start();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @override
|
|
64
|
-
*/
|
|
65
|
-
stopInternal() {
|
|
66
|
-
this.absoluteAttitudeProvider.stop();
|
|
67
|
-
this.gnssWifiProvider.stop();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export default PoseProvider;
|
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import noop from 'lodash.noop';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
Constants as GeoConstants, WGS84, WGS84UserPosition
|
|
6
|
-
} from '@wemap/geo';
|
|
7
|
-
|
|
8
|
-
import { Itinerary } from '@wemap/graph';
|
|
9
|
-
import {
|
|
10
|
-
deg2rad, Quaternion
|
|
11
|
-
} from '@wemap/maths';
|
|
12
|
-
|
|
13
|
-
import StepDetection from './steps/StepDetection';
|
|
14
|
-
import HeadingUnlocker from './helpers/HeadingUnlocker';
|
|
15
|
-
import ThugDetector from './helpers/ThugDetector';
|
|
16
|
-
import Smoother from './helpers/Smoother';
|
|
17
|
-
import RelativeAttitudeProvider from '../../attitude/RelativeAttitudeProvider';
|
|
18
|
-
import ImuProvider from '../../others/ImuProvider';
|
|
19
|
-
import EventType from '../../../events/EventType';
|
|
20
|
-
import MapMatchingProvider from '../../others/MapMatchingProvider';
|
|
21
|
-
import { TimeUtils } from '@wemap/utils';
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const MM_PDR_ANGLE = deg2rad(20);
|
|
25
|
-
const MM_PDR_DIST = 15;
|
|
26
|
-
const MM_CONV_SPEED = 0.7;
|
|
27
|
-
|
|
28
|
-
const LO_SEGMENT_SIZE = 1.5;
|
|
29
|
-
|
|
30
|
-
const DEFAULT_OPTIONS = {
|
|
31
|
-
stepdetectionlocker: true,
|
|
32
|
-
smoother: true,
|
|
33
|
-
onThugEvent: noop
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
class PdrProvider extends MapMatchingProvider {
|
|
37
|
-
|
|
38
|
-
// pdrPosition can be different from this.position
|
|
39
|
-
// pdrPosition is raw position calculated by PdrProvider where
|
|
40
|
-
// this.position is smoothed position.
|
|
41
|
-
pdrPosition = null;
|
|
42
|
-
|
|
43
|
-
static MM_PDR_ANGLE = MM_PDR_ANGLE;
|
|
44
|
-
static MM_PDR_DIST = MM_PDR_DIST;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @override
|
|
48
|
-
*/
|
|
49
|
-
constructor(onEvent, onError, options) {
|
|
50
|
-
super(onEvent, onError, Object.assign({}, DEFAULT_OPTIONS, options));
|
|
51
|
-
|
|
52
|
-
// Input data providers
|
|
53
|
-
this.relativeAttitudeProvider = new RelativeAttitudeProvider(
|
|
54
|
-
e => this.onRelativeAttitudeEvent(e),
|
|
55
|
-
onError,
|
|
56
|
-
this.options
|
|
57
|
-
);
|
|
58
|
-
this.imuProvider = new ImuProvider(
|
|
59
|
-
e => this.onImuEvent(e),
|
|
60
|
-
onError,
|
|
61
|
-
Object.assign({}, this.options,
|
|
62
|
-
{ require: [EventType.Acceleration, EventType.AngularRate] }
|
|
63
|
-
)
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
// Helpers for PDR
|
|
67
|
-
this.stepDetection = new StepDetection();
|
|
68
|
-
this.stepDetectionLocker = new HeadingUnlocker();
|
|
69
|
-
this.smoother = new Smoother();
|
|
70
|
-
this.thugDetector = new ThugDetector();
|
|
71
|
-
|
|
72
|
-
if (this.options.useMapMatching) {
|
|
73
|
-
this.enableMapMatching();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @override
|
|
79
|
-
*/
|
|
80
|
-
static get name() {
|
|
81
|
-
return 'PDR';
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* @override
|
|
86
|
-
*/
|
|
87
|
-
static get displayName() {
|
|
88
|
-
return 'PDR';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @override
|
|
93
|
-
*/
|
|
94
|
-
static get eventsType() {
|
|
95
|
-
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* @override
|
|
100
|
-
*/
|
|
101
|
-
static getRequiredProviders() {
|
|
102
|
-
return [ImuProvider, RelativeAttitudeProvider];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @override
|
|
108
|
-
*/
|
|
109
|
-
startInternal() {
|
|
110
|
-
this.imuProvider.start();
|
|
111
|
-
this.relativeAttitudeProvider.start();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @override
|
|
116
|
-
*/
|
|
117
|
-
stopInternal() {
|
|
118
|
-
this.imuProvider.stop();
|
|
119
|
-
this.relativeAttitudeProvider.stop();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Get provider name
|
|
124
|
-
* @override
|
|
125
|
-
*/
|
|
126
|
-
get nameWithOptions() {
|
|
127
|
-
let name = this.name;
|
|
128
|
-
name += ' (locker: ';
|
|
129
|
-
name += this.options.stepdetectionlocker ? 'Y' : 'N';
|
|
130
|
-
name += ', ';
|
|
131
|
-
name += 'smoo: ';
|
|
132
|
-
name += this.options.smoother ? 'Y' : 'N';
|
|
133
|
-
name += ', ';
|
|
134
|
-
name += 'mm: ';
|
|
135
|
-
name += this.options.useMapMatching ? 'Y' : 'N';
|
|
136
|
-
name += ')';
|
|
137
|
-
return name;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
setHeading(heading) {
|
|
141
|
-
this.relativeAttitudeProvider.setOffset(heading);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
setPosition(position) {
|
|
145
|
-
if (position instanceof WGS84) {
|
|
146
|
-
this.pdrPosition = WGS84UserPosition.fromWGS84(position);
|
|
147
|
-
if (window && window.performance) {
|
|
148
|
-
this.pdrPosition.time = TimeUtils.preciseTime / 1e3;
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
this.pdrPosition = position;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (this.options.smoother) {
|
|
155
|
-
this.smoother.generateNextPositions(this.pdrPosition, true);
|
|
156
|
-
// this.smoother.pullPosition(position.time) should never return null
|
|
157
|
-
this.position = this.smoother.pullPosition(this.pdrPosition.time);
|
|
158
|
-
} else {
|
|
159
|
-
this.position = this.pdrPosition.clone();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this.notify(this.createEvent(EventType.AbsolutePosition, this.position));
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* @override
|
|
167
|
-
*/
|
|
168
|
-
onRelativeAttitudeEvent = events => {
|
|
169
|
-
const attitudeEvent = events[0];
|
|
170
|
-
this.attitude = attitudeEvent.data;
|
|
171
|
-
|
|
172
|
-
const newEvent = attitudeEvent.clone();
|
|
173
|
-
newEvent.dataType = EventType.AbsoluteAttitude;
|
|
174
|
-
this.notify(newEvent);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* @private
|
|
179
|
-
*/
|
|
180
|
-
onImuEvent = imuEvent => {
|
|
181
|
-
|
|
182
|
-
if (!this.attitude) {
|
|
183
|
-
// We should wait attitude for stepDetectionLocker and linear acceleration
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (!this.pdrPosition) {
|
|
188
|
-
// We should wait at least an input position for PDR
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (this.options.stepdetectionlocker
|
|
193
|
-
&& this.stepDetectionLocker.locked
|
|
194
|
-
&& this.stepDetectionLocker.feedHeading(this.attitude.heading)) {
|
|
195
|
-
// Step detection is locked by stepDetectionLocker
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let timestamp, acceleration, angularRate;
|
|
201
|
-
imuEvent.forEach(event => {
|
|
202
|
-
if (event.dataType === EventType.Acceleration) {
|
|
203
|
-
acceleration = event.data;
|
|
204
|
-
timestamp = event.timestamp;
|
|
205
|
-
} else if (event.dataType === EventType.AngularRate) {
|
|
206
|
-
angularRate = event.data;
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const heading = this.attitude.heading;
|
|
211
|
-
|
|
212
|
-
if (this.onThugEvent && this.thugDetector.compute(timestamp, acceleration)) {
|
|
213
|
-
this.onThugEvent();
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Step Detection and Step Size Detection
|
|
218
|
-
*/
|
|
219
|
-
const linearAcc = PdrProvider.computeLinearAcceleration(
|
|
220
|
-
this.attitude.quaternion, acceleration);
|
|
221
|
-
const stepDetected = this.stepDetection.compute(timestamp, linearAcc, angularRate);
|
|
222
|
-
|
|
223
|
-
if (stepDetected) {
|
|
224
|
-
|
|
225
|
-
this.pdrPosition = this.calculateNewPosition(this.pdrPosition, timestamp,
|
|
226
|
-
heading, this.stepDetection.lastStepSize);
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Update current_position
|
|
230
|
-
*/
|
|
231
|
-
if (this.options.smoother) {
|
|
232
|
-
this.smoother.generateNextPositions(this.pdrPosition);
|
|
233
|
-
const newPosition = this.smoother.pullPosition(timestamp);
|
|
234
|
-
// At this time, newPosition can be null if a new step has been detected
|
|
235
|
-
// and smoother has not been completely consumed.
|
|
236
|
-
if (newPosition) {
|
|
237
|
-
this.position = newPosition;
|
|
238
|
-
}
|
|
239
|
-
} else {
|
|
240
|
-
this.position = this.pdrPosition;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
} else if (this.options.smoother) {
|
|
244
|
-
// If no step is detected, we pull last known position from smoother until now (timestamp).
|
|
245
|
-
const smoothedPosition = this.smoother.pullPosition(timestamp);
|
|
246
|
-
if (!smoothedPosition) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
this.position = smoothedPosition;
|
|
250
|
-
} else {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
this.notify(this.createEvent(EventType.AbsolutePosition, this.position));
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
calculateNewPosition(previousPosition, timestamp, heading, stepSize) {
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Compute new_position
|
|
261
|
-
*/
|
|
262
|
-
const newPositionWithoutMM = previousPosition.clone();
|
|
263
|
-
newPositionWithoutMM.move(stepSize, heading);
|
|
264
|
-
newPositionWithoutMM.bearing = heading;
|
|
265
|
-
newPositionWithoutMM.time = timestamp;
|
|
266
|
-
|
|
267
|
-
if (!this.mapMatching) {
|
|
268
|
-
return newPositionWithoutMM;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Try map-matching
|
|
273
|
-
*/
|
|
274
|
-
const projection = this.mapMatching.getProjection(newPositionWithoutMM, true, true);
|
|
275
|
-
if (!projection || !projection.projection) {
|
|
276
|
-
return newPositionWithoutMM;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const projectedPosition = newPositionWithoutMM;
|
|
280
|
-
projectedPosition.level = projection.projection.level;
|
|
281
|
-
|
|
282
|
-
if (projection.distanceFromNearestElement < stepSize) {
|
|
283
|
-
projectedPosition.lat = projection.projection.lat;
|
|
284
|
-
projectedPosition.lng = projection.projection.lng;
|
|
285
|
-
return projectedPosition;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Adapt map-matching to not stick corridor directly
|
|
290
|
-
* /!\ This smoothed position is different from the one of Smoother
|
|
291
|
-
*/
|
|
292
|
-
const smoothedPosition = projectedPosition;
|
|
293
|
-
smoothedPosition.lat = previousPosition.lat;
|
|
294
|
-
smoothedPosition.lng = previousPosition.lng;
|
|
295
|
-
|
|
296
|
-
const smoothedDistance = projection.distanceFromNearestElement * MM_CONV_SPEED;
|
|
297
|
-
const smoothedBearing = previousPosition.bearingTo(projection.projection);
|
|
298
|
-
smoothedPosition.move(smoothedDistance, smoothedBearing);
|
|
299
|
-
|
|
300
|
-
return smoothedPosition;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* MapMatching
|
|
306
|
-
*/
|
|
307
|
-
|
|
308
|
-
enableMapMatching(network, maxDistance, maxAngleBearing) {
|
|
309
|
-
super.enableMapMatching(network, maxDistance || MM_PDR_DIST, maxAngleBearing || MM_PDR_ANGLE);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Itinerary and PDR Locker
|
|
315
|
-
*/
|
|
316
|
-
|
|
317
|
-
setItinerary(itinerary) {
|
|
318
|
-
super.setItinerary(itinerary);
|
|
319
|
-
|
|
320
|
-
if (this.options.stepdetectionlocker) {
|
|
321
|
-
this.stepDetectionLocker.setWaitingOrientation(
|
|
322
|
-
PdrProvider.retrieveWaitingOrientationFromItinerary(itinerary)
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
static retrieveWaitingOrientationFromItinerary(itinerary) {
|
|
328
|
-
|
|
329
|
-
if (!itinerary) {
|
|
330
|
-
throw new Error('Empty itinerary');
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (!(itinerary instanceof Itinerary)) {
|
|
334
|
-
throw new TypeError(itinerary + ' is not an instance of itinerary');
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (itinerary.length < 1) {
|
|
338
|
-
throw new Error('Empty itinerary');
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
const edgeAt = itinerary.getEdgeAt(LO_SEGMENT_SIZE);
|
|
342
|
-
if (edgeAt) {
|
|
343
|
-
return edgeAt.bearing;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (itinerary.length < 2) {
|
|
347
|
-
throw new Error('Itinerary is too short');
|
|
348
|
-
}
|
|
349
|
-
return itinerary.secondEdge.bearing;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
setStepDetectionLockerOrientation(orientation) {
|
|
353
|
-
this.stepDetectionLocker.setWaitingOrientation(orientation);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// Linear acceleration in ENU
|
|
357
|
-
static computeLinearAcceleration(quaternion, acc) {
|
|
358
|
-
const linearAcc = Quaternion.rotate(Quaternion.inverse(quaternion), acc);
|
|
359
|
-
linearAcc[2] -= GeoConstants.EARTH_GRAVITY;
|
|
360
|
-
return linearAcc;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
export default PdrProvider;
|
|
@@ -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;
|