@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,87 @@
|
|
|
1
|
+
import Provider from '../Provider';
|
|
2
|
+
import EventType from '../../events/EventType';
|
|
3
|
+
import { Accelerometer } from '../../Providers';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Inclination provider gives the inclination of the device using Imu Sensor
|
|
7
|
+
* For example, when the top of the device is pointing the sky, inclination = Math.PI/2
|
|
8
|
+
* when the device is layed on a table, inclination = 0
|
|
9
|
+
* This provider use window.orientation to return a result in function of screen orientation
|
|
10
|
+
*/
|
|
11
|
+
class InclinationFromAccProvider extends Provider {
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @override
|
|
16
|
+
*/
|
|
17
|
+
static get displayName() {
|
|
18
|
+
return 'Inclination from acceleration';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @override
|
|
23
|
+
*/
|
|
24
|
+
static get eventsType() {
|
|
25
|
+
return [EventType.Inclination];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @override
|
|
30
|
+
*/
|
|
31
|
+
get _availability() {
|
|
32
|
+
return Accelerometer.availability;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @override
|
|
37
|
+
*/
|
|
38
|
+
start() {
|
|
39
|
+
this.providerId = Accelerometer.addEventListener(
|
|
40
|
+
events => this.onAccelerometerEvent(events[0]),
|
|
41
|
+
this.notifyError,
|
|
42
|
+
this.name);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @override
|
|
47
|
+
*/
|
|
48
|
+
stop() {
|
|
49
|
+
Accelerometer.removeEventListener(this.providerId);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
onAccelerometerEvent = accelerometerEvent => {
|
|
56
|
+
const acc = accelerometerEvent.data;
|
|
57
|
+
|
|
58
|
+
const screenOrientation = window.orientation || 0;
|
|
59
|
+
|
|
60
|
+
const sizeAcc = Math.sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
|
|
61
|
+
const accNormalized = [acc[0] / sizeAcc, acc[1] / sizeAcc, acc[2] / sizeAcc];
|
|
62
|
+
|
|
63
|
+
const q = [accNormalized[2] + 1, accNormalized[1], -accNormalized[0], 0];
|
|
64
|
+
const qSize = Math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
|
|
65
|
+
const qNormalized = [q[0] / qSize, q[1] / qSize, q[2] / qSize, 0];
|
|
66
|
+
|
|
67
|
+
let inclination;
|
|
68
|
+
if (screenOrientation === 0) {
|
|
69
|
+
inclination = Math.asin(2 * qNormalized[1] * qNormalized[0]);
|
|
70
|
+
} else if (screenOrientation === 90) {
|
|
71
|
+
inclination = -Math.asin(2 * qNormalized[2] * qNormalized[0]);
|
|
72
|
+
} else if (screenOrientation === -90) {
|
|
73
|
+
inclination = Math.asin(2 * qNormalized[2] * qNormalized[0]);
|
|
74
|
+
} else if (screenOrientation === 180) {
|
|
75
|
+
inclination = -Math.asin(2 * qNormalized[1] * qNormalized[0]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.notify(this.createEvent(
|
|
79
|
+
EventType.Inclination,
|
|
80
|
+
inclination,
|
|
81
|
+
accelerometerEvent.timestamp,
|
|
82
|
+
[accelerometerEvent]
|
|
83
|
+
));
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default InclinationFromAccProvider;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import Provider from '../Provider';
|
|
2
|
+
import EventType from '../../events/EventType';
|
|
3
|
+
import { Attitude } from '../../Providers';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Inclination provider gives the inclination of the device using Relative Attitude
|
|
7
|
+
* For example, when the top of the device is pointing the sky, inclination = Math.PI/2
|
|
8
|
+
* when the device is layed on a table, inclination = 0
|
|
9
|
+
* This provider use window.orientation to return a result in function of screen orientation
|
|
10
|
+
*/
|
|
11
|
+
class InclinationFromAttitudeProvider extends Provider {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @override
|
|
15
|
+
*/
|
|
16
|
+
static get displayName() {
|
|
17
|
+
return 'Inclination from attitude';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @override
|
|
22
|
+
*/
|
|
23
|
+
static get eventsType() {
|
|
24
|
+
return [EventType.Inclination];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @override
|
|
29
|
+
*/
|
|
30
|
+
get _availability() {
|
|
31
|
+
return Attitude.availability;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
start() {
|
|
38
|
+
this.providerId = Attitude.addEventListener(
|
|
39
|
+
events => {
|
|
40
|
+
const attitudeEvent = events[0];
|
|
41
|
+
const inclination = this.constructor.enuQuatToInclination(
|
|
42
|
+
attitudeEvent.data.quaternion
|
|
43
|
+
);
|
|
44
|
+
this.notify(this.createEvent(
|
|
45
|
+
EventType.Inclination,
|
|
46
|
+
inclination,
|
|
47
|
+
attitudeEvent.timestamp,
|
|
48
|
+
[attitudeEvent]
|
|
49
|
+
));
|
|
50
|
+
},
|
|
51
|
+
this.notifyError,
|
|
52
|
+
this.name);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @override
|
|
57
|
+
*/
|
|
58
|
+
stop() {
|
|
59
|
+
Attitude.removeEventListener(this.providerId);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static enuQuatToInclination(q) {
|
|
63
|
+
const screenOrientation = window.orientation || 0;
|
|
64
|
+
|
|
65
|
+
if (screenOrientation === 0) {
|
|
66
|
+
return Math.asin(2 * (q[2] * q[3] + q[1] * q[0]));
|
|
67
|
+
} else if (screenOrientation === 90) {
|
|
68
|
+
return Math.asin(2 * (q[1] * q[3] - q[2] * q[0]));
|
|
69
|
+
} else if (screenOrientation === -90) {
|
|
70
|
+
return Math.asin(2 * (q[2] * q[0] - q[1] * q[3]));
|
|
71
|
+
}
|
|
72
|
+
// else if (screenOrientation === 180)
|
|
73
|
+
return -Math.asin(2 * (q[2] * q[3] + q[1] * q[0]));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default InclinationFromAttitudeProvider;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import MetaProvider from '../MetaProvider';
|
|
2
|
+
import EventType from '../../events/EventType';
|
|
3
|
+
import Availability from '../../events/Availability';
|
|
4
|
+
import {
|
|
5
|
+
InclinationFromAttitude, InclinationFromAcc
|
|
6
|
+
} from '../../Providers';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Inclination provider gives the inclination of the device using Imu Sensor
|
|
10
|
+
* For example, when the top of the device is pointing the sky, inclination = Math.PI/2
|
|
11
|
+
* when the device is layed on a table, inclination = 0
|
|
12
|
+
* This provider use window.orientation to return a result in function of screen orientation
|
|
13
|
+
*/
|
|
14
|
+
class InclinationProvider extends MetaProvider {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @override
|
|
18
|
+
*/
|
|
19
|
+
static get eventsType() {
|
|
20
|
+
return [EventType.Inclination];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @override
|
|
25
|
+
*/
|
|
26
|
+
get _availability() {
|
|
27
|
+
return Availability.union(
|
|
28
|
+
InclinationFromAcc.availability,
|
|
29
|
+
InclinationFromAttitude.availability
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @override
|
|
35
|
+
*/
|
|
36
|
+
start() {
|
|
37
|
+
|
|
38
|
+
const startInclinationFromAcc = () => {
|
|
39
|
+
this.provider = InclinationFromAcc;
|
|
40
|
+
this.providerId = this.provider.addEventListener(
|
|
41
|
+
events => this.notify(events[0].clone()),
|
|
42
|
+
this.notifyError,
|
|
43
|
+
this.name
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (InclinationFromAttitude.availability) {
|
|
48
|
+
this.provider = InclinationFromAttitude;
|
|
49
|
+
this.providerId = this.provider.addEventListener(
|
|
50
|
+
events => this.notify(events[0].clone()),
|
|
51
|
+
() => {
|
|
52
|
+
InclinationFromAttitude.removeEventListener(this.providerId);
|
|
53
|
+
startInclinationFromAcc();
|
|
54
|
+
},
|
|
55
|
+
this.name);
|
|
56
|
+
} else {
|
|
57
|
+
startInclinationFromAcc();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @override
|
|
63
|
+
*/
|
|
64
|
+
stop() {
|
|
65
|
+
this.provider.removeEventListener(this.providerId);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default InclinationProvider;
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
import isNumber from 'lodash.isnumber';
|
|
3
|
+
|
|
4
|
+
import { UserPosition } from '@wemap/geo';
|
|
5
|
+
import {
|
|
6
|
+
Itinerary, MapMatching
|
|
7
|
+
} from '@wemap/graph';
|
|
8
|
+
import {
|
|
9
|
+
deg2rad, Vector3
|
|
10
|
+
} from '@wemap/maths';
|
|
11
|
+
|
|
12
|
+
import Provider from '../Provider';
|
|
13
|
+
import StepDetectionProvider from '../steps/StepDetectionProvider';
|
|
14
|
+
import HeadingUnlocker from './helpers/HeadingUnlocker';
|
|
15
|
+
import Availability from '../../events/Availability';
|
|
16
|
+
import EventType from '../../events/EventType';
|
|
17
|
+
import AbsoluteAttitudeProvider from '../attitude/absolute/AbsoluteAttitudeProvider';
|
|
18
|
+
import PdrProvider from '../position/relative/PdrProvider';
|
|
19
|
+
import ProviderEvent from '../../events/ProviderEvent';
|
|
20
|
+
|
|
21
|
+
class AbsolutePdrProvider extends Provider {
|
|
22
|
+
|
|
23
|
+
position = null;
|
|
24
|
+
|
|
25
|
+
static MM_PDR_ANGLE = deg2rad(20);
|
|
26
|
+
static MM_PDR_DIST = 15;
|
|
27
|
+
static MM_CONV_SPEED = 0.7;
|
|
28
|
+
|
|
29
|
+
static LO_SEGMENT_SIZE = 1.5;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @override
|
|
33
|
+
*/
|
|
34
|
+
constructor() {
|
|
35
|
+
super();
|
|
36
|
+
|
|
37
|
+
this.relativePosition = [0, 0, 0];
|
|
38
|
+
|
|
39
|
+
this.mapMatching = new MapMatching();
|
|
40
|
+
this.mapMatching.maxAngleBearing = this.constructor.MM_PDR_ANGLE;
|
|
41
|
+
this.mapMatching.maxDistance = this.constructor.MM_PDR_DIST;
|
|
42
|
+
|
|
43
|
+
this.stepDetectionLocker = new HeadingUnlocker();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @override
|
|
48
|
+
*/
|
|
49
|
+
static get displayName() {
|
|
50
|
+
return 'Absolute PDR';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @override
|
|
55
|
+
*/
|
|
56
|
+
static get eventsType() {
|
|
57
|
+
return [EventType.AbsoluteAttitude, EventType.AbsolutePosition];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @override
|
|
62
|
+
*/
|
|
63
|
+
static get _availability() {
|
|
64
|
+
return Availability.merge(
|
|
65
|
+
StepDetectionProvider.availability,
|
|
66
|
+
AbsoluteAttitudeProvider.availability
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @override
|
|
73
|
+
*/
|
|
74
|
+
_start() {
|
|
75
|
+
|
|
76
|
+
this.pdrProviderId = this.scheduler.use(PdrProvider,
|
|
77
|
+
events => this.onPdrEvent(events),
|
|
78
|
+
error => this.notifyError(error),
|
|
79
|
+
this.name);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Position
|
|
83
|
+
*/
|
|
84
|
+
const lastPosition = this.dataStore.getLast(EventType.AbsolutePosition);
|
|
85
|
+
if (lastPosition) {
|
|
86
|
+
this.onPositionChanged(lastPosition);
|
|
87
|
+
}
|
|
88
|
+
this.dataStore.addEventListener(EventType.AbsolutePosition, this.onPositionChanged);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Network
|
|
92
|
+
*/
|
|
93
|
+
this.mapMatching.network = this.dataStore.getLast(EventType.Network);
|
|
94
|
+
this.dataStore.addEventListener(EventType.Network, this.onNetworkChanged);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Itinerary
|
|
98
|
+
*/
|
|
99
|
+
const lastItinerary = this.dataStore.getLast(EventType.Itinerary);
|
|
100
|
+
if (lastItinerary) {
|
|
101
|
+
this.onItineraryChanged(lastItinerary);
|
|
102
|
+
}
|
|
103
|
+
this.dataStore.addEventListener(EventType.Itinerary, this.onItineraryChanged);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @override
|
|
108
|
+
*/
|
|
109
|
+
_stop() {
|
|
110
|
+
this.dataStore.removeEventListener(EventType.AbsolutePosition, this.onPositionChanged);
|
|
111
|
+
this.dataStore.removeEventListener(EventType.Network, this.onNetworkChanged);
|
|
112
|
+
this.dataStore.removeEventListener(EventType.Itinerary, this.onItineraryChanged);
|
|
113
|
+
this.scheduler.release(this.pdrProviderId, this.name);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
onPositionChanged = position => {
|
|
117
|
+
this.position = position.clone();
|
|
118
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, this.position));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
onNetworkChanged = network => {
|
|
122
|
+
this.mapMatching.network = network;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @override
|
|
127
|
+
*/
|
|
128
|
+
onPdrEvent = events => {
|
|
129
|
+
|
|
130
|
+
events.forEach(event => {
|
|
131
|
+
if (event.dataType === EventType.AbsoluteAttitude) {
|
|
132
|
+
this.attitude = event.data;
|
|
133
|
+
this.notify(event);
|
|
134
|
+
} else {
|
|
135
|
+
this.parseRelativePositionEvent(event);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
parseRelativePositionEvent(event) {
|
|
141
|
+
|
|
142
|
+
if (this.position && this.attitude
|
|
143
|
+
&& (!this.options.stepdetectionlocker
|
|
144
|
+
|| !this.stepDetectionLocker.locked
|
|
145
|
+
|| !this.stepDetectionLocker.feedHeading(this.attitude.heading))) {
|
|
146
|
+
|
|
147
|
+
this.position = this.calculateNewPosition(this.position, event);
|
|
148
|
+
|
|
149
|
+
this.notify(this.createEvent(EventType.AbsolutePosition, this.position, event.timestamp));
|
|
150
|
+
|
|
151
|
+
} else {
|
|
152
|
+
// this.pdrPosition has not been initialized
|
|
153
|
+
// or
|
|
154
|
+
// Step detection is locked by stepDetectionLocker
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.relativePosition = event.data.slice(0);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Calculate AbsolutePosition from RelativePosition event
|
|
162
|
+
* @param {UserPosition} previousPosition
|
|
163
|
+
* @param {ProviderEvent} event
|
|
164
|
+
*/
|
|
165
|
+
calculateNewPosition(previousPosition, event) {
|
|
166
|
+
|
|
167
|
+
const offsetPosition = Vector3.subtract(event.data, this.relativePosition);
|
|
168
|
+
|
|
169
|
+
const dist = Math.sqrt(offsetPosition[0] ** 2 + offsetPosition[2] ** 2);
|
|
170
|
+
const bearing = Math.atan2(offsetPosition[0], -offsetPosition[2]);
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* First, compute new position without map-matching
|
|
174
|
+
*/
|
|
175
|
+
const newPositionWithoutMM = previousPosition.clone();
|
|
176
|
+
newPositionWithoutMM.move(dist, bearing, offsetPosition[1]);
|
|
177
|
+
newPositionWithoutMM.bearing = bearing;
|
|
178
|
+
newPositionWithoutMM.time = event.timestamp;
|
|
179
|
+
if (isNumber(newPositionWithoutMM.accuracy) && isNumber(this.attitude.accuracy)) {
|
|
180
|
+
// A bad accuracy from PDR is due to three things:
|
|
181
|
+
// - Attitude accuracy
|
|
182
|
+
// - Misalignement (device heading != walking direction)
|
|
183
|
+
// - Step detection false positives / false negatives
|
|
184
|
+
// Following formula only use attitude accuracy with cone formula
|
|
185
|
+
newPositionWithoutMM.accuracy += (dist / 2) * Math.sin(this.attitude.accuracy / 2);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!this.options.useMapMatching || !this.mapMatching.network) {
|
|
189
|
+
/**
|
|
190
|
+
* If mapMatching is not used or not set, raw position is returned
|
|
191
|
+
*/
|
|
192
|
+
return newPositionWithoutMM;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Secondly, find map-matching projection
|
|
197
|
+
*/
|
|
198
|
+
const projection = this.mapMatching.getProjection(newPositionWithoutMM, true, true);
|
|
199
|
+
if (!projection || !projection.projection) {
|
|
200
|
+
/**
|
|
201
|
+
* If no projection has been found, returns the position without map-matching
|
|
202
|
+
*/
|
|
203
|
+
return newPositionWithoutMM;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const projectedPosition = newPositionWithoutMM;
|
|
207
|
+
projectedPosition.level = projection.projection.level;
|
|
208
|
+
|
|
209
|
+
if (projection.distanceFromNearestElement < dist) {
|
|
210
|
+
/**
|
|
211
|
+
* If projection is not so far from network, projected position is returned
|
|
212
|
+
*/
|
|
213
|
+
projectedPosition.lat = projection.projection.lat;
|
|
214
|
+
projectedPosition.lng = projection.projection.lng;
|
|
215
|
+
return projectedPosition;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* If projected position is far from network, we do not project calculated position directly.
|
|
220
|
+
* This allows to adapt map-matching to not stick corridor directly.
|
|
221
|
+
* /!\ This smoothed position is different from the one of Smoother
|
|
222
|
+
*/
|
|
223
|
+
const smoothedPosition = projectedPosition;
|
|
224
|
+
smoothedPosition.lat = previousPosition.lat;
|
|
225
|
+
smoothedPosition.lng = previousPosition.lng;
|
|
226
|
+
|
|
227
|
+
const smoothedDistance = projection.distanceFromNearestElement * this.constructor.MM_CONV_SPEED;
|
|
228
|
+
const smoothedBearing = previousPosition.bearingTo(projection.projection);
|
|
229
|
+
smoothedPosition.move(smoothedDistance, smoothedBearing);
|
|
230
|
+
|
|
231
|
+
return smoothedPosition;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Itinerary and PDR Locker
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @param {Itinerary} itinerary
|
|
241
|
+
*/
|
|
242
|
+
onItineraryChanged = itinerary => {
|
|
243
|
+
|
|
244
|
+
if (!itinerary || itinerary.edges.length === 0) {
|
|
245
|
+
this.stepDetectionLocker.unlock();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const edgeAt = itinerary.getEdgeAt(this.constructor.LO_SEGMENT_SIZE);
|
|
249
|
+
if (edgeAt) {
|
|
250
|
+
this.stepDetectionLocker.lock(edgeAt.bearing);
|
|
251
|
+
} else {
|
|
252
|
+
this.stepDetectionLocker.lock(itinerary.edges[0].bearing);
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export default AbsolutePdrProvider;
|