@wemap/providers 4.0.0 → 4.0.3
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/dist/index.html +1 -0
- package/debug/dist/turn-detection.html +19 -0
- package/debug/index.js +2 -0
- package/debug/src/AbsoluteAttitudeComponent.jsx +3 -10
- package/debug/src/StepDetectionComponent.jsx +3 -3
- package/debug/src/TurnDetectionComponent.jsx +47 -0
- package/debug/src/Utils.js +20 -0
- package/package.json +7 -9
- package/src/Providers.js +26 -81
- package/src/ProvidersInterface.js +5 -6
- package/src/errors/AskImuOnDesktopError.js +4 -3
- package/src/errors/ContainsIgnoredProviderError.js +4 -3
- package/src/errors/GeolocationApiMissingError.js +4 -3
- package/src/errors/GeolocationPermissionDeniedError.js +4 -3
- package/src/errors/GeolocationPositionUnavailableError.js +4 -3
- package/src/errors/IpResolveServerError.js +4 -3
- package/src/errors/MissingAccelerometerError.js +3 -3
- package/src/errors/MissingArCoreError.js +4 -3
- package/src/errors/MissingGyroscopeError.js +3 -3
- package/src/errors/MissingNativeInterfaceError.js +4 -3
- package/src/errors/MissingSensorError.js +4 -3
- package/src/errors/NoProviderFoundError.js +4 -3
- package/src/events/EventType.js +5 -1
- package/src/events/ProviderEvent.js +7 -0
- package/src/events/ProvidersLoggerOld.js +35 -34
- package/src/mapmatching/MapMatchingHandler.js +335 -69
- package/src/providers/FakeProvider.spec.js +15 -15
- package/src/providers/Provider.js +44 -27
- package/src/providers/Provider.spec.js +18 -29
- package/src/providers/attitude/TurnDectector.js +71 -0
- package/src/providers/attitude/absolute/AbsoluteAttitude.js +232 -0
- package/src/providers/attitude/absolute/{AbsoluteAttitudeFromBrowserProvider.js → AbsoluteAttitudeFromBrowser.js} +4 -4
- package/src/providers/attitude/relative/{RelativeAttitudeProvider.js → RelativeAttitude.js} +5 -8
- package/src/providers/attitude/relative/{RelativeAttitudeFromBrowserProvider.js → RelativeAttitudeFromBrowser.js} +4 -5
- package/src/providers/attitude/relative/{RelativeAttitudeFromEkfProvider.js → RelativeAttitudeFromEkf.js} +7 -8
- package/src/providers/attitude/relative/{RelativeAttitudeFromInertialProvider.js → RelativeAttitudeFromInertial.js} +24 -7
- package/src/providers/imu/{AccelerometerProvider.js → Accelerometer.js} +3 -3
- package/src/providers/imu/{GyroscopeProvider.js → Gyroscope.js} +3 -3
- package/src/providers/imu/HighRotationsDetector.js +62 -0
- package/src/providers/imu/{ImuProvider.js → Imu.js} +3 -3
- package/src/providers/inclination/{InclinationProvider.js → Inclination.js} +5 -6
- package/src/providers/inclination/{InclinationFromAccProvider.js → InclinationFromAcc.js} +4 -3
- package/src/providers/inclination/{InclinationFromRelativeAttitudeProvider.js → InclinationFromRelativeAttitude.js} +4 -3
- package/src/providers/legacy/helpers/ThugDetector.js +7 -7
- package/src/providers/others/{BarcodeProvider.js → Barcode.js} +3 -3
- package/src/providers/others/{CameraNativeProvider.js → CameraNative.js} +3 -3
- package/src/providers/others/{CameraProjectionMatrixProvider.js → CameraProjectionMatrix.js} +4 -4
- package/src/providers/position/absolute/AbsolutePosition.js +217 -0
- package/src/providers/position/absolute/{GnssWifiProvider.js → GnssWifi.js} +9 -8
- package/src/providers/position/absolute/{IpProvider.js → Ip.js} +2 -2
- package/src/providers/position/relative/{ArCoreProvider.js → ArCore.js} +28 -30
- package/src/providers/position/relative/{GeoRelativePositionProvider.js → GeoRelativePosition.js} +6 -6
- package/src/providers/position/relative/{GeoRelativePositionFromArCoreProvider.js → GeoRelativePositionFromArCore.js} +4 -5
- package/src/providers/position/relative/{PdrProvider.js → Pdr.js} +8 -8
- package/src/providers/steps/StepDetectionLadetto.js +12 -13
- package/src/providers/steps/StepDetectionMinMaxPeaks.js +19 -17
- package/src/providers/steps/StepDetectionMinMaxPeaks2.js +17 -18
- package/src/providers/steps/{StepDetectionProvider.js → StepDetector.js} +8 -7
- package/src/providers/steps/StraightLineDetector.js +80 -0
- package/src/smoothers/AttitudeSmoother.js +94 -59
- package/src/providers/MetaProvider.js +0 -44
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromRelAttProvider.js +0 -132
- package/src/providers/attitude/absolute/AbsoluteAttitudeFusedProvider.js +0 -166
- package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.js +0 -175
- package/src/providers/position/absolute/AbsolutePositionFromRelProvider.js +0 -107
- package/src/providers/position/absolute/AbsolutePositionProvider.js +0 -189
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import noop from 'lodash.noop';
|
|
2
|
-
|
|
3
1
|
import EventType from '../events/EventType.js';
|
|
4
2
|
import ProviderEvent from '../events/ProviderEvent.js';
|
|
5
3
|
import ProvidersLoggerOld from '../events/ProvidersLoggerOld.js';
|
|
@@ -7,7 +5,6 @@ import ContainsIgnoredProviderError from '../errors/ContainsIgnoredProviderError
|
|
|
7
5
|
import ProvidersOptions from '../ProvidersOptions.js';
|
|
8
6
|
import ProviderState from './ProviderState.js';
|
|
9
7
|
|
|
10
|
-
let uniqueId = 1;
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
10
|
* A provider is a meta class to define an entity which can be
|
|
@@ -15,25 +12,24 @@ let uniqueId = 1;
|
|
|
15
12
|
*/
|
|
16
13
|
class Provider {
|
|
17
14
|
|
|
15
|
+
/** @type {number} */
|
|
18
16
|
static _callbackUniqueId = 0;
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
/** @type {number} */
|
|
19
|
+
static _uniqueId = 1;
|
|
21
20
|
|
|
22
|
-
_eventsCallbacks = [];
|
|
23
|
-
_monitoringCallbacks = [];
|
|
24
21
|
|
|
22
|
+
/** @type {number} */
|
|
23
|
+
id;
|
|
25
24
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
* @returns {Provider}
|
|
29
|
-
*/
|
|
30
|
-
static get instance() {
|
|
31
|
-
if (!this._instance) {
|
|
32
|
-
this._instance = Reflect.construct(this, []);
|
|
33
|
-
}
|
|
34
|
-
return this._instance;
|
|
35
|
-
}
|
|
25
|
+
/** @type {number} */
|
|
26
|
+
state = ProviderState.STOPPPED;
|
|
36
27
|
|
|
28
|
+
/** @type {ProviderEvent[]} */
|
|
29
|
+
_lastEvents = null;
|
|
30
|
+
|
|
31
|
+
_eventsCallbacks = [];
|
|
32
|
+
_monitoringCallbacks = [];
|
|
37
33
|
|
|
38
34
|
/**
|
|
39
35
|
* Provider constructor
|
|
@@ -44,23 +40,20 @@ class Provider {
|
|
|
44
40
|
throw new Error('Can\'t instantiate Provider directly');
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
throw new Error(`Cannot instantiate ${this.pname} twice`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
this.id = uniqueId++;
|
|
43
|
+
this.id = Provider._uniqueId++;
|
|
52
44
|
|
|
53
45
|
ProvidersLoggerOld.addEvent(this, 'constructor');
|
|
54
46
|
}
|
|
55
47
|
|
|
56
48
|
/**
|
|
57
49
|
* Get the provider name
|
|
58
|
-
* @
|
|
50
|
+
* @type {String} the provider name
|
|
59
51
|
*/
|
|
60
52
|
static get pname() {
|
|
61
53
|
return 'Unknown';
|
|
62
54
|
}
|
|
63
55
|
|
|
56
|
+
/** @type {String} */
|
|
64
57
|
get pname() {
|
|
65
58
|
return this.constructor.pname;
|
|
66
59
|
}
|
|
@@ -76,7 +69,7 @@ class Provider {
|
|
|
76
69
|
}
|
|
77
70
|
|
|
78
71
|
/**
|
|
79
|
-
* @
|
|
72
|
+
* @type {Promise} returns an availability promise
|
|
80
73
|
*/
|
|
81
74
|
get availability() {
|
|
82
75
|
if (ProvidersOptions.ignoreProviders.includes(this.pname)) {
|
|
@@ -86,13 +79,14 @@ class Provider {
|
|
|
86
79
|
return this._availability;
|
|
87
80
|
}
|
|
88
81
|
|
|
82
|
+
/** @type {Promise} */
|
|
89
83
|
get _availability() {
|
|
90
84
|
return Promise.resolve();
|
|
91
85
|
}
|
|
92
86
|
|
|
93
87
|
/**
|
|
94
88
|
* Create an event from current provider
|
|
95
|
-
* @param {
|
|
89
|
+
* @param {String} dataType type of ProviderEvent (from EventType)
|
|
96
90
|
* @param {Object} data data exported to ProviderEvent
|
|
97
91
|
* @returns {ProviderEvent}
|
|
98
92
|
* @protected
|
|
@@ -136,7 +130,7 @@ class Provider {
|
|
|
136
130
|
* @param {Boolean} startIfNecessary
|
|
137
131
|
* @returns {Number}
|
|
138
132
|
*/
|
|
139
|
-
addEventListener(onEvents =
|
|
133
|
+
addEventListener(onEvents = () => {}, onError = () => {}, startIfNecessary = true) {
|
|
140
134
|
const id = ++Provider._callbackUniqueId;
|
|
141
135
|
|
|
142
136
|
/**
|
|
@@ -185,7 +179,7 @@ class Provider {
|
|
|
185
179
|
this.notifyError(e);
|
|
186
180
|
})
|
|
187
181
|
// notifyError can throw an error if onStop is not defined
|
|
188
|
-
.catch(() =>
|
|
182
|
+
.catch(() => {});
|
|
189
183
|
|
|
190
184
|
return id;
|
|
191
185
|
}
|
|
@@ -238,7 +232,7 @@ class Provider {
|
|
|
238
232
|
* @param {Function} onStopped
|
|
239
233
|
* @returns {Number}
|
|
240
234
|
*/
|
|
241
|
-
addMonitoringListener(onStarted =
|
|
235
|
+
addMonitoringListener(onStarted = () => {}, onStopped = () => {}) {
|
|
242
236
|
const id = ++this.constructor._callbackUniqueId;
|
|
243
237
|
this._monitoringCallbacks.push({
|
|
244
238
|
id,
|
|
@@ -286,6 +280,9 @@ class Provider {
|
|
|
286
280
|
|
|
287
281
|
// Notify callbacks
|
|
288
282
|
this._eventsCallbacks.forEach(({ onEvents }) => onEvents(events));
|
|
283
|
+
|
|
284
|
+
// Keep a trace of the last events.
|
|
285
|
+
this._lastEvents = events;
|
|
289
286
|
}
|
|
290
287
|
|
|
291
288
|
/**
|
|
@@ -302,6 +299,26 @@ class Provider {
|
|
|
302
299
|
onError(error);
|
|
303
300
|
});
|
|
304
301
|
}
|
|
302
|
+
|
|
303
|
+
/** @type {ProviderEvent} */
|
|
304
|
+
get lastEvent() {
|
|
305
|
+
return this._lastEvents ? this._lastEvents[0] : null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** @type {ProviderEvent[]} */
|
|
309
|
+
get lastEvents() {
|
|
310
|
+
return this._lastEvents;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Input data from external interface
|
|
315
|
+
* @param {ProviderEvent} event
|
|
316
|
+
* @param {EventType} eventType
|
|
317
|
+
*/
|
|
318
|
+
// eslint-disable-next-line no-unused-vars
|
|
319
|
+
feed(event, eventType) {
|
|
320
|
+
throw new Error('Not implemented');
|
|
321
|
+
}
|
|
305
322
|
}
|
|
306
323
|
|
|
307
324
|
export default Provider;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-nested-callbacks */
|
|
2
2
|
import chai from 'chai';
|
|
3
3
|
import chaiAsPromised from 'chai-as-promised';
|
|
4
|
-
import noop from 'lodash.noop';
|
|
5
4
|
|
|
6
5
|
import Logger from '@wemap/logger';
|
|
7
6
|
|
|
@@ -24,18 +23,11 @@ describe('Provider', () => {
|
|
|
24
23
|
|
|
25
24
|
it('creation/singleton', () => {
|
|
26
25
|
expect(() => new Provider()).throw(Error);
|
|
27
|
-
expect(() => Provider.instance).throw(Error);
|
|
28
|
-
expect(() => FakeProvider1.instance).not.throw(Error);
|
|
29
|
-
expect(() => FakeProvider2.instance).not.throw(Error);
|
|
30
|
-
expect(() => FakeProvider3.instance).not.throw(Error);
|
|
31
|
-
expect(() => FakeProvider4.instance).not.throw(Error);
|
|
32
|
-
expect(FakeProvider1.instance).equals(FakeProvider1.instance);
|
|
33
|
-
expect(FakeProvider4.instance).equals(FakeProvider4.instance);
|
|
34
26
|
});
|
|
35
27
|
|
|
36
28
|
|
|
37
29
|
it('default getter', () => {
|
|
38
|
-
const provider = FakeProvider1
|
|
30
|
+
const provider = FakeProvider1;
|
|
39
31
|
expect(provider.pname).equals(FakeProvider1.pname);
|
|
40
32
|
expect(provider.eventsType).is.empty;
|
|
41
33
|
expect(provider.hasNativeInterface).is.false;
|
|
@@ -45,33 +37,30 @@ describe('Provider', () => {
|
|
|
45
37
|
|
|
46
38
|
it('availability', async () => {
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
await expect(fakeProvider1.availability).to.be.fulfilled;
|
|
40
|
+
await expect(FakeProvider1.availability).to.be.fulfilled;
|
|
50
41
|
ProvidersOptions.ignoreProviders.push(FakeProvider1.pname);
|
|
51
|
-
await expect(
|
|
42
|
+
await expect(FakeProvider1.availability).to.be.rejectedWith(ContainsIgnoredProviderError);
|
|
52
43
|
ProvidersOptions.ignoreProviders = [];
|
|
53
44
|
|
|
54
|
-
await expect(FakeProvider2.
|
|
45
|
+
await expect(FakeProvider2.availability).to.be.rejectedWith(Error);
|
|
55
46
|
|
|
56
|
-
await expect(FakeProvider3.
|
|
57
|
-
await expect(FakeProvider4.
|
|
47
|
+
await expect(FakeProvider3.availability).to.be.fulfilled;
|
|
48
|
+
await expect(FakeProvider4.availability).to.be.fulfilled;
|
|
58
49
|
});
|
|
59
50
|
|
|
60
51
|
it('checkAvailability on start', async () => {
|
|
61
52
|
|
|
62
|
-
const fp2 = FakeProvider2.instance;
|
|
63
|
-
|
|
64
53
|
/**
|
|
65
54
|
* checkAvailabilityOnStart = true
|
|
66
55
|
*/
|
|
67
56
|
let errored = false;
|
|
68
|
-
|
|
57
|
+
FakeProvider2.addEventListener(() => {}, () => (errored = true));
|
|
69
58
|
|
|
70
59
|
await sleep(2);
|
|
71
60
|
|
|
72
61
|
expect(errored).is.true;
|
|
73
|
-
expect(
|
|
74
|
-
expect(
|
|
62
|
+
expect(FakeProvider2.state).equals(ProviderState.STOPPPED);
|
|
63
|
+
expect(FakeProvider2._eventsCallbacks.length).equals(0);
|
|
75
64
|
|
|
76
65
|
/**
|
|
77
66
|
* checkAvailabilityOnStart = false
|
|
@@ -79,16 +68,16 @@ describe('Provider', () => {
|
|
|
79
68
|
ProvidersOptions.checkAvailabilityOnStart = false;
|
|
80
69
|
|
|
81
70
|
errored = false;
|
|
82
|
-
const id =
|
|
71
|
+
const id = FakeProvider2.addEventListener(() => {}, () => (errored = true));
|
|
83
72
|
|
|
84
73
|
await sleep(2);
|
|
85
74
|
|
|
86
75
|
expect(errored).is.false;
|
|
87
|
-
expect(
|
|
76
|
+
expect(FakeProvider2.state).equals(ProviderState.STARTED);
|
|
88
77
|
|
|
89
|
-
|
|
90
|
-
expect(
|
|
91
|
-
expect(
|
|
78
|
+
FakeProvider2.removeEventListener(id);
|
|
79
|
+
expect(FakeProvider2.state).equals(ProviderState.STOPPPED);
|
|
80
|
+
expect(FakeProvider2._eventsCallbacks.length).equals(0);
|
|
92
81
|
|
|
93
82
|
ProvidersOptions.checkAvailabilityOnStart = true;
|
|
94
83
|
});
|
|
@@ -122,13 +111,13 @@ describe('Provider', () => {
|
|
|
122
111
|
|
|
123
112
|
it('start/stop', async () => {
|
|
124
113
|
let errored = false;
|
|
125
|
-
FakeProvider1.
|
|
114
|
+
FakeProvider1.addEventListener(() => {}, (errored = true));
|
|
126
115
|
await sleep(2);
|
|
127
116
|
expect(errored).is.true;
|
|
128
117
|
|
|
129
|
-
await expect(startStop(FakeProvider2
|
|
130
|
-
await expect(startStop(FakeProvider3
|
|
131
|
-
await expect(startStop(FakeProvider4
|
|
118
|
+
await expect(startStop(FakeProvider2)).to.be.fulfilled;
|
|
119
|
+
await expect(startStop(FakeProvider3)).to.be.fulfilled;
|
|
120
|
+
await expect(startStop(FakeProvider4)).to.be.fulfilled;
|
|
132
121
|
|
|
133
122
|
});
|
|
134
123
|
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { std } from '@wemap/maths';
|
|
2
|
+
|
|
3
|
+
import EventType from '../../events/EventType.js';
|
|
4
|
+
import RelativeAttitude from './relative/RelativeAttitude.js';
|
|
5
|
+
import Provider from '../Provider.js';
|
|
6
|
+
|
|
7
|
+
class TurnDetector extends Provider {
|
|
8
|
+
|
|
9
|
+
// in seconds
|
|
10
|
+
static SLIDING_WINDOW_TIME = 0.3;
|
|
11
|
+
|
|
12
|
+
static STD_THRESHOLD = 0.05;
|
|
13
|
+
|
|
14
|
+
/** @type {number} in seconds */
|
|
15
|
+
static CONSIDER_TURN_UNTIL = 1;
|
|
16
|
+
|
|
17
|
+
/** @type {number[]} */
|
|
18
|
+
slidingWindow = [];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @override
|
|
22
|
+
*/
|
|
23
|
+
static get pname() {
|
|
24
|
+
return 'TurnDetector';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @override
|
|
29
|
+
*/
|
|
30
|
+
start() {
|
|
31
|
+
this.providerId = RelativeAttitude.addEventListener(
|
|
32
|
+
events => this._parseRelativeAttitude(events[0]),
|
|
33
|
+
error => this.notifyError(error)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @override
|
|
39
|
+
*/
|
|
40
|
+
stop() {
|
|
41
|
+
RelativeAttitude.removeEventListener(this.providerId);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
isTurning() {
|
|
45
|
+
if (!this.lastEvent || !RelativeAttitude.lastEvent) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const diffTime = RelativeAttitude.lastEvent.data.time - this.lastEvent.data.timestamp;
|
|
50
|
+
return diffTime < TurnDetector.CONSIDER_TURN_UNTIL;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
_parseRelativeAttitude = relativeAttitudeEvent => {
|
|
57
|
+
|
|
58
|
+
const { heading, time: timestamp } = relativeAttitudeEvent.data;
|
|
59
|
+
|
|
60
|
+
this.slidingWindow = this.slidingWindow.filter(item => item[0] >= timestamp - TurnDetector.SLIDING_WINDOW_TIME);
|
|
61
|
+
this.slidingWindow.push([timestamp, heading]);
|
|
62
|
+
|
|
63
|
+
const stdVal = std(this.slidingWindow.map(item => item[1]));
|
|
64
|
+
if (stdVal > TurnDetector.STD_THRESHOLD) {
|
|
65
|
+
this.notify(this.createEvent(EventType.Turn, { timestamp }, [relativeAttitudeEvent]));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default new TurnDetector();
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { AbsoluteHeading, Attitude } from '@wemap/geo';
|
|
2
|
+
import { Quaternion } from '@wemap/maths';
|
|
3
|
+
import { PromiseUtils } from '@wemap/utils';
|
|
4
|
+
|
|
5
|
+
import Provider from '../../Provider.js';
|
|
6
|
+
import EventType from '../../../events/EventType.js';
|
|
7
|
+
import AbsoluteAttitudeFromBrowser from './AbsoluteAttitudeFromBrowser.js';
|
|
8
|
+
import RelativeAttitude from '../relative/RelativeAttitude.js';
|
|
9
|
+
import ProviderEvent from '../../../events/ProviderEvent.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Absolute attitude provider gives the device attitude in East-North-Up (ENU) frame
|
|
13
|
+
*/
|
|
14
|
+
class AbsoluteAttitude extends Provider {
|
|
15
|
+
|
|
16
|
+
/** @type {boolean} */
|
|
17
|
+
_attitudeFromBrowserErrored = false;
|
|
18
|
+
|
|
19
|
+
/** @type {boolean} */
|
|
20
|
+
_attitudeFromRelativeErrored = false;
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* RELATIVE
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** @type {Attitude} */
|
|
27
|
+
_relativeAttitude = null;
|
|
28
|
+
|
|
29
|
+
/** @type {number} in radians/s */
|
|
30
|
+
_relativeAccuracy = 0;
|
|
31
|
+
|
|
32
|
+
/** @type {ProviderEvent<Attitude|AbsoluteHeading>} */
|
|
33
|
+
_lastForcedHeadingEvent;
|
|
34
|
+
|
|
35
|
+
/** @type {number[]} quaternion offset from relative to absolute */
|
|
36
|
+
_relAbsQuat;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
41
|
+
|
|
42
|
+
this._attitudeFromBrowserErrored = false;
|
|
43
|
+
this._attitudeFromRelativeErrored = false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @override
|
|
48
|
+
*/
|
|
49
|
+
static get pname() {
|
|
50
|
+
return 'AbsoluteAttitude';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @override
|
|
55
|
+
*/
|
|
56
|
+
static get eventsType() {
|
|
57
|
+
return [EventType.AbsoluteAttitude];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @override
|
|
62
|
+
*/
|
|
63
|
+
get _availability() {
|
|
64
|
+
return PromiseUtils.any([
|
|
65
|
+
AbsoluteAttitudeFromBrowser.availability,
|
|
66
|
+
RelativeAttitude.availability
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @override
|
|
72
|
+
*/
|
|
73
|
+
start() {
|
|
74
|
+
|
|
75
|
+
this.fromBrowserProviderId = AbsoluteAttitudeFromBrowser.addEventListener(
|
|
76
|
+
events => this._onAttitudeFromBrowser(events[0]),
|
|
77
|
+
error => {
|
|
78
|
+
this._attitudeFromBrowserErrored = true;
|
|
79
|
+
this.onError(error);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
this.relativeAttitudeProviderId = RelativeAttitude.addEventListener(
|
|
84
|
+
events => this._onRelativeAttitudeEvent(events[0]),
|
|
85
|
+
error => {
|
|
86
|
+
this._attitudeFromRelativeErrored = true;
|
|
87
|
+
this.notifyError(error);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @override
|
|
95
|
+
*/
|
|
96
|
+
stop() {
|
|
97
|
+
AbsoluteAttitudeFromBrowser.removeEventListener(this.fromBrowserProviderId);
|
|
98
|
+
RelativeAttitude.removeEventListener(this.relativeAttitudeProviderId);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
onError(error) {
|
|
102
|
+
if (this._attitudeFromBrowserErrored && this._attitudeFromRelativeErrored) {
|
|
103
|
+
this.notifyError(error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param {ProviderEvent<Attitude|AbsoluteHeading>} absoluteHeadingEvent
|
|
110
|
+
*/
|
|
111
|
+
_forceHeadingForRelative = (absoluteHeadingEvent, force = false) => {
|
|
112
|
+
|
|
113
|
+
if (!force && this.lastEvent
|
|
114
|
+
&& absoluteHeadingEvent.data.accuracy > this.lastEvent.data.accuracy) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const currentRelativeHeading = this._relativeAttitude ? this._relativeAttitude.heading : 0;
|
|
119
|
+
|
|
120
|
+
this._relAbsQuat = Quaternion.fromAxisAngle(
|
|
121
|
+
[0, 0, 1],
|
|
122
|
+
currentRelativeHeading - absoluteHeadingEvent.data.heading
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
this._relativeAccuracy = 0;
|
|
126
|
+
this._lastForcedHeadingEvent = absoluteHeadingEvent;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {ProviderEvent<Attitude>} event
|
|
131
|
+
*/
|
|
132
|
+
_onRelativeAttitudeEvent(event) {
|
|
133
|
+
|
|
134
|
+
if (!this._lastForcedHeadingEvent) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const { quaternion, accuracy, time } = event.data;
|
|
139
|
+
|
|
140
|
+
// Calculate relative accuracy
|
|
141
|
+
if (this._relativeAttitude) {
|
|
142
|
+
this._relativeAccuracy += (time - this._relativeAttitude.time) * accuracy;
|
|
143
|
+
}
|
|
144
|
+
// Keep the relative attitude event for the calculation of relAbsQuat
|
|
145
|
+
this._relativeAttitude = event.data;
|
|
146
|
+
|
|
147
|
+
const accuracyWithRelative = Math.min(
|
|
148
|
+
this._lastForcedHeadingEvent.data.accuracy + this._relativeAccuracy,
|
|
149
|
+
Math.PI
|
|
150
|
+
);
|
|
151
|
+
const accuracyWithAbsolute = this._eventFromBrowser.data.accuracy;
|
|
152
|
+
|
|
153
|
+
let newAccuracy;
|
|
154
|
+
let relAbsQuat;
|
|
155
|
+
if (accuracyWithAbsolute < accuracyWithRelative) {
|
|
156
|
+
const currentHeading = this._relativeAttitude ? this._relativeAttitude.heading : 0;
|
|
157
|
+
newAccuracy = accuracyWithAbsolute;
|
|
158
|
+
relAbsQuat = Quaternion.fromAxisAngle([0, 0, 1], currentHeading - this._eventFromBrowser.data.heading);
|
|
159
|
+
} else {
|
|
160
|
+
newAccuracy = accuracyWithRelative;
|
|
161
|
+
relAbsQuat = this._relAbsQuat;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const absoluteQuat = Quaternion.multiply(relAbsQuat, quaternion);
|
|
165
|
+
const attitude = new Attitude(absoluteQuat, time, newAccuracy);
|
|
166
|
+
|
|
167
|
+
this.notify(this.createEvent(
|
|
168
|
+
EventType.AbsoluteAttitude,
|
|
169
|
+
attitude,
|
|
170
|
+
[event, this._lastForcedHeadingEvent]
|
|
171
|
+
));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @param {ProviderEvent<Attitude>} event
|
|
177
|
+
*/
|
|
178
|
+
_onAttitudeFromBrowser(event) {
|
|
179
|
+
this._eventFromBrowser = event;
|
|
180
|
+
|
|
181
|
+
if (!this._lastForcedHeadingEvent) {
|
|
182
|
+
this._forceHeadingForRelative(event);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Absolute attitude from browser is not used anymore due to magnetometer inaccuracy on pitch and roll
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @override
|
|
191
|
+
* @param {AbsoluteHeading|Attitude|ProviderEvent} data
|
|
192
|
+
*/
|
|
193
|
+
feed(data) {
|
|
194
|
+
|
|
195
|
+
if (data instanceof AbsoluteHeading) {
|
|
196
|
+
|
|
197
|
+
if (data.time === null) {
|
|
198
|
+
throw Error('the time of the absolute heading is not defined');
|
|
199
|
+
}
|
|
200
|
+
if (data.accuracy === null) {
|
|
201
|
+
throw Error('the accuracy of the absolute heading is not defined');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this._forceHeadingForRelative(new ProviderEvent(EventType.AbsoluteHeading, data));
|
|
205
|
+
|
|
206
|
+
} else if (data instanceof Attitude) {
|
|
207
|
+
|
|
208
|
+
if (data.time === null) {
|
|
209
|
+
throw Error('the time of the attitude is not defined');
|
|
210
|
+
}
|
|
211
|
+
if (data.accuracy === null) {
|
|
212
|
+
throw Error('the accuracy of the attitude is not defined');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
this._forceHeadingForRelative(new ProviderEvent(EventType.AbsoluteHeading, data));
|
|
216
|
+
|
|
217
|
+
} else if (data instanceof ProviderEvent) {
|
|
218
|
+
|
|
219
|
+
if (data.dataType !== EventType.AbsoluteHeading
|
|
220
|
+
|| !(data.data instanceof AbsoluteHeading)) {
|
|
221
|
+
throw Error('the provider event is not an AbsoluteHeading');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this._forceHeadingForRelative(data);
|
|
225
|
+
|
|
226
|
+
} else {
|
|
227
|
+
throw new Error('data is nor an AbsoluteHeading or an Attitude object');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export default new AbsoluteAttitude();
|
|
@@ -15,7 +15,7 @@ import EventType from '../../../events/EventType.js';
|
|
|
15
15
|
import AskImuOnDesktopError from '../../../errors/AskImuOnDesktopError.js';
|
|
16
16
|
import MissingMagnetometerError from '../../../errors/MissingMagnetometerError.js';
|
|
17
17
|
import MissingSensorError from '../../../errors/MissingSensorError.js';
|
|
18
|
-
import
|
|
18
|
+
import AbsolutePosition from '../../position/absolute/AbsolutePosition.js';
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -35,7 +35,7 @@ import { AbsolutePosition } from '../../../Providers.js';
|
|
|
35
35
|
*
|
|
36
36
|
* -----------------------------------
|
|
37
37
|
*/
|
|
38
|
-
class
|
|
38
|
+
class AbsoluteAttitudeFromBrowser extends Provider {
|
|
39
39
|
|
|
40
40
|
// from http://tyrex.inria.fr/mobile/benchmarks-attitude/
|
|
41
41
|
static DEFAULT_ACCURACY = deg2rad(15);
|
|
@@ -207,7 +207,7 @@ class AbsoluteAttitudeFromBrowserProvider extends Provider {
|
|
|
207
207
|
if (isSkyMode) {
|
|
208
208
|
alpha = 180 - e.webkitCompassHeading;
|
|
209
209
|
} else {
|
|
210
|
-
alpha =
|
|
210
|
+
alpha = AbsoluteAttitudeFromBrowser.webkitCompassToHeading(
|
|
211
211
|
e.webkitCompassHeading, e.beta, e.gamma);
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -276,4 +276,4 @@ class AbsoluteAttitudeFromBrowserProvider extends Provider {
|
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
export default
|
|
279
|
+
export default new AbsoluteAttitudeFromBrowser();
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import noop from 'lodash.noop';
|
|
2
|
-
|
|
3
1
|
import Provider from '../../Provider.js';
|
|
4
2
|
import EventType from '../../../events/EventType.js';
|
|
5
3
|
import ProviderState from '../../ProviderState.js';
|
|
6
|
-
import {
|
|
7
|
-
RelativeAttitudeFromInertial, ArCore
|
|
8
|
-
} from '../../../Providers.js';
|
|
9
4
|
|
|
5
|
+
import RelativeAttitudeFromInertial from './RelativeAttitudeFromInertial.js';
|
|
6
|
+
import ArCore from '../../position/relative/ArCore.js';
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
9
|
* Relative attitude provider gives the device attitude in East-North-Up (ENU) frame using
|
|
13
10
|
* browser deviceorientation
|
|
14
11
|
* The provider does not work until an offset is given.
|
|
15
12
|
*/
|
|
16
|
-
class
|
|
13
|
+
class RelativeAttitude extends Provider {
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
16
|
* @override
|
|
@@ -85,7 +82,7 @@ class RelativeAttitudeProvider extends Provider {
|
|
|
85
82
|
this.notify(relativeAttitudeEvent.clone());
|
|
86
83
|
}
|
|
87
84
|
},
|
|
88
|
-
|
|
85
|
+
() => {},
|
|
89
86
|
false
|
|
90
87
|
);
|
|
91
88
|
};
|
|
@@ -95,4 +92,4 @@ class RelativeAttitudeProvider extends Provider {
|
|
|
95
92
|
}
|
|
96
93
|
}
|
|
97
94
|
|
|
98
|
-
export default
|
|
95
|
+
export default new RelativeAttitude();
|
|
@@ -6,7 +6,7 @@ import Provider from '../../Provider.js';
|
|
|
6
6
|
import EventType from '../../../events/EventType.js';
|
|
7
7
|
import AskImuOnDesktopError from '../../../errors/AskImuOnDesktopError.js';
|
|
8
8
|
import MissingSensorError from '../../../errors/MissingSensorError.js';
|
|
9
|
-
import
|
|
9
|
+
import RelativeAttitudeFromInertial from './RelativeAttitudeFromInertial.js';
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -24,7 +24,7 @@ import RelativeAttitudeFromInertialProvider from './RelativeAttitudeFromInertial
|
|
|
24
24
|
*
|
|
25
25
|
* -----------------------------------
|
|
26
26
|
*/
|
|
27
|
-
class
|
|
27
|
+
class RelativeAttitudeFromBrowser extends Provider {
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* @override
|
|
@@ -88,11 +88,10 @@ class RelativeAttitudeFromBrowserProvider extends Provider {
|
|
|
88
88
|
const quaternion = Rotations.eulerToQuaternionZXYDegrees([e.alpha, e.beta, e.gamma]);
|
|
89
89
|
const attitude = new Attitude(quaternion,
|
|
90
90
|
e.timeStamp / 1e3,
|
|
91
|
-
|
|
92
|
-
this.pname
|
|
91
|
+
RelativeAttitudeFromInertial.DEFAULT_DRIFT
|
|
93
92
|
);
|
|
94
93
|
this.notify(this.createEvent(EventType.RelativeAttitude, attitude));
|
|
95
94
|
};
|
|
96
95
|
}
|
|
97
96
|
|
|
98
|
-
export default
|
|
97
|
+
export default new RelativeAttitudeFromBrowser();
|