@wemap/positioning 2.0.0 → 2.2.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/.eslintrc.json +4 -2
- package/debug/absolute-attitude.html +16 -0
- package/debug/arcore.html +16 -0
- package/debug/gnss-wifi-pdr.html +16 -0
- package/debug/gnss-wifi.html +16 -0
- package/debug/imu.html +16 -0
- package/debug/inclination.html +16 -0
- package/debug/pdr.html +16 -0
- package/debug/pose.html +16 -0
- package/debug/positioning.html +16 -0
- package/debug/relative-attitude.html +16 -0
- package/package.json +7 -4
- package/src/PositioningHandler.js +96 -34
- package/src/components/AbsoluteAttitudeComponent.jsx +104 -0
- package/src/components/ArCoreComponent.jsx +74 -0
- package/src/components/GnssWifiComponent.jsx +58 -0
- package/src/components/GnssWifiPdrComponent.jsx +94 -0
- package/src/components/ImuComponent.jsx +100 -0
- package/src/components/InclinationComponent.jsx +53 -0
- package/src/components/MapComponent.jsx +226 -0
- package/src/components/PdrComponent.jsx +97 -0
- package/src/components/PoseComponent.jsx +81 -0
- package/src/components/PositioningComponent.jsx +26 -0
- package/src/components/PositioningInclinationComponent.jsx +76 -0
- package/src/components/PositioningPoseComponent.jsx +120 -0
- package/src/components/RelativeAttitudeComponent.jsx +82 -0
- package/src/components/StartStopComponent.jsx +50 -0
- package/src/components/Utils.js +92 -0
- package/src/components/index.js +32 -0
- package/src/errors/AskImuOnDesktopError.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/events/EventType.js +20 -0
- package/src/events/ProviderError.js +52 -0
- package/src/events/ProviderEvent.js +35 -0
- package/src/index.js +2 -2
- package/src/providers/Constants.js +5 -0
- package/src/providers/FakeAbsolutePositionProvider.js +56 -0
- package/src/providers/Provider.js +230 -0
- package/src/providers/ProviderOptions.js +28 -0
- package/{src.old → src}/providers/ProvidersLogger.js +2 -2
- package/src/providers/attitude/AbsoluteAttitudeProvider.js +207 -0
- package/src/providers/attitude/RelativeAttitudeProvider.js +129 -0
- package/src/providers/others/ImuProvider.js +186 -0
- package/src/providers/others/InclinationProvider.js +107 -0
- package/{src.old/providers/LocationSource.js → src/providers/others/MapMatchingProvider.js} +5 -148
- package/src/providers/pose/ArCoreProvider.js +127 -0
- package/src/providers/pose/GnssWifiPdrProvider.js +233 -0
- package/src/providers/pose/PoseProvider.js +90 -0
- package/{src.old/providers/PdrLocationSource.js → src/providers/pose/pdr/PdrProvider.js} +145 -113
- package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/Smoother.js +1 -1
- package/src/providers/position/GnssWifiProvider.js +129 -0
- package/src/providers/position/IpProvider.js +75 -0
- package/webpack/webpack.common.js +1 -1
- package/webpack/webpack.dev.js +1 -1
- package/debug/index.html +0 -15
- package/debug/index.old.html +0 -37
- package/scripts/release-github.js +0 -216
- package/src/providers/FakeLocationSource.js +0 -36
- package/src.old/Constants.js +0 -11
- package/src.old/NavigationHandler.js +0 -244
- package/src.old/Pose.js +0 -8
- package/src.old/attitude/AttitudeHandler.js +0 -342
- package/src.old/components/AbsoluteAttitude.jsx +0 -136
- package/src.old/components/Imu.jsx +0 -89
- package/src.old/components/LocationSource.jsx +0 -434
- package/src.old/components/Logger.jsx +0 -113
- package/src.old/components/NavigationDebugApp.jsx +0 -106
- package/src.old/components/Others.jsx +0 -121
- package/src.old/components/RelativeAttitude.jsx +0 -104
- package/src.old/components/Utils.js +0 -35
- package/src.old/components/index.js +0 -13
- package/src.old/index.js +0 -7
- package/src.old/providers/FixedLocationImuLocationSource.js +0 -66
- package/src.old/providers/GnssLocationSource.js +0 -118
- package/src.old/providers/GnssPdrLocationSource.js +0 -182
- package/src.old/providers/IPLocationSource.js +0 -96
- package/src.old/sensors/SensorsCompatibility.js +0 -486
- package/src.old/sensors/SensorsCompatibility.spec.js +0 -270
- package/src.old/sensors/SensorsLogger.js +0 -94
- package/src.old/sensors/SensorsLoggerUtils.js +0 -35
- /package/{src.old → src/providers}/attitude/EkfAttitude.js +0 -0
- /package/{src.old → src/providers}/attitude/EkfAttitude.spec.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/HeadingUnlocker.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/HeadingUnlocker.spec.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/Smoother.spec.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/ThugDetector.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetection.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionLadetto.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionMinMaxPeaks.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionMinMaxPeaks2.js +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/* eslint max-statements: ["error", 40]*/
|
|
2
|
+
|
|
3
|
+
import { WGS84UserPosition } from '@wemap/geo';
|
|
4
|
+
|
|
5
|
+
import MapMatchingProvider from '../others/MapMatchingProvider';
|
|
6
|
+
import PdrProvider from './pdr/PdrProvider';
|
|
7
|
+
import GnssWifiProvider from '../position/GnssWifiProvider';
|
|
8
|
+
import EventType from '../../events/EventType';
|
|
9
|
+
import AbsoluteAttitudeProvider from '../attitude/AbsoluteAttitudeProvider';
|
|
10
|
+
import Constants from '../Constants';
|
|
11
|
+
import ProviderError from '../../events/ProviderError';
|
|
12
|
+
|
|
13
|
+
const GPF_ACCURACY = 25;
|
|
14
|
+
const GPF_DISTANCE = 25;
|
|
15
|
+
|
|
16
|
+
const MM_GNSS_DIST = 20;
|
|
17
|
+
const MM_GNSS_ANGLE = 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), e => this.onProviderError(e), options);
|
|
28
|
+
this.gnssWifiProvider = new GnssWifiProvider(e => this.onGnssWifiEvent(e), e => this.onProviderError(e), options);
|
|
29
|
+
this.absoluteAttitudeProvider = new AbsoluteAttitudeProvider(
|
|
30
|
+
e => this.onAbsoluteAttitudeEvent(e),
|
|
31
|
+
e => this.onProviderError(e),
|
|
32
|
+
options
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
this.gpsLastUpdate = 0;
|
|
36
|
+
this.isFirstGnssUpdate = true;
|
|
37
|
+
this.isFirstAttitudeUpdate = true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @override
|
|
43
|
+
*/
|
|
44
|
+
static get displayName() {
|
|
45
|
+
return 'GnssWifiPdr';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @override
|
|
50
|
+
*/
|
|
51
|
+
static get eventsType() {
|
|
52
|
+
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @override
|
|
57
|
+
*/
|
|
58
|
+
static get requiredProviders() {
|
|
59
|
+
return [PdrProvider, GnssWifiProvider, AbsoluteAttitudeProvider];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @override
|
|
65
|
+
*/
|
|
66
|
+
startInternal() {
|
|
67
|
+
this.pdrProvider.start();
|
|
68
|
+
this.gnssWifiProvider.start();
|
|
69
|
+
this.absoluteAttitudeProvider.start();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @override
|
|
74
|
+
*/
|
|
75
|
+
stop() {
|
|
76
|
+
this.imuProvider.stop();
|
|
77
|
+
this.gnssWifiProvider.stop();
|
|
78
|
+
this.absoluteAttitudeProvider.stop();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
onPdrEvent(pdrEvent) {
|
|
85
|
+
pdrEvent.forEach(event => {
|
|
86
|
+
if (event.dataType === EventType.AbsolutePosition) {
|
|
87
|
+
this.location = event.data;
|
|
88
|
+
} else if (event.dataType === EventType.AbsoluteAttitude) {
|
|
89
|
+
this.attitude = event.data;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
this.notify(...pdrEvent);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
onGnssWifiEvent(events) {
|
|
99
|
+
|
|
100
|
+
const gnssWifiEvent = events[0];
|
|
101
|
+
const location = gnssWifiEvent.data;
|
|
102
|
+
|
|
103
|
+
// This should be called to update True North / Magnetic North declination
|
|
104
|
+
this.absoluteAttitudeProvider.setLocation(location);
|
|
105
|
+
|
|
106
|
+
if (location.accuracy > GPF_ACCURACY) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.gnssLocation = location.clone();
|
|
111
|
+
this.gnssLocation.alt = Constants.DEFAULT_ALTITUDE;
|
|
112
|
+
|
|
113
|
+
if (!this.location || this.location
|
|
114
|
+
&& this.location.distanceTo(this.gnssLocation) > GPF_DISTANCE) {
|
|
115
|
+
|
|
116
|
+
if (!this.mapMatching || !this.attitude) {
|
|
117
|
+
this.pdrProvider.setLocation(this.gnssLocation);
|
|
118
|
+
} else {
|
|
119
|
+
|
|
120
|
+
this.gnssLocation.bearing = this.attitude.headingDegrees;
|
|
121
|
+
const projection = this.mapMatching.getProjection(this.gnssLocation);
|
|
122
|
+
|
|
123
|
+
if (projection && projection.projection) {
|
|
124
|
+
|
|
125
|
+
// Create a new location from projection and new GNSS location.
|
|
126
|
+
const projectedLocation = WGS84UserPosition.fromWGS84(projection.projection, this.gnssLocation);
|
|
127
|
+
this.pdrProvider.setLocation(projectedLocation);
|
|
128
|
+
|
|
129
|
+
// // If nearest element is an edge, use its orientation to set heading
|
|
130
|
+
// if (projection.nearestElement instanceof Edge) {
|
|
131
|
+
// const edgeBearing = projection.nearestElement.bearing;
|
|
132
|
+
// const diff1 = MathUtils.diffAngle(MathUtils.deg2rad(this.gnssLocation.bearing), edgeBearing);
|
|
133
|
+
// const diff2 = MathUtils.diffAngle(MathUtils.deg2rad(this.gnssLocation.bearing), edgeBearing + Math.PI);
|
|
134
|
+
// this.pdrProvider.setHeading(diff1 < diff2 ? edgeBearing : edgeBearing + Math.PI);
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
if (this.lastAttitude) {
|
|
138
|
+
this.pdrProvider.setHeading(this.lastAttitude.heading);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
} else {
|
|
142
|
+
this.pdrProvider.setLocation(this.gnssLocation);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
onAbsoluteAttitudeEvent(events) {
|
|
150
|
+
|
|
151
|
+
const attitude = events[0].data;
|
|
152
|
+
|
|
153
|
+
if (this.isFirstAttitudeUpdate) {
|
|
154
|
+
this.pdrProvider.setHeading(attitude.heading);
|
|
155
|
+
this.isFirstAttitudeUpdate = false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.lastAttitude = attitude;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
onProviderError(errors) {
|
|
162
|
+
this.notifyError(...ProviderError.modifyArrayDataType(errors, EventType.AbsoluteAttitude));
|
|
163
|
+
this.notifyError(...ProviderError.modifyArrayDataType(errors, EventType.AbsolutePosition));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @override
|
|
168
|
+
*/
|
|
169
|
+
static checkAvailabilityErrors() {
|
|
170
|
+
const errors = super.checkAvailabilityErrors();
|
|
171
|
+
return ProviderError.modifyArrayDataType(
|
|
172
|
+
errors,
|
|
173
|
+
EventType.AbsolutePosition
|
|
174
|
+
).concat(
|
|
175
|
+
ProviderError.modifyArrayDataType(
|
|
176
|
+
errors,
|
|
177
|
+
EventType.AbsoluteAttitude
|
|
178
|
+
)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* MapMatching
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
enableMapMatching(network = null, maxDistance = MM_GNSS_DIST, maxAngleBearing = MM_GNSS_ANGLE) {
|
|
187
|
+
this.pdrProvider.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
188
|
+
super.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
setNetwork(network) {
|
|
193
|
+
this.pdrProvider.setNetwork(network);
|
|
194
|
+
super.setNetwork(network);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Itinerary
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
setItinerary(itinerary) {
|
|
202
|
+
|
|
203
|
+
const isFirstItinerary = !this.itinerary;
|
|
204
|
+
|
|
205
|
+
super.setItinerary(itinerary);
|
|
206
|
+
|
|
207
|
+
if (isFirstItinerary && itinerary.length > 0) {
|
|
208
|
+
|
|
209
|
+
// 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).
|
|
210
|
+
|
|
211
|
+
if (!this.gnssLocation
|
|
212
|
+
|| itinerary.length < 2
|
|
213
|
+
|| !itinerary.points[0].equalsTo(this.gnssLocation)) {
|
|
214
|
+
console.warn('Itinerary has not been calculated from GnssWifiPdrProvider and these is not recommanded');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let startEdge;
|
|
218
|
+
if (itinerary.firstEdge.getLength() <= MM_GNSS_DIST) {
|
|
219
|
+
startEdge = itinerary.firstEdge;
|
|
220
|
+
} else {
|
|
221
|
+
startEdge = itinerary.secondEdge;
|
|
222
|
+
}
|
|
223
|
+
const startPoint = WGS84UserPosition.fromWGS84(startEdge.node1);
|
|
224
|
+
startPoint.alt = Constants.DEFAULT_ALTITUDE;
|
|
225
|
+
this.pdrProvider.setLocation(startPoint);
|
|
226
|
+
this.pdrProvider.setStepDetectionLockerOrientation(startEdge.getBearing());
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export default GnssWifiPdrProvider;
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
import ProviderError from '../../events/ProviderError';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Pose provider is the provider used by the PositioningHandler. It uses the best fusion
|
|
10
|
+
* of what he can and provides an AbsoluteAttitude and an AbsolutePosition as an output.
|
|
11
|
+
*/
|
|
12
|
+
class PoseProvider extends Provider {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @override
|
|
16
|
+
*/
|
|
17
|
+
constructor(onEvent, onError, options) {
|
|
18
|
+
super(onEvent, onError, options);
|
|
19
|
+
|
|
20
|
+
this.absoluteAttitudeProvider = new AbsoluteAttitudeProvider(onEvent, e => this.onAbsoluteAttitudeError(e));
|
|
21
|
+
this.gnssWifiProvider = new GnssWifiProvider((events) => {
|
|
22
|
+
this.absoluteAttitudeProvider.setLocation(events[0].data);
|
|
23
|
+
onEvent(events);
|
|
24
|
+
}, e => this.onGnssWifiError(e));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @override
|
|
29
|
+
*/
|
|
30
|
+
static get displayName() {
|
|
31
|
+
return 'Pose provider';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
static get eventsType() {
|
|
38
|
+
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Return the list of required providers
|
|
43
|
+
*/
|
|
44
|
+
static get requiredProviders() {
|
|
45
|
+
return [AbsoluteAttitudeProvider, GnssWifiProvider];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @override
|
|
50
|
+
*/
|
|
51
|
+
startInternal() {
|
|
52
|
+
this.absoluteAttitudeProvider.start();
|
|
53
|
+
this.gnssWifiProvider.start();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @override
|
|
58
|
+
*/
|
|
59
|
+
stopInternal() {
|
|
60
|
+
this.absoluteAttitudeProvider.stop();
|
|
61
|
+
this.gnssWifiProvider.stop();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
onAbsoluteAttitudeError(errors) {
|
|
65
|
+
this.notifyError(...ProviderError.modifyArrayDataType(errors, EventType.AbsoluteAttitude));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
onGnssWifiError(errors) {
|
|
69
|
+
this.notifyError(...ProviderError.modifyArrayDataType(errors, EventType.AbsolutePosition));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @override
|
|
74
|
+
*/
|
|
75
|
+
static checkAvailabilityErrors() {
|
|
76
|
+
const errorsAttitude = AbsoluteAttitudeProvider.checkAvailabilityErrors();
|
|
77
|
+
const errorsGnssWifi = GnssWifiProvider.checkAvailabilityErrors();
|
|
78
|
+
return ProviderError.modifyArrayDataType(
|
|
79
|
+
errorsGnssWifi,
|
|
80
|
+
EventType.AbsolutePosition
|
|
81
|
+
).concat(
|
|
82
|
+
ProviderError.modifyArrayDataType(
|
|
83
|
+
errorsAttitude,
|
|
84
|
+
EventType.AbsoluteAttitude
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default PoseProvider;
|
|
@@ -7,15 +7,15 @@ import {
|
|
|
7
7
|
rad2deg, Quaternion
|
|
8
8
|
} from '@wemap/maths';
|
|
9
9
|
|
|
10
|
-
import LocationSource from './LocationSource';
|
|
11
|
-
import AttitudeHandler from '../attitude/AttitudeHandler';
|
|
12
|
-
import Constants from '../Constants';
|
|
13
|
-
import SensorsLogger from '../sensors/SensorsLogger';
|
|
14
|
-
import SensorsCompatibility from '../sensors/SensorsCompatibility';
|
|
15
10
|
import StepDetection from './steps/StepDetection';
|
|
16
|
-
import HeadingUnlocker from './
|
|
17
|
-
import ThugDetector from './
|
|
18
|
-
import Smoother from './
|
|
11
|
+
import HeadingUnlocker from './helpers/HeadingUnlocker';
|
|
12
|
+
import ThugDetector from './helpers/ThugDetector';
|
|
13
|
+
import Smoother from './helpers/Smoother';
|
|
14
|
+
import RelativeAttitudeProvider from '../../attitude/RelativeAttitudeProvider';
|
|
15
|
+
import ImuProvider from '../../others/ImuProvider';
|
|
16
|
+
import EventType from '../../../events/EventType';
|
|
17
|
+
import MapMatchingProvider from '../../others/MapMatchingProvider';
|
|
18
|
+
import ProviderError from '../../../events/ProviderError';
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
const MM_PDR_ANGLE = 20;
|
|
@@ -30,138 +30,135 @@ const DEFAULT_OPTIONS = {
|
|
|
30
30
|
onThugEvent: noop
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
class
|
|
33
|
+
class PdrProvider extends MapMatchingProvider {
|
|
34
34
|
|
|
35
|
-
// pdrLocation can be different from this.
|
|
36
|
-
// pdrLocation is raw location calculated by
|
|
37
|
-
// this.
|
|
35
|
+
// pdrLocation can be different from this.location
|
|
36
|
+
// pdrLocation is raw location calculated by PdrProvider where
|
|
37
|
+
// this.location is smoothed location.
|
|
38
38
|
pdrLocation = null;
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.stepDetectionLockerEnabled = options.stepdetectionlocker !== null ? options.stepdetectionlocker : DEFAULT_OPTIONS.stepdetectionlocker;
|
|
46
|
-
this.smootherEnabled = options.smoother !== null ? options.smoother : DEFAULT_OPTIONS.smoother;
|
|
47
|
-
this.onThugEvent = options.onThugEvent !== null ? options.onThugEvent : DEFAULT_OPTIONS.onThugEvent;
|
|
40
|
+
/**
|
|
41
|
+
* @override
|
|
42
|
+
*/
|
|
43
|
+
constructor(onEvent, onError, options) {
|
|
44
|
+
super(onEvent, onError, Object.assign(DEFAULT_OPTIONS, options || {}));
|
|
48
45
|
|
|
49
46
|
// Input data providers
|
|
50
|
-
this.
|
|
51
|
-
|
|
47
|
+
this.relativeAttitudeProvider = new RelativeAttitudeProvider(
|
|
48
|
+
e => this.onRelativeAttitudeEvent(e),
|
|
49
|
+
e => this.onProviderError(e),
|
|
50
|
+
options
|
|
51
|
+
);
|
|
52
|
+
this.imuProvider = new ImuProvider(
|
|
53
|
+
e => this.onImuEvent(e),
|
|
54
|
+
e => this.onProviderError(e),
|
|
55
|
+
Object.assign(options || {}, { require: [EventType.Acceleration, EventType.AngularRate] })
|
|
56
|
+
);
|
|
52
57
|
|
|
53
58
|
// Helpers for PDR
|
|
54
59
|
this.stepDetection = new StepDetection();
|
|
55
60
|
this.stepDetectionLocker = new HeadingUnlocker();
|
|
56
61
|
this.smoother = new Smoother();
|
|
57
62
|
this.thugDetector = new ThugDetector();
|
|
63
|
+
|
|
64
|
+
if (this.options.useMapMatching) {
|
|
65
|
+
this.enableMapMatching();
|
|
66
|
+
}
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
|
|
60
70
|
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
super.start();
|
|
66
|
-
|
|
67
|
-
return Promise.all([
|
|
68
|
-
this.sensorsCompatibility.startImu(this.onNewMotion, {
|
|
69
|
-
accelerometer: true,
|
|
70
|
-
gyroscope: true
|
|
71
|
-
}),
|
|
72
|
-
this.attitudeHandler.startRelative(this.onNewAttitude, AttitudeHandler.RelativeMethod.INTERNAL_EKF)
|
|
73
|
-
]);
|
|
71
|
+
* @override
|
|
72
|
+
*/
|
|
73
|
+
static get displayName() {
|
|
74
|
+
return 'PDR';
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
/**
|
|
77
|
-
* Stop the location source algorithm
|
|
78
78
|
* @override
|
|
79
79
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
this.attitudeHandler.stopRelative();
|
|
84
|
-
this.sensorsCompatibility.stopImu();
|
|
80
|
+
static get eventsType() {
|
|
81
|
+
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
85
82
|
}
|
|
86
83
|
|
|
87
84
|
/**
|
|
88
|
-
* Get provider name
|
|
89
85
|
* @override
|
|
90
86
|
*/
|
|
91
|
-
get
|
|
92
|
-
|
|
93
|
-
name += ' (locker: ';
|
|
94
|
-
name += this.stepDetectionLockerEnabled ? 'Y' : 'N';
|
|
95
|
-
name += ', ';
|
|
96
|
-
name += 'smoo: ';
|
|
97
|
-
name += this.smootherEnabled ? 'Y' : 'N';
|
|
98
|
-
name += ', ';
|
|
99
|
-
name += 'mm: ';
|
|
100
|
-
name += this.mapMatching ? 'Y' : 'N';
|
|
101
|
-
name += ')';
|
|
102
|
-
return name;
|
|
87
|
+
static get requiredProviders() {
|
|
88
|
+
return [ImuProvider, RelativeAttitudeProvider];
|
|
103
89
|
}
|
|
104
90
|
|
|
91
|
+
|
|
105
92
|
/**
|
|
106
|
-
* Get provider name
|
|
107
93
|
* @override
|
|
108
94
|
*/
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
startInternal() {
|
|
96
|
+
this.imuProvider.start();
|
|
97
|
+
this.relativeAttitudeProvider.start();
|
|
111
98
|
}
|
|
112
99
|
|
|
113
100
|
/**
|
|
114
101
|
* @override
|
|
115
102
|
*/
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
super.notify();
|
|
103
|
+
stopInternal() {
|
|
104
|
+
this.imuProvider.stop();
|
|
105
|
+
this.relativeAttitudeProvider.stop();
|
|
121
106
|
}
|
|
122
107
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Get provider name
|
|
110
|
+
* @override
|
|
111
|
+
*/
|
|
112
|
+
get nameWithOptions() {
|
|
113
|
+
let name = this.name;
|
|
114
|
+
name += ' (locker: ';
|
|
115
|
+
name += this.options.stepdetectionlocker ? 'Y' : 'N';
|
|
116
|
+
name += ', ';
|
|
117
|
+
name += 'smoo: ';
|
|
118
|
+
name += this.options.smoother ? 'Y' : 'N';
|
|
119
|
+
name += ', ';
|
|
120
|
+
name += 'mm: ';
|
|
121
|
+
name += this.options.useMapMatching ? 'Y' : 'N';
|
|
122
|
+
name += ')';
|
|
123
|
+
return name;
|
|
127
124
|
}
|
|
128
125
|
|
|
129
126
|
setHeading(heading) {
|
|
130
|
-
this.
|
|
131
|
-
if (this.logger) {
|
|
132
|
-
this.logger.feedWithCurrentTime(SensorsLogger.DataType.USER_INPUT_HEADING, heading);
|
|
133
|
-
}
|
|
127
|
+
this.relativeAttitudeProvider.setOffset(heading);
|
|
134
128
|
}
|
|
135
129
|
|
|
136
130
|
setLocation(location) {
|
|
137
131
|
this.pdrLocation = location;
|
|
138
132
|
|
|
139
|
-
if (this.
|
|
133
|
+
if (this.options.smoother) {
|
|
140
134
|
this.smoother.generateNextLocations(location, true);
|
|
141
135
|
// this.smoother.pullLocation(location.time) should never return null
|
|
142
|
-
this.
|
|
136
|
+
this.location = this.smoother.pullLocation(location.time);
|
|
143
137
|
} else {
|
|
144
|
-
this.
|
|
138
|
+
this.location = location.clone();
|
|
145
139
|
}
|
|
146
140
|
|
|
147
|
-
this.notify();
|
|
148
|
-
|
|
149
|
-
if (this.logger) {
|
|
150
|
-
const data = [location.lat, location.lng];
|
|
151
|
-
if (location.altitude) {
|
|
152
|
-
data.push(location.altitude);
|
|
153
|
-
}
|
|
154
|
-
this.logger.feedWithCurrentTime(SensorsLogger.DataType.USER_INPUT_POSITION, data);
|
|
155
|
-
}
|
|
141
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, this.location));
|
|
156
142
|
}
|
|
157
143
|
|
|
158
|
-
|
|
159
|
-
|
|
144
|
+
/**
|
|
145
|
+
* @override
|
|
146
|
+
*/
|
|
147
|
+
onRelativeAttitudeEvent = events => {
|
|
148
|
+
const attitudeEvent = events[0];
|
|
149
|
+
this.attitude = attitudeEvent.data;
|
|
150
|
+
|
|
151
|
+
const newEvent = attitudeEvent.clone();
|
|
152
|
+
newEvent.dataType = EventType.AbsoluteAttitude;
|
|
153
|
+
this.notify(newEvent);
|
|
160
154
|
}
|
|
161
155
|
|
|
162
|
-
|
|
156
|
+
/**
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
onImuEvent = imuEvent => {
|
|
163
160
|
|
|
164
|
-
if (!this.
|
|
161
|
+
if (!this.attitude) {
|
|
165
162
|
// We should wait attitude for stepDetectionLocker and linear acceleration
|
|
166
163
|
return;
|
|
167
164
|
}
|
|
@@ -171,18 +168,25 @@ class PdrLocationSource extends LocationSource {
|
|
|
171
168
|
return;
|
|
172
169
|
}
|
|
173
170
|
|
|
174
|
-
if (this.
|
|
171
|
+
if (this.options.stepdetectionlocker
|
|
175
172
|
&& this.stepDetectionLocker.locked
|
|
176
|
-
&& this.stepDetectionLocker.feedHeading(this.
|
|
173
|
+
&& this.stepDetectionLocker.feedHeading(this.attitude.heading)) {
|
|
177
174
|
// Step detection is locked by stepDetectionLocker
|
|
178
|
-
// We still need to notify for attitude
|
|
179
|
-
this.notify();
|
|
180
175
|
return;
|
|
181
176
|
}
|
|
182
177
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
178
|
+
|
|
179
|
+
let timestamp, acceleration, angularRate;
|
|
180
|
+
imuEvent.forEach(event => {
|
|
181
|
+
if (event.dataType === EventType.Acceleration) {
|
|
182
|
+
acceleration = event.data;
|
|
183
|
+
timestamp = event.timestamp;
|
|
184
|
+
} else if (event.dataType === EventType.AngularRate) {
|
|
185
|
+
angularRate = event.data;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const heading = this.attitude.heading;
|
|
186
190
|
|
|
187
191
|
if (this.onThugEvent && this.thugDetector.compute(timestamp, acceleration)) {
|
|
188
192
|
this.onThugEvent();
|
|
@@ -191,35 +195,63 @@ class PdrLocationSource extends LocationSource {
|
|
|
191
195
|
/**
|
|
192
196
|
* Step Detection and Step Size Detection
|
|
193
197
|
*/
|
|
194
|
-
const linearAcc =
|
|
195
|
-
this.
|
|
196
|
-
const stepDetected = this.stepDetection.compute(timestamp, linearAcc,
|
|
198
|
+
const linearAcc = PdrProvider.computeLinearAcceleration(
|
|
199
|
+
this.attitude.quaternion, acceleration);
|
|
200
|
+
const stepDetected = this.stepDetection.compute(timestamp, linearAcc, angularRate);
|
|
197
201
|
|
|
198
202
|
if (stepDetected) {
|
|
199
203
|
|
|
200
204
|
this.pdrLocation = this.calculateNewLocation(this.pdrLocation, timestamp,
|
|
201
205
|
heading, this.stepDetection.lastStepSize);
|
|
202
206
|
|
|
203
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Update current_position
|
|
209
|
+
*/
|
|
210
|
+
if (this.options.smoother) {
|
|
204
211
|
this.smoother.generateNextLocations(this.pdrLocation);
|
|
212
|
+
const newLocation = this.smoother.pullLocation(timestamp);
|
|
213
|
+
// At this time, newLocation can be null if a new step has been detected
|
|
214
|
+
// and smoother has not been completely consumed.
|
|
215
|
+
if (newLocation) {
|
|
216
|
+
this.location = newLocation;
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
this.location = this.pdrLocation;
|
|
205
220
|
}
|
|
206
221
|
|
|
207
|
-
|
|
208
|
-
* Update current_position
|
|
209
|
-
*/
|
|
210
|
-
this.pose.location = this.smootherEnabled
|
|
211
|
-
? this.smoother.pullLocation(timestamp)
|
|
212
|
-
: this.pdrLocation;
|
|
213
|
-
|
|
214
|
-
} else if (this.smootherEnabled) {
|
|
222
|
+
} else if (this.options.smoother) {
|
|
215
223
|
// If no step is detected, we pull last known location from smoother until now (timestamp).
|
|
216
224
|
const smoothedLocation = this.smoother.pullLocation(timestamp);
|
|
217
|
-
if (smoothedLocation) {
|
|
218
|
-
|
|
225
|
+
if (!smoothedLocation) {
|
|
226
|
+
return;
|
|
219
227
|
}
|
|
228
|
+
this.location = smoothedLocation;
|
|
229
|
+
} else {
|
|
230
|
+
return;
|
|
220
231
|
}
|
|
221
232
|
|
|
222
|
-
this.notify();
|
|
233
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, this.location));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
onProviderError(errors) {
|
|
237
|
+
this.notifyError(...ProviderError.modifyArrayDataType(errors, EventType.AbsoluteAttitude));
|
|
238
|
+
this.notifyError(...ProviderError.modifyArrayDataType(errors, EventType.AbsolutePosition));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @override
|
|
243
|
+
*/
|
|
244
|
+
static checkAvailabilityErrors() {
|
|
245
|
+
const errors = super.checkAvailabilityErrors();
|
|
246
|
+
return ProviderError.modifyArrayDataType(
|
|
247
|
+
errors,
|
|
248
|
+
EventType.AbsolutePosition
|
|
249
|
+
).concat(
|
|
250
|
+
ProviderError.modifyArrayDataType(
|
|
251
|
+
errors,
|
|
252
|
+
EventType.AbsoluteAttitude
|
|
253
|
+
)
|
|
254
|
+
);
|
|
223
255
|
}
|
|
224
256
|
|
|
225
257
|
calculateNewLocation(previousLocation, timestamp, heading, stepSize) {
|
|
@@ -262,8 +294,8 @@ class PdrLocationSource extends LocationSource {
|
|
|
262
294
|
* MapMatching
|
|
263
295
|
*/
|
|
264
296
|
|
|
265
|
-
enableMapMatching(network
|
|
266
|
-
super.enableMapMatching(network, maxDistance, maxAngleBearing);
|
|
297
|
+
enableMapMatching(network, maxDistance, maxAngleBearing) {
|
|
298
|
+
super.enableMapMatching(network, maxDistance || MM_PDR_DIST, maxAngleBearing || MM_PDR_ANGLE);
|
|
267
299
|
}
|
|
268
300
|
|
|
269
301
|
|
|
@@ -274,9 +306,9 @@ class PdrLocationSource extends LocationSource {
|
|
|
274
306
|
setItinerary(itinerary) {
|
|
275
307
|
super.setItinerary(itinerary);
|
|
276
308
|
|
|
277
|
-
if (this.
|
|
309
|
+
if (this.options.stepdetectionlocker) {
|
|
278
310
|
this.stepDetectionLocker.setWaitingOrientation(
|
|
279
|
-
|
|
311
|
+
PdrProvider.retrieveWaitingOrientationFromItinerary(itinerary)
|
|
280
312
|
);
|
|
281
313
|
}
|
|
282
314
|
}
|
|
@@ -317,4 +349,4 @@ class PdrLocationSource extends LocationSource {
|
|
|
317
349
|
}
|
|
318
350
|
}
|
|
319
351
|
|
|
320
|
-
export default
|
|
352
|
+
export default PdrProvider;
|