@wemap/providers 12.10.8 → 12.10.9
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/dist/helpers/CustomMapProvider.d.ts +10 -0
- package/{index.ts → dist/index.d.ts} +0 -14
- package/dist/index.js +1 -3446
- package/dist/index.js.map +1 -1
- package/{src/ProvidersOptions.ts → dist/src/ProvidersOptions.d.ts} +7 -16
- package/dist/src/errors/AskImuOnDesktopError.d.ts +5 -0
- package/dist/src/errors/ContainsIgnoredProviderError.d.ts +5 -0
- package/dist/src/errors/GeolocationApiMissingError.d.ts +5 -0
- package/dist/src/errors/GeolocationPermissionDeniedError.d.ts +5 -0
- package/dist/src/errors/GeolocationPositionUnavailableError.d.ts +5 -0
- package/dist/src/errors/IpResolveServerError.d.ts +5 -0
- package/dist/src/errors/MissingAccelerometerError.d.ts +6 -0
- package/dist/src/errors/MissingArCoreError.d.ts +5 -0
- package/dist/src/errors/MissingGyroscopeError.d.ts +6 -0
- package/dist/src/errors/MissingMagnetometerError.d.ts +5 -0
- package/dist/src/errors/MissingNativeInterfaceError.d.ts +5 -0
- package/dist/src/errors/MissingPoleStarError.d.ts +5 -0
- package/dist/src/errors/MissingSensorError.d.ts +6 -0
- package/dist/src/errors/NoProviderFoundError.d.ts +5 -0
- package/dist/src/events/AvailabilityHelper.d.ts +5 -0
- package/dist/src/events/ProvidersLoggerOld.d.ts +24 -0
- package/dist/src/events/Types.d.ts +34 -0
- package/dist/src/mapmatching/MapMatchingHandler.d.ts +93 -0
- package/dist/src/providers/Constants.d.ts +4 -0
- package/{src/providers/NativeProviders.ts → dist/src/providers/NativeProviders.d.ts} +2 -23
- package/dist/src/providers/Provider.d.ts +64 -0
- package/dist/src/providers/attitude/EkfAttitude.d.ts +41 -0
- package/dist/src/providers/attitude/TurnProvider.d.ts +17 -0
- package/dist/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.d.ts +60 -0
- package/dist/src/providers/attitude/absolute/AbsoluteAttitudeProvider.d.ts +44 -0
- package/dist/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.d.ts +31 -0
- package/dist/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.d.ts +26 -0
- package/dist/src/providers/attitude/relative/RelativeAttitudeFromInertialProvider.d.ts +18 -0
- package/dist/src/providers/attitude/relative/RelativeAttitudeProvider.d.ts +25 -0
- package/dist/src/providers/imu/AccelerometerProvider.d.ts +11 -0
- package/dist/src/providers/imu/GyroscopeProvider.d.ts +11 -0
- package/dist/src/providers/imu/HighRotationsProvider.d.ts +15 -0
- package/dist/src/providers/imu/ImuProvider.d.ts +34 -0
- package/dist/src/providers/imu/MagnetometerCalibrationProvider.d.ts +11 -0
- package/dist/src/providers/inclination/InclinationFromAccProvider.d.ts +18 -0
- package/dist/src/providers/inclination/InclinationFromRelativeAttitudeProvider.d.ts +19 -0
- package/dist/src/providers/inclination/InclinationProvider.d.ts +18 -0
- package/dist/src/providers/legacy/helpers/HeadingUnlocker.d.ts +12 -0
- package/dist/src/providers/legacy/helpers/ThugDetector.d.ts +8 -0
- package/dist/src/providers/others/CameraNativeProvider.d.ts +11 -0
- package/dist/src/providers/others/CameraProjectionMatrixProvider.d.ts +11 -0
- package/dist/src/providers/position/absolute/AbsolutePositionProvider.d.ts +35 -0
- package/dist/src/providers/position/absolute/GnssWifiProvider.d.ts +28 -0
- package/dist/src/providers/position/absolute/IpProvider.d.ts +16 -0
- package/dist/src/providers/position/absolute/PoleStarProvider.d.ts +14 -0
- package/dist/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.d.ts +17 -0
- package/dist/src/providers/position/relative/GeoRelativePositionProvider.d.ts +12 -0
- package/dist/src/providers/position/relative/PdrProvider.d.ts +15 -0
- package/dist/src/providers/steps/StepDetectionLadetto.d.ts +15 -0
- package/dist/src/providers/steps/StepDetectionMinMaxPeaks.d.ts +19 -0
- package/dist/src/providers/steps/StepDetectionMinMaxPeaks2.d.ts +27 -0
- package/dist/src/providers/steps/StepDetectionMinMaxPeaks3.d.ts +24 -0
- package/dist/src/providers/steps/StepProvider.d.ts +36 -0
- package/dist/src/providers/steps/StraightLineProvider.d.ts +21 -0
- package/dist/src/providers/vision/ArCoreProvider.d.ts +50 -0
- package/dist/src/providers/vision/BarcodeProvider.d.ts +11 -0
- package/dist/src/providers/vision/vps/ImageRelocalization.d.ts +11 -0
- package/dist/src/providers/vision/vps/RelativeRotationCalc.d.ts +10 -0
- package/dist/src/providers/vision/vps/VpsMetadata.d.ts +33 -0
- package/dist/src/providers/vision/vps/VpsProvider.d.ts +45 -0
- package/dist/src/providers/vision/vps/VpsRequest.d.ts +18 -0
- package/dist/src/providers/vision/vps/VpsResponse.d.ts +15 -0
- package/dist/src/smoothers/AttitudeSmoother.d.ts +23 -0
- package/dist/src/smoothers/PositionSmoother.d.ts +21 -0
- package/package.json +16 -12
- package/src/errors/AskImuOnDesktopError.ts +0 -10
- package/src/errors/ContainsIgnoredProviderError.ts +0 -10
- package/src/errors/GeolocationApiMissingError.ts +0 -10
- package/src/errors/GeolocationPermissionDeniedError.ts +0 -10
- package/src/errors/GeolocationPositionUnavailableError.ts +0 -10
- package/src/errors/IpResolveServerError.ts +0 -10
- package/src/errors/MissingAccelerometerError.ts +0 -11
- package/src/errors/MissingArCoreError.ts +0 -10
- package/src/errors/MissingGyroscopeError.ts +0 -11
- package/src/errors/MissingMagnetometerError.ts +0 -9
- package/src/errors/MissingNativeInterfaceError.ts +0 -11
- package/src/errors/MissingPoleStarError.ts +0 -10
- package/src/errors/MissingSensorError.ts +0 -15
- package/src/errors/NoProviderFoundError.ts +0 -10
- package/src/events/AvailabilityHelper.spec.ts +0 -30
- package/src/events/AvailabilityHelper.ts +0 -28
- package/src/events/ProvidersLoggerOld.ts +0 -87
- package/src/events/Types.ts +0 -18
- package/src/mapmatching/MapMatchingHandler.spec.ts +0 -142
- package/src/mapmatching/MapMatchingHandler.ts +0 -540
- package/src/providers/Constants.ts +0 -5
- package/src/providers/FakeProvider.spec.ts +0 -49
- package/src/providers/Provider.spec.ts +0 -113
- package/src/providers/Provider.ts +0 -244
- package/src/providers/attitude/EkfAttitude.spec.ts +0 -115
- package/src/providers/attitude/EkfAttitude.ts +0 -233
- package/src/providers/attitude/TurnProvider.ts +0 -58
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.ts +0 -267
- package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.ts +0 -268
- package/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.ts +0 -84
- package/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.ts +0 -89
- package/src/providers/attitude/relative/RelativeAttitudeFromInertialProvider.ts +0 -66
- package/src/providers/attitude/relative/RelativeAttitudeProvider.ts +0 -70
- package/src/providers/imu/AccelerometerProvider.ts +0 -28
- package/src/providers/imu/GyroscopeProvider.ts +0 -27
- package/src/providers/imu/HighRotationsProvider.ts +0 -49
- package/src/providers/imu/ImuProvider.ts +0 -110
- package/src/providers/imu/MagnetometerCalibrationProvider.ts +0 -21
- package/src/providers/inclination/InclinationFromAccProvider.ts +0 -57
- package/src/providers/inclination/InclinationFromRelativeAttitudeProvider.ts +0 -51
- package/src/providers/inclination/InclinationProvider.ts +0 -59
- package/src/providers/legacy/helpers/HeadingUnlocker.spec.ts +0 -53
- package/src/providers/legacy/helpers/HeadingUnlocker.ts +0 -44
- package/src/providers/legacy/helpers/ThugDetector.ts +0 -30
- package/src/providers/others/CameraNativeProvider.ts +0 -29
- package/src/providers/others/CameraProjectionMatrixProvider.ts +0 -25
- package/src/providers/position/absolute/AbsolutePositionProvider.spec.ts +0 -31
- package/src/providers/position/absolute/AbsolutePositionProvider.ts +0 -277
- package/src/providers/position/absolute/GnssWifiProvider.ts +0 -126
- package/src/providers/position/absolute/GnssWifiProviders.spec.ts +0 -90
- package/src/providers/position/absolute/IpProvider.ts +0 -47
- package/src/providers/position/absolute/PoleStarProvider.ts +0 -88
- package/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.ts +0 -82
- package/src/providers/position/relative/GeoRelativePositionProvider.ts +0 -35
- package/src/providers/position/relative/PdrProvider.ts +0 -107
- package/src/providers/steps/StepDetectionLadetto.ts +0 -67
- package/src/providers/steps/StepDetectionMinMaxPeaks.ts +0 -70
- package/src/providers/steps/StepDetectionMinMaxPeaks2.ts +0 -99
- package/src/providers/steps/StepDetectionMinMaxPeaks3.ts +0 -192
- package/src/providers/steps/StepProvider.ts +0 -151
- package/src/providers/steps/StraightLineProvider.ts +0 -69
- package/src/providers/vision/ArCoreProvider.ts +0 -184
- package/src/providers/vision/BarcodeProvider.ts +0 -28
- package/src/providers/vision/vps/ImageRelocalization.ts +0 -98
- package/src/providers/vision/vps/RelativeRotationCalc.ts +0 -58
- package/src/providers/vision/vps/VpsMetadata.ts +0 -63
- package/src/providers/vision/vps/VpsProvider.ts +0 -251
- package/src/providers/vision/vps/VpsRequest.ts +0 -29
- package/src/providers/vision/vps/VpsResponse.ts +0 -43
- package/src/providers/vision/vps/VpsSchema.json +0 -90
- package/src/smoothers/AttitudeSmoother.ts +0 -110
- package/src/smoothers/PositionSmoother.spec.ts +0 -53
- package/src/smoothers/PositionSmoother.ts +0 -96
- package/tsconfig.json +0 -3
- package/vite.config.ts +0 -4
- /package/{src/providers/ProviderState.ts → dist/src/providers/ProviderState.d.ts} +0 -0
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/* eslint-disable complexity */
|
|
2
|
-
/* eslint-disable max-statements */
|
|
3
|
-
import { SharedCameras, Camera } from '@wemap/camera';
|
|
4
|
-
import { Attitude } from '@wemap/geo';
|
|
5
|
-
import Logger from '@wemap/logger';
|
|
6
|
-
import { Quaternion, deg2rad } from '@wemap/maths';
|
|
7
|
-
import { TimeUtils } from '@wemap/utils';
|
|
8
|
-
|
|
9
|
-
import Provider from '../../Provider.js';
|
|
10
|
-
import Inclination from '../../inclination/InclinationProvider.js';
|
|
11
|
-
import ImageRelocalization from './ImageRelocalization.js';
|
|
12
|
-
import AbsoluteAttitudeProvider from '../../attitude/absolute/AbsoluteAttitudeProvider.js';
|
|
13
|
-
import RelativeRotationCalc from './RelativeRotationCalc.js';
|
|
14
|
-
import GnssWifiProvider from '../../position/absolute/GnssWifiProvider.js';
|
|
15
|
-
import AbsolutePositionProvider from '../../position/absolute/AbsolutePositionProvider.js';
|
|
16
|
-
import PoleStarProvider from '../../position/absolute/PoleStarProvider.js';
|
|
17
|
-
import { AbsoluteAttitude, AbsolutePosition } from '../../../events/Types.js';
|
|
18
|
-
import { CoarsePose } from './VpsMetadata.js';
|
|
19
|
-
|
|
20
|
-
export type VpsEvent = { absoluteAttitude: AbsoluteAttitude, absolutePosition: AbsolutePosition };
|
|
21
|
-
class VpsProvider extends Provider<VpsEvent> {
|
|
22
|
-
|
|
23
|
-
static MIN_TIME_BETWEEN_TWO_REQUESTS = 1000; // in ms
|
|
24
|
-
static DEFAULT_MIN_INCLINATION_FOR_REQUEST = deg2rad(60); // in radians
|
|
25
|
-
static DEFAULT_WAIT_TIME_MIN_INCLINATION_FOR_REQUEST = 200; // in ms
|
|
26
|
-
static DEFAULT_USE_COARSE_POSE = true;
|
|
27
|
-
static CAMERA_TO_SMARTPHONE_ROT = Quaternion.fromAxisAngle([1, 0, 0], Math.PI);
|
|
28
|
-
|
|
29
|
-
_relativeRotationCalc?: RelativeRotationCalc;
|
|
30
|
-
|
|
31
|
-
_serverError = false;
|
|
32
|
-
_cameraError = false;
|
|
33
|
-
|
|
34
|
-
_camera: Camera | null = null;
|
|
35
|
-
_endpoint: string | null = null;
|
|
36
|
-
|
|
37
|
-
_inclinationProviderId?: number;
|
|
38
|
-
|
|
39
|
-
_minInclinationForRequest = VpsProvider.DEFAULT_MIN_INCLINATION_FOR_REQUEST;
|
|
40
|
-
_waitTimeMinInclinationForRequest = VpsProvider.DEFAULT_WAIT_TIME_MIN_INCLINATION_FOR_REQUEST;
|
|
41
|
-
_useCoarsePose = VpsProvider.DEFAULT_USE_COARSE_POSE;
|
|
42
|
-
|
|
43
|
-
getName = () => 'Vps';
|
|
44
|
-
|
|
45
|
-
availability = () => Camera.checkAvailability();
|
|
46
|
-
|
|
47
|
-
start() {
|
|
48
|
-
|
|
49
|
-
// 1. Inclination
|
|
50
|
-
this._inclinationProviderId = Inclination.addEventListener();
|
|
51
|
-
|
|
52
|
-
// 2. Relative Rotation Calc
|
|
53
|
-
this._relativeRotationCalc = new RelativeRotationCalc();
|
|
54
|
-
|
|
55
|
-
// 3. Add listeners on shared cameras to detect new cameras
|
|
56
|
-
SharedCameras.on('added', this._onCameraDetected);
|
|
57
|
-
SharedCameras.on('removed', this._onCameraRemoved);
|
|
58
|
-
|
|
59
|
-
// 4. If a camera already exists, use it
|
|
60
|
-
if (SharedCameras.list.length) {
|
|
61
|
-
if (SharedCameras.list.length > 1) {
|
|
62
|
-
Logger.warn('It seems that more than 1 camera has been detected'
|
|
63
|
-
+ ' for VPS. Taking the first...');
|
|
64
|
-
}
|
|
65
|
-
this._useCamera(SharedCameras.list[0].camera);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
stop() {
|
|
70
|
-
|
|
71
|
-
Inclination.removeEventListener(this._inclinationProviderId);
|
|
72
|
-
|
|
73
|
-
this._relativeRotationCalc?.release();
|
|
74
|
-
|
|
75
|
-
SharedCameras.off('added', this._onCameraDetected);
|
|
76
|
-
SharedCameras.off('removed', this._onCameraRemoved);
|
|
77
|
-
|
|
78
|
-
this._camera = null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
_onCameraDetected = ({ camera }: { camera: Camera }) => {
|
|
82
|
-
if (this._camera) {
|
|
83
|
-
Logger.warn('It seems that more than 1 camera has been detected'
|
|
84
|
-
+ ' for VPS. Taking the first...');
|
|
85
|
-
}
|
|
86
|
-
this._useCamera(camera);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
_onCameraRemoved = () => {
|
|
90
|
-
if (this._camera) {
|
|
91
|
-
this._camera.off('started', this._internalStart);
|
|
92
|
-
this._camera.off('stopped', this._internalStop);
|
|
93
|
-
} else {
|
|
94
|
-
Logger.warn('There is no previously detected camera but once has stopped');
|
|
95
|
-
}
|
|
96
|
-
this._camera = null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
_useCamera(camera: Camera) {
|
|
100
|
-
this._camera = camera;
|
|
101
|
-
|
|
102
|
-
camera.on('started', this._internalStart);
|
|
103
|
-
camera.on('stopped', this._internalStop);
|
|
104
|
-
|
|
105
|
-
if (camera.state === 'started') {
|
|
106
|
-
this._internalStart();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
_internalStart = async () => {
|
|
112
|
-
|
|
113
|
-
if (!this._endpoint) {
|
|
114
|
-
this.notifyError(new Error('VPS endpoint has not been set before calling start()'));
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
let lastRequestTime = null;
|
|
119
|
-
const isProviderStopped = () => this.state === 'stopped';
|
|
120
|
-
while (!isProviderStopped()) {
|
|
121
|
-
|
|
122
|
-
// 1. Handle the time to wait between two requests (MIN_TIME_BETWEEN_TWO_REQUESTS)
|
|
123
|
-
if (lastRequestTime !== null) {
|
|
124
|
-
const diffTime = TimeUtils.preciseTime() - lastRequestTime;
|
|
125
|
-
const timeToWait = Math.max(0, VpsProvider.MIN_TIME_BETWEEN_TWO_REQUESTS - diffTime);
|
|
126
|
-
await new Promise(resolve => setTimeout(resolve, timeToWait));
|
|
127
|
-
}
|
|
128
|
-
lastRequestTime = TimeUtils.preciseTime();
|
|
129
|
-
|
|
130
|
-
// 2. Check if Vps is not stopped and camera is still started
|
|
131
|
-
if (isProviderStopped()
|
|
132
|
-
|| !this._camera
|
|
133
|
-
|| this._camera.state !== 'started') {
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 2.a. Do not send an image if smartphone looks at the floor
|
|
138
|
-
const inclination = Inclination.lastEvent ? Inclination.lastEvent : null;
|
|
139
|
-
if (inclination !== null
|
|
140
|
-
&& inclination < this._minInclinationForRequest) {
|
|
141
|
-
await new Promise(resolve => setTimeout(resolve, this._waitTimeMinInclinationForRequest));
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// 3. Get current image from camera and relocalize it.
|
|
146
|
-
|
|
147
|
-
// 3.a. Get current image and time it.
|
|
148
|
-
this._relativeRotationCalc?.tickStart();
|
|
149
|
-
const image = await this._camera.currentImage;
|
|
150
|
-
if (!image) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// 3.b. Retrieve coarse position if necessary.
|
|
155
|
-
let coarsePose: CoarsePose | null = null;
|
|
156
|
-
const bestCoarsePosition = AbsolutePositionProvider.getBestPositionEvent(GnssWifiProvider.lastEvent, PoleStarProvider.lastEvent);
|
|
157
|
-
if (this._useCoarsePose && (bestCoarsePosition || AbsoluteAttitudeProvider.lastEvent)) {
|
|
158
|
-
coarsePose = {
|
|
159
|
-
...(bestCoarsePosition && {position: bestCoarsePosition}),
|
|
160
|
-
...(AbsoluteAttitudeProvider.lastEvent && {attitude: AbsoluteAttitudeProvider.lastEvent})
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 3.c. Send image and metadata.
|
|
165
|
-
const res = await ImageRelocalization.relocalize(this._endpoint, image, null, coarsePose);
|
|
166
|
-
if (!res || !res.success) {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// 4. If relocalization is successful, apply the transforms
|
|
171
|
-
const enuToCameraRot = res.attitude!.quaternion;
|
|
172
|
-
const enuToSmartphoneRot = Quaternion.multiply(
|
|
173
|
-
enuToCameraRot,
|
|
174
|
-
VpsProvider.CAMERA_TO_SMARTPHONE_ROT
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
const deviceQuaternion = Quaternion.multiply(
|
|
178
|
-
Quaternion.fromAxisAngle([0, 0, 1], deg2rad(window.orientation || 0)),
|
|
179
|
-
enuToSmartphoneRot
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const diffAttitude = this._relativeRotationCalc?.tickEnd() || new Attitude([1, 0, 0, 0]);
|
|
183
|
-
const deviceQuaternionWithRelOffset = Quaternion.multiply(
|
|
184
|
-
deviceQuaternion,
|
|
185
|
-
diffAttitude.quaternion
|
|
186
|
-
);
|
|
187
|
-
const attitude = new AbsoluteAttitude(
|
|
188
|
-
deviceQuaternionWithRelOffset,
|
|
189
|
-
res.attitude!.time,
|
|
190
|
-
res.attitude!.accuracy
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
// [16/06/22] Force VPS accuracy to 5m if the information does not exist
|
|
194
|
-
// this allows to correctly fuse positions from different providers (VPS,
|
|
195
|
-
// GnssWifi, Pole Star...)
|
|
196
|
-
const devicePosition = res.position!.clone();
|
|
197
|
-
if (devicePosition.accuracy === null) {
|
|
198
|
-
devicePosition.accuracy = 5;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// 5. Finally, notify the listeners if the VPS is not stopped
|
|
202
|
-
if (isProviderStopped()) {
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
this.notify({
|
|
207
|
-
absoluteAttitude: attitude,
|
|
208
|
-
absolutePosition: devicePosition
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
_internalStop = () => {
|
|
215
|
-
// do nothing
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
get endpoint() {
|
|
219
|
-
return this._endpoint;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
set endpoint(endpoint) {
|
|
223
|
-
this._endpoint = endpoint;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
get minInclinationForRequest() {
|
|
227
|
-
return this._minInclinationForRequest;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
set minInclinationForRequest(minInclinationForRequest) {
|
|
231
|
-
this._minInclinationForRequest = minInclinationForRequest;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
get waitTimeMinInclinationForRequest() {
|
|
235
|
-
return this._waitTimeMinInclinationForRequest;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
set waitTimeMinInclinationForRequest(waitTimeMinInclinationForRequest) {
|
|
239
|
-
this._waitTimeMinInclinationForRequest = waitTimeMinInclinationForRequest;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
get useCoarsePose() {
|
|
243
|
-
return this._useCoarsePose;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
set useCoarsePose(useCoarsePose) {
|
|
247
|
-
this._useCoarsePose = useCoarsePose;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export default new VpsProvider();
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { canvasToBase64, base64ToCanvas } from '@wemap/camera';
|
|
2
|
-
|
|
3
|
-
import VpsMetadata, { VpsMetadataJson } from './VpsMetadata.js';
|
|
4
|
-
|
|
5
|
-
export type VpsRequestJson = VpsMetadataJson & {
|
|
6
|
-
image: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
class VpsRequest {
|
|
10
|
-
|
|
11
|
-
constructor(public metadata: VpsMetadata, public image: HTMLCanvasElement) {}
|
|
12
|
-
|
|
13
|
-
toJson() {
|
|
14
|
-
const base64Image = canvasToBase64(this.image);
|
|
15
|
-
return {
|
|
16
|
-
image: base64Image,
|
|
17
|
-
...this.metadata.toJson()
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static fromJson(json: VpsRequestJson) {
|
|
22
|
-
return new VpsRequest(
|
|
23
|
-
VpsMetadata.fromJson(json),
|
|
24
|
-
base64ToCanvas(json.image)
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default VpsRequest;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Attitude, AttitudeJson, UserPosition, UserPositionJson } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
export type VpsResponseJson = {
|
|
4
|
-
success: boolean,
|
|
5
|
-
attitude?: AttitudeJson,
|
|
6
|
-
position?: UserPositionJson
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
class VpsResponse {
|
|
10
|
-
|
|
11
|
-
constructor(
|
|
12
|
-
public success: boolean,
|
|
13
|
-
public attitude: Attitude | null = null,
|
|
14
|
-
public position: UserPosition | null = null
|
|
15
|
-
) { }
|
|
16
|
-
|
|
17
|
-
toJson(): VpsResponseJson {
|
|
18
|
-
return {
|
|
19
|
-
success: this.success,
|
|
20
|
-
attitude: this.attitude?.toJson(),
|
|
21
|
-
position: this.position?.toJson()
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static fromJson(json: VpsResponseJson, imageRecordTime: number | null = null) {
|
|
26
|
-
|
|
27
|
-
let attitude: Attitude | null = null;
|
|
28
|
-
if (json.attitude) {
|
|
29
|
-
attitude = Attitude.fromJson(json.attitude);
|
|
30
|
-
attitude.time = imageRecordTime;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
let position: UserPosition | null = null;
|
|
34
|
-
if (json.position) {
|
|
35
|
-
position = UserPosition.fromJson(json.position);
|
|
36
|
-
position.time = imageRecordTime;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return new VpsResponse(json.success, attitude, position);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default VpsResponse;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/schema#",
|
|
3
|
-
"title": "JSON SCHEMA for Visual Positioning Service (VPS)",
|
|
4
|
-
"$comment": "Helped from https://github.com/OpenArCloud/oscp-geopose-protocol",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"required": ["imageBytes", "size"],
|
|
7
|
-
"properties": {
|
|
8
|
-
"imageBytes": {
|
|
9
|
-
"$comment": "base64 image",
|
|
10
|
-
"type": "string",
|
|
11
|
-
"pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
|
|
12
|
-
},
|
|
13
|
-
"cameraParams": {
|
|
14
|
-
"type": "object",
|
|
15
|
-
"properties": {
|
|
16
|
-
"intrinsic": {
|
|
17
|
-
"$comment": "[fx, s, cx, 0, fy, cy, 0, 0, 1] (row-major)",
|
|
18
|
-
"type": "array",
|
|
19
|
-
"minLength": 9,
|
|
20
|
-
"maxLength": 9
|
|
21
|
-
},
|
|
22
|
-
"distortions": {
|
|
23
|
-
"$comment": "[k1, k2, p1, p2, k3]",
|
|
24
|
-
"type": "array",
|
|
25
|
-
"minLength": 5,
|
|
26
|
-
"maxLength": 5
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
"imageFormat": {
|
|
31
|
-
"type": "string",
|
|
32
|
-
"enum": [
|
|
33
|
-
"RGBA32",
|
|
34
|
-
"GRAY8"
|
|
35
|
-
]
|
|
36
|
-
},
|
|
37
|
-
"size": {
|
|
38
|
-
"$comment": "[width, height] (in pixels)",
|
|
39
|
-
"type": "array",
|
|
40
|
-
"minLength": 2,
|
|
41
|
-
"maxLength": 2
|
|
42
|
-
},
|
|
43
|
-
"coarseLocation": {
|
|
44
|
-
"type": "object",
|
|
45
|
-
"required": ["latitude", "longitude"],
|
|
46
|
-
"properties": {
|
|
47
|
-
"latitude": {
|
|
48
|
-
"type": "number"
|
|
49
|
-
},
|
|
50
|
-
"longitude": {
|
|
51
|
-
"type": "number"
|
|
52
|
-
},
|
|
53
|
-
"altitude": {
|
|
54
|
-
"type": "number"
|
|
55
|
-
},
|
|
56
|
-
"level": {
|
|
57
|
-
"$comment": "OpenStreetMap level",
|
|
58
|
-
"type": "number",
|
|
59
|
-
"multipleOf": 1
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
"coarseAttitude": {
|
|
64
|
-
"type": "object",
|
|
65
|
-
"required": ["w", "x", "y", "z"],
|
|
66
|
-
"properties": {
|
|
67
|
-
"w": {
|
|
68
|
-
"type": "number",
|
|
69
|
-
"minimum": -1,
|
|
70
|
-
"maximum": 1
|
|
71
|
-
},
|
|
72
|
-
"x": {
|
|
73
|
-
"type": "number",
|
|
74
|
-
"minimum": -1,
|
|
75
|
-
"maximum": 1
|
|
76
|
-
},
|
|
77
|
-
"y": {
|
|
78
|
-
"type": "number",
|
|
79
|
-
"minimum": -1,
|
|
80
|
-
"maximum": 1
|
|
81
|
-
},
|
|
82
|
-
"z": {
|
|
83
|
-
"type": "number",
|
|
84
|
-
"minimum": -1,
|
|
85
|
-
"maximum": 1
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { Attitude } from '@wemap/geo';
|
|
2
|
-
import { deg2rad, diffAngle, Quaternion } from '@wemap/maths';
|
|
3
|
-
|
|
4
|
-
class AttitudeSmoother {
|
|
5
|
-
|
|
6
|
-
static ROTATION_SPEED_JUMP_THRESHOLD = deg2rad(180); // in radians/s
|
|
7
|
-
static ROTATION_SPEED_CONVERGENCE = deg2rad(10); // in radians/s
|
|
8
|
-
static HIGH_JUMP_THRESHOLD = deg2rad(20); // in radians/s
|
|
9
|
-
static ROTATION_SPEED_HIGH_JUMP_CONVERGENCE = deg2rad(100); // in radians/s
|
|
10
|
-
static PITCH_UNCERTAINITY_HEADING_THRESHOLD = deg2rad(5); // in radians/s
|
|
11
|
-
|
|
12
|
-
_previousAttitude?: Attitude;
|
|
13
|
-
|
|
14
|
-
_smoothing : null | {
|
|
15
|
-
interpAttitude(attitude: Attitude): Attitude,
|
|
16
|
-
toTime: number
|
|
17
|
-
} = null;
|
|
18
|
-
|
|
19
|
-
constructor(public callback: (attitude: Attitude) => void) {}
|
|
20
|
-
|
|
21
|
-
feed(newAttitude: Attitude) {
|
|
22
|
-
|
|
23
|
-
if (newAttitude.time === null) {
|
|
24
|
-
throw new Error('newAttitude does not have time property');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const { _previousAttitude: previousAttitude } = this;
|
|
28
|
-
this._previousAttitude = newAttitude;
|
|
29
|
-
|
|
30
|
-
if (!previousAttitude) {
|
|
31
|
-
this.callback(newAttitude);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/*
|
|
36
|
-
* Comparison between two successive Attitude from the "feed" function
|
|
37
|
-
*/
|
|
38
|
-
if (AttitudeSmoother.isJump(previousAttitude, newAttitude)) {
|
|
39
|
-
|
|
40
|
-
const fromAttitude = this._smoothing === null
|
|
41
|
-
? previousAttitude
|
|
42
|
-
: this._smoothing.interpAttitude(previousAttitude);
|
|
43
|
-
|
|
44
|
-
const fromHeading = fromAttitude.heading;
|
|
45
|
-
const toHeading = newAttitude.heading;
|
|
46
|
-
const diffAngleHeading = diffAngle(toHeading, fromHeading);
|
|
47
|
-
|
|
48
|
-
const isHighJump = Math.abs(diffAngleHeading) < AttitudeSmoother.HIGH_JUMP_THRESHOLD;
|
|
49
|
-
const rotationSpeedConvergence = isHighJump
|
|
50
|
-
? AttitudeSmoother.ROTATION_SPEED_CONVERGENCE
|
|
51
|
-
: AttitudeSmoother.ROTATION_SPEED_HIGH_JUMP_CONVERGENCE;
|
|
52
|
-
|
|
53
|
-
const fromTime = fromAttitude.time!;
|
|
54
|
-
const timeToConsume = Math.abs(diffAngleHeading) / rotationSpeedConvergence;
|
|
55
|
-
const multiplier = diffAngleHeading < 0 ? -1 : 1;
|
|
56
|
-
|
|
57
|
-
this._smoothing = {
|
|
58
|
-
toTime: fromTime + timeToConsume,
|
|
59
|
-
|
|
60
|
-
interpAttitude: (attitude: Attitude) => {
|
|
61
|
-
const angle = rotationSpeedConvergence * (attitude.time! - fromTime);
|
|
62
|
-
const interpHeading = fromHeading + angle * multiplier;
|
|
63
|
-
const offsetQuat = Quaternion.fromAxisAngle([0, 0, 1], toHeading - interpHeading);
|
|
64
|
-
const interpQuat = Quaternion.multiply(offsetQuat, attitude.quaternion);
|
|
65
|
-
return new Attitude(interpQuat, attitude.time, attitude.accuracy);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (this._smoothing !== null) {
|
|
71
|
-
if (newAttitude.time >= this._smoothing.toTime) {
|
|
72
|
-
// This means that is the last epoch for smoothing
|
|
73
|
-
this._smoothing = null;
|
|
74
|
-
} else {
|
|
75
|
-
const interpAttitude = this._smoothing.interpAttitude(newAttitude);
|
|
76
|
-
this.callback(interpAttitude);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this.callback(newAttitude);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* @param {Attitude} previousAttitude
|
|
86
|
-
* @param {Attitude} newAttitude
|
|
87
|
-
* @returns {boolean}
|
|
88
|
-
*/
|
|
89
|
-
static isJump(previousAttitude: Attitude, newAttitude: Attitude) {
|
|
90
|
-
const fromHeading = previousAttitude.heading;
|
|
91
|
-
const toHeading = newAttitude.heading;
|
|
92
|
-
const diffAngleHeading = diffAngle(toHeading, fromHeading);
|
|
93
|
-
const diffTime = newAttitude.time! - previousAttitude.time!;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Heading is calculated from two different formulas in function of the pitch angle.
|
|
97
|
-
* Do not consider a jump if attitude is close to the change of the methods
|
|
98
|
-
* @see MathsRotations#getHeadingFromQuaternion()
|
|
99
|
-
*/
|
|
100
|
-
const [qw, qx, qy, qz] = newAttitude.quaternion;
|
|
101
|
-
const distToPitchThreshold = Math.abs(Math.asin(2 * (qw * qx + qy * qz)) - Math.PI / 4);
|
|
102
|
-
if (distToPitchThreshold < AttitudeSmoother.PITCH_UNCERTAINITY_HEADING_THRESHOLD) {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return Math.abs(diffAngleHeading) > AttitudeSmoother.ROTATION_SPEED_JUMP_THRESHOLD * diffTime;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export default AttitudeSmoother;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import chai from 'chai';
|
|
2
|
-
import chaiAlmost from 'chai-almost';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
Constants as GeoConstants, Coordinates, UserPosition
|
|
6
|
-
} from '@wemap/geo';
|
|
7
|
-
|
|
8
|
-
import Smoother from './PositionSmoother.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const expect = chai.expect;
|
|
12
|
-
chai.use(chaiAlmost(GeoConstants.EPS_MM));
|
|
13
|
-
|
|
14
|
-
const positions = [
|
|
15
|
-
[0, 0, 0, 0],
|
|
16
|
-
[0.2, 4.5E-6, 1.7E-6, 0],
|
|
17
|
-
[1.3, 3.6E-5, 3.6E-5, 1],
|
|
18
|
-
[1.7, 4.0E-5, 3.6E-5, 0],
|
|
19
|
-
[3.5, 4.0E-5, 3.0E-5, 0],
|
|
20
|
-
[4, 3.4E-5, 9.0E-6, 0]
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
const createPosition = (i: number) => new UserPosition(positions[i][1], positions[i][2], null, null, positions[i][0]);
|
|
24
|
-
|
|
25
|
-
const ratio = 1e-1;
|
|
26
|
-
|
|
27
|
-
const reducePositionTime = () => positions.forEach(pos => (pos[0] *= ratio));
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
describe('PositionSmoother', () => {
|
|
31
|
-
|
|
32
|
-
it('Last position reached', done => {
|
|
33
|
-
|
|
34
|
-
reducePositionTime();
|
|
35
|
-
|
|
36
|
-
const lastPosition = createPosition(positions.length - 1);
|
|
37
|
-
const smoother = new Smoother(position => {
|
|
38
|
-
if (Coordinates.equals(position, lastPosition)) {
|
|
39
|
-
done();
|
|
40
|
-
}
|
|
41
|
-
}, 60 / ratio);
|
|
42
|
-
|
|
43
|
-
positions.forEach((pos, index) => {
|
|
44
|
-
setTimeout(() => smoother.feed(createPosition(index), ratio), pos[0] * 1e3);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('Errors', () => {
|
|
49
|
-
const smoother = new Smoother();
|
|
50
|
-
expect(() => smoother.feed(new UserPosition(0, 0))).throw(Error);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
});
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { Level, UserPosition } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
class PositionSmoother {
|
|
4
|
-
|
|
5
|
-
// Generated positions by second
|
|
6
|
-
static DEFAULT_FREQUENCY = 60;
|
|
7
|
-
|
|
8
|
-
// flyby (in second)
|
|
9
|
-
static DEFAULT_FLYBY_TIME = 1;
|
|
10
|
-
|
|
11
|
-
positionsQueue: UserPosition[] = [];
|
|
12
|
-
previousPosition: UserPosition | null = null;
|
|
13
|
-
timeoutNotify?: any; // can be number if web or NodeJS.Timer
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @param frequency in Hz
|
|
18
|
-
*/
|
|
19
|
-
constructor(
|
|
20
|
-
public callback?: (position: UserPosition) => void,
|
|
21
|
-
public frequency = PositionSmoother.DEFAULT_FREQUENCY
|
|
22
|
-
) {}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param flybyTime in seconds
|
|
26
|
-
*/
|
|
27
|
-
feed(newPosition: UserPosition, flybyTime = PositionSmoother.DEFAULT_FLYBY_TIME) {
|
|
28
|
-
|
|
29
|
-
if (!(newPosition instanceof UserPosition)) {
|
|
30
|
-
throw new TypeError('newPosition is not instance of UserPosition');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (newPosition.time === null) {
|
|
34
|
-
throw new Error('newPosition does not have time property');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
let previousPosition;
|
|
38
|
-
if (this.positionsQueue.length !== 0) {
|
|
39
|
-
previousPosition = this.positionsQueue[0];
|
|
40
|
-
this.positionsQueue = [];
|
|
41
|
-
} else {
|
|
42
|
-
previousPosition = this.previousPosition;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (previousPosition) {
|
|
46
|
-
|
|
47
|
-
const refTimestamp = newPosition.time;
|
|
48
|
-
const distance = previousPosition.distanceTo(newPosition);
|
|
49
|
-
const azimuth = previousPosition.bearingTo(newPosition);
|
|
50
|
-
|
|
51
|
-
let i = 1;
|
|
52
|
-
const nSamples = this.frequency * flybyTime + 1;
|
|
53
|
-
|
|
54
|
-
const newPositionLevel = Level.clone(newPosition.level);
|
|
55
|
-
while (i < nSamples + 1) {
|
|
56
|
-
const smoothedPosition = previousPosition.destinationPoint(distance * i / nSamples, azimuth);
|
|
57
|
-
smoothedPosition.time = refTimestamp + (i - 1) / this.frequency;
|
|
58
|
-
smoothedPosition.level = newPositionLevel;
|
|
59
|
-
smoothedPosition.bearing = newPosition.bearing;
|
|
60
|
-
smoothedPosition.accuracy = Math.max(
|
|
61
|
-
smoothedPosition.accuracy! + (newPosition.accuracy! - smoothedPosition.accuracy!) * i / nSamples,
|
|
62
|
-
0
|
|
63
|
-
);
|
|
64
|
-
this.positionsQueue.push(smoothedPosition);
|
|
65
|
-
i++;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (this.timeoutNotify) {
|
|
69
|
-
clearTimeout(this.timeoutNotify);
|
|
70
|
-
}
|
|
71
|
-
} else {
|
|
72
|
-
this.positionsQueue.push(newPosition.clone());
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
this.previousPosition = newPosition;
|
|
76
|
-
this._notifyNext();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
_notifyNext = () => {
|
|
80
|
-
if (!this.positionsQueue.length) return;
|
|
81
|
-
this.callback?.(this.positionsQueue.shift() as UserPosition);
|
|
82
|
-
if (this.positionsQueue.length !== 0) {
|
|
83
|
-
this.timeoutNotify = setTimeout(this._notifyNext, 1e3 / this.frequency);
|
|
84
|
-
} else {
|
|
85
|
-
delete this.timeoutNotify;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
clear() {
|
|
90
|
-
clearTimeout(this.timeoutNotify);
|
|
91
|
-
delete this.timeoutNotify;
|
|
92
|
-
this.positionsQueue = [];
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export default PositionSmoother;
|
package/tsconfig.json
DELETED
package/vite.config.ts
DELETED
|
File without changes
|