@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,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AbsoluteHeading, Attitude
|
|
3
|
+
} from '@wemap/geo';
|
|
4
|
+
|
|
5
|
+
import MetaProvider from '../../MetaProvider';
|
|
6
|
+
import EventType from '../../../events/EventType';
|
|
7
|
+
import Availability from '../../../events/Availability';
|
|
8
|
+
import {
|
|
9
|
+
AbsoluteAttitudeFromBrowser, AbsoluteAttitudeFromRelAtt
|
|
10
|
+
} from '../../../Providers';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Absolute attitude provider gives the device attitude in East-North-Up (ENU) frame
|
|
15
|
+
*/
|
|
16
|
+
class AbsoluteAttitudeProvider extends MetaProvider {
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
|
|
21
|
+
this.attitudeFromBrowserErrored = false;
|
|
22
|
+
this.attitudeFromRelAttErrored = false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @override
|
|
27
|
+
*/
|
|
28
|
+
static get displayName() {
|
|
29
|
+
return 'Absolute Attitude';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @override
|
|
34
|
+
*/
|
|
35
|
+
static get eventsType() {
|
|
36
|
+
return [EventType.AbsoluteAttitude];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @override
|
|
41
|
+
*/
|
|
42
|
+
get _availability() {
|
|
43
|
+
return Availability.union(
|
|
44
|
+
AbsoluteAttitudeFromBrowser.availability,
|
|
45
|
+
AbsoluteAttitudeFromRelAtt.availability
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @override
|
|
51
|
+
*/
|
|
52
|
+
start() {
|
|
53
|
+
|
|
54
|
+
this.fromBrowserProviderId = AbsoluteAttitudeFromBrowser.addEventListener(
|
|
55
|
+
events => this.onAttitudeFromBrowser(events[0]),
|
|
56
|
+
error => {
|
|
57
|
+
this.attitudeFromBrowserErrored = true;
|
|
58
|
+
this.onError(error);
|
|
59
|
+
},
|
|
60
|
+
this.name);
|
|
61
|
+
|
|
62
|
+
this.fromRelAttProviderId = AbsoluteAttitudeFromRelAtt.addEventListener(
|
|
63
|
+
events => this.onAttitudeFromRelAtt(events[0]),
|
|
64
|
+
error => {
|
|
65
|
+
this.attitudeFromRelAttErrored = true;
|
|
66
|
+
this.onError(error);
|
|
67
|
+
},
|
|
68
|
+
this.name);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
onError(error) {
|
|
72
|
+
if (this.attitudeFromBrowserErrored && this.attitudeFromRelAttErrored) {
|
|
73
|
+
this.notifyError(error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
onAttitudeFromBrowser(event) {
|
|
78
|
+
this.eventFromBrowser = event;
|
|
79
|
+
if (!this.eventFromRelAtt
|
|
80
|
+
|| event.data.accuracy <= this.eventFromRelAtt.data.accuracy) {
|
|
81
|
+
this.notify(event.clone());
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onAttitudeFromRelAtt(event) {
|
|
86
|
+
this.eventFromRelAtt = event;
|
|
87
|
+
if (!this.eventFromBrowser
|
|
88
|
+
|| event.data.accuracy <= this.eventFromBrowser.data.accuracy) {
|
|
89
|
+
this.notify(event.clone());
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @override
|
|
95
|
+
*/
|
|
96
|
+
stop() {
|
|
97
|
+
AbsoluteAttitudeFromBrowser.removeEventListener(this.fromBrowserProviderId);
|
|
98
|
+
AbsoluteAttitudeFromRelAtt.removeEventListener(this.fromRelAttProviderId);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @override
|
|
103
|
+
* @param {AbsoluteHeading|Attitude} data
|
|
104
|
+
*/
|
|
105
|
+
feed(data) {
|
|
106
|
+
|
|
107
|
+
if (data instanceof AbsoluteHeading) {
|
|
108
|
+
|
|
109
|
+
if (data.time === null) {
|
|
110
|
+
throw Error('the time of the absolute heading is not defined');
|
|
111
|
+
}
|
|
112
|
+
if (data.accuracy === null) {
|
|
113
|
+
throw Error('the accuracy of the absolute heading is not defined');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.notify(this.createEvent(
|
|
117
|
+
EventType.AbsoluteAttitude,
|
|
118
|
+
data.toAttitude(),
|
|
119
|
+
data.time
|
|
120
|
+
));
|
|
121
|
+
|
|
122
|
+
} else if (data instanceof Attitude) {
|
|
123
|
+
|
|
124
|
+
if (data.time === null) {
|
|
125
|
+
throw Error('the time of the attitude is not defined');
|
|
126
|
+
}
|
|
127
|
+
if (data.accuracy === null) {
|
|
128
|
+
throw Error('the accuracy of the attitude is not defined');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.notify(this.createEvent(
|
|
132
|
+
EventType.AbsoluteAttitude,
|
|
133
|
+
data,
|
|
134
|
+
data.time
|
|
135
|
+
));
|
|
136
|
+
|
|
137
|
+
} else {
|
|
138
|
+
throw new Error('data is nor an AbsoluteHeading or an Attitude object');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export default AbsoluteAttitudeProvider;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import isnumber from 'lodash.isnumber';
|
|
2
|
+
|
|
3
|
+
import { Attitude } from '@wemap/geo';
|
|
4
|
+
import { Rotations } from '@wemap/maths';
|
|
5
|
+
import { BrowserUtils } from '@wemap/utils';
|
|
6
|
+
|
|
7
|
+
import Provider from '../../Provider';
|
|
8
|
+
import EventType from '../../../events/EventType';
|
|
9
|
+
import AskImuOnDesktopError from '../../../errors/AskImuOnDesktopError';
|
|
10
|
+
import MissingSensorError from '../../../errors/MissingSensorError';
|
|
11
|
+
import Availability from '../../../events/Availability';
|
|
12
|
+
import RelativeAttitudeProvider from './RelativeAttitudeProvider';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Relative attitude provider gives the device attitude in a custom frame (x-right, y-front, z-up) using
|
|
17
|
+
* browser deviceorientation
|
|
18
|
+
*
|
|
19
|
+
* -----------------------------------
|
|
20
|
+
* Overview of compatibilities:
|
|
21
|
+
* -----------------------------------
|
|
22
|
+
*
|
|
23
|
+
* Chrome Android (v72.0.3626): YES (via deviceorientation but deviceorientation.alpha is unreliable! Sometimes it starts at 0°, sometimes at 270°)
|
|
24
|
+
* Safari iOS (v12.0): YES (via deviceorientation)
|
|
25
|
+
* Opera Android (v50.2.2426): NO {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/ondeviceorientation}
|
|
26
|
+
* Firefox Android (v65.0.1): YES (via deviceorientation)
|
|
27
|
+
*
|
|
28
|
+
* -----------------------------------
|
|
29
|
+
*/
|
|
30
|
+
class RelativeAttitudeFromBrowserProvider extends Provider {
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @override
|
|
34
|
+
*/
|
|
35
|
+
static get displayName() {
|
|
36
|
+
return 'Relative Attitude from Browser';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @override
|
|
41
|
+
*/
|
|
42
|
+
static get eventsType() {
|
|
43
|
+
return [EventType.RelativeAttitude];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @override
|
|
48
|
+
*/
|
|
49
|
+
get _availability() {
|
|
50
|
+
return BrowserUtils.isMobile
|
|
51
|
+
? Availability.yes()
|
|
52
|
+
: Availability.no(new AskImuOnDesktopError());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @override
|
|
57
|
+
*/
|
|
58
|
+
start() {
|
|
59
|
+
window.addEventListener('deviceorientation', this.onDeviceOrientationEvent, true);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @override
|
|
64
|
+
*/
|
|
65
|
+
stop() {
|
|
66
|
+
window.removeEventListener('deviceorientation', this.onDeviceOrientationEvent, true);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
onDeviceOrientationEvent = e => {
|
|
71
|
+
|
|
72
|
+
const timestamp = e.timeStamp / 1e3;
|
|
73
|
+
|
|
74
|
+
if (!isnumber(e.alpha) || !isnumber(e.beta) || !isnumber(e.gamma)) {
|
|
75
|
+
this.notifyError(new MissingSensorError().from('deviceorientation'));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const quaternion = Rotations.eulerToQuaternionZXYDegrees([e.alpha, e.beta, e.gamma]);
|
|
80
|
+
const attitude = new Attitude(quaternion,
|
|
81
|
+
timestamp,
|
|
82
|
+
RelativeAttitudeProvider.DEFAULT_DRIFT,
|
|
83
|
+
this.name
|
|
84
|
+
);
|
|
85
|
+
this.notify(this.createEvent(EventType.RelativeAttitude, attitude, timestamp));
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export default RelativeAttitudeFromBrowserProvider;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Attitude } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import Provider from '../../Provider';
|
|
4
|
+
import Availability from '../../../events/Availability';
|
|
5
|
+
import EventType from '../../../events/EventType';
|
|
6
|
+
import EkfAttitude from '../EkfAttitude';
|
|
7
|
+
import RelativeAttitudeProvider from './RelativeAttitudeProvider';
|
|
8
|
+
import {
|
|
9
|
+
Accelerometer, Gyroscope
|
|
10
|
+
} from '../../../Providers';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Relative attitude provider gives the device attitude in East-North-Up (ENU) frame using
|
|
15
|
+
* browser deviceorientation
|
|
16
|
+
* The provider does not work until an offset is given.
|
|
17
|
+
*/
|
|
18
|
+
class RelativeAttitudeFromEkfProvider extends Provider {
|
|
19
|
+
|
|
20
|
+
lastTimestamp = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @override
|
|
24
|
+
*/
|
|
25
|
+
constructor(context) {
|
|
26
|
+
super(context);
|
|
27
|
+
this.ekfAttitude = new EkfAttitude();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @override
|
|
32
|
+
*/
|
|
33
|
+
static get displayName() {
|
|
34
|
+
return 'Relative Attitude from Ekf';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @override
|
|
39
|
+
*/
|
|
40
|
+
static get eventsType() {
|
|
41
|
+
return [EventType.RelativeAttitude];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @override
|
|
46
|
+
*/
|
|
47
|
+
get _availability() {
|
|
48
|
+
return Availability.merge(
|
|
49
|
+
Accelerometer.availability,
|
|
50
|
+
Gyroscope.availability,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @override
|
|
56
|
+
*/
|
|
57
|
+
start() {
|
|
58
|
+
this.accelerometerProviderId = Accelerometer.addEventListener(
|
|
59
|
+
events => this.onAccelerometerEvent(events[0]),
|
|
60
|
+
this.notifyError,
|
|
61
|
+
this.name);
|
|
62
|
+
|
|
63
|
+
this.gyroscopeProviderId = Gyroscope.addEventListener(
|
|
64
|
+
events => (this.gyroscopeEvent = events[0]),
|
|
65
|
+
this.notifyError,
|
|
66
|
+
this.name);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @override
|
|
71
|
+
*/
|
|
72
|
+
stop() {
|
|
73
|
+
Accelerometer.removeEventListener(this.accelerometerProviderId);
|
|
74
|
+
Gyroscope.removeEventListener(this.gyroscopeProviderId);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
onAccelerometerEvent = accelerationEvent => {
|
|
81
|
+
|
|
82
|
+
if (!this.gyroscopeEvent) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const acceleration = accelerationEvent.data;
|
|
87
|
+
const { timestamp } = accelerationEvent;
|
|
88
|
+
|
|
89
|
+
// Handle timestamps and dt
|
|
90
|
+
if (this.lastTimestamp === 0) {
|
|
91
|
+
this.lastTimestamp = timestamp;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const diffTime = timestamp - this.lastTimestamp;
|
|
95
|
+
this.lastTimestamp = timestamp;
|
|
96
|
+
|
|
97
|
+
const quaternion = this.ekfAttitude.update(diffTime, acceleration, this.gyroscopeEvent.data);
|
|
98
|
+
|
|
99
|
+
if (quaternion) {
|
|
100
|
+
const attitude = new Attitude(quaternion,
|
|
101
|
+
timestamp,
|
|
102
|
+
RelativeAttitudeProvider.DEFAULT_DRIFT,
|
|
103
|
+
this.name
|
|
104
|
+
);
|
|
105
|
+
this.notify(this.createEvent(
|
|
106
|
+
EventType.RelativeAttitude,
|
|
107
|
+
attitude,
|
|
108
|
+
timestamp,
|
|
109
|
+
[accelerationEvent, this.gyroscopeEvent]));
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export default RelativeAttitudeFromEkfProvider;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { deg2rad } from '@wemap/maths';
|
|
2
|
+
|
|
3
|
+
import Provider from '../../Provider';
|
|
4
|
+
import EventType from '../../../events/EventType';
|
|
5
|
+
import Availability from '../../../events/Availability';
|
|
6
|
+
import noop from 'lodash.noop';
|
|
7
|
+
import ProviderState from '../../ProviderState';
|
|
8
|
+
import {
|
|
9
|
+
RelativeAttitudeFromEkf, RelativeAttitudeFromBrowser, ArCore
|
|
10
|
+
} from '../../../Providers';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Relative attitude provider gives the device attitude in East-North-Up (ENU) frame using
|
|
15
|
+
* browser deviceorientation
|
|
16
|
+
* The provider does not work until an offset is given.
|
|
17
|
+
*/
|
|
18
|
+
class RelativeAttitudeProvider extends Provider {
|
|
19
|
+
/**
|
|
20
|
+
* default relative attitude drift in rad.second-1
|
|
21
|
+
*/
|
|
22
|
+
static DEFAULT_DRIFT = deg2rad(15) / 60;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
lastTimestamp = 0;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @override
|
|
29
|
+
*/
|
|
30
|
+
static get displayName() {
|
|
31
|
+
return 'Relative Attitude';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
static get eventsType() {
|
|
38
|
+
return [EventType.RelativeAttitude];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @override
|
|
43
|
+
*/
|
|
44
|
+
get _availability() {
|
|
45
|
+
return Availability.union(
|
|
46
|
+
RelativeAttitudeFromEkf.availability,
|
|
47
|
+
RelativeAttitudeFromBrowser.availability
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @override
|
|
53
|
+
*/
|
|
54
|
+
start() {
|
|
55
|
+
this.provider = RelativeAttitudeFromEkf.availability.isSupported
|
|
56
|
+
? RelativeAttitudeFromEkf
|
|
57
|
+
: RelativeAttitudeFromBrowser;
|
|
58
|
+
|
|
59
|
+
this.listenerId = this.provider.addEventListener(
|
|
60
|
+
events => {
|
|
61
|
+
if (ArCore.state === ProviderState.STOPPPED) {
|
|
62
|
+
this.notify(events[0].clone());
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
this.notifyError,
|
|
66
|
+
this.name);
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
this.arCoreMonitoringId = ArCore.addMonitoringListener(this.listenArCore, this.unlistenArCore);
|
|
70
|
+
if (ArCore.state === ProviderState.STARTED) {
|
|
71
|
+
this.listenArCore();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @override
|
|
77
|
+
*/
|
|
78
|
+
stop() {
|
|
79
|
+
this.provider.removeEventListener(this.listenerId);
|
|
80
|
+
ArCore.removeMonitoringListener(this.arCoreMonitoringId);
|
|
81
|
+
this.unlistenArCore();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
listenArCore = () => {
|
|
85
|
+
this.arCoreProviderId = ArCore.addEventListener(
|
|
86
|
+
events => {
|
|
87
|
+
const relativeAttitudeEvent = events.find(event => event.dataType === EventType.RelativeAttitude);
|
|
88
|
+
if (relativeAttitudeEvent) {
|
|
89
|
+
this.notify(relativeAttitudeEvent.clone());
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
noop,
|
|
93
|
+
this.name,
|
|
94
|
+
false
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
unlistenArCore = () => {
|
|
99
|
+
ArCore.removeEventListener(this.arCoreProviderId);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default RelativeAttitudeProvider;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import Provider from '../Provider';
|
|
2
|
+
import EventType from '../../events/EventType';
|
|
3
|
+
import MissingAccelerometerError from '../../errors/MissingAccelerometerError';
|
|
4
|
+
import { Imu } from '../../Providers';
|
|
5
|
+
|
|
6
|
+
class AccelerometerProvider extends Provider {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @override
|
|
10
|
+
*/
|
|
11
|
+
static get displayName() {
|
|
12
|
+
return 'Accelerometer';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @override
|
|
17
|
+
*/
|
|
18
|
+
static get eventsType() {
|
|
19
|
+
return [EventType.Acceleration];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @override
|
|
24
|
+
*/
|
|
25
|
+
get _availability() {
|
|
26
|
+
return Imu.availability;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @override
|
|
31
|
+
*/
|
|
32
|
+
start() {
|
|
33
|
+
this.providerId = Imu.addEventListener(
|
|
34
|
+
events => this.parseImuEvents(events),
|
|
35
|
+
this.notifyError,
|
|
36
|
+
this.name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @override
|
|
41
|
+
*/
|
|
42
|
+
stop() {
|
|
43
|
+
Imu.removeEventListener(this.providerId);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
parseImuEvents = events => {
|
|
50
|
+
|
|
51
|
+
const accelerationEvent = events.find(event => event.dataType === EventType.Acceleration);
|
|
52
|
+
if (!accelerationEvent) {
|
|
53
|
+
this.notifyError(new MissingAccelerometerError().from('devicemotion'));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.notify(accelerationEvent.clone());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default AccelerometerProvider;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import Provider from '../Provider';
|
|
2
|
+
import EventType from '../../events/EventType';
|
|
3
|
+
import MissingGyroscopeError from '../../errors/MissingGyroscopeError';
|
|
4
|
+
import { Imu } from '../../Providers';
|
|
5
|
+
|
|
6
|
+
class GyroscopeProvider extends Provider {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @override
|
|
10
|
+
*/
|
|
11
|
+
static get displayName() {
|
|
12
|
+
return 'Gyroscope';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @override
|
|
17
|
+
*/
|
|
18
|
+
static get eventsType() {
|
|
19
|
+
return [EventType.AngularRate];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @override
|
|
24
|
+
*/
|
|
25
|
+
get _availability() {
|
|
26
|
+
return Imu.availability;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @override
|
|
31
|
+
*/
|
|
32
|
+
start() {
|
|
33
|
+
this.providerId = Imu.addEventListener(
|
|
34
|
+
events => this.parseImuEvents(events),
|
|
35
|
+
this.notifyError,
|
|
36
|
+
this.name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @override
|
|
41
|
+
*/
|
|
42
|
+
stop() {
|
|
43
|
+
Imu.removeEventListener(this.providerId);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
parseImuEvents = events => {
|
|
50
|
+
|
|
51
|
+
const gyroscopeEvent = events.find(event => event.dataType === EventType.AngularRate);
|
|
52
|
+
if (!gyroscopeEvent) {
|
|
53
|
+
this.notifyError(new MissingGyroscopeError().from('devicemotion'));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.notify(gyroscopeEvent.clone());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default GyroscopeProvider;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import isnumber from 'lodash.isnumber';
|
|
2
|
+
|
|
3
|
+
import { deg2rad } from '@wemap/maths';
|
|
4
|
+
import {
|
|
5
|
+
Browser, BrowserUtils
|
|
6
|
+
} from '@wemap/utils';
|
|
7
|
+
|
|
8
|
+
import Provider from '../Provider';
|
|
9
|
+
import EventType from '../../events/EventType';
|
|
10
|
+
import AskImuOnDesktopError from '../../errors/AskImuOnDesktopError';
|
|
11
|
+
import Availability from '../../events/Availability';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Imu (Inertial Measurement Unit) provider retrieve acceleration data
|
|
15
|
+
* and/or angular rate data from inertial sensors.
|
|
16
|
+
*
|
|
17
|
+
* -----------------------------------
|
|
18
|
+
* Overview of compatibilities:
|
|
19
|
+
* -----------------------------------
|
|
20
|
+
*
|
|
21
|
+
* Chrome Android (v72.0.3626): YES (via devicemotion)
|
|
22
|
+
* Safari iOS (v12.0): YES (via devicemotion)
|
|
23
|
+
* Opera Android (v50.2.2426): NO {@link https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent}
|
|
24
|
+
* Firefox Android (v65.0.1): YES (via devicemotion)
|
|
25
|
+
*
|
|
26
|
+
* -----------------------------------
|
|
27
|
+
*/
|
|
28
|
+
class ImuProvider extends Provider {
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @override
|
|
32
|
+
*/
|
|
33
|
+
static get displayName() {
|
|
34
|
+
return 'Inertial Measurement Unit';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @override
|
|
39
|
+
*/
|
|
40
|
+
static get eventsType() {
|
|
41
|
+
return [EventType.AngularRate, EventType.Acceleration];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @override
|
|
46
|
+
*/
|
|
47
|
+
get _availability() {
|
|
48
|
+
return BrowserUtils.isMobile
|
|
49
|
+
? Availability.yes()
|
|
50
|
+
: Availability.no(new AskImuOnDesktopError());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @override
|
|
55
|
+
*/
|
|
56
|
+
start() {
|
|
57
|
+
window.addEventListener('devicemotion', this.parseDeviceMotionEvent, true);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @override
|
|
62
|
+
*/
|
|
63
|
+
stop() {
|
|
64
|
+
window.removeEventListener('devicemotion', this.parseDeviceMotionEvent, true);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* devicemotion callback
|
|
69
|
+
* @param {DeviceMotionEvent} e device motion event
|
|
70
|
+
* @returns {ProviderEvent[]} an array of provider events
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
parseDeviceMotionEvent = e => {
|
|
74
|
+
|
|
75
|
+
const events = [];
|
|
76
|
+
|
|
77
|
+
const timestamp = e.timeStamp / 1e3;
|
|
78
|
+
|
|
79
|
+
let acc;
|
|
80
|
+
if (e.accelerationIncludingGravity) {
|
|
81
|
+
const {
|
|
82
|
+
x, y, z
|
|
83
|
+
} = e.accelerationIncludingGravity;
|
|
84
|
+
|
|
85
|
+
if (isnumber(x) && isnumber(y) && isnumber(z)) {
|
|
86
|
+
acc = [x, y, z];
|
|
87
|
+
|
|
88
|
+
if (BrowserUtils.name === Browser.SAFARI) {
|
|
89
|
+
acc[0] *= -1;
|
|
90
|
+
acc[1] *= -1;
|
|
91
|
+
acc[2] *= -1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (acc) {
|
|
97
|
+
events.push(this.createEvent(EventType.Acceleration, acc, timestamp));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let gyr;
|
|
101
|
+
if (e.rotationRate) {
|
|
102
|
+
const {
|
|
103
|
+
alpha, beta, gamma
|
|
104
|
+
} = e.rotationRate;
|
|
105
|
+
|
|
106
|
+
if (isnumber(alpha) && isnumber(beta) && isnumber(gamma)) {
|
|
107
|
+
gyr = [deg2rad(alpha), deg2rad(beta), deg2rad(gamma)];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (gyr) {
|
|
112
|
+
events.push(this.createEvent(EventType.AngularRate, gyr, timestamp));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (events.length !== 0) {
|
|
116
|
+
this.notify(...events);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default ImuProvider;
|