@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.
Files changed (66) hide show
  1. package/debug/dist/index.html +1 -0
  2. package/debug/dist/turn-detection.html +19 -0
  3. package/debug/index.js +2 -0
  4. package/debug/src/AbsoluteAttitudeComponent.jsx +3 -10
  5. package/debug/src/StepDetectionComponent.jsx +3 -3
  6. package/debug/src/TurnDetectionComponent.jsx +47 -0
  7. package/debug/src/Utils.js +20 -0
  8. package/package.json +7 -9
  9. package/src/Providers.js +26 -81
  10. package/src/ProvidersInterface.js +5 -6
  11. package/src/errors/AskImuOnDesktopError.js +4 -3
  12. package/src/errors/ContainsIgnoredProviderError.js +4 -3
  13. package/src/errors/GeolocationApiMissingError.js +4 -3
  14. package/src/errors/GeolocationPermissionDeniedError.js +4 -3
  15. package/src/errors/GeolocationPositionUnavailableError.js +4 -3
  16. package/src/errors/IpResolveServerError.js +4 -3
  17. package/src/errors/MissingAccelerometerError.js +3 -3
  18. package/src/errors/MissingArCoreError.js +4 -3
  19. package/src/errors/MissingGyroscopeError.js +3 -3
  20. package/src/errors/MissingNativeInterfaceError.js +4 -3
  21. package/src/errors/MissingSensorError.js +4 -3
  22. package/src/errors/NoProviderFoundError.js +4 -3
  23. package/src/events/EventType.js +5 -1
  24. package/src/events/ProviderEvent.js +7 -0
  25. package/src/events/ProvidersLoggerOld.js +35 -34
  26. package/src/mapmatching/MapMatchingHandler.js +335 -69
  27. package/src/providers/FakeProvider.spec.js +15 -15
  28. package/src/providers/Provider.js +44 -27
  29. package/src/providers/Provider.spec.js +18 -29
  30. package/src/providers/attitude/TurnDectector.js +71 -0
  31. package/src/providers/attitude/absolute/AbsoluteAttitude.js +232 -0
  32. package/src/providers/attitude/absolute/{AbsoluteAttitudeFromBrowserProvider.js → AbsoluteAttitudeFromBrowser.js} +4 -4
  33. package/src/providers/attitude/relative/{RelativeAttitudeProvider.js → RelativeAttitude.js} +5 -8
  34. package/src/providers/attitude/relative/{RelativeAttitudeFromBrowserProvider.js → RelativeAttitudeFromBrowser.js} +4 -5
  35. package/src/providers/attitude/relative/{RelativeAttitudeFromEkfProvider.js → RelativeAttitudeFromEkf.js} +7 -8
  36. package/src/providers/attitude/relative/{RelativeAttitudeFromInertialProvider.js → RelativeAttitudeFromInertial.js} +24 -7
  37. package/src/providers/imu/{AccelerometerProvider.js → Accelerometer.js} +3 -3
  38. package/src/providers/imu/{GyroscopeProvider.js → Gyroscope.js} +3 -3
  39. package/src/providers/imu/HighRotationsDetector.js +62 -0
  40. package/src/providers/imu/{ImuProvider.js → Imu.js} +3 -3
  41. package/src/providers/inclination/{InclinationProvider.js → Inclination.js} +5 -6
  42. package/src/providers/inclination/{InclinationFromAccProvider.js → InclinationFromAcc.js} +4 -3
  43. package/src/providers/inclination/{InclinationFromRelativeAttitudeProvider.js → InclinationFromRelativeAttitude.js} +4 -3
  44. package/src/providers/legacy/helpers/ThugDetector.js +7 -7
  45. package/src/providers/others/{BarcodeProvider.js → Barcode.js} +3 -3
  46. package/src/providers/others/{CameraNativeProvider.js → CameraNative.js} +3 -3
  47. package/src/providers/others/{CameraProjectionMatrixProvider.js → CameraProjectionMatrix.js} +4 -4
  48. package/src/providers/position/absolute/AbsolutePosition.js +217 -0
  49. package/src/providers/position/absolute/{GnssWifiProvider.js → GnssWifi.js} +9 -8
  50. package/src/providers/position/absolute/{IpProvider.js → Ip.js} +2 -2
  51. package/src/providers/position/relative/{ArCoreProvider.js → ArCore.js} +28 -30
  52. package/src/providers/position/relative/{GeoRelativePositionProvider.js → GeoRelativePosition.js} +6 -6
  53. package/src/providers/position/relative/{GeoRelativePositionFromArCoreProvider.js → GeoRelativePositionFromArCore.js} +4 -5
  54. package/src/providers/position/relative/{PdrProvider.js → Pdr.js} +8 -8
  55. package/src/providers/steps/StepDetectionLadetto.js +12 -13
  56. package/src/providers/steps/StepDetectionMinMaxPeaks.js +19 -17
  57. package/src/providers/steps/StepDetectionMinMaxPeaks2.js +17 -18
  58. package/src/providers/steps/{StepDetectionProvider.js → StepDetector.js} +8 -7
  59. package/src/providers/steps/StraightLineDetector.js +80 -0
  60. package/src/smoothers/AttitudeSmoother.js +94 -59
  61. package/src/providers/MetaProvider.js +0 -44
  62. package/src/providers/attitude/absolute/AbsoluteAttitudeFromRelAttProvider.js +0 -132
  63. package/src/providers/attitude/absolute/AbsoluteAttitudeFusedProvider.js +0 -166
  64. package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.js +0 -175
  65. package/src/providers/position/absolute/AbsolutePositionFromRelProvider.js +0 -107
  66. 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
- state = ProviderState.STOPPPED;
18
+ /** @type {number} */
19
+ static _uniqueId = 1;
21
20
 
22
- _eventsCallbacks = [];
23
- _monitoringCallbacks = [];
24
21
 
22
+ /** @type {number} */
23
+ id;
25
24
 
26
- /**
27
- * Singleton pattern using reflection.
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
- if (this._instance) {
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
- * @returns {String} the provider name
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
- * @returns {Promise} returns an availability promise
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 {ProviderEvent#DataType} dataType type of ProviderEvent
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 = noop, onError = noop, startIfNecessary = true) {
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(() => noop);
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 = noop, onStopped = noop) {
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.instance;
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
- const fakeProvider1 = FakeProvider1.instance;
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(fakeProvider1.availability).to.be.rejectedWith(ContainsIgnoredProviderError);
42
+ await expect(FakeProvider1.availability).to.be.rejectedWith(ContainsIgnoredProviderError);
52
43
  ProvidersOptions.ignoreProviders = [];
53
44
 
54
- await expect(FakeProvider2.instance.availability).to.be.rejectedWith(Error);
45
+ await expect(FakeProvider2.availability).to.be.rejectedWith(Error);
55
46
 
56
- await expect(FakeProvider3.instance.availability).to.be.fulfilled;
57
- await expect(FakeProvider4.instance.availability).to.be.fulfilled;
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
- fp2.addEventListener(noop, () => (errored = true));
57
+ FakeProvider2.addEventListener(() => {}, () => (errored = true));
69
58
 
70
59
  await sleep(2);
71
60
 
72
61
  expect(errored).is.true;
73
- expect(fp2.state).equals(ProviderState.STOPPPED);
74
- expect(fp2._eventsCallbacks.length).equals(0);
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 = fp2.addEventListener(noop, () => (errored = true));
71
+ const id = FakeProvider2.addEventListener(() => {}, () => (errored = true));
83
72
 
84
73
  await sleep(2);
85
74
 
86
75
  expect(errored).is.false;
87
- expect(fp2.state).equals(ProviderState.STARTED);
76
+ expect(FakeProvider2.state).equals(ProviderState.STARTED);
88
77
 
89
- fp2.removeEventListener(id);
90
- expect(fp2.state).equals(ProviderState.STOPPPED);
91
- expect(fp2._eventsCallbacks.length).equals(0);
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.instance.addEventListener(noop, (errored = true));
114
+ FakeProvider1.addEventListener(() => {}, (errored = true));
126
115
  await sleep(2);
127
116
  expect(errored).is.true;
128
117
 
129
- await expect(startStop(FakeProvider2.instance)).to.be.fulfilled;
130
- await expect(startStop(FakeProvider3.instance)).to.be.fulfilled;
131
- await expect(startStop(FakeProvider4.instance)).to.be.fulfilled;
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 { AbsolutePosition } from '../../../Providers.js';
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 AbsoluteAttitudeFromBrowserProvider extends Provider {
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 = AbsoluteAttitudeFromBrowserProvider.webkitCompassToHeading(
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 AbsoluteAttitudeFromBrowserProvider;
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 RelativeAttitudeProvider extends Provider {
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
- noop,
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 RelativeAttitudeProvider;
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 RelativeAttitudeFromInertialProvider from './RelativeAttitudeFromInertialProvider.js';
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 RelativeAttitudeFromBrowserProvider extends Provider {
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
- RelativeAttitudeFromInertialProvider.DEFAULT_DRIFT,
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 RelativeAttitudeFromBrowserProvider;
97
+ export default new RelativeAttitudeFromBrowser();