@wemap/positioning 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +4 -2
- package/debug/absolute-attitude.html +16 -0
- package/debug/arcore.html +16 -0
- package/debug/gnss-wifi-pdr.html +16 -0
- package/debug/gnss-wifi.html +16 -0
- package/debug/imu.html +16 -0
- package/debug/inclination.html +16 -0
- package/debug/pdr.html +16 -0
- package/debug/pose.html +16 -0
- package/debug/positioning.html +16 -0
- package/debug/relative-attitude.html +16 -0
- package/package.json +7 -4
- package/src/PositioningHandler.js +96 -34
- package/src/components/AbsoluteAttitudeComponent.jsx +104 -0
- package/src/components/ArCoreComponent.jsx +74 -0
- package/src/components/GnssWifiComponent.jsx +58 -0
- package/src/components/GnssWifiPdrComponent.jsx +94 -0
- package/src/components/ImuComponent.jsx +100 -0
- package/src/components/InclinationComponent.jsx +53 -0
- package/src/components/MapComponent.jsx +226 -0
- package/src/components/PdrComponent.jsx +97 -0
- package/src/components/PoseComponent.jsx +81 -0
- package/src/components/PositioningComponent.jsx +26 -0
- package/src/components/PositioningInclinationComponent.jsx +76 -0
- package/src/components/PositioningPoseComponent.jsx +120 -0
- package/src/components/RelativeAttitudeComponent.jsx +82 -0
- package/src/components/StartStopComponent.jsx +50 -0
- package/src/components/Utils.js +92 -0
- package/src/components/index.js +32 -0
- package/src/errors/AskImuOnDesktopError.js +9 -0
- package/src/errors/GeolocationApiMissingError.js +9 -0
- package/src/errors/GeolocationPermissionDeniedError.js +9 -0
- package/src/errors/GeolocationPositionUnavailableError.js +9 -0
- package/src/errors/IpResolveServerError.js +9 -0
- package/src/errors/MissingAccelerometerError.js +11 -0
- package/src/errors/MissingArCoreError.js +9 -0
- package/src/errors/MissingGyroscopeError.js +11 -0
- package/src/errors/MissingMagnetometerError.js +9 -0
- package/src/errors/MissingNativeInterfaceError.js +9 -0
- package/src/errors/MissingSensorError.js +14 -0
- package/src/events/EventType.js +20 -0
- package/src/events/ProviderError.js +52 -0
- package/src/events/ProviderEvent.js +35 -0
- package/src/index.js +2 -2
- package/src/providers/Constants.js +5 -0
- package/src/providers/FakeAbsolutePositionProvider.js +56 -0
- package/src/providers/Provider.js +230 -0
- package/src/providers/ProviderOptions.js +28 -0
- package/{src.old → src}/providers/ProvidersLogger.js +2 -2
- package/src/providers/attitude/AbsoluteAttitudeProvider.js +207 -0
- package/src/providers/attitude/RelativeAttitudeProvider.js +129 -0
- package/src/providers/others/ImuProvider.js +186 -0
- package/src/providers/others/InclinationProvider.js +107 -0
- package/{src.old/providers/LocationSource.js → src/providers/others/MapMatchingProvider.js} +5 -148
- package/src/providers/pose/ArCoreProvider.js +127 -0
- package/src/providers/pose/GnssWifiPdrProvider.js +233 -0
- package/src/providers/pose/PoseProvider.js +90 -0
- package/{src.old/providers/PdrLocationSource.js → src/providers/pose/pdr/PdrProvider.js} +145 -113
- package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/Smoother.js +1 -1
- package/src/providers/position/GnssWifiProvider.js +129 -0
- package/src/providers/position/IpProvider.js +75 -0
- package/webpack/webpack.common.js +1 -1
- package/webpack/webpack.dev.js +1 -1
- package/debug/index.html +0 -15
- package/debug/index.old.html +0 -37
- package/scripts/release-github.js +0 -216
- package/src/providers/FakeLocationSource.js +0 -36
- package/src.old/Constants.js +0 -11
- package/src.old/NavigationHandler.js +0 -244
- package/src.old/Pose.js +0 -8
- package/src.old/attitude/AttitudeHandler.js +0 -342
- package/src.old/components/AbsoluteAttitude.jsx +0 -136
- package/src.old/components/Imu.jsx +0 -89
- package/src.old/components/LocationSource.jsx +0 -434
- package/src.old/components/Logger.jsx +0 -113
- package/src.old/components/NavigationDebugApp.jsx +0 -106
- package/src.old/components/Others.jsx +0 -121
- package/src.old/components/RelativeAttitude.jsx +0 -104
- package/src.old/components/Utils.js +0 -35
- package/src.old/components/index.js +0 -13
- package/src.old/index.js +0 -7
- package/src.old/providers/FixedLocationImuLocationSource.js +0 -66
- package/src.old/providers/GnssLocationSource.js +0 -118
- package/src.old/providers/GnssPdrLocationSource.js +0 -182
- package/src.old/providers/IPLocationSource.js +0 -96
- package/src.old/sensors/SensorsCompatibility.js +0 -486
- package/src.old/sensors/SensorsCompatibility.spec.js +0 -270
- package/src.old/sensors/SensorsLogger.js +0 -94
- package/src.old/sensors/SensorsLoggerUtils.js +0 -35
- /package/{src.old → src/providers}/attitude/EkfAttitude.js +0 -0
- /package/{src.old → src/providers}/attitude/EkfAttitude.spec.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/HeadingUnlocker.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/HeadingUnlocker.spec.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/Smoother.spec.js +0 -0
- /package/{src.old/providers/pdr → src/providers/pose/pdr/helpers}/ThugDetector.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetection.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionLadetto.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionMinMaxPeaks.js +0 -0
- /package/{src.old/providers → src/providers/pose/pdr}/steps/StepDetectionMinMaxPeaks2.js +0 -0
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import noop from 'lodash.noop';
|
|
2
|
-
|
|
3
|
-
import { WGS84UserPosition, Itinerary } from '@wemap/geo';
|
|
4
|
-
|
|
5
|
-
import LocationSource from './providers/LocationSource';
|
|
6
|
-
import IPLocationSource from './providers/IPLocationSource';
|
|
7
|
-
import GnssLocationSource from './providers/GnssLocationSource';
|
|
8
|
-
import PdrLocationSource from './providers/PdrLocationSource';
|
|
9
|
-
import GnssPdrLocationSource from './providers/GnssPdrLocationSource';
|
|
10
|
-
import FixedLocationImuLocationSource from './providers/FixedLocationImuLocationSource';
|
|
11
|
-
import SensorsLogger from './sensors/SensorsLogger';
|
|
12
|
-
|
|
13
|
-
const DEFAULT_ALTITUDE = 1.6;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @private
|
|
17
|
-
*/
|
|
18
|
-
class NavigationHandler {
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Constructor of NavigationHandler
|
|
22
|
-
* @param {Function} callbackOnStart callback when navigation starts
|
|
23
|
-
* @param {Function} callbackOnStop callback when navigation stops
|
|
24
|
-
* @param {Function} callbackOnNewPose callback on new pose
|
|
25
|
-
* @public
|
|
26
|
-
*/
|
|
27
|
-
constructor(callbackOnStart, callbackOnStop, callbackOnNewPose) {
|
|
28
|
-
this.callback = this.callback.bind(this);
|
|
29
|
-
|
|
30
|
-
this.callbackOnStart = callbackOnStart || noop;
|
|
31
|
-
this.callbackOnStop = callbackOnStop || noop;
|
|
32
|
-
this.callbackOnNewPose = callbackOnNewPose || noop;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Starts navigation from an initial position an initial heading
|
|
38
|
-
* @param {*} initialPosition initial position {lat: xx, lng: xx}
|
|
39
|
-
* @param {Number} initialHeading initial heading in radians and clockwise: north: 0, east = PI/2
|
|
40
|
-
* @param {Array} path an optional itinerary (list of 2D points [lng, lat])
|
|
41
|
-
* @public
|
|
42
|
-
*/
|
|
43
|
-
startRelative(initialPosition, initialHeading, path = null) {
|
|
44
|
-
|
|
45
|
-
const initialPositionWgs84 = new WGS84UserPosition(
|
|
46
|
-
initialPosition.lat,
|
|
47
|
-
initialPosition.lng,
|
|
48
|
-
initialPosition.alt || DEFAULT_ALTITUDE
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
// stop current location source if already started
|
|
52
|
-
if (this.locationSource) {
|
|
53
|
-
this.locationSource.stop();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
this.locationSource = new PdrLocationSource(this.callback, {
|
|
57
|
-
'stepdetectionlocker': true,
|
|
58
|
-
'smoother': true
|
|
59
|
-
});
|
|
60
|
-
this.locationSource.setLogger(this.logger);
|
|
61
|
-
|
|
62
|
-
if (path) {
|
|
63
|
-
const itinerary = Itinerary.fromPoints(path);
|
|
64
|
-
this.locationSource.enableMapMatching(itinerary);
|
|
65
|
-
this.locationSource.setItinerary(itinerary);
|
|
66
|
-
}
|
|
67
|
-
this.locationSource.setLocation(initialPositionWgs84);
|
|
68
|
-
this.locationSource.setHeading(initialHeading);
|
|
69
|
-
const promise = this.locationSource.start();
|
|
70
|
-
|
|
71
|
-
this.callbackOnStart();
|
|
72
|
-
return promise;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Starts navigation handler without any knowledge on starting point
|
|
77
|
-
* @param {Array} path an optional itinerary (list of 2D points [lng, lat])
|
|
78
|
-
* @public
|
|
79
|
-
*/
|
|
80
|
-
startAbsolute(path) {
|
|
81
|
-
// stop if already started
|
|
82
|
-
if (this.locationSource) {
|
|
83
|
-
this.locationSource.stop();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const itinerary = Itinerary.fromPoints(path);
|
|
87
|
-
this.locationSource = new GnssPdrLocationSource(this.callback);
|
|
88
|
-
this.locationSource.enableMapMatching(itinerary);
|
|
89
|
-
this.locationSource.setItinerary(itinerary);
|
|
90
|
-
this.locationSource.setLogger(this.logger);
|
|
91
|
-
|
|
92
|
-
const promise = this.locationSource.start();
|
|
93
|
-
this.callbackOnStart();
|
|
94
|
-
return promise;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
locateme(
|
|
98
|
-
options = {
|
|
99
|
-
ip: true,
|
|
100
|
-
browser: true,
|
|
101
|
-
attitude: true
|
|
102
|
-
}
|
|
103
|
-
) {
|
|
104
|
-
const useIPProvider = !options.hasOwnProperty('ip') || options.ip === true;
|
|
105
|
-
const useBrowserProvider = !options.hasOwnProperty('browser') || options.browser === true;
|
|
106
|
-
const useImu = !options.hasOwnProperty('attitude') || options.attitude === true;
|
|
107
|
-
|
|
108
|
-
return new Promise((resolve, reject) => {
|
|
109
|
-
const gnss = new GnssLocationSource(pose => {
|
|
110
|
-
resolve(pose);
|
|
111
|
-
this.callback(pose);
|
|
112
|
-
}, useImu);
|
|
113
|
-
|
|
114
|
-
const ip = new IPLocationSource(pose => {
|
|
115
|
-
resolve(pose);
|
|
116
|
-
this.callback(pose);
|
|
117
|
-
}, useImu);
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
this.locationSource
|
|
121
|
-
&& LocationSource.getMostAccurateLocationSource(this.locationSource, gnss) === this.locationSource
|
|
122
|
-
) {
|
|
123
|
-
resolve(this.locationSource.getPose());
|
|
124
|
-
} else {
|
|
125
|
-
if (this.locationSource) {
|
|
126
|
-
this.locationSource.stop();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (useBrowserProvider) {
|
|
130
|
-
this.locationSource = gnss;
|
|
131
|
-
gnss.start().catch(e => {
|
|
132
|
-
if (useIPProvider) {
|
|
133
|
-
this.locationSource = ip;
|
|
134
|
-
ip.start();
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
reject(e);
|
|
138
|
-
});
|
|
139
|
-
} else if (useIPProvider) {
|
|
140
|
-
this.locationSource = ip;
|
|
141
|
-
ip.start();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Stop relative, absolute or locateme navigation if started
|
|
150
|
-
* @public
|
|
151
|
-
*/
|
|
152
|
-
stop() {
|
|
153
|
-
if (
|
|
154
|
-
this.locationSource
|
|
155
|
-
) {
|
|
156
|
-
this.locationSource.stop();
|
|
157
|
-
this.locationSource = null;
|
|
158
|
-
}
|
|
159
|
-
this.callbackOnStop();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* @see LocationSource#getProjectionOnNetwork()
|
|
165
|
-
* @public
|
|
166
|
-
*/
|
|
167
|
-
getProjectionOnNetwork(location) {
|
|
168
|
-
return this.locationSource.getProjectionOnNetwork(location);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* @see LocationSource#getItineraryInfo()
|
|
173
|
-
* @public
|
|
174
|
-
*/
|
|
175
|
-
getItineraryInfo(location) {
|
|
176
|
-
return this.locationSource.getItineraryInfo(location);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
forceUserLocation(location) {
|
|
180
|
-
if (
|
|
181
|
-
this.locationSource
|
|
182
|
-
&& (!(this.locationSource instanceof FixedLocationImuLocationSource) || !location)
|
|
183
|
-
) {
|
|
184
|
-
this.locationSource.stop();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (location) {
|
|
188
|
-
if (
|
|
189
|
-
!this.locationSource
|
|
190
|
-
|| !(this.locationSource instanceof FixedLocationImuLocationSource)
|
|
191
|
-
) {
|
|
192
|
-
this.locationSource = new FixedLocationImuLocationSource(this.callback);
|
|
193
|
-
this.locationSource.start(location);
|
|
194
|
-
} else {
|
|
195
|
-
this.locationSource.setLocation(location);
|
|
196
|
-
}
|
|
197
|
-
} else {
|
|
198
|
-
this.locationSource = null;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* @private
|
|
204
|
-
*/
|
|
205
|
-
callback(pose) {
|
|
206
|
-
this.callbackOnNewPose(pose);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Assign a SensorsLogger to LocationSource and start recording.
|
|
211
|
-
* This logger will be fed with sensors output.
|
|
212
|
-
* Logger is not working on locateme()
|
|
213
|
-
* @param {SensorsLogger} logger An instance of SensorsLogger.
|
|
214
|
-
* @public
|
|
215
|
-
*/
|
|
216
|
-
startLogger(logger) {
|
|
217
|
-
if (!(logger instanceof SensorsLogger)) {
|
|
218
|
-
throw new Error('logger is not an instance of SensorsLogger');
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
this.logger = logger;
|
|
222
|
-
|
|
223
|
-
if (this.locationSource) {
|
|
224
|
-
this.locationSource.setLogger(this.logger);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Stop recording sensors
|
|
230
|
-
* @public
|
|
231
|
-
*/
|
|
232
|
-
stopLogger() {
|
|
233
|
-
this.logger = null;
|
|
234
|
-
if (this.locationSource) {
|
|
235
|
-
this.locationSource.setLogger(this.logger);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
static get DEFAULT_ALTITUDE() {
|
|
240
|
-
return DEFAULT_ALTITUDE;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export default NavigationHandler;
|
package/src.old/Pose.js
DELETED
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
import geomagnetism from 'geomagnetism';
|
|
2
|
-
|
|
3
|
-
import { Attitude } from '@wemap/geo';
|
|
4
|
-
import {
|
|
5
|
-
deg2rad, Quaternion
|
|
6
|
-
} from '@wemap/maths';
|
|
7
|
-
|
|
8
|
-
import EkfAttitude from './EkfAttitude';
|
|
9
|
-
import SensorsCompatibility from '../sensors/SensorsCompatibility';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const RelativeMethod = {
|
|
13
|
-
AUTOMATIC: 0,
|
|
14
|
-
BROWSER: 1,
|
|
15
|
-
INTERNAL_EKF: 2
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const AbsoluteMethod = {
|
|
19
|
-
AUTOMATIC: 0,
|
|
20
|
-
BROWSER: 1,
|
|
21
|
-
INTERNAL_EKF: 2,
|
|
22
|
-
INTERNAL_CUSTOM: 3
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class AttitudeHandler {
|
|
27
|
-
|
|
28
|
-
isRelativeStarted = false;
|
|
29
|
-
|
|
30
|
-
constructor() {
|
|
31
|
-
this.sensorsCompatibility = new SensorsCompatibility();
|
|
32
|
-
this.relativeOffsetQuaternion = [1, 0, 0, 0];
|
|
33
|
-
this.ekfAttitude = new EkfAttitude();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
static get RelativeMethod() {
|
|
37
|
-
return RelativeMethod;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
static get AbsoluteMethod() {
|
|
41
|
-
return AbsoluteMethod;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setLogger(logger) {
|
|
45
|
-
this.sensorsCompatibility.setLogger(logger);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
startRelative(callback, method = RelativeMethod.INTERNAL_EKF) {
|
|
49
|
-
|
|
50
|
-
if (method === RelativeMethod.AUTOMATIC) {
|
|
51
|
-
throw new Error('Do not use automatic method for the moment');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
let promise;
|
|
55
|
-
|
|
56
|
-
this.relativeMethodAnswer = false;
|
|
57
|
-
|
|
58
|
-
const fn = (quaternion, timestamp) => {
|
|
59
|
-
if (quaternion) {
|
|
60
|
-
callback(new Attitude(quaternion), timestamp);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
this.relativeMethod = method;
|
|
65
|
-
|
|
66
|
-
if (method === RelativeMethod.AUTOMATIC) {
|
|
67
|
-
|
|
68
|
-
promise = new Promise((resolve, reject) => {
|
|
69
|
-
// Try internal EKF first
|
|
70
|
-
this.startRelative(callback, RelativeMethod.INTERNAL_EKF)
|
|
71
|
-
.then(resolve)
|
|
72
|
-
.catch(() => {
|
|
73
|
-
this.stopRelative();
|
|
74
|
-
// If EKF did not work, try Browser method
|
|
75
|
-
this.startRelative(callback, RelativeMethod.BROWSER)
|
|
76
|
-
.then(resolve)
|
|
77
|
-
.catch(() => {
|
|
78
|
-
this.stopRelative();
|
|
79
|
-
reject();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
} else if (method === RelativeMethod.BROWSER) {
|
|
85
|
-
|
|
86
|
-
promise = this.sensorsCompatibility.startRelativeOrientation((quaternion, timestamp) => {
|
|
87
|
-
quaternion = Quaternion.multiply(this.relativeOffsetQuaternion, quaternion);
|
|
88
|
-
fn(quaternion, timestamp);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
} else if (method === RelativeMethod.INTERNAL_EKF) {
|
|
92
|
-
|
|
93
|
-
let lastTimestamp = 0;
|
|
94
|
-
promise = this.sensorsCompatibility.startImu(accGyrEvent => {
|
|
95
|
-
const timestamp = accGyrEvent.timestamp;
|
|
96
|
-
const acc = accGyrEvent.acc;
|
|
97
|
-
const gyr = accGyrEvent.gyr;
|
|
98
|
-
|
|
99
|
-
// Handle timestamps and dt
|
|
100
|
-
if (lastTimestamp === 0) {
|
|
101
|
-
lastTimestamp = timestamp;
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const diffTime = timestamp - lastTimestamp;
|
|
105
|
-
lastTimestamp = timestamp;
|
|
106
|
-
const quaternion = this.ekfAttitude.update(diffTime, acc, gyr);
|
|
107
|
-
fn(quaternion, timestamp);
|
|
108
|
-
}, {
|
|
109
|
-
accelerometer: true,
|
|
110
|
-
gyroscope: true
|
|
111
|
-
});
|
|
112
|
-
} else {
|
|
113
|
-
return Promise.reject();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
this.isRelativeStarted = true;
|
|
117
|
-
|
|
118
|
-
return promise;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
stopRelative() {
|
|
123
|
-
this.isRelativeStarted = false;
|
|
124
|
-
|
|
125
|
-
if (this.relativeMethod === RelativeMethod.BROWSER) {
|
|
126
|
-
this.sensorsCompatibility.stopRelativeOrientation();
|
|
127
|
-
} else if (this.relativeMethod === RelativeMethod.INTERNAL_EKF) {
|
|
128
|
-
this.sensorsCompatibility.stopImu();
|
|
129
|
-
}
|
|
130
|
-
this.relativeMethod = null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
*
|
|
136
|
-
* Set yaw offset, this value will be used as the filter does not use magnetometer
|
|
137
|
-
* @param {Number} heading heading offset in radians and clockwise
|
|
138
|
-
*/
|
|
139
|
-
setRelativeHeading(heading) {
|
|
140
|
-
|
|
141
|
-
// Minus before "heading" is here because ENU attitude is counter-clockwise whereas WGS84 heading is clockwise.
|
|
142
|
-
heading = -heading;
|
|
143
|
-
|
|
144
|
-
// Offset from window orientation
|
|
145
|
-
heading += deg2rad(window.orientation || 0);
|
|
146
|
-
|
|
147
|
-
// // We don't know the method used, so we set both
|
|
148
|
-
this.relativeOffsetQuaternion = Quaternion.fromAxisAngle([0, 0, 1], heading);
|
|
149
|
-
|
|
150
|
-
// We don't know the method used, so we set both
|
|
151
|
-
this.ekfAttitude.setOrientationYaw(heading);
|
|
152
|
-
|
|
153
|
-
if (this.relativeMethod === RelativeMethod.BROWSER && this.relativeMethodAnswer) {
|
|
154
|
-
this.stopRelative();
|
|
155
|
-
return this.startRelative(this.relativeCallback, RelativeMethod.BROWSER);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return Promise.resolve();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
startAbsolute(callback, method = AbsoluteMethod.BROWSER) {
|
|
163
|
-
|
|
164
|
-
if (method === AbsoluteMethod.AUTOMATIC) {
|
|
165
|
-
throw new Error('Do not use automatic method for the moment');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
let promise;
|
|
169
|
-
|
|
170
|
-
this.absoluteMethodAnswer = false;
|
|
171
|
-
|
|
172
|
-
const fn = (quaternion, timestamp, externalData) => {
|
|
173
|
-
if (!quaternion || !this.declinationQuaternion) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
const trueQuaternion = Quaternion.multiply(this.declinationQuaternion, quaternion);
|
|
177
|
-
callback(new Attitude(trueQuaternion), timestamp, externalData);
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
this.absoluteMethod = method;
|
|
181
|
-
|
|
182
|
-
if (method === AbsoluteMethod.AUTOMATIC) {
|
|
183
|
-
|
|
184
|
-
promise = new Promise((resolve, reject) => {
|
|
185
|
-
|
|
186
|
-
// Try internal EKF first
|
|
187
|
-
this.startAbsolute(callback, AbsoluteMethod.INTERNAL_EKF).catch(() => {
|
|
188
|
-
this.stopAbsolute();
|
|
189
|
-
|
|
190
|
-
// If EKF did not work, try internal custom method
|
|
191
|
-
this.startAbsolute(callback, AbsoluteMethod.INTERNAL_CUSTOM).catch(() => {
|
|
192
|
-
this.stopAbsolute();
|
|
193
|
-
|
|
194
|
-
// If internal custom did not work, try Browser method
|
|
195
|
-
this.startAbsolute(callback, AbsoluteMethod.BROWSER).catch(() => {
|
|
196
|
-
|
|
197
|
-
this.stopAbsolute();
|
|
198
|
-
reject();
|
|
199
|
-
|
|
200
|
-
}).then(resolve);
|
|
201
|
-
|
|
202
|
-
}).then(resolve);
|
|
203
|
-
|
|
204
|
-
}).then(resolve);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
} else if (method === AbsoluteMethod.INTERNAL_CUSTOM) {
|
|
208
|
-
|
|
209
|
-
let lastAttitude;
|
|
210
|
-
let isFirst = true;
|
|
211
|
-
|
|
212
|
-
promise = new Promise((resolve, reject) => {
|
|
213
|
-
|
|
214
|
-
const startRelativeFn = (heading) => {
|
|
215
|
-
this.stopAbsolute();
|
|
216
|
-
|
|
217
|
-
// Mandatory, otherwise this.absoluteMethod is null and cannot be stopped
|
|
218
|
-
this.absoluteMethod = AbsoluteMethod.INTERNAL_CUSTOM;
|
|
219
|
-
|
|
220
|
-
this.startRelative(callback)
|
|
221
|
-
.then(resolve)
|
|
222
|
-
.catch(() => {
|
|
223
|
-
this.stopRelative();
|
|
224
|
-
reject();
|
|
225
|
-
});
|
|
226
|
-
this.setRelativeHeading(heading);
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const customCallback = (attitude, timestamp, externalData) => {
|
|
230
|
-
lastAttitude = attitude;
|
|
231
|
-
|
|
232
|
-
if (isFirst) {
|
|
233
|
-
this.timeoutAbsoluteFirstMillis = setTimeout(() => {
|
|
234
|
-
startRelativeFn(externalData && externalData.webkitCompassHeading
|
|
235
|
-
? deg2rad(externalData.webkitCompassHeading)
|
|
236
|
-
: lastAttitude.heading);
|
|
237
|
-
}, 300);
|
|
238
|
-
|
|
239
|
-
isFirst = false;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
this.startAbsolute(customCallback, AbsoluteMethod.BROWSER)
|
|
245
|
-
.catch(() => {
|
|
246
|
-
this.stopAbsolute();
|
|
247
|
-
reject();
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
} else if (method === AbsoluteMethod.BROWSER) {
|
|
252
|
-
promise = this.sensorsCompatibility.startAbsoluteOrientation((quaternion, timestamp, externalData) => {
|
|
253
|
-
fn(quaternion, timestamp, externalData);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
} else if (method === AbsoluteMethod.INTERNAL_EKF) {
|
|
257
|
-
let lastTimestamp = 0;
|
|
258
|
-
promise = this.sensorsCompatibility.startImu(accGyrMagEvent => {
|
|
259
|
-
const timestamp = accGyrMagEvent.timestamp;
|
|
260
|
-
const acc = accGyrMagEvent.acc;
|
|
261
|
-
const gyr = accGyrMagEvent.gyr;
|
|
262
|
-
const mag = accGyrMagEvent.mag;
|
|
263
|
-
|
|
264
|
-
// Handle timestamps and dt
|
|
265
|
-
if (lastTimestamp === 0) {
|
|
266
|
-
lastTimestamp = timestamp;
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
const diffTime = timestamp - lastTimestamp;
|
|
270
|
-
lastTimestamp = timestamp;
|
|
271
|
-
const quaternion = this.ekfAttitude.update(diffTime, acc, gyr, mag);
|
|
272
|
-
fn(quaternion, timestamp);
|
|
273
|
-
});
|
|
274
|
-
} else {
|
|
275
|
-
promise = Promise.reject();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return promise;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
stopAbsolute() {
|
|
282
|
-
if (this.absoluteMethod === AbsoluteMethod.BROWSER) {
|
|
283
|
-
this.sensorsCompatibility.stopAbsoluteOrientation();
|
|
284
|
-
} else if (this.absoluteMethod === AbsoluteMethod.INTERNAL_EKF) {
|
|
285
|
-
this.sensorsCompatibility.stopImu();
|
|
286
|
-
} else if (this.absoluteMethod === AbsoluteMethod.INTERNAL_CUSTOM) {
|
|
287
|
-
this.stopRelative();
|
|
288
|
-
}
|
|
289
|
-
if (this.timeoutAbsoluteFirstMillis) {
|
|
290
|
-
clearTimeout(this.timeoutAbsoluteFirstMillis);
|
|
291
|
-
this.timeoutAbsoluteFirstMillis = null;
|
|
292
|
-
}
|
|
293
|
-
this.absoluteMethod = null;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// This method should be theoretically called every time the user moves.
|
|
297
|
-
// But in reality declination does not change as much.
|
|
298
|
-
setUserLocationForAbsolute(userLocation) {
|
|
299
|
-
const wmmResult = geomagnetism.model().point([userLocation.lat, userLocation.lng]);
|
|
300
|
-
// Declination is given in NED frame and our code use ENU, that is why we have: "-decl"
|
|
301
|
-
this.declinationQuaternion = Quaternion.fromAxisAngle([0, 0, 1], - deg2rad(wmmResult.decl));
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
startMonitoringInclination(callback) {
|
|
305
|
-
|
|
306
|
-
this.sensorsCompatibilityInclination = new SensorsCompatibility();
|
|
307
|
-
|
|
308
|
-
return this.sensorsCompatibility.startImu(({ acc }) => {
|
|
309
|
-
|
|
310
|
-
const screenOrientation = window.orientation || 0;
|
|
311
|
-
|
|
312
|
-
const sizeAcc = Math.sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
|
|
313
|
-
const accNormalized = [acc[0] / sizeAcc, acc[1] / sizeAcc, acc[2] / sizeAcc];
|
|
314
|
-
|
|
315
|
-
const q = [accNormalized[2] + 1, accNormalized[1], -accNormalized[0], 0];
|
|
316
|
-
const qSize = Math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
|
|
317
|
-
const qNormalized = [q[0] / qSize, q[1] / qSize, q[2] / qSize, 0];
|
|
318
|
-
|
|
319
|
-
let inclination;
|
|
320
|
-
if (screenOrientation === 0) {
|
|
321
|
-
inclination = Math.asin(2 * qNormalized[1] * qNormalized[0]);
|
|
322
|
-
} else if (screenOrientation === 90) {
|
|
323
|
-
inclination = -Math.asin(2 * qNormalized[2] * qNormalized[0]);
|
|
324
|
-
} else if (screenOrientation === -90) {
|
|
325
|
-
inclination = Math.asin(2 * qNormalized[2] * qNormalized[0]);
|
|
326
|
-
} else if (screenOrientation === 180) {
|
|
327
|
-
inclination = -Math.asin(2 * qNormalized[1] * qNormalized[0]);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
callback(inclination);
|
|
331
|
-
|
|
332
|
-
}, { accelerometer: true });
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
stopMonitoringInclination() {
|
|
336
|
-
if (this.sensorsCompatibilityInclination) {
|
|
337
|
-
this.sensorsCompatibilityInclination.stopImu();
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
export default AttitudeHandler;
|