@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,172 @@
|
|
|
1
|
+
import noop from 'lodash.noop';
|
|
2
|
+
|
|
3
|
+
import { UserPosition } from '@wemap/geo';
|
|
4
|
+
import {
|
|
5
|
+
MapMatching, Network
|
|
6
|
+
} from '@wemap/graph';
|
|
7
|
+
import { deg2rad } from '@wemap/maths';
|
|
8
|
+
|
|
9
|
+
import MetaProvider from '../../MetaProvider';
|
|
10
|
+
import EventType from '../../../events/EventType';
|
|
11
|
+
import ProviderEvent from '../../../events/ProviderEvent';
|
|
12
|
+
import Availability from '../../../events/Availability';
|
|
13
|
+
import {
|
|
14
|
+
AbsolutePositionFromRel, GnssWifi
|
|
15
|
+
} from '../../../Providers';
|
|
16
|
+
import ProvidersOptions from '../../../ProvidersOptions';
|
|
17
|
+
|
|
18
|
+
class AbsolutePositionProvider extends MetaProvider {
|
|
19
|
+
|
|
20
|
+
static ACCURACY_RELOC_RATIO = 2;
|
|
21
|
+
static MM_MAX_ANGLE = deg2rad(20);
|
|
22
|
+
static MM_MAX_DIST = 15;
|
|
23
|
+
static MM_MIN_DIST = 1;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
this.mapMatching = new MapMatching();
|
|
29
|
+
this.mapMatching.maxDistance = AbsolutePositionProvider.MM_MAX_DIST;
|
|
30
|
+
this.mapMatching.maxAngleBearing = AbsolutePositionProvider.MM_MAX_ANGLE;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @override
|
|
35
|
+
*/
|
|
36
|
+
static get displayName() {
|
|
37
|
+
return 'Absolute position from Relative position';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @override
|
|
42
|
+
*/
|
|
43
|
+
static get eventsType() {
|
|
44
|
+
return [EventType.AbsolutePosition];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @override
|
|
49
|
+
*/
|
|
50
|
+
get _availability() {
|
|
51
|
+
return Availability.union(
|
|
52
|
+
AbsolutePositionFromRel.availability,
|
|
53
|
+
GnssWifi.availability
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @override
|
|
60
|
+
*/
|
|
61
|
+
start() {
|
|
62
|
+
if (AbsolutePositionFromRel.availability.isSupported) {
|
|
63
|
+
this.fromRelPosProviderId = AbsolutePositionFromRel.addEventListener(
|
|
64
|
+
events => this.onAbsolutePositionFromRel(events[0]),
|
|
65
|
+
noop,
|
|
66
|
+
this.name
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.gnssWifiProviderId = GnssWifi.addEventListener(
|
|
71
|
+
events => this.onAbsolutePosition(events[0]),
|
|
72
|
+
noop,
|
|
73
|
+
this.name
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @override
|
|
81
|
+
*/
|
|
82
|
+
stop() {
|
|
83
|
+
if (this.fromRelPosProviderId) {
|
|
84
|
+
AbsolutePositionFromRel.removeEventListener(this.fromRelPosProviderId);
|
|
85
|
+
}
|
|
86
|
+
GnssWifi.removeEventListener(this.gnssWifiProviderId);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
onAbsolutePosition(newPositionEvent) {
|
|
90
|
+
if (this.lastEvent) {
|
|
91
|
+
|
|
92
|
+
const newPosition = newPositionEvent.data;
|
|
93
|
+
const lastPosition = this.lastEvent.data;
|
|
94
|
+
|
|
95
|
+
if (newPosition.distanceTo(lastPosition) < newPosition.accuracy
|
|
96
|
+
&& newPosition.accuracy > lastPosition.accuracy / AbsolutePositionProvider.ACCURACY_RELOC_RATIO) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.notify(newPositionEvent.clone());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {ProviderEvent} newPositionEvent
|
|
106
|
+
*/
|
|
107
|
+
onAbsolutePositionFromRel(newPositionEvent) {
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* If map matching is not used or not set, raw position is returned
|
|
111
|
+
*/
|
|
112
|
+
if (!ProvidersOptions.useMapMatching
|
|
113
|
+
|| !this.mapMatching.network) {
|
|
114
|
+
this.notify(newPositionEvent.clone());
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const newPosition = newPositionEvent.data;
|
|
119
|
+
const projection = this.mapMatching.getProjection(newPosition, true, true);
|
|
120
|
+
if (!projection || !projection.projection) {
|
|
121
|
+
// If no projection has been found, returns the position without map-matching
|
|
122
|
+
this.notify(newPositionEvent.clone());
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const projectedPosition = newPosition.clone();
|
|
127
|
+
|
|
128
|
+
// Anyway, the projected level is used for new position
|
|
129
|
+
projectedPosition.level = projection.projection.level;
|
|
130
|
+
|
|
131
|
+
// Do not use projection if it too close from itinerary,
|
|
132
|
+
// this allows left/right movements (ie with ArCore)
|
|
133
|
+
if (projection.distanceFromNearestElement > AbsolutePositionProvider.MM_MIN_DIST) {
|
|
134
|
+
projectedPosition.lat = projection.projection.lat;
|
|
135
|
+
projectedPosition.lng = projection.projection.lng;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.notify(this.createEvent(
|
|
139
|
+
EventType.AbsolutePosition,
|
|
140
|
+
projectedPosition,
|
|
141
|
+
newPositionEvent
|
|
142
|
+
));
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @override
|
|
148
|
+
* @param {UserPosition} position
|
|
149
|
+
*/
|
|
150
|
+
feed(data) {
|
|
151
|
+
if (data instanceof UserPosition) {
|
|
152
|
+
const position = data;
|
|
153
|
+
if (position.time === null) {
|
|
154
|
+
throw Error('the time of the position is not defined');
|
|
155
|
+
}
|
|
156
|
+
if (position.accuracy === null) {
|
|
157
|
+
throw Error('the accuracy of the position is not defined');
|
|
158
|
+
}
|
|
159
|
+
this.onAbsolutePosition(this.createEvent(
|
|
160
|
+
EventType.AbsolutePosition, position, position.time
|
|
161
|
+
));
|
|
162
|
+
} else if (data instanceof Network) {
|
|
163
|
+
this.mapMatching.network = data;
|
|
164
|
+
} else {
|
|
165
|
+
throw new Error('Unknown feed object');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default AbsolutePositionProvider;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { deg2rad } from '@wemap/maths';
|
|
2
|
+
import { UserPosition } from '@wemap/geo';
|
|
3
|
+
import { TimeUtils } from '@wemap/utils';
|
|
4
|
+
|
|
5
|
+
import EventType from '../../../events/EventType';
|
|
6
|
+
import GeolocationApiMissingError from '../../../errors/GeolocationApiMissingError';
|
|
7
|
+
import Provider from '../../Provider';
|
|
8
|
+
import GeolocationPermissionDeniedError from '../../../errors/GeolocationPermissionDeniedError';
|
|
9
|
+
import GeolocationPositionUnavailableError from '../../../errors/GeolocationPositionUnavailableError';
|
|
10
|
+
import Availability from '../../../events/Availability';
|
|
11
|
+
import Constants from '../../Constants';
|
|
12
|
+
|
|
13
|
+
const POSITION_OPTIONS = {
|
|
14
|
+
enableHighAccuracy: true,
|
|
15
|
+
timeout: Infinity,
|
|
16
|
+
maximumAge: 0
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* GnssWifiProvider is a provider based on navigator.geolocation.
|
|
21
|
+
* This API does not allow us to know if the position returned is provided
|
|
22
|
+
* by Wifi Fingerprinting algorithms or by GNSS. That is why the name is
|
|
23
|
+
* "GnssWifi".
|
|
24
|
+
*/
|
|
25
|
+
class GnssWifiProvider extends Provider {
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @override
|
|
29
|
+
*/
|
|
30
|
+
static get displayName() {
|
|
31
|
+
return 'GNSS / Wifi from Browser';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
static get eventsType() {
|
|
38
|
+
return [EventType.AbsolutePosition];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @override
|
|
43
|
+
*/
|
|
44
|
+
get _availability() {
|
|
45
|
+
return typeof(navigator) === 'object' && navigator.geolocation
|
|
46
|
+
? Availability.yes()
|
|
47
|
+
: Availability.no(new GeolocationApiMissingError());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @override
|
|
52
|
+
*/
|
|
53
|
+
start() {
|
|
54
|
+
|
|
55
|
+
this.geoLocationId = navigator.geolocation.watchPosition(
|
|
56
|
+
this.onNewPosition,
|
|
57
|
+
this.onPositionError,
|
|
58
|
+
POSITION_OPTIONS
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @override
|
|
65
|
+
*/
|
|
66
|
+
stop() {
|
|
67
|
+
|
|
68
|
+
navigator.geolocation.clearWatch(this.geoLocationId);
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
onNewPosition = geolocation => {
|
|
76
|
+
const { coords } = geolocation;
|
|
77
|
+
if (!coords) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let bearing;
|
|
82
|
+
if (coords.heading) {
|
|
83
|
+
bearing = deg2rad(coords.heading);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const timestamp = TimeUtils.unixTimestampToPreciseTime(geolocation.timestamp) / 1e3;
|
|
87
|
+
|
|
88
|
+
const position = new UserPosition(
|
|
89
|
+
coords.latitude,
|
|
90
|
+
coords.longitude,
|
|
91
|
+
Constants.DEFAULT_ALTITUDE,
|
|
92
|
+
null,
|
|
93
|
+
timestamp,
|
|
94
|
+
coords.accuracy,
|
|
95
|
+
bearing,
|
|
96
|
+
this.name);
|
|
97
|
+
|
|
98
|
+
this.notify(this.createEvent(
|
|
99
|
+
EventType.AbsolutePosition, position, timestamp
|
|
100
|
+
));
|
|
101
|
+
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
onPositionError = error => {
|
|
105
|
+
|
|
106
|
+
let customError;
|
|
107
|
+
switch (error.code) {
|
|
108
|
+
case 1:
|
|
109
|
+
customError = new GeolocationPermissionDeniedError(error.message);
|
|
110
|
+
break;
|
|
111
|
+
case 2:
|
|
112
|
+
customError = new GeolocationPositionUnavailableError(error.message);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
customError = new Error(error.message);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.notifyError(customError);
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default GnssWifiProvider;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { UserPosition } from '@wemap/geo';
|
|
2
|
+
import { TimeUtils } from '@wemap/utils';
|
|
3
|
+
|
|
4
|
+
import EventType from '../../../events/EventType';
|
|
5
|
+
import Provider from '../../Provider';
|
|
6
|
+
import IpResolveServerError from '../../../errors/IpResolveServerError';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* GnssWifiProvider is a provider based on navigator.geolocation.
|
|
10
|
+
* This API does not allow us to know if the position returned is provided
|
|
11
|
+
* by Wifi Fingerprinting algorithms or by GNSS. That is why the name is
|
|
12
|
+
* "GnssWifi".
|
|
13
|
+
*/
|
|
14
|
+
class IpProvider extends Provider {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @override
|
|
18
|
+
*/
|
|
19
|
+
static get displayName() {
|
|
20
|
+
return 'IP from ipinfo.io';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @override
|
|
25
|
+
*/
|
|
26
|
+
static get eventsType() {
|
|
27
|
+
return [EventType.AbsolutePosition];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @override
|
|
32
|
+
*/
|
|
33
|
+
start() {
|
|
34
|
+
|
|
35
|
+
fetch('https://ipinfo.io/geo?token=24a7ca2f3b489d')
|
|
36
|
+
.then((response) => {
|
|
37
|
+
if (!response) {
|
|
38
|
+
this.notifyError(new IpResolveServerError());
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const timestamp = TimeUtils.preciseTime / 1e3;
|
|
43
|
+
|
|
44
|
+
const latLngStr = response.loc.split(',');
|
|
45
|
+
const position = new UserPosition(
|
|
46
|
+
parseFloat(latLngStr[0]),
|
|
47
|
+
parseFloat(latLngStr[1]),
|
|
48
|
+
null,
|
|
49
|
+
null,
|
|
50
|
+
timestamp
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
this.notify(this.createEvent(
|
|
54
|
+
EventType.AbsolutePosition, position, timestamp
|
|
55
|
+
));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @override
|
|
61
|
+
*/
|
|
62
|
+
stop() {
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default IpProvider;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
2
|
+
import {
|
|
3
|
+
Attitude, RelativePosition
|
|
4
|
+
} from '@wemap/geo';
|
|
5
|
+
import { deg2rad } from '@wemap/maths';
|
|
6
|
+
import { TimeUtils } from '@wemap/utils';
|
|
7
|
+
|
|
8
|
+
import Provider from '../../Provider';
|
|
9
|
+
import EventType from '../../../events/EventType';
|
|
10
|
+
import MissingArCoreError from '../../../errors/MissingArCoreError';
|
|
11
|
+
import MissingNativeInterfaceError from '../../../errors/MissingNativeInterfaceError';
|
|
12
|
+
import Availability from '../../../events/Availability';
|
|
13
|
+
import ProviderState from '../../ProviderState';
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const Payload = {
|
|
17
|
+
Pose: {
|
|
18
|
+
ref: 2 ** 0,
|
|
19
|
+
size: 7
|
|
20
|
+
},
|
|
21
|
+
Barcode: {
|
|
22
|
+
ref: 2 ** 1,
|
|
23
|
+
size: 1
|
|
24
|
+
},
|
|
25
|
+
ProjMat: {
|
|
26
|
+
ref: 2 ** 2,
|
|
27
|
+
size: 16
|
|
28
|
+
},
|
|
29
|
+
ImageRef: {
|
|
30
|
+
ref: 2 ** 3,
|
|
31
|
+
size: 1
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
class ArCoreProvider extends Provider {
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* default relative attitude drift in rad.second-1
|
|
39
|
+
*/
|
|
40
|
+
static RELATIVE_ATTITUDE_DRIFT = deg2rad(3) / 60;
|
|
41
|
+
|
|
42
|
+
previousPosition = [0, 0, 0];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @override
|
|
46
|
+
*/
|
|
47
|
+
static get displayName() {
|
|
48
|
+
return 'ArCore provider';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @override
|
|
53
|
+
*/
|
|
54
|
+
static get eventsType() {
|
|
55
|
+
return [EventType.RelativeAttitude, EventType.RelativePosition, EventType.Barcode];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @override
|
|
61
|
+
*/
|
|
62
|
+
start() {
|
|
63
|
+
if (this.nativeProvider) {
|
|
64
|
+
this.nativeProvider.start();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.pullDataLoop();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @override
|
|
72
|
+
*/
|
|
73
|
+
stop() {
|
|
74
|
+
if (this.nativeProvider) {
|
|
75
|
+
this.nativeProvider.stop();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
pullDataLoop = () => {
|
|
80
|
+
|
|
81
|
+
if (this.state === ProviderState.STOPPPED) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const payload = JSON.parse(this.nativeProvider.getInfo());
|
|
86
|
+
if (payload.length > 1) {
|
|
87
|
+
this.parsePayload(payload);
|
|
88
|
+
}
|
|
89
|
+
requestAnimationFrame(this.pullDataLoop);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
parsePayload(payload) {
|
|
93
|
+
|
|
94
|
+
const ref = payload[0];
|
|
95
|
+
let bufferIndex = 1;
|
|
96
|
+
|
|
97
|
+
const events = [];
|
|
98
|
+
|
|
99
|
+
const time = TimeUtils.preciseTime / 1e3;
|
|
100
|
+
|
|
101
|
+
if (ref & Payload.Pose.ref) {
|
|
102
|
+
|
|
103
|
+
const attitude = new Attitude(
|
|
104
|
+
payload.slice(bufferIndex, bufferIndex + 4),
|
|
105
|
+
time,
|
|
106
|
+
this.constructor.RELATIVE_ATTITUDE_DRIFT,
|
|
107
|
+
);
|
|
108
|
+
events.push(this.createEvent(EventType.RelativeAttitude, attitude));
|
|
109
|
+
|
|
110
|
+
const newPosition = [payload[bufferIndex + 4], payload[bufferIndex + 5], payload[bufferIndex + 6]];
|
|
111
|
+
const position = new RelativePosition(
|
|
112
|
+
newPosition[0] - this.previousPosition[0],
|
|
113
|
+
newPosition[1] - this.previousPosition[1],
|
|
114
|
+
newPosition[2] - this.previousPosition[2],
|
|
115
|
+
time,
|
|
116
|
+
1e-4
|
|
117
|
+
);
|
|
118
|
+
this.previousPosition = newPosition;
|
|
119
|
+
events.push(this.createEvent(EventType.RelativePosition, position));
|
|
120
|
+
|
|
121
|
+
bufferIndex += Payload.Pose.size;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (ref & Payload.Barcode.ref) {
|
|
125
|
+
events.push(this.createEvent(EventType.Barcode, payload[bufferIndex]));
|
|
126
|
+
bufferIndex += Payload.Barcode.size;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (ref & Payload.ProjMat.ref) {
|
|
130
|
+
const projMatrix = payload.slice(bufferIndex, bufferIndex + Payload.ProjMat.size);
|
|
131
|
+
events.push(this.createEvent(EventType.ProjectionMatrix, projMatrix));
|
|
132
|
+
bufferIndex += Payload.ProjMat.size;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (events.length !== 0) {
|
|
136
|
+
this.notify(...events);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
get nativeProvider() {
|
|
142
|
+
|
|
143
|
+
if (!this._nativeProvider) {
|
|
144
|
+
|
|
145
|
+
if (!this.nativeInterface) {
|
|
146
|
+
throw new MissingNativeInterfaceError();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this._nativeProvider = this.nativeInterface.getArCoreProvider();
|
|
150
|
+
if (!this._nativeProvider) {
|
|
151
|
+
throw new MissingArCoreError();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return this._nativeProvider;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @override
|
|
161
|
+
*/
|
|
162
|
+
get _availability() {
|
|
163
|
+
try {
|
|
164
|
+
const nativeProvider = this.nativeProvider;
|
|
165
|
+
|
|
166
|
+
if (!nativeProvider.checkAvailability()) {
|
|
167
|
+
return Availability.no(new MissingArCoreError());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
} catch (e) {
|
|
171
|
+
return Availability.no(e);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return Availability.yes();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
enableBarcodeScanner() {
|
|
178
|
+
if (this.nativeProvider) {
|
|
179
|
+
this.nativeProvider.enableBarcodeScanner();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
disableBarcodeScanner() {
|
|
184
|
+
if (this.nativeProvider) {
|
|
185
|
+
this.nativeProvider.disableBarcodeScanner();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @override
|
|
191
|
+
*/
|
|
192
|
+
static get useCameraNatively() {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export default ArCoreProvider;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { GeoRelativePosition } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import EventType from '../../../events/EventType';
|
|
4
|
+
import Provider from '../../Provider';
|
|
5
|
+
import {
|
|
6
|
+
ArCore, AbsoluteAttitude
|
|
7
|
+
} from '../../../Providers';
|
|
8
|
+
|
|
9
|
+
class GeoRelativePositionFromArCoreProvider extends Provider {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @override
|
|
13
|
+
*/
|
|
14
|
+
get _availability() {
|
|
15
|
+
return ArCore.availability;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @override
|
|
20
|
+
*/
|
|
21
|
+
start() {
|
|
22
|
+
|
|
23
|
+
this.arCoreProviderId = ArCore.addEventListener(
|
|
24
|
+
this.onArCoreEvents,
|
|
25
|
+
this.notifyError,
|
|
26
|
+
this.name);
|
|
27
|
+
|
|
28
|
+
this.absoluteAttitudeProviderId = AbsoluteAttitude.addEventListener(
|
|
29
|
+
events => (this.absoluteAttitudeEvent = events[0]),
|
|
30
|
+
this.notifyError,
|
|
31
|
+
this.name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
stop() {
|
|
38
|
+
ArCore.removeEventListener(this.arCoreProviderId);
|
|
39
|
+
AbsoluteAttitude.removeEventListener(this.absoluteAttitudeProviderId);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
onArCoreEvents = events => {
|
|
43
|
+
const relativeAttitudeEvent = events.find(event => event.dataType === EventType.RelativeAttitude);
|
|
44
|
+
const relativePositionEvent = events.find(event => event.dataType === EventType.RelativePosition);
|
|
45
|
+
|
|
46
|
+
if (relativeAttitudeEvent && relativePositionEvent && this.absoluteAttitudeEvent) {
|
|
47
|
+
this.compute(relativePositionEvent, relativeAttitudeEvent, this.absoluteAttitudeEvent);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
compute(relativePositionEvent, relativeAttitudeEvent, absoluteAttitudeEvent) {
|
|
52
|
+
const relativePosition = relativePositionEvent.data;
|
|
53
|
+
const relativeAttitude = relativeAttitudeEvent.data;
|
|
54
|
+
const absoluteAttitude = absoluteAttitudeEvent.data;
|
|
55
|
+
|
|
56
|
+
const rotation = absoluteAttitude.heading - relativeAttitude.heading;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Here, we transform "relativePosition" which is defined in ArCore frame to a relative "position" defined in ENU frame
|
|
60
|
+
*/
|
|
61
|
+
const east = Math.cos(rotation) * relativePosition.x - Math.sin(rotation) * relativePosition.z;
|
|
62
|
+
const north = -Math.sin(rotation) * relativePosition.x - Math.cos(rotation) * relativePosition.z;
|
|
63
|
+
const up = relativePosition.y;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Relative position is defined in ENU frame
|
|
67
|
+
*/
|
|
68
|
+
const position = new GeoRelativePosition(
|
|
69
|
+
east,
|
|
70
|
+
north,
|
|
71
|
+
up,
|
|
72
|
+
relativePosition.time,
|
|
73
|
+
0
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
this.notify(this.createEvent(
|
|
77
|
+
EventType.GeoRelativePosition,
|
|
78
|
+
position,
|
|
79
|
+
relativePosition.time,
|
|
80
|
+
[relativePositionEvent, relativeAttitudeEvent, absoluteAttitudeEvent]
|
|
81
|
+
));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default GeoRelativePositionFromArCoreProvider;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import MetaProvider from '../../MetaProvider';
|
|
2
|
+
import Availability from '../../../events/Availability';
|
|
3
|
+
import EventType from '../../../events/EventType';
|
|
4
|
+
import {
|
|
5
|
+
Pdr, GeoRelativePositionFromArCore
|
|
6
|
+
} from '../../../Providers';
|
|
7
|
+
|
|
8
|
+
class GeoRelativePositionProvider extends MetaProvider {
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @override
|
|
12
|
+
*/
|
|
13
|
+
static get displayName() {
|
|
14
|
+
return 'Geo Relative Position';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @override
|
|
19
|
+
*/
|
|
20
|
+
static get eventsType() {
|
|
21
|
+
return [EventType.GeoRelativePosition];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @override
|
|
26
|
+
*/
|
|
27
|
+
get _availability() {
|
|
28
|
+
return Availability.union(
|
|
29
|
+
Pdr.availability,
|
|
30
|
+
GeoRelativePositionFromArCore.availability
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @override
|
|
37
|
+
*/
|
|
38
|
+
start() {
|
|
39
|
+
|
|
40
|
+
if (GeoRelativePositionFromArCore.availability.isSupported) {
|
|
41
|
+
this.geoRelativeProvider = GeoRelativePositionFromArCore;
|
|
42
|
+
} else {
|
|
43
|
+
this.geoRelativeProvider = Pdr;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.providerId = this.geoRelativeProvider.addEventListener(
|
|
47
|
+
events => {
|
|
48
|
+
const event = events.find(_event => _event.dataType === EventType.GeoRelativePosition);
|
|
49
|
+
if (event) {
|
|
50
|
+
this.notify(event.clone());
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
this.notifyError,
|
|
54
|
+
this.name
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @override
|
|
60
|
+
*/
|
|
61
|
+
stop() {
|
|
62
|
+
this.geoRelativeProvider.removeEventListener(this.providerId);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default GeoRelativePositionProvider;
|