@wemap/providers 9.0.3 → 9.0.5
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/index.js +3 -2
- package/package.json +6 -6
- package/src/ProvidersInterface.js +1 -1
- package/src/providers/Provider.js +1 -1
- package/src/providers/attitude/relative/RelativeAttitude.js +1 -1
- package/src/providers/others/CameraNative.js +1 -1
- package/src/providers/others/CameraProjectionMatrix.js +1 -1
- package/src/providers/position/absolute/AbsolutePosition.js +15 -44
- package/src/providers/position/relative/GeoRelativePositionFromArCore.js +1 -1
- package/src/providers/{position/relative → vision}/ArCore.js +6 -5
- package/src/providers/{others → vision}/Barcode.js +1 -1
- package/src/providers/vision/ImageRelocalization.js +120 -0
- package/src/providers/vision/Vps.js +34 -138
package/index.js
CHANGED
|
@@ -36,7 +36,6 @@ export { default as Inclination } from './src/providers/inclination/Inclination.
|
|
|
36
36
|
export { default as StepDetector } from './src/providers/steps/StepDetector.js';
|
|
37
37
|
export { default as StraightLineDetector } from './src/providers/steps/StraightLineDetector.js';
|
|
38
38
|
|
|
39
|
-
export { default as ArCore } from './src/providers/position/relative/ArCore.js';
|
|
40
39
|
export { default as Pdr } from './src/providers/position/relative/Pdr.js';
|
|
41
40
|
export { default as GeoRelativePositionFromArCore } from './src/providers/position/relative/GeoRelativePositionFromArCore.js';
|
|
42
41
|
export { default as GeoRelativePosition } from './src/providers/position/relative/GeoRelativePosition.js';
|
|
@@ -46,8 +45,10 @@ export { default as PoleStar } from './src/providers/position/absolute/PoleStar.
|
|
|
46
45
|
export { default as Ip } from './src/providers/position/absolute/Ip.js';
|
|
47
46
|
export { default as AbsolutePosition } from './src/providers/position/absolute/AbsolutePosition.js';
|
|
48
47
|
|
|
48
|
+
export { default as ArCore } from './src/providers/vision/ArCore.js';
|
|
49
|
+
export { default as ImageRelocalization } from './src/providers/vision/ImageRelocalization.js';
|
|
49
50
|
export { default as Vps } from './src/providers/vision/Vps.js';
|
|
51
|
+
export { default as Barcode } from './src/providers/vision/Barcode.js';
|
|
50
52
|
|
|
51
|
-
export { default as Barcode } from './src/providers/others/Barcode.js';
|
|
52
53
|
export { default as CameraNative } from './src/providers/others/CameraNative.js';
|
|
53
54
|
export { default as CameraProjectionMatrix } from './src/providers/others/CameraProjectionMatrix.js';
|
package/package.json
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@wemap/camera": "^9.0.0",
|
|
12
|
-
"@wemap/geo": "^9.0.
|
|
12
|
+
"@wemap/geo": "^9.0.4",
|
|
13
13
|
"@wemap/geomagnetism": "^0.1.1",
|
|
14
14
|
"@wemap/logger": "^9.0.0",
|
|
15
|
-
"@wemap/map": "^9.0.
|
|
15
|
+
"@wemap/map": "^9.0.4",
|
|
16
16
|
"@wemap/maths": "^9.0.0",
|
|
17
|
-
"@wemap/osm": "^9.0.
|
|
18
|
-
"@wemap/routers": "^9.0.
|
|
17
|
+
"@wemap/osm": "^9.0.4",
|
|
18
|
+
"@wemap/routers": "^9.0.4",
|
|
19
19
|
"@wemap/utils": "^9.0.0"
|
|
20
20
|
},
|
|
21
21
|
"description": "A package using different geoloc systems",
|
|
@@ -42,6 +42,6 @@
|
|
|
42
42
|
"url": "git+https://github.com/wemap/wemap-modules-js.git"
|
|
43
43
|
},
|
|
44
44
|
"type": "module",
|
|
45
|
-
"version": "9.0.
|
|
46
|
-
"gitHead": "
|
|
45
|
+
"version": "9.0.5",
|
|
46
|
+
"gitHead": "a383d28828b66c60339a021c53ed55be62da96c0"
|
|
47
47
|
}
|
|
@@ -10,7 +10,7 @@ import MapMatchingHandler from './mapmatching/MapMatchingHandler.js';
|
|
|
10
10
|
|
|
11
11
|
import AbsoluteAttitude from './providers/attitude/absolute/AbsoluteAttitude.js';
|
|
12
12
|
import AbsolutePosition from './providers/position/absolute/AbsolutePosition.js';
|
|
13
|
-
import Barcode from './providers/
|
|
13
|
+
import Barcode from './providers/vision/Barcode.js';
|
|
14
14
|
import CameraNative from './providers/others/CameraNative.js';
|
|
15
15
|
import CameraProjectionMatrix from './providers/others/CameraProjectionMatrix.js';
|
|
16
16
|
import Inclination from './providers/inclination/Inclination.js';
|
|
@@ -95,7 +95,7 @@ class Provider {
|
|
|
95
95
|
const event = new ProviderEvent(dataType, data);
|
|
96
96
|
const newStack = fromEvents.reduce((acc, _event) => acc.concat(_event.providersStack), []);
|
|
97
97
|
// Remove duplicates and keep lasts
|
|
98
|
-
event.providersStack =
|
|
98
|
+
event.providersStack = Array.from(new Set(newStack.reverse())).reverse();
|
|
99
99
|
return event;
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -3,7 +3,7 @@ import EventType from '../../../events/EventType.js';
|
|
|
3
3
|
import ProviderState from '../../ProviderState.js';
|
|
4
4
|
|
|
5
5
|
import RelativeAttitudeFromInertial from './RelativeAttitudeFromInertial.js';
|
|
6
|
-
import ArCore from '../../
|
|
6
|
+
import ArCore from '../../vision/ArCore.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Relative attitude provider gives the device attitude in East-North-Up (ENU) frame using
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Provider from '../Provider.js';
|
|
2
2
|
import EventType from '../../events/EventType.js';
|
|
3
|
-
import ArCore from '../
|
|
3
|
+
import ArCore from '../vision/ArCore.js';
|
|
4
4
|
import ProviderState from '../ProviderState.js';
|
|
5
5
|
|
|
6
6
|
class CameraNative extends Provider {
|
|
@@ -20,13 +20,6 @@ class AbsolutePosition extends Provider {
|
|
|
20
20
|
/** @type {boolean} */
|
|
21
21
|
static USE_MM_FOR_FEED = true;
|
|
22
22
|
|
|
23
|
-
// /** @type {number} */
|
|
24
|
-
// static POLESTAR_TIME_DISCARD_GNSSWIFI_FROM_LAST_FIX = 3000;
|
|
25
|
-
|
|
26
|
-
// /** @type {number} */
|
|
27
|
-
// static GNSSWIFI_DISCARD_POLESTAR_IF_ACCURACY_RATIO_BETTER_THAN = 2;
|
|
28
|
-
|
|
29
|
-
|
|
30
23
|
/** @type {number?} */
|
|
31
24
|
_gnssWifiProviderId;
|
|
32
25
|
|
|
@@ -39,9 +32,6 @@ class AbsolutePosition extends Provider {
|
|
|
39
32
|
/** @type {boolean?} */
|
|
40
33
|
_waitUntilNextVpsPosition = false;
|
|
41
34
|
|
|
42
|
-
// /** @type {?number} */
|
|
43
|
-
// _lastPolestarFix;
|
|
44
|
-
|
|
45
35
|
/**
|
|
46
36
|
* @override
|
|
47
37
|
*/
|
|
@@ -81,45 +71,26 @@ class AbsolutePosition extends Provider {
|
|
|
81
71
|
// do nothing
|
|
82
72
|
});
|
|
83
73
|
|
|
84
|
-
if (ProvidersOptions.hasVps) {
|
|
85
|
-
|
|
86
|
-
this._vpsProviderId = Vps.addEventListener(events => {
|
|
87
|
-
this._onAbsolutePosition(events.find(event => event.dataType === EventType.AbsolutePosition));
|
|
88
|
-
Vps.removeEventListener(this._vpsProviderId);
|
|
89
|
-
this._vpsProviderId = null;
|
|
90
|
-
});
|
|
91
74
|
|
|
92
|
-
|
|
75
|
+
// GnssWifi
|
|
76
|
+
this._gnssWifiProviderId = GnssWifi.addEventListener(
|
|
77
|
+
events => {
|
|
78
|
+
// bearing from GnssWifi is not reliable for our usecase
|
|
79
|
+
events[0].data.bearing = null;
|
|
80
|
+
this._onAbsolutePosition(events[0], false);
|
|
81
|
+
}
|
|
82
|
+
);
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// console.log(`[Dev] Formula - PS: ${PoleStar.lastEvent.data.accuracy},
|
|
101
|
-
// GNSSWifi: ${events[0].data.accuracy},
|
|
102
|
-
// ratio: ${PoleStar.lastEvent.data.accuracy / events[0].data.accuracy}`);
|
|
103
|
-
// if (PoleStar.lastEvent.data.accuracy / events[0].data.accuracy > AbsolutePosition.GNSSWIFI_DISCARD_POLESTAR_IF_ACCURACY_RATIO_BETTER_THAN) {
|
|
104
|
-
// // Except if the accuracy of the Polestar position is really better than the GNSSWifi position
|
|
105
|
-
// // In this case we add the level provided by Pole Star to the position
|
|
106
|
-
// console.log(`[Dev] Apply PS level ${PoleStar.lastEvent.data.level} to GnssWifi`);
|
|
107
|
-
// events[0].data.level = PoleStar.lastEvent.data.level;
|
|
108
|
-
// useLevel = true;
|
|
109
|
-
// } else {
|
|
110
|
-
// console.log('[Dev] Discard GnssWifi fix with accuracy: ', events[0].data.accuracy);
|
|
111
|
-
// return;
|
|
112
|
-
// }
|
|
113
|
-
// }
|
|
114
|
-
// console.log('[Dev] Use GnssWifi fix with accuracy: ', events[0].data.accuracy);
|
|
115
|
-
// bearing from GnssWifi is not reliable for our usecase
|
|
116
|
-
events[0].data.bearing = null;
|
|
117
|
-
this._onAbsolutePosition(events[0], false);
|
|
118
|
-
}
|
|
84
|
+
// Vps
|
|
85
|
+
if (ProvidersOptions.hasVps) {
|
|
86
|
+
this._vpsProviderId = Vps.addEventListener(
|
|
87
|
+
events => this._onAbsolutePosition(events.find(event => event.dataType === EventType.AbsolutePosition)),
|
|
88
|
+
error => this.notifyError(error),
|
|
89
|
+
false
|
|
119
90
|
);
|
|
120
|
-
|
|
121
91
|
}
|
|
122
92
|
|
|
93
|
+
// PoleStar
|
|
123
94
|
if (ProvidersOptions.hasPoleStar) {
|
|
124
95
|
this._polestarProviderId = PoleStar.addEventListener(events => {
|
|
125
96
|
|
|
@@ -3,7 +3,7 @@ import { GeoRelativePosition } from '@wemap/geo';
|
|
|
3
3
|
import EventType from '../../../events/EventType.js';
|
|
4
4
|
import AbsoluteAttitude from '../../attitude/absolute/AbsoluteAttitude.js';
|
|
5
5
|
import Provider from '../../Provider.js';
|
|
6
|
-
import ArCore from '
|
|
6
|
+
import ArCore from '../../vision/ArCore.js';
|
|
7
7
|
|
|
8
8
|
class GeoRelativePositionFromArCore extends Provider {
|
|
9
9
|
|
|
@@ -5,11 +5,12 @@ import {
|
|
|
5
5
|
import { deg2rad } from '@wemap/maths';
|
|
6
6
|
import { TimeUtils } from '@wemap/utils';
|
|
7
7
|
|
|
8
|
-
import Provider from '
|
|
9
|
-
import EventType from '
|
|
10
|
-
import MissingArCoreError from '
|
|
11
|
-
import MissingNativeInterfaceError from '
|
|
12
|
-
import ProviderState from '
|
|
8
|
+
import Provider from '../Provider.js';
|
|
9
|
+
import EventType from '../../events/EventType.js';
|
|
10
|
+
import MissingArCoreError from '../../errors/MissingArCoreError.js';
|
|
11
|
+
import MissingNativeInterfaceError from '../../errors/MissingNativeInterfaceError.js';
|
|
12
|
+
import ProviderState from '../ProviderState.js';
|
|
13
|
+
|
|
13
14
|
class ArCore extends Provider {
|
|
14
15
|
|
|
15
16
|
static Payload = {
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { CameraUtils } from '@wemap/camera';
|
|
2
|
+
import { Attitude, Coordinates, UserPosition } from '@wemap/geo';
|
|
3
|
+
import Logger from '@wemap/logger';
|
|
4
|
+
import { TimeUtils } from '@wemap/utils';
|
|
5
|
+
|
|
6
|
+
import VpsMetadata from './VpsMetadata.js';
|
|
7
|
+
|
|
8
|
+
class ImageRelocalization {
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {HTMLCanvasElement} imageCanvas
|
|
12
|
+
* @param {{intrinsic:number[], distortions:number[]}} calibration
|
|
13
|
+
* @param {{position: Coordinates, positionAccuracy: number}} coarsePose
|
|
14
|
+
* @returns {object}
|
|
15
|
+
*/
|
|
16
|
+
static _prepareRequest(imageCanvas, calibration, coarsePose) {
|
|
17
|
+
const requestTime = TimeUtils.preciseTime() / 1e3;
|
|
18
|
+
|
|
19
|
+
CameraUtils.convertToGrayscale(imageCanvas);
|
|
20
|
+
const reducedImage = CameraUtils.reduceImageSize(imageCanvas, 1280);
|
|
21
|
+
const base64Image = CameraUtils.canvasToBase64(reducedImage);
|
|
22
|
+
|
|
23
|
+
const metadata = new VpsMetadata();
|
|
24
|
+
metadata.time = requestTime;
|
|
25
|
+
metadata.size = { width: reducedImage.width, height: reducedImage.height };
|
|
26
|
+
metadata.calibration = calibration;
|
|
27
|
+
metadata.coarse = coarsePose;
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
image: base64Image,
|
|
31
|
+
...metadata.toJson()
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {object} json
|
|
37
|
+
* @returns {{userPosition: UserPosition, attitude: Attitude}}
|
|
38
|
+
*/
|
|
39
|
+
static _parseJsonResponse(json, requestTime = null) {
|
|
40
|
+
|
|
41
|
+
const attitude = new Attitude([
|
|
42
|
+
json.attitude.w, json.attitude.x,
|
|
43
|
+
json.attitude.y, json.attitude.z
|
|
44
|
+
], requestTime, 0);
|
|
45
|
+
|
|
46
|
+
const userPosition = new UserPosition(
|
|
47
|
+
json.coordinates.lat,
|
|
48
|
+
json.coordinates.lng,
|
|
49
|
+
json.coordinates.alt,
|
|
50
|
+
typeof json.coordinates.level === 'undefined' ? null : json.coordinates.level,
|
|
51
|
+
requestTime,
|
|
52
|
+
0,
|
|
53
|
+
attitude.heading
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return { userPosition, attitude };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {string} endpointUrl
|
|
61
|
+
* @param {HTMLCanvasElement} imageCanvas
|
|
62
|
+
* @param {{intrinsic:number[], distortions:number[]}} calibration
|
|
63
|
+
* @param {{position: Coordinates, positionAccuracy: number}} coarsePose
|
|
64
|
+
* @returns {{userPosition: UserPosition, attitude: Attitude}|null}
|
|
65
|
+
*/
|
|
66
|
+
static async relocalize(endpointUrl, imageCanvas, calibration = null, coarsePose = null) {
|
|
67
|
+
|
|
68
|
+
// 1. Prepare the request
|
|
69
|
+
const jsonPayload = this._prepareRequest(imageCanvas, calibration, coarsePose);
|
|
70
|
+
|
|
71
|
+
// 2. Send the request
|
|
72
|
+
let serverResponse;
|
|
73
|
+
try {
|
|
74
|
+
serverResponse = await fetch(endpointUrl, {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
body: JSON.stringify(jsonPayload),
|
|
77
|
+
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }
|
|
78
|
+
});
|
|
79
|
+
} catch (e) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (serverResponse.status !== 200) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const json = await serverResponse.json();
|
|
88
|
+
if (json.error) {
|
|
89
|
+
Logger.warn(json.error);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 3. Parse the response
|
|
94
|
+
const { userPosition, attitude } = this._parseJsonResponse(json, jsonPayload.time);
|
|
95
|
+
|
|
96
|
+
return { userPosition, attitude };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static getHeadingFromQuaternion(quaternion) {
|
|
100
|
+
|
|
101
|
+
const [qw, qx, qy, qz] = quaternion;
|
|
102
|
+
|
|
103
|
+
const s = Math.sqrt(2) / 2;
|
|
104
|
+
const C = [s * (qw - qx), s * (qw + qx), s * (qy + qz), s * (qz - qy)];
|
|
105
|
+
return -Math.atan2(2 * C[3] * C[0] - 2 * C[2] * C[1], 1 - 2 * C[1] ** 2 - 2 * C[3] ** 2);
|
|
106
|
+
|
|
107
|
+
// ---- Not optimized version ----
|
|
108
|
+
|
|
109
|
+
// const eulerAnglesAR = Rotations.quaternionToEulerZXY(
|
|
110
|
+
// Quaternion.multiply(
|
|
111
|
+
// quaternion,
|
|
112
|
+
// Quaternion.fromAxisAngle([1, 0, 0], Math.PI / 2)
|
|
113
|
+
// )
|
|
114
|
+
// );
|
|
115
|
+
|
|
116
|
+
// return -eulerAnglesAR[0];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default ImageRelocalization;
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/* eslint-disable max-statements */
|
|
2
|
-
import { SharedCameras,
|
|
3
|
-
import { Attitude
|
|
2
|
+
import { SharedCameras, Camera } from '@wemap/camera';
|
|
3
|
+
import { Attitude } from '@wemap/geo';
|
|
4
4
|
import Logger from '@wemap/logger';
|
|
5
|
-
import {
|
|
5
|
+
import { Quaternion, deg2rad } from '@wemap/maths';
|
|
6
6
|
import { TimeUtils } from '@wemap/utils';
|
|
7
7
|
|
|
8
8
|
import EventType from '../../events/EventType.js';
|
|
9
|
-
import ProviderEvent from '../../events/ProviderEvent.js';
|
|
10
9
|
import Provider from '../Provider.js';
|
|
11
10
|
import ProviderState from '../ProviderState.js';
|
|
11
|
+
import ImageRelocalization from './ImageRelocalization.js';
|
|
12
12
|
|
|
13
13
|
class Vps extends Provider {
|
|
14
14
|
|
|
15
15
|
static MIN_TIME_BETWEEN_TWO_REQUESTS = 1000;
|
|
16
16
|
|
|
17
|
+
static CAMERA_TO_SMARTPHONE_ROT = Quaternion.fromAxisAngle([1, 0, 0], Math.PI);
|
|
18
|
+
|
|
17
19
|
/** @type {boolean} */
|
|
18
20
|
_serverError = false;
|
|
19
21
|
|
|
@@ -25,7 +27,7 @@ class Vps extends Provider {
|
|
|
25
27
|
|
|
26
28
|
/** @type {?string} */
|
|
27
29
|
_endpoint = null;
|
|
28
|
-
|
|
30
|
+
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* @override
|
|
@@ -119,170 +121,64 @@ class Vps extends Provider {
|
|
|
119
121
|
|
|
120
122
|
_internalStart = async () => {
|
|
121
123
|
|
|
122
|
-
this._serverError = false;
|
|
123
|
-
|
|
124
124
|
if (!this._endpoint) {
|
|
125
|
-
this.
|
|
126
|
-
Logger.error('VPS endpoint has not been set before calling start()');
|
|
127
|
-
this.stop();
|
|
125
|
+
this.notifyError(new Error('VPS endpoint has not been set before calling start()'));
|
|
128
126
|
return;
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
while (this.state !== ProviderState.STOPPPED) {
|
|
132
130
|
|
|
131
|
+
// 1. Handle the time to wait between two requests (MIN_TIME_BETWEEN_TWO_REQUESTS)
|
|
133
132
|
if (this.lastEvent) {
|
|
134
133
|
const diffTime = TimeUtils.preciseTime() - this.lastEvent.data.time * 1e3;
|
|
135
134
|
const timeToWait = Math.max(0, Vps.MIN_TIME_BETWEEN_TWO_REQUESTS - diffTime);
|
|
136
135
|
await new Promise(resolve => setTimeout(resolve, timeToWait));
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
|
|
138
|
+
// 2. Check if Vps is not stopped and camera is still started
|
|
139
|
+
if (this.state === ProviderState.STOPPPED
|
|
140
|
+
|| !this._camera
|
|
141
|
+
|| this._camera.state !== Camera.State.STARTED) {
|
|
140
142
|
break;
|
|
141
143
|
}
|
|
142
144
|
|
|
143
|
-
//
|
|
145
|
+
// 3. Get current image from camera and relocalize it.
|
|
146
|
+
const image = await this._camera.currentImage;
|
|
147
|
+
const res = await ImageRelocalization.relocalize(this._endpoint, image);
|
|
144
148
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
break;
|
|
149
|
+
if (!res) {
|
|
150
|
+
continue;
|
|
148
151
|
}
|
|
149
|
-
const payload = await this._prepareRequest();
|
|
150
152
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
// 4. If relocalization is successful, apply the transforms
|
|
154
|
+
const enuToCameraRot = res.attitude.quaternion;
|
|
155
|
+
const enuToSmartphoneRot = Quaternion.multiply(
|
|
156
|
+
enuToCameraRot,
|
|
157
|
+
Vps.CAMERA_TO_SMARTPHONE_ROT
|
|
158
|
+
);
|
|
154
159
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
});
|
|
160
|
+
const deviceQuaternion = Quaternion.multiply(
|
|
161
|
+
Quaternion.fromAxisAngle([0, 0, 1], deg2rad(window.orientation || 0)),
|
|
162
|
+
enuToSmartphoneRot
|
|
163
|
+
);
|
|
164
|
+
const attitude = new Attitude(deviceQuaternion, res.attitude.time, res.attitude.accuracy);
|
|
161
165
|
|
|
166
|
+
// 5. Finally, notify the listeners if the VPS is not stopped
|
|
162
167
|
if (this.state === ProviderState.STOPPPED) {
|
|
163
168
|
break;
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
+
this.notify(
|
|
172
|
+
this.createEvent(EventType.AbsoluteAttitude, attitude),
|
|
173
|
+
this.createEvent(EventType.AbsolutePosition, res.userPosition)
|
|
174
|
+
);
|
|
171
175
|
|
|
172
|
-
// 4. Notify events
|
|
173
|
-
if (events.length) {
|
|
174
|
-
this.notify(...events);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (this.state !== ProviderState.STOPPPED) {
|
|
179
|
-
this.stop();
|
|
180
176
|
}
|
|
181
177
|
}
|
|
182
178
|
|
|
183
179
|
_internalStop = () => {
|
|
184
180
|
// do nothing
|
|
185
181
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* @returns {Object}
|
|
190
|
-
*/
|
|
191
|
-
async _prepareRequest() {
|
|
192
|
-
|
|
193
|
-
const camera = this._camera;
|
|
194
|
-
|
|
195
|
-
// Retrieve the image
|
|
196
|
-
const image = await camera.currentImage;
|
|
197
|
-
const time = TimeUtils.preciseTime() / 1e3;
|
|
198
|
-
// TODO: move the grayscale conversion in the currentImage getter
|
|
199
|
-
CameraUtils.convertToGrayscale(image);
|
|
200
|
-
const reducedImage = CameraUtils.reduceImageSize(image, 1280);
|
|
201
|
-
// const reducedImage = CameraUtils.reduceImageSize(image, 720, 720);
|
|
202
|
-
const { height, width } = reducedImage;
|
|
203
|
-
const base64Image = CameraUtils.canvasToBase64(reducedImage);
|
|
204
|
-
|
|
205
|
-
// Retrieve the calibration matrix
|
|
206
|
-
const calibration = CameraUtils.createCameraCalibrationFromWidthHeightFov(
|
|
207
|
-
width, height, deg2rad(camera.hardwareVerticalFov)
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
// Build the payload
|
|
211
|
-
return {
|
|
212
|
-
calibration,
|
|
213
|
-
size: [width, height],
|
|
214
|
-
image: base64Image,
|
|
215
|
-
time
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* @param {Response} res
|
|
221
|
-
* @param {String} url
|
|
222
|
-
* @param {Number} requestTime
|
|
223
|
-
* @returns {ProviderEvent[]}
|
|
224
|
-
*/
|
|
225
|
-
async _parseResponse(res, url, requestTime) {
|
|
226
|
-
if (res.status !== 200) {
|
|
227
|
-
Logger.warn(`The VPS server (${url}) has encountered a problem`);
|
|
228
|
-
this._serverError = true;
|
|
229
|
-
return [];
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const json = await res.json();
|
|
233
|
-
if (json.error) {
|
|
234
|
-
return [];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const { attitude, userPosition } = Vps._parseJsonResponse(json, requestTime);
|
|
238
|
-
|
|
239
|
-
const events = [
|
|
240
|
-
this.createEvent(EventType.AbsoluteAttitude, attitude),
|
|
241
|
-
this.createEvent(EventType.AbsolutePosition, userPosition)
|
|
242
|
-
];
|
|
243
|
-
|
|
244
|
-
return events;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
static _parseJsonResponse(json, requestTime) {
|
|
249
|
-
|
|
250
|
-
const enuToCameraRot = [
|
|
251
|
-
json.attitude.w,
|
|
252
|
-
json.attitude.x,
|
|
253
|
-
json.attitude.y,
|
|
254
|
-
json.attitude.z
|
|
255
|
-
];
|
|
256
|
-
|
|
257
|
-
const cameraToSmartphoneRot = Quaternion.fromAxisAngle(
|
|
258
|
-
[1, 0, 0],
|
|
259
|
-
Math.PI
|
|
260
|
-
);
|
|
261
|
-
const enuToSmartphoneRot = Quaternion.multiply(
|
|
262
|
-
enuToCameraRot,
|
|
263
|
-
cameraToSmartphoneRot
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
const quaternionWithScreenRotation = Quaternion.multiply(
|
|
267
|
-
Quaternion.fromAxisAngle([0, 0, 1], deg2rad(window.orientation || 0)),
|
|
268
|
-
enuToSmartphoneRot
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
const attitude = new Attitude(quaternionWithScreenRotation, requestTime, 0);
|
|
272
|
-
|
|
273
|
-
const userPosition = new UserPosition(
|
|
274
|
-
json.coordinates.lat,
|
|
275
|
-
json.coordinates.lng,
|
|
276
|
-
json.coordinates.alt,
|
|
277
|
-
typeof json.coordinates.level === 'undefined' ? null : json.coordinates.level,
|
|
278
|
-
requestTime,
|
|
279
|
-
0,
|
|
280
|
-
attitude.heading
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return { userPosition, attitude };
|
|
285
|
-
}
|
|
286
182
|
}
|
|
287
183
|
|
|
288
184
|
export default new Vps();
|