@wemap/positioning 2.1.0 → 2.3.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/debug/arcore-absolute.html +16 -0
- package/debug/arcore.html +16 -0
- package/package.json +2 -1
- package/src/PositioningHandler.js +19 -5
- package/src/components/AbsoluteAttitudeComponent.jsx +2 -2
- package/src/components/ArCoreAbsoluteComponent.jsx +100 -0
- package/src/components/ArCoreComponent.jsx +74 -0
- package/src/components/GnssWifiComponent.jsx +14 -2
- package/src/components/GnssWifiPdrComponent.jsx +11 -2
- package/src/components/MapComponent.jsx +237 -0
- package/src/components/PdrComponent.jsx +12 -3
- package/src/components/PoseComponent.jsx +7 -0
- package/src/components/PositioningPoseComponent.jsx +12 -3
- package/src/components/Utils.js +18 -0
- package/src/components/index.js +4 -0
- package/src/errors/MissingArCoreError.js +9 -0
- package/src/errors/MissingNativeInterfaceError.js +9 -0
- package/src/providers/Provider.js +15 -3
- package/src/providers/ProviderOptions.js +1 -1
- package/src/providers/attitude/AbsoluteAttitudeProvider.js +6 -6
- package/src/providers/others/MapMatchingProvider.js +19 -19
- package/src/providers/pose/ArCoreAbsoluteProvider.js +186 -0
- package/src/providers/pose/ArCoreProvider.js +115 -0
- package/src/providers/pose/GnssWifiPdrProvider.js +20 -20
- package/src/providers/pose/PoseProvider.js +1 -1
- package/src/providers/pose/pdr/PdrProvider.js +39 -39
- package/src/providers/pose/pdr/helpers/Smoother.js +33 -33
- package/src/providers/pose/pdr/helpers/Smoother.spec.js +7 -7
- package/src/providers/position/GnssWifiProvider.js +5 -5
- package/src/providers/position/IpProvider.js +2 -2
- package/webpack/webpack.common.js +1 -1
- 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/attitude/EkfAttitude.js +0 -238
- package/src.old/attitude/EkfAttitude.spec.js +0 -116
- 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/providers/LocationSource.js +0 -290
- package/src.old/providers/PdrLocationSource.js +0 -320
- package/src.old/providers/ProvidersLogger.js +0 -77
- package/src.old/providers/pdr/HeadingUnlocker.js +0 -41
- package/src.old/providers/pdr/HeadingUnlocker.spec.js +0 -26
- package/src.old/providers/pdr/Smoother.js +0 -90
- package/src.old/providers/pdr/Smoother.spec.js +0 -424
- package/src.old/providers/pdr/ThugDetector.js +0 -37
- package/src.old/providers/steps/StepDetection.js +0 -7
- package/src.old/providers/steps/StepDetectionLadetto.js +0 -67
- package/src.old/providers/steps/StepDetectionMinMaxPeaks.js +0 -80
- package/src.old/providers/steps/StepDetectionMinMaxPeaks2.js +0 -108
- 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
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
// in seconds
|
|
3
|
-
const WINDOW_TIME = 0.3;
|
|
4
|
-
|
|
5
|
-
// in seconds
|
|
6
|
-
const MIN_TIME_BETWEEN_STEPS = 0.4;
|
|
7
|
-
|
|
8
|
-
// in Hz
|
|
9
|
-
const MAX_FRENQUENCY = 4;
|
|
10
|
-
const MIN_FRENQUENCY = 1;
|
|
11
|
-
|
|
12
|
-
// in m.s-2
|
|
13
|
-
const VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD = 0.75;
|
|
14
|
-
const VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD = -0.3;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class StepDetectionMinMaxPeaks2 {
|
|
18
|
-
|
|
19
|
-
constructor() {
|
|
20
|
-
this.slidingWindow = [];
|
|
21
|
-
|
|
22
|
-
this.lastStepTimestamp = -MIN_TIME_BETWEEN_STEPS;
|
|
23
|
-
this.previousVerticalAcc = 0;
|
|
24
|
-
this.influence = 0.2;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
compute(timestamp, linearAcc, angularRate) {
|
|
29
|
-
|
|
30
|
-
const verticalAcc = this.influence * (linearAcc[2] * 2) + (1 - this.influence) * this.previousVerticalAcc;
|
|
31
|
-
this.previousVerticalAcc = verticalAcc;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (Math.sqrt(angularRate[0] ** 2 + angularRate[1] ** 2 + angularRate[2] ** 2) > 0.75) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (this.lastStepTimestamp && this.lastStepTimestamp + MIN_TIME_BETWEEN_STEPS > timestamp) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
let maxValue = Number.MIN_SAFE_INTEGER;
|
|
43
|
-
let minValue = Number.MAX_SAFE_INTEGER;
|
|
44
|
-
|
|
45
|
-
this.slidingWindow.forEach(function(item, index, object) {
|
|
46
|
-
if (item.timestamp < timestamp - WINDOW_TIME) {
|
|
47
|
-
object.splice(index, 1);
|
|
48
|
-
} else {
|
|
49
|
-
maxValue = Math.max(item.verticalAcc, maxValue);
|
|
50
|
-
minValue = Math.min(item.verticalAcc, minValue);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
this.slidingWindow.push({
|
|
54
|
-
timestamp: timestamp,
|
|
55
|
-
verticalAcc: verticalAcc
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (maxValue > VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD
|
|
60
|
-
&& minValue < VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD) {
|
|
61
|
-
|
|
62
|
-
const timeInterval = this.lastStepTimestamp ? timestamp - this.lastStepTimestamp : 1;
|
|
63
|
-
this.frequency = Math.min(Math.max((1 / timeInterval), MIN_FRENQUENCY), MAX_FRENQUENCY);
|
|
64
|
-
|
|
65
|
-
this.lastStepTimestamp = timestamp;
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get lastStepSize() {
|
|
73
|
-
|
|
74
|
-
if (!this.frequency) {
|
|
75
|
-
return 0;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const kParamA = 0.45;
|
|
79
|
-
const kParamB = 0.2;
|
|
80
|
-
return kParamA + kParamB * this.frequency;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get speed() {
|
|
84
|
-
return this.lastStepSize && this.frequency ? this.lastStepSize * this.frequency : 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
mean(data) {
|
|
88
|
-
let sum = 0.0, mean = 0.0;
|
|
89
|
-
|
|
90
|
-
for (let i = 0; i < data.length; ++i) {
|
|
91
|
-
sum += data[i].verticalAcc;
|
|
92
|
-
}
|
|
93
|
-
mean = sum / data.length;
|
|
94
|
-
return mean;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
stddev(data) {
|
|
98
|
-
const theMean = this.mean(data);
|
|
99
|
-
let standardDeviation = 0;
|
|
100
|
-
for (let i = 0; i < data.length; ++i) {
|
|
101
|
-
standardDeviation += (data[i].verticalAcc - theMean) ** 2;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return Math.sqrt(standardDeviation / data.length);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export default StepDetectionMinMaxPeaks2;
|
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
/* global Accelerometer, Gyroscope, Magnetometer, AbsoluteOrientationSensor, RelativeOrientationSensor */
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
deg2rad, rad2deg, Quaternion, Rotations
|
|
5
|
-
} from '@wemap/maths';
|
|
6
|
-
|
|
7
|
-
import SensorsLogger from './SensorsLogger';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const BROWSER = {
|
|
11
|
-
UNKNOWN: 0,
|
|
12
|
-
IOS_SAFARI: 1,
|
|
13
|
-
FIREFOX: 2,
|
|
14
|
-
OPERA: 3,
|
|
15
|
-
ANDROID_CHROME: 4,
|
|
16
|
-
ANDROID_STOCK: 5
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const defaultMotionSensors = {
|
|
20
|
-
accelerometer: true,
|
|
21
|
-
gyroscope: true,
|
|
22
|
-
magnetometer: true
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 5 April 2019
|
|
27
|
-
* The Generic Sensors API methods have been disabled due to a cross-origin problem.
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* 13 August 2019
|
|
31
|
-
* The Generic Sensors API methods have been disabled due to empty notifications when app is fullscreen and have no focus.
|
|
32
|
-
*/
|
|
33
|
-
const ENABLE_GENERIC_SENSORS_API = false;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Keep a trace of each instance for SensorsLogger
|
|
37
|
-
* TODO: Should be removed when logger will be updated with providers
|
|
38
|
-
*/
|
|
39
|
-
const instances = [];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// -----------------------------------
|
|
43
|
-
// -----------------------------------
|
|
44
|
-
// Overview of compatibilities:
|
|
45
|
-
// -----------------------------------
|
|
46
|
-
//
|
|
47
|
-
// --------
|
|
48
|
-
// Chrome Android (v72.0.3626)
|
|
49
|
-
// --------
|
|
50
|
-
// Accelerometer + Gyroscope: YES (via Sensors API if present or devicemotion otherwise)
|
|
51
|
-
// Relative orientation: YES (via RelativeOrientationSensor if present or deviceorientation otherwise but deviceorientation.alpha is unreliable! Sometimes it starts at 0°, sometimes at 270°)
|
|
52
|
-
// Absolute orientation: YES (via AbsoluteOrientationSensor if present or deviceorientationabsolute otherwise)
|
|
53
|
-
// --------
|
|
54
|
-
//
|
|
55
|
-
// --------
|
|
56
|
-
// Safari iOS (v12.0)
|
|
57
|
-
// --------
|
|
58
|
-
// Accelerometer + Gyroscope: YES (via devicemotion)
|
|
59
|
-
// Relative orientation: YES (via deviceorientation)
|
|
60
|
-
// Absolute orientation: YES (via deviceorientation and event.webkitCompassHeading)
|
|
61
|
-
// --------
|
|
62
|
-
//
|
|
63
|
-
// --------
|
|
64
|
-
// Opera (v50.2.2426)
|
|
65
|
-
// --------
|
|
66
|
-
// Accelerometer + Gyroscope: NO (https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent)
|
|
67
|
-
// Relative orientation: NO (https://developer.mozilla.org/en-US/docs/Web/API/Window/ondeviceorientation)
|
|
68
|
-
// Absolute orientation: NO (https://developer.mozilla.org/en-US/docs/Web/API/Window/ondeviceorientation)
|
|
69
|
-
// devicemotion and deviceorientation send only one callback and data is empty.
|
|
70
|
-
// --------
|
|
71
|
-
//
|
|
72
|
-
// --------
|
|
73
|
-
// Firefox (v65.0.1)
|
|
74
|
-
// --------
|
|
75
|
-
// Accelerometer + Gyroscope: YES (via devicemotion)
|
|
76
|
-
// Relative orientation: YES (via deviceorientation)
|
|
77
|
-
// Absolute orientation: NO (https://www.fxsitecompat.com/en-CA/docs/2018/various-device-sensor-apis-are-now-deprecated/)
|
|
78
|
-
// --------
|
|
79
|
-
// -----------------------------------
|
|
80
|
-
|
|
81
|
-
class SensorsCompatibility {
|
|
82
|
-
|
|
83
|
-
imuTickInterval = null;
|
|
84
|
-
|
|
85
|
-
constructor() {
|
|
86
|
-
this.browser = this.retrieveBrowser();
|
|
87
|
-
instances.push(this);
|
|
88
|
-
|
|
89
|
-
this.lastGyroscopeValue = null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Parse the user agent to get OS and browser so we know how to normalize values
|
|
93
|
-
retrieveBrowser() {
|
|
94
|
-
const userAgent = window.navigator.userAgent;
|
|
95
|
-
// IOS uses a special property
|
|
96
|
-
if (userAgent.match(/(iPad|iPhone|iPod)/i)) {
|
|
97
|
-
return BROWSER.IOS_SAFARI;
|
|
98
|
-
} else if (userAgent.match(/Firefox/i)) {
|
|
99
|
-
return BROWSER.FIREFOX;
|
|
100
|
-
} else if (userAgent.match(/Opera/i)) {
|
|
101
|
-
return BROWSER.OPERA;
|
|
102
|
-
} else if (userAgent.match(/Android/i)) {
|
|
103
|
-
// TODO: check with android_stock browser
|
|
104
|
-
return BROWSER.ANDROID_CHROME;
|
|
105
|
-
}
|
|
106
|
-
return BROWSER.UNKNOWN;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
setLogger(logger) {
|
|
110
|
-
|
|
111
|
-
if (logger && !(logger instanceof SensorsLogger)) {
|
|
112
|
-
throw new Error('logger is not an instance of SensorsLogger');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
this.logger = logger;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
static addLoggerOnKnownInstances(logger) {
|
|
119
|
-
instances.forEach(instance => instance.addLogger(logger));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
hasArSensors() {
|
|
123
|
-
return this.startAbsoluteOrientation(this.stopAbsoluteOrientation);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/*
|
|
127
|
-
* Manage Accelerometer - Gyroscope - Magnetometer
|
|
128
|
-
*/
|
|
129
|
-
|
|
130
|
-
startImu(callback, _sensors = defaultMotionSensors, frequency = 60) {
|
|
131
|
-
|
|
132
|
-
let isResolved = false;
|
|
133
|
-
|
|
134
|
-
const sensors = !_sensors ? defaultMotionSensors : _sensors;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (ENABLE_GENERIC_SENSORS_API) {
|
|
138
|
-
if (sensors.accelerometer && window.Accelerometer) {
|
|
139
|
-
this.accelerometerSensor = new Accelerometer({ frequency: frequency });
|
|
140
|
-
this.accelerometerSensor.start();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (sensors.gyroscope && window.Gyroscope) {
|
|
144
|
-
this.gyroscopeSensor = new Gyroscope({ frequency: frequency });
|
|
145
|
-
this.gyroscopeSensor.start();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (sensors.magnetometer && window.Magnetometer) {
|
|
149
|
-
this.magnetometerSensor = new Magnetometer({ frequency: frequency });
|
|
150
|
-
this.magnetometerSensor.start();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return new Promise((resolve) => {
|
|
155
|
-
|
|
156
|
-
const notifyFn = (output) => {
|
|
157
|
-
if (sensors.accelerometer && !output.acc
|
|
158
|
-
|| sensors.gyroscope && !output.gyr
|
|
159
|
-
|| sensors.magnetometer && !output.mag) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
callback(output);
|
|
164
|
-
|
|
165
|
-
if (this.logger) {
|
|
166
|
-
if (output.acc) {
|
|
167
|
-
this.logger.feed(SensorsLogger.DataType.ACCELEROMETER, output.timestamp, output.acc, true);
|
|
168
|
-
}
|
|
169
|
-
if (output.gyr) {
|
|
170
|
-
this.logger.feed(SensorsLogger.DataType.GYROSCOPE, output.timestamp, output.gyr, true);
|
|
171
|
-
}
|
|
172
|
-
if (output.mag) {
|
|
173
|
-
this.logger.feed(SensorsLogger.DataType.MAGNETOMETER, output.timestamp, output.mag, true);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (!isResolved) {
|
|
178
|
-
resolve();
|
|
179
|
-
isResolved = true;
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
if (this.accelerometerSensor || this.gyroscopeSensor || this.magnetometerSensor) {
|
|
184
|
-
|
|
185
|
-
// Create a scheduler using frequency parameter
|
|
186
|
-
const schedulerFn = () => {
|
|
187
|
-
this.imuTickInterval = setInterval(() => {
|
|
188
|
-
notifyFn(this.onImuTick());
|
|
189
|
-
}, 1 / frequency * 1000);
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
schedulerFn();
|
|
193
|
-
|
|
194
|
-
} else if (sensors.accelerometer || sensors.gyroscope || sensors.magnetometer) {
|
|
195
|
-
|
|
196
|
-
this.onDeviceMotionEventListener = (e) => {
|
|
197
|
-
notifyFn(this.onDeviceMotion(e));
|
|
198
|
-
};
|
|
199
|
-
window.addEventListener('devicemotion', this.onDeviceMotionEventListener, true);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
stopImu() {
|
|
206
|
-
|
|
207
|
-
if (this.imuTickInterval) {
|
|
208
|
-
clearInterval(this.imuTickInterval);
|
|
209
|
-
this.imuTickInterval = null;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (this.accelerometerSensor || this.gyroscopeSensor || this.magnetometerSensor) {
|
|
213
|
-
if (this.accelerometerSensor) {
|
|
214
|
-
this.accelerometerSensor.stop();
|
|
215
|
-
this.accelerometerSensor = null;
|
|
216
|
-
}
|
|
217
|
-
if (this.gyroscopeSensor) {
|
|
218
|
-
this.gyroscopeSensor.stop();
|
|
219
|
-
this.gyroscopeSensor = null;
|
|
220
|
-
}
|
|
221
|
-
if (this.magnetometerSensor) {
|
|
222
|
-
this.magnetometerSensor.stop();
|
|
223
|
-
this.magnetometerSensor = null;
|
|
224
|
-
}
|
|
225
|
-
} else if (this.onDeviceMotionEventListener) {
|
|
226
|
-
window.removeEventListener('devicemotion', this.onDeviceMotionEventListener, true);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
onImuTick() {
|
|
231
|
-
const acc = this.accelerometerSensor;
|
|
232
|
-
const accValues = acc && acc.x ? [acc.x, acc.y, acc.z] : null;
|
|
233
|
-
|
|
234
|
-
const gyr = this.gyroscopeSensor;
|
|
235
|
-
const gyrValues = gyr && gyr.x ? [gyr.x, gyr.y, gyr.z] : null;
|
|
236
|
-
|
|
237
|
-
const mag = this.magnetometerSensor;
|
|
238
|
-
const magValues = mag && mag.x ? [mag.x, mag.y, mag.z] : null;
|
|
239
|
-
|
|
240
|
-
let timestamp = 0;
|
|
241
|
-
if (accValues) {
|
|
242
|
-
timestamp = acc.timestamp;
|
|
243
|
-
} else if (gyrValues) {
|
|
244
|
-
timestamp = gyr.timestamp;
|
|
245
|
-
} else if (magValues) {
|
|
246
|
-
timestamp = mag.timestamp;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Alignment of acc and gyr is made by taking the last value of accelerometer, gyroscope and magnetometer.
|
|
250
|
-
// This is not perfect but far enough for almost all algorithms.
|
|
251
|
-
const output = {
|
|
252
|
-
timestamp: timestamp / 1e3,
|
|
253
|
-
acc: accValues,
|
|
254
|
-
gyr: gyrValues,
|
|
255
|
-
mag: magValues
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
return output;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Verified for IOS_SAFARI, ANDROID_CHROME, FIREFOX
|
|
263
|
-
* Not working for OPERA
|
|
264
|
-
* @param {DeviceMotionEvent} e device motion event
|
|
265
|
-
*/
|
|
266
|
-
onDeviceMotion(e) {
|
|
267
|
-
const timestamp = e.timeStamp / 1e3;
|
|
268
|
-
|
|
269
|
-
let acc = null;
|
|
270
|
-
|
|
271
|
-
if (e.accelerationIncludingGravity) {
|
|
272
|
-
const {
|
|
273
|
-
x, y, z
|
|
274
|
-
} = e.accelerationIncludingGravity;
|
|
275
|
-
|
|
276
|
-
if (x && y && z) {
|
|
277
|
-
acc = [x, y, z];
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (this.browser === BROWSER.IOS_SAFARI && acc) {
|
|
282
|
-
acc[0] *= -1;
|
|
283
|
-
acc[1] *= -1;
|
|
284
|
-
acc[2] *= -1;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
let gyr = null;
|
|
289
|
-
|
|
290
|
-
if (e.rotationRate) {
|
|
291
|
-
const {
|
|
292
|
-
alpha, beta, gamma
|
|
293
|
-
} = e.rotationRate;
|
|
294
|
-
|
|
295
|
-
if (alpha && beta && gamma) {
|
|
296
|
-
gyr = [alpha * Math.PI / 180, beta * Math.PI / 180, gamma * Math.PI / 180];
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const output = {
|
|
301
|
-
timestamp: timestamp,
|
|
302
|
-
acc: acc,
|
|
303
|
-
gyr: gyr,
|
|
304
|
-
mag: null
|
|
305
|
-
};
|
|
306
|
-
return output;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
/*
|
|
311
|
-
* Manage absolute orientation
|
|
312
|
-
*/
|
|
313
|
-
|
|
314
|
-
startAbsoluteOrientation(callback, frequency = 60) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
let isResolved = false;
|
|
318
|
-
|
|
319
|
-
return new Promise((resolve, reject) => {
|
|
320
|
-
|
|
321
|
-
const notifyFn = (timestamp, quaternion, extraData) => {
|
|
322
|
-
if (!quaternion) {
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
callback(quaternion, timestamp, extraData);
|
|
327
|
-
|
|
328
|
-
if (this.logger) {
|
|
329
|
-
this.logger.feed(SensorsLogger.DataType.DEVICE_ORIENTATION_ABSOLUTE, timestamp, quaternion, true);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (!isResolved) {
|
|
333
|
-
resolve();
|
|
334
|
-
isResolved = true;
|
|
335
|
-
}
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
if (ENABLE_GENERIC_SENSORS_API && window.AbsoluteOrientationSensor) {
|
|
339
|
-
// Cool! The device is compatible with Sensor_API.
|
|
340
|
-
|
|
341
|
-
this.absoluteOrientationSensor = new AbsoluteOrientationSensor({ frequency: frequency });
|
|
342
|
-
this.absoluteOrientationSensor.addEventListener('reading', (e) => {
|
|
343
|
-
if (!e.target.quaternion) {
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
notifyFn(e.timeStamp, Quaternion.xyzw2wxyz(e.target.quaternion));
|
|
347
|
-
});
|
|
348
|
-
this.absoluteOrientationSensor.start();
|
|
349
|
-
|
|
350
|
-
} else {
|
|
351
|
-
|
|
352
|
-
switch (this.browser) {
|
|
353
|
-
|
|
354
|
-
case BROWSER.ANDROID_CHROME:
|
|
355
|
-
|
|
356
|
-
this.onDeviceOrientationAbsoluteEventListener = (e) => {
|
|
357
|
-
if (!e.alpha || !e.beta || !e.gamma) {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
notifyFn(e.timeStamp / 1e3, Rotations.eulerToQuaternionZXYDegrees([e.alpha, e.beta, e.gamma]));
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
window.addEventListener('deviceorientationabsolute', this.onDeviceOrientationAbsoluteEventListener, true);
|
|
364
|
-
|
|
365
|
-
break;
|
|
366
|
-
|
|
367
|
-
case BROWSER.IOS_SAFARI:
|
|
368
|
-
|
|
369
|
-
this.onDeviceOrientationAbsoluteSafariEventListener = (e) => {
|
|
370
|
-
|
|
371
|
-
if (!e.webkitCompassHeading || !e.beta || !e.gamma) {
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
let webkitCompassHeading = -e.webkitCompassHeading;
|
|
376
|
-
if (e.beta > 62) {
|
|
377
|
-
webkitCompassHeading = SensorsCompatibility.headingEusToEnu(180 - webkitCompassHeading, e.beta, e.gamma);
|
|
378
|
-
}
|
|
379
|
-
const quaternion = Rotations.eulerToQuaternionZXYDegrees([webkitCompassHeading, e.beta, e.gamma]);
|
|
380
|
-
notifyFn(e.timeStamp / 1e3, quaternion, { 'webkitCompassHeading': e.webkitCompassHeading });
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
window.addEventListener('deviceorientation', this.onDeviceOrientationAbsoluteSafariEventListener, true);
|
|
384
|
-
|
|
385
|
-
// Be Careful: webkitCompassHeading is not continuous.
|
|
386
|
-
// It value changes with thresholds: beta > 30deg and beta < 62deg
|
|
387
|
-
console.warn('[Sensors] Be careful, you are using webkitCompassHeading on iOS and this method is unreliable (not continuous)');
|
|
388
|
-
|
|
389
|
-
break;
|
|
390
|
-
|
|
391
|
-
default:
|
|
392
|
-
reject(new Error('Your browser cannot provide absolute orientation or we do not know how to parse its data'));
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
stopAbsoluteOrientation() {
|
|
399
|
-
if (this.absoluteOrientationSensor) {
|
|
400
|
-
this.absoluteOrientationSensor.stop();
|
|
401
|
-
this.absoluteOrientationSensor = null;
|
|
402
|
-
} else if (this.onDeviceOrientationAbsoluteEventListener) {
|
|
403
|
-
window.removeEventListener('deviceorientationabsolute', this.onDeviceOrientationAbsoluteEventListener, true);
|
|
404
|
-
} else if (this.onDeviceOrientationAbsoluteSafariEventListener) {
|
|
405
|
-
window.removeEventListener('deviceorientation', this.onDeviceOrientationAbsoluteSafariEventListener, true);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
static headingEusToEnu(_alpha, _beta, _gamma) {
|
|
410
|
-
const alpha = deg2rad(_alpha);
|
|
411
|
-
const beta = deg2rad(_beta);
|
|
412
|
-
const gamma = deg2rad(_gamma);
|
|
413
|
-
|
|
414
|
-
return rad2deg(Math.atan2(
|
|
415
|
-
Math.cos(alpha) * Math.sin(gamma) + Math.cos(gamma) * Math.sin(alpha) * Math.sin(beta),
|
|
416
|
-
Math.sin(alpha) * Math.sin(gamma) - Math.cos(alpha) * Math.cos(gamma) * Math.sin(beta)));
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/*
|
|
420
|
-
* Manage relative orientation
|
|
421
|
-
*/
|
|
422
|
-
|
|
423
|
-
startRelativeOrientation(callback, frequency = 60) {
|
|
424
|
-
|
|
425
|
-
let isResolved = false;
|
|
426
|
-
|
|
427
|
-
return new Promise((resolve) => {
|
|
428
|
-
|
|
429
|
-
const notifyFn = (timestamp, quaternion) => {
|
|
430
|
-
if (!quaternion) {
|
|
431
|
-
return;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
if (!isResolved) {
|
|
435
|
-
resolve();
|
|
436
|
-
isResolved = true;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
callback(quaternion, timestamp);
|
|
440
|
-
|
|
441
|
-
if (this.logger) {
|
|
442
|
-
this.logger.feed(SensorsLogger.DataType.DEVICE_ORIENTATION_RELATIVE, timestamp, quaternion, true);
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
if (ENABLE_GENERIC_SENSORS_API && window.RelativeOrientationSensor) {
|
|
447
|
-
// Cool! The device is compatible with Sensor_API.
|
|
448
|
-
|
|
449
|
-
this.relativeOrientationSensor = new RelativeOrientationSensor({ frequency: frequency });
|
|
450
|
-
this.relativeOrientationSensor.addEventListener('reading', (e) => {
|
|
451
|
-
if (!e.target.quaternion) {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
notifyFn(e.timeStamp / 1e3, Quaternion.xyzw2wxyz(e.target.quaternion));
|
|
455
|
-
});
|
|
456
|
-
this.relativeOrientationSensor.start();
|
|
457
|
-
|
|
458
|
-
} else {
|
|
459
|
-
|
|
460
|
-
this.onDeviceOrientationRelativeEventListener = (e) => {
|
|
461
|
-
if (!e.alpha || !e.beta || !e.gamma) {
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
notifyFn(e.timeStamp / 1e3, Rotations.eulerToQuaternionZXYDegrees([e.alpha, e.beta, e.gamma]));
|
|
465
|
-
};
|
|
466
|
-
window.addEventListener('deviceorientation', this.onDeviceOrientationRelativeEventListener, true);
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (this.browser === BROWSER.ANDROID_CHROME) {
|
|
471
|
-
console.warn('[Sensors] Be careful, you are using relative orientation on Android Chrome and this method is unreliable');
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
stopRelativeOrientation() {
|
|
477
|
-
if (this.relativeOrientationSensor) {
|
|
478
|
-
this.relativeOrientationSensor.stop();
|
|
479
|
-
this.relativeOrientationSensor = null;
|
|
480
|
-
} else if (this.onDeviceOrientationRelativeEventListener) {
|
|
481
|
-
window.removeEventListener('deviceorientation', this.onDeviceOrientationRelativeEventListener, true);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
export default SensorsCompatibility;
|