@wemap/providers 12.10.8-alpha.1 → 12.10.8
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/index.js +3446 -1
- package/dist/index.js.map +1 -1
- package/{dist/index.d.ts → index.ts} +14 -0
- package/package.json +11 -15
- package/{dist/src/ProvidersOptions.d.ts → src/ProvidersOptions.ts} +16 -7
- package/src/errors/AskImuOnDesktopError.ts +10 -0
- package/src/errors/ContainsIgnoredProviderError.ts +10 -0
- package/src/errors/GeolocationApiMissingError.ts +10 -0
- package/src/errors/GeolocationPermissionDeniedError.ts +10 -0
- package/src/errors/GeolocationPositionUnavailableError.ts +10 -0
- package/src/errors/IpResolveServerError.ts +10 -0
- package/src/errors/MissingAccelerometerError.ts +11 -0
- package/src/errors/MissingArCoreError.ts +10 -0
- package/src/errors/MissingGyroscopeError.ts +11 -0
- package/src/errors/MissingMagnetometerError.ts +9 -0
- package/src/errors/MissingNativeInterfaceError.ts +11 -0
- package/src/errors/MissingPoleStarError.ts +10 -0
- package/src/errors/MissingSensorError.ts +15 -0
- package/src/errors/NoProviderFoundError.ts +10 -0
- package/src/events/AvailabilityHelper.spec.ts +30 -0
- package/src/events/AvailabilityHelper.ts +28 -0
- package/src/events/ProvidersLoggerOld.ts +87 -0
- package/src/events/Types.ts +18 -0
- package/src/mapmatching/MapMatchingHandler.spec.ts +142 -0
- package/src/mapmatching/MapMatchingHandler.ts +540 -0
- package/src/providers/Constants.ts +5 -0
- package/src/providers/FakeProvider.spec.ts +49 -0
- package/{dist/src/providers/NativeProviders.d.ts → src/providers/NativeProviders.ts} +23 -2
- package/src/providers/Provider.spec.ts +113 -0
- package/src/providers/Provider.ts +244 -0
- package/src/providers/attitude/EkfAttitude.spec.ts +115 -0
- package/src/providers/attitude/EkfAttitude.ts +233 -0
- package/src/providers/attitude/TurnProvider.ts +58 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.ts +267 -0
- package/src/providers/attitude/absolute/AbsoluteAttitudeProvider.ts +268 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.ts +84 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.ts +89 -0
- package/src/providers/attitude/relative/RelativeAttitudeFromInertialProvider.ts +66 -0
- package/src/providers/attitude/relative/RelativeAttitudeProvider.ts +70 -0
- package/src/providers/imu/AccelerometerProvider.ts +28 -0
- package/src/providers/imu/GyroscopeProvider.ts +27 -0
- package/src/providers/imu/HighRotationsProvider.ts +49 -0
- package/src/providers/imu/ImuProvider.ts +110 -0
- package/src/providers/imu/MagnetometerCalibrationProvider.ts +21 -0
- package/src/providers/inclination/InclinationFromAccProvider.ts +57 -0
- package/src/providers/inclination/InclinationFromRelativeAttitudeProvider.ts +51 -0
- package/src/providers/inclination/InclinationProvider.ts +59 -0
- package/src/providers/legacy/helpers/HeadingUnlocker.spec.ts +53 -0
- package/src/providers/legacy/helpers/HeadingUnlocker.ts +44 -0
- package/src/providers/legacy/helpers/ThugDetector.ts +30 -0
- package/src/providers/others/CameraNativeProvider.ts +29 -0
- package/src/providers/others/CameraProjectionMatrixProvider.ts +25 -0
- package/src/providers/position/absolute/AbsolutePositionProvider.spec.ts +31 -0
- package/src/providers/position/absolute/AbsolutePositionProvider.ts +277 -0
- package/src/providers/position/absolute/GnssWifiProvider.ts +126 -0
- package/src/providers/position/absolute/GnssWifiProviders.spec.ts +90 -0
- package/src/providers/position/absolute/IpProvider.ts +47 -0
- package/src/providers/position/absolute/PoleStarProvider.ts +88 -0
- package/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.ts +82 -0
- package/src/providers/position/relative/GeoRelativePositionProvider.ts +35 -0
- package/src/providers/position/relative/PdrProvider.ts +107 -0
- package/src/providers/steps/StepDetectionLadetto.ts +67 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks.ts +70 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks2.ts +99 -0
- package/src/providers/steps/StepDetectionMinMaxPeaks3.ts +192 -0
- package/src/providers/steps/StepProvider.ts +151 -0
- package/src/providers/steps/StraightLineProvider.ts +69 -0
- package/src/providers/vision/ArCoreProvider.ts +184 -0
- package/src/providers/vision/BarcodeProvider.ts +28 -0
- package/src/providers/vision/vps/ImageRelocalization.ts +98 -0
- package/src/providers/vision/vps/RelativeRotationCalc.ts +58 -0
- package/src/providers/vision/vps/VpsMetadata.ts +63 -0
- package/src/providers/vision/vps/VpsProvider.ts +251 -0
- package/src/providers/vision/vps/VpsRequest.ts +29 -0
- package/src/providers/vision/vps/VpsResponse.ts +43 -0
- package/src/providers/vision/vps/VpsSchema.json +90 -0
- package/src/smoothers/AttitudeSmoother.ts +110 -0
- package/src/smoothers/PositionSmoother.spec.ts +53 -0
- package/src/smoothers/PositionSmoother.ts +96 -0
- package/tsconfig.json +3 -0
- package/vite.config.ts +4 -0
- package/dist/helpers/CustomMapProvider.d.ts +0 -10
- package/dist/src/errors/AskImuOnDesktopError.d.ts +0 -5
- package/dist/src/errors/ContainsIgnoredProviderError.d.ts +0 -5
- package/dist/src/errors/GeolocationApiMissingError.d.ts +0 -5
- package/dist/src/errors/GeolocationPermissionDeniedError.d.ts +0 -5
- package/dist/src/errors/GeolocationPositionUnavailableError.d.ts +0 -5
- package/dist/src/errors/IpResolveServerError.d.ts +0 -5
- package/dist/src/errors/MissingAccelerometerError.d.ts +0 -6
- package/dist/src/errors/MissingArCoreError.d.ts +0 -5
- package/dist/src/errors/MissingGyroscopeError.d.ts +0 -6
- package/dist/src/errors/MissingMagnetometerError.d.ts +0 -5
- package/dist/src/errors/MissingNativeInterfaceError.d.ts +0 -5
- package/dist/src/errors/MissingPoleStarError.d.ts +0 -5
- package/dist/src/errors/MissingSensorError.d.ts +0 -6
- package/dist/src/errors/NoProviderFoundError.d.ts +0 -5
- package/dist/src/events/AvailabilityHelper.d.ts +0 -5
- package/dist/src/events/AvailabilityHelper.spec.d.ts +0 -1
- package/dist/src/events/ProvidersLoggerOld.d.ts +0 -24
- package/dist/src/events/Types.d.ts +0 -34
- package/dist/src/mapmatching/MapMatchingHandler.d.ts +0 -93
- package/dist/src/mapmatching/MapMatchingHandler.spec.d.ts +0 -1
- package/dist/src/providers/Constants.d.ts +0 -4
- package/dist/src/providers/FakeProvider.spec.d.ts +0 -36
- package/dist/src/providers/Provider.d.ts +0 -64
- package/dist/src/providers/Provider.spec.d.ts +0 -1
- package/dist/src/providers/attitude/EkfAttitude.d.ts +0 -41
- package/dist/src/providers/attitude/EkfAttitude.spec.d.ts +0 -1
- package/dist/src/providers/attitude/TurnProvider.d.ts +0 -17
- package/dist/src/providers/attitude/absolute/AbsoluteAttitudeFromBrowserProvider.d.ts +0 -60
- package/dist/src/providers/attitude/absolute/AbsoluteAttitudeProvider.d.ts +0 -44
- package/dist/src/providers/attitude/relative/RelativeAttitudeFromBrowserProvider.d.ts +0 -31
- package/dist/src/providers/attitude/relative/RelativeAttitudeFromEkfProvider.d.ts +0 -26
- package/dist/src/providers/attitude/relative/RelativeAttitudeFromInertialProvider.d.ts +0 -18
- package/dist/src/providers/attitude/relative/RelativeAttitudeProvider.d.ts +0 -25
- package/dist/src/providers/imu/AccelerometerProvider.d.ts +0 -11
- package/dist/src/providers/imu/GyroscopeProvider.d.ts +0 -11
- package/dist/src/providers/imu/HighRotationsProvider.d.ts +0 -15
- package/dist/src/providers/imu/ImuProvider.d.ts +0 -34
- package/dist/src/providers/imu/MagnetometerCalibrationProvider.d.ts +0 -11
- package/dist/src/providers/inclination/InclinationFromAccProvider.d.ts +0 -18
- package/dist/src/providers/inclination/InclinationFromRelativeAttitudeProvider.d.ts +0 -19
- package/dist/src/providers/inclination/InclinationProvider.d.ts +0 -18
- package/dist/src/providers/legacy/helpers/HeadingUnlocker.d.ts +0 -12
- package/dist/src/providers/legacy/helpers/HeadingUnlocker.spec.d.ts +0 -1
- package/dist/src/providers/legacy/helpers/ThugDetector.d.ts +0 -8
- package/dist/src/providers/others/CameraNativeProvider.d.ts +0 -11
- package/dist/src/providers/others/CameraProjectionMatrixProvider.d.ts +0 -11
- package/dist/src/providers/position/absolute/AbsolutePositionProvider.d.ts +0 -35
- package/dist/src/providers/position/absolute/AbsolutePositionProvider.spec.d.ts +0 -1
- package/dist/src/providers/position/absolute/GnssWifiProvider.d.ts +0 -28
- package/dist/src/providers/position/absolute/GnssWifiProviders.spec.d.ts +0 -1
- package/dist/src/providers/position/absolute/IpProvider.d.ts +0 -16
- package/dist/src/providers/position/absolute/PoleStarProvider.d.ts +0 -14
- package/dist/src/providers/position/relative/GeoRelativePositionFromArCoreProvider.d.ts +0 -17
- package/dist/src/providers/position/relative/GeoRelativePositionProvider.d.ts +0 -12
- package/dist/src/providers/position/relative/PdrProvider.d.ts +0 -15
- package/dist/src/providers/steps/StepDetectionLadetto.d.ts +0 -15
- package/dist/src/providers/steps/StepDetectionMinMaxPeaks.d.ts +0 -19
- package/dist/src/providers/steps/StepDetectionMinMaxPeaks2.d.ts +0 -27
- package/dist/src/providers/steps/StepDetectionMinMaxPeaks3.d.ts +0 -24
- package/dist/src/providers/steps/StepProvider.d.ts +0 -36
- package/dist/src/providers/steps/StraightLineProvider.d.ts +0 -21
- package/dist/src/providers/vision/ArCoreProvider.d.ts +0 -50
- package/dist/src/providers/vision/BarcodeProvider.d.ts +0 -11
- package/dist/src/providers/vision/vps/ImageRelocalization.d.ts +0 -11
- package/dist/src/providers/vision/vps/RelativeRotationCalc.d.ts +0 -10
- package/dist/src/providers/vision/vps/VpsMetadata.d.ts +0 -33
- package/dist/src/providers/vision/vps/VpsProvider.d.ts +0 -45
- package/dist/src/providers/vision/vps/VpsRequest.d.ts +0 -18
- package/dist/src/providers/vision/vps/VpsResponse.d.ts +0 -15
- package/dist/src/smoothers/AttitudeSmoother.d.ts +0 -23
- package/dist/src/smoothers/PositionSmoother.d.ts +0 -21
- package/dist/src/smoothers/PositionSmoother.spec.d.ts +0 -1
- package/dist/vite.config.d.ts +0 -19
- /package/{dist/src/providers/ProviderState.d.ts → src/providers/ProviderState.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3447 @@
|
|
|
1
|
-
"use strict";var t=Object.defineProperty,e=(e,i,s)=>(((e,i,s)=>{i in e?t(e,i,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[i]=s})(e,"symbol"!=typeof i?i+"":i,s),s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("@wemap/geo"),s=require("@wemap/maths"),r=require("@wemap/routers"),n=require("@wemap/utils"),o=require("@wemap/logger"),a=require("geomag"),l=require("@wemap/camera");function h(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t)for(const i in t)if("default"!==i){const s=Object.getOwnPropertyDescriptor(t,i);Object.defineProperty(e,i,s.get?s:{enumerable:!0,get:()=>t[i]})}return e.default=t,Object.freeze(e)}const c=h(a);class d extends i.Attitude{}class u extends i.Attitude{}class v extends i.UserPosition{}const E={useMapMatching:!0,ignoreProviders:[],optionalProviders:[],stopOnError:!0,checkAvailabilityOnStart:!0,get hasPoleStar(){return this.optionalProviders.includes("PoleStar")}};const _=new class{constructor(){e(this,"_enabled",!1),e(this,"currentId",0),e(this,"objectsIdMap",new WeakMap),e(this,"pushEvents",{}),e(this,"pushEventsRef",{}),e(this,"interval"),e(this,"initDate")}get enabled(){return this._enabled}set enabled(t){this._enabled=t}initializeInterval(){this.interval||(this.interval=window.setInterval((()=>{for(const[t,e]of Object.entries(this.pushEvents))o.debug("Received "+e+" notifications from "+this.pushEventsRef[Number(t)].getName()+" last second");this.pushEvents={},this.pushEventsRef={}}),1e3))}getObjectId(t){return this.objectsIdMap.has(t)||this.objectsIdMap.set(t,++this.currentId),this.objectsIdMap.get(t)}addEvent(t,e){if(!this.enabled)return;this.initDate||(this.initDate=Date.now()),this.initializeInterval();const i=this.getObjectId(t),s=t.getName();o.debug(s+"["+i+"]."+e)}incrementNotifications(t){if(!this.enabled)return;const e=this.getObjectId(t);let i=this.pushEvents[e];i||(i=0,this.pushEventsRef[e]=t),this.pushEvents[e]=i+1}},m=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(m,"DEFAULT_MESSAGE","Contains ignored provider");let p=m;const g=class t{constructor(){e(this,"id"),e(this,"state","stopped"),e(this,"_lastEvent",null),e(this,"_eventsCallbacks",[]),e(this,"_monitoringCallbacks",[]),e(this,"notify",(t=>{_.incrementNotifications(this),this._eventsCallbacks.forEach((e=>{var i;return null==(i=e.onEvent)?void 0:i.call(e,t)})),this._lastEvent=t})),e(this,"notifyError",(t=>{this._eventsCallbacks.forEach((({id:e,onError:i})=>{E.stopOnError&&this.removeEventListener(e),null==i||i(t)}))})),this.id=t._uniqueId++,_.addEvent(this,"constructor")}getAvailability(){return E.ignoreProviders.includes(this.getName())?Promise.resolve(new p):this.availability()}get hasNativeInterface(){return Boolean(this.nativeInterface)}get nativeInterface(){return"undefined"!=typeof window&&window.__nativeProviders||null}get nativeJsInterface(){return"undefined"==typeof window?null:(window.__nativeJsProviders||(window.__nativeJsProviders={}),window.__nativeJsProviders)}get useCameraNatively(){return!1}addEventListener(e=null,i=null,s=!0){const r=++t._callbackUniqueId;if(this._eventsCallbacks.push({id:r,onEvent:e||(()=>{}),onError:i||(()=>{}),optional:!s}),!s)return r;if("stopped"!==this.state)return r;this.state="starting";let n=Promise.resolve();return E.checkAvailabilityOnStart&&(n=this.getAvailability()),(async()=>{const t=await n;if(t)return this.state="stopped",void this.notifyError(t);_.addEvent(this,"start"),this.start(),this.state="started",this._monitoringCallbacks.forEach((t=>{var e;return null==(e=t.onStarted)?void 0:e.call(t)}))})(),r}removeEventListener(t){const e=this._eventsCallbacks.find((e=>e.id===t));e&&(this._eventsCallbacks=this._eventsCallbacks.filter((t=>t!==e)),e.optional||this._eventsCallbacks.find((t=>!t.optional))||"stopped"!==this.state&&(_.addEvent(this,"stop"),this.stop(),this.state="stopped",this._monitoringCallbacks.forEach((t=>{var e;return null==(e=t.onStopped)?void 0:e.call(t)}))))}addMonitoringListener(e,i){const s=t._callbackUniqueId++;return this._monitoringCallbacks.push({id:s,onStarted:e||null,onStopped:i||null}),s}removeMonitoringListener(t){this._monitoringCallbacks=this._monitoringCallbacks.filter((e=>e.id!==t))}get lastEvent(){return this._lastEvent}};e(g,"_callbackUniqueId",0),e(g,"_uniqueId",1);let A=g;class I{static async every(t){for(const e of t){const t=await e;if(t)return t}return null}static async some(t){let e;for(const i of t){const t=await i;if(!t)return null;e||(e=t)}return e||null}}const f=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(f,"DEFAULT_MESSAGE","It seems that you ask for IMU events on a desktop browser");let P=f;const T=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}from(t){return this.message+=" from "+t,this}};e(T,"DEFAULT_MESSAGE","Impossible to retrieve events, a sensor is missing");let S=T;class y extends S{constructor(t){super(t)}}const M=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(M,"DEFAULT_MESSAGE","Geolocation api is missing");let b=M;const R=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(R,"DEFAULT_MESSAGE","Geolocation permission denied");let L=R;const w=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(w,"DEFAULT_MESSAGE","Geolocation position unavailable");let N=w;const D=1.6,C=class t extends A{constructor(){super(...arguments),e(this,"discardPositionsAbove",t.DEFAULT_DISCARD_POSITIONS_ABOVE),e(this,"enableHighAccuracy",!0),e(this,"geoLocationId"),e(this,"getName",(()=>"GnssWifi")),e(this,"onNewPosition",(t=>{const{coords:e}=t;if(!e)return;let r;e.heading&&(r=s.deg2rad(e.heading));const o=n.TimeUtils.unixTimestampToPreciseTime(t.timestamp)/1e3,a=new i.UserPosition(e.latitude,e.longitude,D,null,o,e.accuracy,r);this.enableHighAccuracy&&"number"==typeof this.discardPositionsAbove&&e.accuracy>this.discardPositionsAbove||this.notify(a)})),e(this,"onPositionError",(t=>{let e;switch(o.warn(`[Providers] watchPosition error: [${t.code}] ${t.message}`),t.code){case 1:e=new L(t.message);break;case 2:e=new N(t.message);break;default:e=new Error(t.message)}this.notifyError(e)}))}get positionOptions(){return{enableHighAccuracy:this.enableHighAccuracy,timeout:1/0,maximumAge:0}}availability(){return"object"==typeof navigator&&navigator.geolocation?Promise.resolve():Promise.resolve(new b)}start(){navigator.geolocation.getCurrentPosition(this.onNewPosition,this.onPositionError,this.positionOptions),setTimeout((()=>{this.geoLocationId=navigator.geolocation.watchPosition(this.onNewPosition,this.onPositionError,this.positionOptions)}),150)}stop(){void 0!==this.geoLocationId&&navigator.geolocation.clearWatch(this.geoLocationId)}};e(C,"DEFAULT_DISCARD_POSITIONS_ABOVE",50);const F=new C,O=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(O,"DEFAULT_MESSAGE","ARCore is missing");let x=O;const U=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(U,"DEFAULT_MESSAGE","Native interface is missing. You are maybe trying to execute a code which is not available in a web browser");let H=U;const B=class t extends A{constructor(){super(...arguments),e(this,"_nativeProvider"),e(this,"previousPosition",[0,0,0]),e(this,"getName",(()=>"ArCore")),e(this,"pullDataLoop",(()=>{if("stopped"===this.state)return;const t=JSON.parse(this.nativeProvider.getInfo());t.length>1&&this.parsePayload(t),requestAnimationFrame(this.pullDataLoop)}))}availability(){try{if(!this.nativeProvider.checkAvailability())return Promise.resolve(new x)}catch(t){return Promise.resolve(t)}return Promise.resolve()}start(){var t;null==(t=this.nativeProvider)||t.start(),this.pullDataLoop()}stop(){var t;null==(t=this.nativeProvider)||t.stop()}parsePayload(e){const s=e[0];let r,o,a,l,h=1;const c=n.TimeUtils.preciseTime()/1e3;if(s&t.Payload.Pose.ref){r=new d(e.slice(h,h+4),c,t.RELATIVE_ATTITUDE_DRIFT);const s=[e[h+4],e[h+5],e[h+6]];o=new i.RelativePosition(s[0]-this.previousPosition[0],s[1]-this.previousPosition[1],s[2]-this.previousPosition[2],c,1e-4),this.previousPosition=s,h+=t.Payload.Pose.size}s&t.Payload.Barcode.ref&&(l=e[h],h+=t.Payload.Barcode.size),s&t.Payload.ProjMat.ref&&(a=e.slice(h,h+t.Payload.ProjMat.size),h+=t.Payload.ProjMat.size),this.notify({relativePosition:o,relativeAttitude:r,...l&&{barcode:l},...a&&{cameraProjection:a}})}get nativeProvider(){if(!this._nativeProvider){if(!this.nativeInterface)throw new H;if(this._nativeProvider=this.nativeInterface.getArCoreProvider(),!this._nativeProvider)throw new x}return this._nativeProvider}enableBarcodeScanner(){try{this.nativeProvider.enableBarcodeScanner()}catch(t){this.notifyError(t)}}disableBarcodeScanner(){try{this.nativeProvider.disableBarcodeScanner()}catch(t){this.notifyError(t)}}get useCameraNatively(){return!0}};e(B,"Payload",{Pose:{ref:1,size:7},Barcode:{ref:2,size:1},ProjMat:{ref:4,size:16},ImageRef:{ref:8,size:1}}),e(B,"RELATIVE_ATTITUDE_DRIFT",s.deg2rad(3)/60);const W=new B;const V=new class extends A{constructor(){super(...arguments),e(this,"absoluteAttitudeProviderId"),e(this,"arCoreProviderId"),e(this,"absoluteAttitudeEvent"),e(this,"getName",(()=>"GeoRelativePositionFromArCore")),e(this,"onArCoreEvents",(t=>{const e=t.relativeAttitude,i=t.relativePosition;e&&i&&this.absoluteAttitudeEvent&&this.compute(i,e,this.absoluteAttitudeEvent)}))}availability(){return I.every([W.getAvailability(),xt.getAvailability()])}start(){this.arCoreProviderId=W.addEventListener(this.onArCoreEvents,this.notifyError),this.absoluteAttitudeProviderId=xt.addEventListener((t=>this.absoluteAttitudeEvent=t),this.notifyError)}stop(){W.removeEventListener(this.arCoreProviderId),xt.removeEventListener(this.absoluteAttitudeProviderId)}compute(t,e,s){const r=s.heading-e.heading,n=Math.cos(r)*t.x-Math.sin(r)*t.z,o=-Math.sin(r)*t.x-Math.cos(r)*t.z,a=t.y,l=new i.GeoRelativePosition(n,o,a,t.time,0,s.heading);this.notify(l)}},G={acc:.5,gyr:.3},k={acc:.5,gyr:.3,yc:2};class Q{constructor(t=[0,0,1],i=[-1,0,0]){e(this,"P"),e(this,"accRef"),e(this,"cRef"),e(this,"noises"),e(this,"quaternion"),this.accRef=t,this.cRef=i,this.P=s.Matrix4.fromDiagVector(Array(4).fill(.1**2)),this.quaternion=null,this.noises={},this.setRelativeNoises(G),this.setAbsoluteNoises(k)}setRelativeNoises(t){this.noises.relative={acc:s.Matrix3.diag(Array(3).fill(t.acc**2)),gyr:s.Matrix3.diag(Array(3).fill(t.gyr**2))}}setAbsoluteNoises(t){this.noises.absolute={acc:s.Matrix3.diag(Array(3).fill(t.acc**2)),gyr:s.Matrix3.diag(Array(3).fill(t.gyr**2)),yc:s.Matrix3.diag(Array(3).fill(t.yc**2))}}tryInitialize(t,e){const i=s.Vector3.normalize(t);if(e){const t=s.Vector3.normalize(e),r=s.Vector3.normalize(s.Vector3.cross(t,i)),n=s.Vector3.cross(i,r),o=[[r[0],n[0],i[0]],[r[1],n[1],i[1]],[r[2],n[2],i[2]]];this.quaternion=s.Quaternion.fromMatrix3Matlab(o)}else{const t=s.Vector3.dot(i,this.accRef)+1,e=s.Vector3.cross(i,this.accRef);let r=[t,e[0],e[1],e[2]];r=s.Quaternion.normalize(r),this.quaternion=r}return this.quaternion}update(t,e,i,r){if(!this.quaternion)return this.tryInitialize(e,r);let n=this.quaternion;const o=n,a=s.Vector3.multiplyScalar(i,.5*t),l=this.computeC([1,a[0],a[1],a[2]]),h=s.Matrix4.multiplyVector(l,n),c=s.Matrix3.diag([o[0],o[0],o[0]]),d=s.Matrix3.skew([o[1],o[2],o[3]]),u=[-1*o[1],-1*o[2],-1*o[3]],v=s.Matrix.concatRow([u],s.Matrix3.sum(d,c)),E=s.Matrix4.multiplyScalar(s.Matrix.multiply(s.Matrix.multiply(v,this.noises[r?"absolute":"relative"].gyr),s.Matrix.transpose(v)),(t/2)**2),_=s.Matrix4.sum(s.Matrix4.multiply(s.Matrix4.multiply(l,this.P),s.Matrix4.transpose(l)),E),m=s.Vector3.normalize(e);let p,g,A;if(r){const t=s.Vector3.normalize(r),e=s.Vector3.cross(m,t),i=s.Vector3.normalize(e),n=s.Vector3.subtract(i,s.Quaternion.rotateMatlab(h,this.cRef)),o=s.Vector3.subtract(m,s.Quaternion.rotateMatlab(h,this.accRef));p=s.Vector.concat(n,o);const a=this.jacobianES(h,this.cRef),l=this.jacobianES(h,this.accRef);A=s.Matrix.concatRow(a,l);const c=s.Matrix.concatLine(this.noises.absolute.yc,s.Matrix3.zeros),d=s.Matrix.concatLine(s.Matrix3.zeros,this.noises.absolute.acc),u=s.Matrix.concatRow(c,d);g=s.Matrix.multiply(s.Matrix.multiply(_,s.Matrix.transpose(A)),s.Matrix.inverse(s.Matrix.sum(s.Matrix.multiply(s.Matrix.multiply(A,_),s.Matrix.transpose(A)),u)))}else{p=s.Vector3.subtract(m,s.Quaternion.rotateMatlab(h,this.accRef)),A=this.jacobianES(h,this.accRef);const t=this.noises.relative.acc;g=s.Matrix.multiply(s.Matrix.multiply(_,s.Matrix.transpose(A)),s.Matrix3.inverse(s.Matrix3.sum(s.Matrix.multiply(s.Matrix.multiply(A,_),s.Matrix.transpose(A)),t)))}n=s.Quaternion.sum(h,s.Matrix.multiplyVector(g,p));const I=s.Matrix4.multiply(s.Matrix4.subtract(s.Matrix4.identity,s.Matrix.multiply(g,A)),_);return n=s.Quaternion.normalize(n),this.quaternion=n,this.P=I,n}computeC(t){return[[t[0],-t[1],-t[2],-t[3]],[t[1],t[0],t[3],-t[2]],[t[2],-t[3],t[0],t[1]],[t[3],t[2],-t[1],t[0]]]}jacobianES(t,e){const[i,s,r,n]=t,[o,a,l]=e;return[[2*n*a-2*r*l,2*r*a+2*n*l,2*s*a-2*i*l-4*r*o,2*i*a+2*s*l-4*n*o],[2*s*l-2*n*o,2*i*l-4*s*a+2*r*o,2*s*o+2*n*l,2*r*l-2*i*o-4*n*a],[2*r*o-2*s*a,2*n*o-4*s*l-2*i*a,2*i*o-4*r*l+2*n*a,2*s*o+2*r*a]]}}const q=new class extends A{constructor(){super(...arguments),e(this,"getName",(()=>"IMU")),e(this,"parseDeviceMotionEvent",(t=>{const e=t.timeStamp/1e3;let i,r;if(t.accelerationIncludingGravity){const{x:e,y:s,z:r}=t.accelerationIncludingGravity;"number"==typeof e&&"number"==typeof s&&"number"==typeof r&&(i=[e,s,r],n.BrowserUtils.getName()!==n.Browser.SAFARI&&n.BrowserUtils.getName()!==n.Browser.IOS_WEBVIEW||(i[0]*=-1,i[1]*=-1,i[2]*=-1))}if(t.rotationRate){const{alpha:e,beta:i,gamma:n}=t.rotationRate;"number"==typeof e&&"number"==typeof i&&"number"==typeof n&&(r=[s.deg2rad(e),s.deg2rad(i),s.deg2rad(n)])}(i||r)&&this.notify({...i&&{acceleration:{timestamp:e,values:i}},...r&&{angularRate:{timestamp:e,values:r}}})}))}availability(){return n.BrowserUtils.isMobile?Promise.resolve():Promise.resolve(new P)}start(){const t=()=>window.addEventListener("devicemotion",this.parseDeviceMotionEvent,!0),e=DeviceMotionEvent.requestPermission||void 0;e?e().then((e=>{if("granted"!==e)throw new Error("Permission not granted");t()})).catch(this.notifyError):t()}stop(){window.removeEventListener("devicemotion",this.parseDeviceMotionEvent,!0)}},j=class t extends S{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(j,"DEFAULT_MESSAGE","Impossible to retrieve Acceleration data");let z=j;const J=new class extends A{constructor(){super(...arguments),e(this,"imuProviderId"),e(this,"getName",(()=>"Accelerometer")),e(this,"availability",(()=>q.getAvailability()))}start(){this.imuProviderId=q.addEventListener((t=>{t.acceleration?this.notify(t.acceleration):this.notifyError((new z).from("devicemotion"))}),this.notifyError)}stop(){q.removeEventListener(this.imuProviderId)}};class Y extends S{constructor(t){super(t||S.DEFAULT_MESSAGE)}}e(Y,"DEFAULT_MESSAGE","Impossible to retrieve Angular Rate data");const X=new class extends A{constructor(){super(...arguments),e(this,"imuProviderId"),e(this,"getName",(()=>"Gyroscope")),e(this,"availability",(()=>q.getAvailability()))}start(){this.imuProviderId=q.addEventListener((t=>{t.angularRate?this.notify(t.angularRate):this.notifyError((new Y).from("devicemotion"))}),this.notifyError)}stop(){q.removeEventListener(this.imuProviderId)}},K=class t extends A{constructor(){super(...arguments),e(this,"accelerometerProviderId"),e(this,"ekfAttitude",new Q),e(this,"gyroscopeEvent"),e(this,"gyroscopeProviderId"),e(this,"lastTimestamp",0),e(this,"getName",(()=>"RelativeAttitudeFromEkf")),e(this,"onAccelerometerEvent",(e=>{if(!this.gyroscopeEvent)return;const{values:i,timestamp:s}=e;if(0===this.lastTimestamp)return void(this.lastTimestamp=s);const r=s-this.lastTimestamp;this.lastTimestamp=s;const n=this.ekfAttitude.update(r,i,this.gyroscopeEvent.values);if(n){const e=new d(n,s,t.DEFAULT_DRIFT);this.notify(e)}}))}availability(){return I.every([J.getAvailability(),X.getAvailability()])}start(){this.accelerometerProviderId=J.addEventListener((t=>this.onAccelerometerEvent(t)),(t=>this.notifyError(t))),this.gyroscopeProviderId=X.addEventListener((t=>this.gyroscopeEvent=t),(t=>this.notifyError(t)))}stop(){J.removeEventListener(this.accelerometerProviderId),X.removeEventListener(this.gyroscopeProviderId)}};e(K,"DEFAULT_DRIFT",s.deg2rad(5)/60);const Z=new K,$=class t extends A{constructor(){super(...arguments),e(this,"getName",(()=>"RelativeAttitudeFromBrowser")),e(this,"onDeviceOrientationEvent",(e=>{if("number"!=typeof e.alpha||"number"!=typeof e.beta||"number"!=typeof e.gamma)return void this.notifyError((new S).from("deviceorientation"));const i=s.Rotations.eulerToQuaternionZXYDegrees([e.alpha,e.beta,e.gamma]),r=new d(i,e.timeStamp/1e3,t.DEFAULT_DRIFT);this.notify(r)}))}availability(){return n.BrowserUtils.isMobile?Promise.resolve():Promise.resolve(new P)}start(){const t=()=>window.addEventListener("deviceorientation",this.onDeviceOrientationEvent,!0),e=DeviceOrientationEvent.requestPermission||void 0;e?e().then((e=>{if("granted"!==e)throw new Error("Permission not granted");t()})).catch((t=>this.notifyError(t))):t()}stop(){window.removeEventListener("deviceorientation",this.onDeviceOrientationEvent,!0)}};e($,"DEFAULT_DRIFT",s.deg2rad(5)/60);const tt=new $,et=class t extends A{constructor(){super(...arguments),e(this,"gyroscopeProviderId"),e(this,"getName",(()=>"HighRotationsProvider")),e(this,"availability",(()=>X.getAvailability())),e(this,"_parseGyroscopeEvent",(e=>{const{values:i,timestamp:r}=e;s.Vector3.norm(i)>t.THRESHOLD&&this.notify({timestamp:r})}))}start(){this.gyroscopeProviderId=X.addEventListener(this._parseGyroscopeEvent,this.notifyError)}stop(){X.removeEventListener(this.gyroscopeProviderId)}isInProgress(){if(!this.lastEvent||!X.lastEvent)return!1;return X.lastEvent.timestamp-this.lastEvent.timestamp<t.DELAY_CONSIDERATION}};e(et,"THRESHOLD",10),e(et,"DELAY_CONSIDERATION",3);const it=new et,st=class t extends A{constructor(){super(...arguments),e(this,"_highRotationsProviderId"),e(this,"listenerId"),e(this,"provider"),e(this,"getName",(()=>"RelativeAttitudeFromInertial"))}availability(){return I.some([Z.getAvailability(),tt.getAvailability()])}start(){Z.getAvailability().then((t=>{this.provider=t?tt:Z,this.listenerId=this.provider.addEventListener((t=>this._parseEvent(t)),this.notifyError),this._highRotationsProviderId=it.addEventListener(null,this.notifyError)}))}_parseEvent(e){const i=e.clone();if(it.isInProgress()){let e=(i.accuracy||0)+100*t.DEFAULT_DRIFT;e=Math.min(e,Math.PI),i.accuracy=e}this.notify(i)}stop(){this.provider&&(this.provider.removeEventListener(this.listenerId),delete this.provider),it.removeEventListener(this._highRotationsProviderId)}};e(st,"DEFAULT_DRIFT",s.deg2rad(5)/60);const rt=new st,nt=class t{constructor(){e(this,"frequency",0),e(this,"lastVerticalAcc",0),e(this,"maxAcceleration",0),e(this,"lastStepTimestamp",-t.MIN_TIME_BETWEEN_STEPS)}compute(e,i){let s=!1;const r=i[2],n=e-this.lastStepTimestamp;if(r>this.lastVerticalAcc)r>this.maxAcceleration&&(this.maxAcceleration=r);else if(this.maxAcceleration>t.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD&&n>t.MIN_TIME_BETWEEN_STEPS){this.maxAcceleration=0;const i=e-this.lastStepTimestamp;this.frequency=Math.min(Math.max(1/i,t.MIN_FRENQUENCY),t.MAX_FRENQUENCY),s=!0,this.lastStepTimestamp=e}else this.maxAcceleration=0;return this.lastVerticalAcc=r,s}get lastStepSize(){if(!this.frequency)return 0;return.45+.2*this.frequency}get speed(){return this.lastStepTimestamp?this.lastStepSize*this.frequency:0}};e(nt,"MIN_TIME_BETWEEN_STEPS",.4),e(nt,"MAX_FRENQUENCY",4),e(nt,"MIN_FRENQUENCY",1),e(nt,"VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD",1);let ot=nt;const at=class t{constructor(){e(this,"frequency",0),e(this,"lastStepTimestamp",-t.MIN_TIME_BETWEEN_STEPS),e(this,"slidingWindow",[])}compute(e,i){if(this.lastStepTimestamp&&this.lastStepTimestamp+t.MIN_TIME_BETWEEN_STEPS>e)return!1;let s=Number.MIN_SAFE_INTEGER,r=Number.MAX_SAFE_INTEGER;const n=t.WINDOW_TIME;if(this.slidingWindow.forEach(((t,i,o)=>{t.timestamp<e-n?o.splice(i,1):(s=Math.max(t.verticalAcc,s),r=Math.min(t.verticalAcc,r))})),this.slidingWindow.push({timestamp:e,verticalAcc:i[2]}),s>t.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD&&r<t.VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD){const i=this.lastStepTimestamp?e-this.lastStepTimestamp:1;return this.frequency=Math.min(Math.max(1/i,t.MIN_FRENQUENCY),t.MAX_FRENQUENCY),this.lastStepTimestamp=e,!0}return!1}get lastStepSize(){if(!this.frequency)return 0;return.45+.2*this.frequency}get speed(){return this.lastStepTimestamp?this.lastStepSize*this.frequency:0}};e(at,"WINDOW_TIME",.3),e(at,"MIN_TIME_BETWEEN_STEPS",.4),e(at,"MAX_FRENQUENCY",4),e(at,"MIN_FRENQUENCY",1),e(at,"VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD",1.5),e(at,"VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD",-1);let lt=at;const ht=class t{constructor(){e(this,"frequency",0),e(this,"influence",.2),e(this,"slidingWindow",[]),e(this,"lastStepTimestamp",-t.MIN_TIME_BETWEEN_STEPS),e(this,"previousVerticalAcc",0)}compute(e,i,s){const r=this.influence*(2*i[2])+(1-this.influence)*this.previousVerticalAcc;if(this.previousVerticalAcc=r,Math.sqrt(s[0]**2+s[1]**2+s[2]**2)>.75)return!1;if(this.lastStepTimestamp&&this.lastStepTimestamp+t.MIN_TIME_BETWEEN_STEPS>e)return!1;let n=Number.MIN_SAFE_INTEGER,o=Number.MAX_SAFE_INTEGER;if(this.slidingWindow.forEach(((i,s,r)=>{i.timestamp<e-t.WINDOW_TIME?r.splice(s,1):(n=Math.max(i.verticalAcc,n),o=Math.min(i.verticalAcc,o))})),this.slidingWindow.push({timestamp:e,verticalAcc:r}),n>t.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD&&o<t.VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD){const i=this.lastStepTimestamp?e-this.lastStepTimestamp:1;return this.frequency=Math.min(Math.max(1/i,t.MIN_FRENQUENCY),t.MAX_FRENQUENCY),this.lastStepTimestamp=e,!0}return!1}get lastStepSize(){if(!this.frequency)return 0;return.45+.2*this.frequency}get speed(){return this.lastStepSize&&this.frequency?this.lastStepSize*this.frequency:0}mean(t){let e=0,i=0;for(let s=0;s<t.length;++s)e+=t[s].verticalAcc;return i=e/t.length,i}stddev(t){const e=this.mean(t);let i=0;for(let s=0;s<t.length;++s)i+=(t[s].verticalAcc-e)**2;return Math.sqrt(i/t.length)}};e(ht,"WINDOW_TIME",.3),e(ht,"MIN_TIME_BETWEEN_STEPS",.4),e(ht,"MAX_FRENQUENCY",4),e(ht,"MIN_FRENQUENCY",1),e(ht,"VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD",.75),e(ht,"VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD",-.3);let ct=ht;const dt=class t{constructor(){e(this,"frequency",0),e(this,"influence",.05),e(this,"slidingWindow",[]),e(this,"lastStepTimestamp",-t.MIN_TIME_BETWEEN_STEPS),e(this,"previousVerticalAcc",0),e(this,"previousHorizontalAcc",0)}compute(e,i){const s=this.influence*i[2]+(1-this.influence)*this.previousVerticalAcc;this.previousVerticalAcc=s,this.slidingWindow=this.slidingWindow.filter((i=>i.timestamp>=e-t.WINDOW_TIME)),this.slidingWindow.push({timestamp:e,verticalAcc:s});if(this.lastStepTimestamp&&this.lastStepTimestamp+t.MIN_TIME_BETWEEN_STEPS>e)return!1;let r=Number.MIN_VALUE,n=-1,o=!1;if(this.slidingWindow.forEach(((e,i)=>{e.verticalAcc>r&&e.verticalAcc>=t.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD&&(r=e.verticalAcc,n=i,o=!0)})),!o)return!1;let a=!1,l=Number.MAX_VALUE;for(let u=0;u<n;u++){const e=this.slidingWindow[u].verticalAcc;if(l=Math.min(l,e),e<t.VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD){a=!0;break}}if(!a)return!1;const h=r-.5*(r-l);let c=!1;for(let t=n+1;t<this.slidingWindow.length;t++)if(this.slidingWindow[t].verticalAcc<=h){c=!0;break}if(!c)return!1;const d=this.lastStepTimestamp?e-this.lastStepTimestamp:1;return this.frequency=Math.min(Math.max(1/d,t.MIN_FRENQUENCY),t.MAX_FRENQUENCY),this.lastStepTimestamp=e,!0}get lastStepSize(){if(!this.frequency)return 0;return.45+.2*this.frequency}get speed(){return this.lastStepSize&&this.frequency?this.lastStepSize*this.frequency:0}mean(t){let e=0,i=0;for(let s=0;s<t.length;++s)e+=t[s];return i=e/t.length,i}stddev(t){const e=this.mean(t);let i=0;for(let s=0;s<t.length;++s)i+=(t[s]-e)**2;return Math.sqrt(i/t.length)}};e(dt,"WINDOW_TIME",.6),e(dt,"MIN_TIME_BETWEEN_STEPS",.6),e(dt,"MAX_FRENQUENCY",4),e(dt,"MIN_FRENQUENCY",1),e(dt,"VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD",.2),e(dt,"VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD",-.1);let ut=dt;const vt=class t extends A{constructor(){super(),e(this,"accelerometerProviderId"),e(this,"attitudeProviderId"),e(this,"gyroscopeProviderId"),e(this,"angularRateEvent"),e(this,"attitudeEvent"),e(this,"numOfSteps",0),e(this,"stepDetector"),e(this,"_stepSizeMultiplier",t.DEFAULT_STEP_SIZE_MULTIPLIER),e(this,"_algorithm",t.DEFAULT_ALGORITHM),e(this,"_accValues",[]),e(this,"getName",(()=>"StepDetector")),e(this,"onAccelerometerEvent",(e=>{if(!this.attitudeEvent||!this.angularRateEvent)return;const{values:i,timestamp:s}=e,r=t.computeLinearAcceleration(this.attitudeEvent.quaternion,i);if(this.stepDetector.compute(s,r,this.angularRateEvent.values)){const t=this.stepDetector.lastStepSize*this._stepSizeMultiplier;this.numOfSteps++,this.notify({size:t,number:this.numOfSteps})}})),this.algorithm=this._algorithm}availability(){return I.every([J.getAvailability(),X.getAvailability(),rt.getAvailability()])}start(){this.numOfSteps=0,this.accelerometerProviderId=J.addEventListener(this.onAccelerometerEvent,this.notifyError),this.gyroscopeProviderId=X.addEventListener((t=>this.angularRateEvent=t),this.notifyError),this.attitudeProviderId=rt.addEventListener((t=>this.attitudeEvent=t),this.notifyError)}stop(){J.removeEventListener(this.accelerometerProviderId),X.removeEventListener(this.gyroscopeProviderId),rt.removeEventListener(this.attitudeProviderId)}static computeLinearAcceleration(t,e){const r=s.Quaternion.rotateMatlab(s.Quaternion.inverse(t),e);return r[2]-=i.Constants.EARTH_GRAVITY,r}set stepSizeMultiplier(t){this._stepSizeMultiplier=t}get stepSizeMultiplier(){return this._stepSizeMultiplier}set algorithm(t){switch(t){case"ladetto":this.stepDetector=new ot;break;case"minMaxPeaks":this.stepDetector=new lt;break;case"minMaxPeaks2":this.stepDetector=new ct;break;default:t="minMaxPeaks3",this.stepDetector=new ut}this._algorithm=t}get algorithm(){return this._algorithm}};e(vt,"DEFAULT_STEP_SIZE_MULTIPLIER",1),e(vt,"DEFAULT_ALGORITHM","minMaxPeaks3");const Et=new vt;const _t=new class extends A{constructor(){super(...arguments),e(this,"absoluteAttitudeProviderId"),e(this,"stepDetectionProviderId"),e(this,"attitudeEvent"),e(this,"misalignmentError",s.deg2rad(3)),e(this,"getName",(()=>"Pdr")),e(this,"onStepEvent",(t=>{if(!this.attitudeEvent)return;const e=t.size,s=this.attitudeEvent,r=s.heading,n=s.accuracy+this.misalignmentError,o=e/2*Math.sin(n/2),a=s.time,l=new i.GeoRelativePosition(e*Math.sin(r),e*Math.cos(r),0,a,o,r);this.notify(l)}))}availability(){return I.every([Et.getAvailability(),xt.getAvailability()])}start(){this.stepDetectionProviderId=Et.addEventListener(this.onStepEvent,this.notifyError),this.absoluteAttitudeProviderId=xt.addEventListener((t=>this.attitudeEvent=t),this.notifyError)}stop(){Et.removeEventListener(this.stepDetectionProviderId),xt.removeEventListener(this.absoluteAttitudeProviderId)}};const mt=new class extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"geoRelativeProvider"),e(this,"getName",(()=>"GeoRelativePosition"))}availability(){return I.some([_t.getAvailability(),V.getAvailability()])}async start(){const t=await V.getAvailability();this.geoRelativeProvider=t?_t:V,this.providerId=this.geoRelativeProvider.addEventListener(this.notify,this.notifyError)}stop(){var t;null==(t=this.geoRelativeProvider)||t.removeEventListener(this.providerId),delete this.geoRelativeProvider}};const pt=new class extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"getName",(()=>"InclinationFromAcc")),e(this,"availability",(()=>J.getAvailability())),e(this,"onAccelerometerEvent",(t=>{const e=t.values,i=window.orientation||0,s=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),r=[e[0]/s,e[1]/s,e[2]/s],n=[r[2]+1,r[1],-r[0],0],o=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]),a=[n[0]/o,n[1]/o,n[2]/o,0];let l;l=0===i?Math.asin(2*a[1]*a[0]):90===i?-Math.asin(2*a[2]*a[0]):-90===i?Math.asin(2*a[2]*a[0]):-Math.asin(2*a[1]*a[0]),this.notify(l)}))}start(){this.providerId=J.addEventListener(this.onAccelerometerEvent,this.notifyError)}stop(){J.removeEventListener(this.providerId)}};const gt=new class extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"getName",(()=>"InclinationFromRelativeAttitude")),e(this,"availability",(()=>rt.getAvailability()))}start(){this.providerId=rt.addEventListener((t=>{const e=this.enuQuatToInclination(t.quaternion);this.notify(e)}),this.notifyError)}stop(){rt.removeEventListener(this.providerId)}enuQuatToInclination(t){const e=window.orientation||0;return 0===e?Math.asin(2*(t[2]*t[3]+t[1]*t[0])):90===e?Math.asin(2*(t[1]*t[3]-t[2]*t[0])):-90===e?Math.asin(2*(t[2]*t[0]-t[1]*t[3])):-Math.asin(2*(t[2]*t[3]+t[1]*t[0]))}};const At=new class extends A{constructor(){super(...arguments),e(this,"provider"),e(this,"providerId"),e(this,"getName",(()=>"Inclination"))}availability(){return I.some([pt.getAvailability(),gt.getAvailability()])}async start(){const t=()=>{this.provider=pt,this.providerId=this.provider.addEventListener(this.notify,this.notifyError)};await gt.getAvailability()?(this.provider=gt,this.providerId=this.provider.addEventListener(this.notify,(()=>{gt.removeEventListener(this.providerId),t()}))):t()}stop(){this.provider&&this.provider.removeEventListener(this.providerId)}};class It{constructor(t,e=null,i=null,s=null){this.size=t,this.calibration=e,this.coarse=i,this.device=s}toJson(){return{size:[this.size.width,this.size.height],...this.calibration&&{calibration:this.calibration},...this.coarse&&{coarse:{...this.coarse.attitude&&{attitude:this.coarse.attitude.toJson()},...this.coarse.position&&{position:this.coarse.position.toJson()}}},..."object"==typeof this.device&&{device:this.device}}}static fromJson(t){var e,s;return new It({width:t.size[0],height:t.size[1]},t.calibration,{...(null==(e=t.coarse)?void 0:e.position)&&{position:i.UserPosition.fromJson(t.coarse.position)},...(null==(s=t.coarse)?void 0:s.attitude)&&{attitude:i.Attitude.fromJson(t.coarse.attitude)}},t.device)}}class ft{constructor(t,e){this.metadata=t,this.image=e}toJson(){return{image:l.canvasToBase64(this.image),...this.metadata.toJson()}}static fromJson(t){return new ft(It.fromJson(t),l.base64ToCanvas(t.image))}}class Pt{constructor(t,e=null,i=null){this.success=t,this.attitude=e,this.position=i}toJson(){var t,e;return{success:this.success,attitude:null==(t=this.attitude)?void 0:t.toJson(),position:null==(e=this.position)?void 0:e.toJson()}}static fromJson(t,e=null){let s=null;t.attitude&&(s=i.Attitude.fromJson(t.attitude),s.time=e);let r=null;return t.position&&(r=i.UserPosition.fromJson(t.position),r.time=e),new Pt(t.success,s,r)}}class Tt{static _prepareRequest(t,e=null,i=null){l.convertToGrayscale(t);const s=l.reduceImageSize(t,1280),r=new It({width:s.width,height:s.height},e,i,n.UserAgentUtils.getDeviceFromUserAgent());return new ft(r,s)}static async relocalize(t,e,i=null,s=null,r=null){const a=n.TimeUtils.preciseTime()/1e3,l=this._prepareRequest(e,i,s);let h;try{const e=JSON.stringify(l.toJson());o.debug(`[VPS] Request (${(e.length/1024).toFixed(0)} kB) sent to server ${t}`),h=await fetch(t,{method:"POST",body:e,headers:Object.assign({"Content-Type":"application/json",Accept:"application/vnd.geopose+json; version=1"},r||{})})}catch(u){return o.debug("[VPS] Server respond error"),null}if(200!==h.status)return o.debug("[VPS] Server respond error"),null;const c=await h.json(),d=Pt.fromJson(c,a);return o.debug("[VPS] Server respond "+(d.success?"success":"not found")),d}static getHeadingFromQuaternion(t){const[e,i,s,r]=t,n=Math.sqrt(2)/2,o=[n*(e-i),n*(e+i),n*(s+r),n*(r-s)];return-Math.atan2(2*o[3]*o[0]-2*o[2]*o[1],1-2*o[1]**2-2*o[3]**2)}}class St{constructor(){e(this,"_providerId"),e(this,"_isRunning",!1),e(this,"_dataOnStart",null)}tickStart(){this._dataOnStart=null,this._isRunning||(this._isRunning=!0,this._providerId=tt.addEventListener((t=>{this._dataOnStart||(this._dataOnStart=t)})))}tickEnd(){if(!this._isRunning)return o.warn("You have to call tickStart before tickEnd"),null;if(this._internalStop(),!this._dataOnStart)return o.warn("Delay was too short between tickStart and tickEnd or RelativeAttitudeProvider cannot be retrieved."),null;const t=tt.lastEvent;return i.Attitude.diff(this._dataOnStart,t)}_internalStop(){tt.removeEventListener(this._providerId),delete this._providerId,this._isRunning=!1}release(){this._isRunning&&this._internalStop()}}const yt=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(yt,"DEFAULT_MESSAGE","PoleStar is missing");let Mt=yt;const bt=new class extends A{constructor(){super(),e(this,"getName",(()=>"PoleStar")),this.addMethodsToNativeJsProvider()}availability(){try{return this.nativeProvider.checkAvailability(),Promise.resolve()}catch(t){return Promise.resolve(t)}}setApiKey(t){this.nativeProvider.setApiKey(t)}start(){this.nativeProvider.start()}stop(){this.nativeProvider.stop()}get nativeProvider(){if(!this.nativeInterface)throw new H;const t=this.nativeInterface.getPoleStarProvider();if(!t)throw new Mt;return t}addMethodsToNativeJsProvider(){this.nativeJsInterface&&(this.nativeJsInterface.polestar={callbackError:t=>this.notifyError(new Error(t)),callbackPosition:t=>{const e=JSON.parse(t),i=n.TimeUtils.unixTimestampToPreciseTime(e.time)/1e3,r=new v(e.lat,e.lng,D,e.alt/5,i,e.accuracy,s.deg2rad(e.bearing));this.notify(r)}})}},Rt=class t extends A{constructor(){super(...arguments),e(this,"_relativeRotationCalc"),e(this,"_serverError",!1),e(this,"_cameraError",!1),e(this,"_camera",null),e(this,"_endpoint",null),e(this,"_inclinationProviderId"),e(this,"_minInclinationForRequest",t.DEFAULT_MIN_INCLINATION_FOR_REQUEST),e(this,"_waitTimeMinInclinationForRequest",t.DEFAULT_WAIT_TIME_MIN_INCLINATION_FOR_REQUEST),e(this,"_useCoarsePose",t.DEFAULT_USE_COARSE_POSE),e(this,"getName",(()=>"Vps")),e(this,"availability",(()=>l.Camera.checkAvailability())),e(this,"_onCameraDetected",(({camera:t})=>{this._camera&&o.warn("It seems that more than 1 camera has been detected for VPS. Taking the first..."),this._useCamera(t)})),e(this,"_onCameraRemoved",(()=>{this._camera?(this._camera.off("started",this._internalStart),this._camera.off("stopped",this._internalStop)):o.warn("There is no previously detected camera but once has stopped"),this._camera=null})),e(this,"_internalStart",(async()=>{var e,r;if(!this._endpoint)return void this.notifyError(new Error("VPS endpoint has not been set before calling start()"));let o=null;const a=()=>"stopped"===this.state;for(;!a();){if(null!==o){const e=n.TimeUtils.preciseTime()-o,i=Math.max(0,t.MIN_TIME_BETWEEN_TWO_REQUESTS-e);await new Promise((t=>setTimeout(t,i)))}if(o=n.TimeUtils.preciseTime(),a()||!this._camera||"started"!==this._camera.state)break;const l=At.lastEvent?At.lastEvent:null;if(null!==l&&l<this._minInclinationForRequest){await new Promise((t=>setTimeout(t,this._waitTimeMinInclinationForRequest)));continue}null==(e=this._relativeRotationCalc)||e.tickStart();const h=await this._camera.currentImage;if(!h)continue;let c=null;const d=Nt.getBestPositionEvent(F.lastEvent,bt.lastEvent);this._useCoarsePose&&(d||xt.lastEvent)&&(c={...d&&{position:d},...xt.lastEvent&&{attitude:xt.lastEvent}});const v=await Tt.relocalize(this._endpoint,h,null,c);if(!v||!v.success)continue;const E=v.attitude.quaternion,_=s.Quaternion.multiply(E,t.CAMERA_TO_SMARTPHONE_ROT),m=s.Quaternion.multiply(s.Quaternion.fromAxisAngle([0,0,1],s.deg2rad(window.orientation||0)),_),p=(null==(r=this._relativeRotationCalc)?void 0:r.tickEnd())||new i.Attitude([1,0,0,0]),g=s.Quaternion.multiply(m,p.quaternion),A=new u(g,v.attitude.time,v.attitude.accuracy),I=v.position.clone();if(null===I.accuracy&&(I.accuracy=5),a())break;this.notify({absoluteAttitude:A,absolutePosition:I})}})),e(this,"_internalStop",(()=>{}))}start(){this._inclinationProviderId=At.addEventListener(),this._relativeRotationCalc=new St,l.SharedCameras.on("added",this._onCameraDetected),l.SharedCameras.on("removed",this._onCameraRemoved),l.SharedCameras.list.length&&(l.SharedCameras.list.length>1&&o.warn("It seems that more than 1 camera has been detected for VPS. Taking the first..."),this._useCamera(l.SharedCameras.list[0].camera))}stop(){var t;At.removeEventListener(this._inclinationProviderId),null==(t=this._relativeRotationCalc)||t.release(),l.SharedCameras.off("added",this._onCameraDetected),l.SharedCameras.off("removed",this._onCameraRemoved),this._camera=null}_useCamera(t){this._camera=t,t.on("started",this._internalStart),t.on("stopped",this._internalStop),"started"===t.state&&this._internalStart()}get endpoint(){return this._endpoint}set endpoint(t){this._endpoint=t}get minInclinationForRequest(){return this._minInclinationForRequest}set minInclinationForRequest(t){this._minInclinationForRequest=t}get waitTimeMinInclinationForRequest(){return this._waitTimeMinInclinationForRequest}set waitTimeMinInclinationForRequest(t){this._waitTimeMinInclinationForRequest=t}get useCoarsePose(){return this._useCoarsePose}set useCoarsePose(t){this._useCoarsePose=t}};e(Rt,"MIN_TIME_BETWEEN_TWO_REQUESTS",1e3),e(Rt,"DEFAULT_MIN_INCLINATION_FOR_REQUEST",s.deg2rad(60)),e(Rt,"DEFAULT_WAIT_TIME_MIN_INCLINATION_FOR_REQUEST",200),e(Rt,"DEFAULT_USE_COARSE_POSE",!0),e(Rt,"CAMERA_TO_SMARTPHONE_ROT",s.Quaternion.fromAxisAngle([1,0,0],Math.PI));const Lt=new Rt,wt=class t extends A{constructor(){super(...arguments),e(this,"_polestarProviderId"),e(this,"_vpsProviderId"),e(this,"_gnssWifiProviderId"),e(this,"_relativePositionProviderId"),e(this,"_mapMatchingHandlerId"),e(this,"useAllAbsolutePositions",!1),e(this,"_waitUntilNextVpsPosition",!1),e(this,"_lastPolestarFix",null),e(this,"getName",(()=>"AbsolutePosition"))}availability(){return I.some([mt.getAvailability(),F.getAvailability(),...E.hasPoleStar?[bt.getAvailability()]:[],Lt.getAvailability()])}start(){mt.getAvailability().then((t=>{t||(this._relativePositionProviderId=mt.addEventListener((t=>this._onRelativePosition(t))))})),this._gnssWifiProviderId=F.addEventListener((t=>{const e=t.clone();e.bearing=null,this._onAbsolutePosition(e,!1)})),this._vpsProviderId=Lt.addEventListener((t=>this._onAbsolutePosition(t.absolutePosition)),this.notifyError,!1),E.hasPoleStar&&(this._polestarProviderId=bt.addEventListener((t=>{var e;this._lastPolestarFix=n.TimeUtils.preciseTime();if(!this._onAbsolutePosition(t)&&null===(null==(e=this.lastEvent)?void 0:e.level)){const e=this.lastEvent.clone();e.level=t.level,this.notify(e)}}))),this._mapMatchingHandlerId=Gt.addEventListener()}stop(){this._relativePositionProviderId&&(mt.removeEventListener(this._relativePositionProviderId),delete this._relativePositionProviderId),this._gnssWifiProviderId&&(F.removeEventListener(this._gnssWifiProviderId),delete this._gnssWifiProviderId),this._vpsProviderId&&(Lt.removeEventListener(this._vpsProviderId),delete this._vpsProviderId),this._polestarProviderId&&(bt.removeEventListener(this._polestarProviderId),delete this._polestarProviderId),Gt.removeEventListener(this._mapMatchingHandlerId)}_shouldTakeIntoAccountNewAbsolutePosition(e,s=!0){const r=e,n=this.lastEvent||null;if(!n)return!0;const o=r.accuracy*t.ACCURACY_RELOC_RATIO<=n.accuracy;if(o)return!0;const a=n.distanceTo(r)>n.accuracy+r.accuracy;if(a)return!0;const l=a&&r.accuracy<=n.accuracy;if(o&&l)return!0;return!(!s||i.Level.equals(r.level,n.level))}_onAbsolutePosition(t,e=!0){if(!this._shouldTakeIntoAccountNewAbsolutePosition(t,e)&&!this.useAllAbsolutePositions)return!1;const i=t.clone(),s=this.lastEvent?this.lastEvent:null;return s&&(e||(i.level=s.level),null===i.bearing&&(i.bearing=s.bearing)),Gt.canUseMapMatching()?Gt.notifyPositionFromAbsolute(i):(this.notify(i),!0)}_onRelativePosition(t){if(!this.lastEvent||this._waitUntilNextVpsPosition)return!1;const e=this.lastEvent,i=t,s=Math.sqrt(i.x**2+i.y**2),r=Math.atan2(i.x,i.y),n=null!==e.alt?i.z:null,o=e.destinationPoint(s,r,n);return o.bearing=i.bearing,o.time=i.time,o.accuracy+=i.accuracy,Gt.canUseMapMatching()?Gt.notifyPositionFromRelative(o):(this.notify(o),!0)}feed(e){let s;if(!(e instanceof i.UserPosition))throw new Error("data is nor an UserPosition or an AbsolutePositionEvent");if(null===e.time)throw Error("the time of the position is not defined");if(null===e.accuracy)throw Error("the accuracy of the position is not defined");s=e,t.USE_MM_FOR_FEED&&Gt.canUseMapMatching()?Gt.notifyPositionFromFeed(s):this.notify(s)}getBestPositionEvent(...t){return t.reduce(((t,e)=>{if(!t)return e;if(!e||null===e.accuracy||null===e.time)return t;const{accuracy:i,time:s}=e,{accuracy:r,time:n}=t;return i<r+1.3888*(s-n)?e:t}),null)}};e(wt,"ACCURACY_RELOC_RATIO",1),e(wt,"USE_MM_FOR_FEED",!0);const Nt=new wt;class Dt extends A{constructor(){super(...arguments),e(this,"DEFAULT_ACCURACY",s.deg2rad(15)),e(this,"absolutePositionProviderId"),e(this,"absolutePositionEvent"),e(this,"declinationQuaternion"),e(this,"magQuaternion"),e(this,"magQuaternionTimestamp"),e(this,"iosPreviousQuat"),e(this,"iosIsSkyMode",null),e(this,"getName",(()=>"AbsoluteAttitudeFromBrowser")),e(this,"onDeviceOrientationChromeEvent",(t=>{this.magQuaternionTimestamp=t.timeStamp/1e3,"number"==typeof t.alpha&&"number"==typeof t.beta&&"number"==typeof t.gamma?(this.magQuaternion=s.Rotations.eulerToQuaternionZXYDegrees([t.alpha,t.beta,t.gamma]),this.compute()):this.notifyError((new S).from("deviceorientationabsolute"))})),e(this,"onDeviceOrientationSafariEvent",(t=>{if(this.magQuaternionTimestamp=t.timeStamp/1e3,"number"!=typeof t.beta||"number"!=typeof t.gamma)return void this.notifyError((new S).from("deviceorientation"));if("number"!=typeof t.webkitCompassHeading)return void this.notifyError((new y).from("deviceorientation"));let e;const[i,r,n,o]=s.Rotations.eulerToQuaternionZXYDegrees([t.webkitCompassHeading,t.beta,t.gamma]),a=s.rad2deg(Math.acos(i**2-r**2-n**2+o**2));let l=null;a>136?l=!0:a<134?l=!1:this.iosPreviousQuat&&null!==this.iosIsSkyMode&&(l=s.Quaternion.distance([i,r,n,o],this.iosPreviousQuat)<.5?this.iosIsSkyMode:!this.iosIsSkyMode),this.iosPreviousQuat=[i,r,n,o],this.iosIsSkyMode=l,void 0!==l&&(e=l?180-t.webkitCompassHeading:Dt.webkitCompassToHeading(t.webkitCompassHeading,t.beta,t.gamma),this.magQuaternion=s.Rotations.eulerToQuaternionZXYDegrees([e,t.beta,t.gamma]),this.compute())})),e(this,"onAbsolutePositionEvent",(t=>{this.absolutePositionEvent=t;const e=c.field(t.lat,t.lng);this.declinationQuaternion=s.Quaternion.fromAxisAngle([0,0,1],-s.deg2rad(e.declination)),Nt.removeEventListener(this.absolutePositionProviderId),delete this.absolutePositionProviderId,this.compute()}))}availability(){return n.BrowserUtils.isMobile?Promise.resolve():Promise.resolve(new P)}start(){const t=()=>{switch(n.BrowserUtils.getName()){case n.Browser.CHROME:window.addEventListener("deviceorientationabsolute",this.onDeviceOrientationChromeEvent,!0);break;case n.Browser.SAFARI:case n.Browser.IOS_WEBVIEW:window.addEventListener("deviceorientation",this.onDeviceOrientationSafariEvent,!0)}},e=DeviceOrientationEvent.requestPermission||void 0;e?e().then((e=>{if("granted"!==e)throw new Error("Permission not granted");t()})).catch(this.notifyError):t();const i=Nt.lastEvent;i?this.onAbsolutePositionEvent(i):this.absolutePositionProviderId=Nt.addEventListener(this.onAbsolutePositionEvent,this.notifyError,!1)}stop(){switch(n.BrowserUtils.getName()){case n.Browser.CHROME:window.removeEventListener("deviceorientationabsolute",this.onDeviceOrientationChromeEvent,!0);break;case n.Browser.SAFARI:case n.Browser.IOS_WEBVIEW:window.removeEventListener("deviceorientation",this.onDeviceOrientationSafariEvent,!0)}Nt.removeEventListener(this.absolutePositionProviderId)}compute(){if(!this.declinationQuaternion||!this.magQuaternion||!this.absolutePositionEvent)return;const t=s.Quaternion.multiply(this.declinationQuaternion,this.magQuaternion),e=new u(t,this.magQuaternionTimestamp,this.DEFAULT_ACCURACY);this.notify(e)}static webkitCompassToHeading(t,e,i){const r=s.deg2rad(t),n=s.deg2rad(e),o=s.deg2rad(i),a=Math.cos(r/2),l=Math.cos(n/2),h=Math.cos(o/2),c=Math.sin(r/2),d=Math.sin(n/2),u=Math.sin(o/2),v=a*l*h-c*d*u,E=c*l*h+a*d*u;return s.rad2deg(-2*Math.atan(E/v))}}const Ct=new Dt;const Ft=new class extends A{constructor(){super(...arguments),e(this,"arCoreMonitoringId"),e(this,"arCoreProviderId"),e(this,"inertialProviderId"),e(this,"getName",(()=>"RelativeAttitude")),e(this,"availability",(()=>rt.getAvailability())),e(this,"listenInertial",(()=>{this.inertialProviderId=rt.addEventListener(this.notify,this.notifyError)})),e(this,"unlistenInertial",(()=>{rt.removeEventListener(this.inertialProviderId)})),e(this,"listenArCore",(()=>{this.arCoreProviderId=W.addEventListener((t=>this.notify(t.relativeAttitude)),null,!1)})),e(this,"unlistenArCore",(()=>{W.removeEventListener(this.arCoreProviderId)}))}start(){this.arCoreMonitoringId=W.addMonitoringListener((()=>{this.listenArCore(),this.unlistenInertial()}),(()=>{this.unlistenArCore(),this.listenInertial()})),"started"===W.state?this.listenArCore():this.listenInertial()}stop(){W.removeMonitoringListener(this.arCoreMonitoringId),this.unlistenArCore(),this.unlistenInertial()}},Ot=class t extends A{constructor(){super(...arguments),e(this,"_absAttitudeFromBrowser"),e(this,"_vpsProviderId"),e(this,"fromBrowserProviderId"),e(this,"highRotationProviderId"),e(this,"inclinationProviderId"),e(this,"relativeAttitudeProviderId"),e(this,"_attitudeFromBrowserErrored",!1),e(this,"_attitudeFromRelativeErrored",!1),e(this,"_relativeAttitude",null),e(this,"_relativeAccuracy",0),e(this,"_lastForcedHeadingEvent"),e(this,"_relAbsQuat"),e(this,"_wasHighRotationInProgress",!1),e(this,"_timeFirstDivergence",null),e(this,"_callbackMagCalibration"),e(this,"getName",(()=>"AbsoluteAttitude")),e(this,"_onError",(t=>{this._attitudeFromBrowserErrored&&this._attitudeFromRelativeErrored&&this.notifyError(t)})),e(this,"_forceHeadingForRelative",(t=>{if(this.lastEvent&&t.accuracy>this.lastEvent.accuracy)return;const e=e=>{const i=e.heading;this._relAbsQuat=s.Quaternion.fromAxisAngle([0,0,1],i-t.heading),this._relativeAccuracy=0,this._lastForcedHeadingEvent=t};if(this._relativeAttitude)return void e(this._relativeAttitude);const i=Ft.addEventListener((t=>{e(t),Ft.removeEventListener(i)}))})),e(this,"_onRelativeAttitudeEvent",(e=>{var r;const{quaternion:n,accuracy:o,time:a}=e;if(this._relativeAttitude&&(this._relativeAccuracy+=(a-this._relativeAttitude.time)*o),this._relativeAttitude=e,!this._lastForcedHeadingEvent||!this._relAbsQuat)return;const l=Math.min((this._lastForcedHeadingEvent.accuracy||0)+this._relativeAccuracy,Math.PI),h=it.isInProgress();let c=!1;if(this._absAttitudeFromBrowser){const{accuracy:e,heading:o}=this._absAttitudeFromBrowser;if(this._wasHighRotationInProgress&&!h)this._forceHeadingForRelative(this._absAttitudeFromBrowser);else if(e<l){const e=s.Quaternion.multiply(this._relAbsQuat,n),l=new i.Attitude(e),h=Math.abs(s.diffAngle(l.heading,o)),d=At.lastEvent;h>t.REL_ABS_DIVERGENCE_ANGLE_THRESHOLD&&null!==d&&Math.abs(d-Math.PI/4)>t.REL_ABS_DIVERGENCE_INCLINATION_THRESHOLD&&(c=!0,null!==this._timeFirstDivergence&&a-this._timeFirstDivergence>t.REL_ABS_DIVERGENCE_TIME_THRESHOLD?(this._forceHeadingForRelative(this._absAttitudeFromBrowser),null==(r=this._callbackMagCalibration)||r.call(this,{angle:h}),this._timeFirstDivergence=null):null===this._timeFirstDivergence&&(this._timeFirstDivergence=a))}}c||(this._timeFirstDivergence=null),this._wasHighRotationInProgress=h;const d=s.Quaternion.multiply(this._relAbsQuat,n),v=new u(d,a,l);this.notify(v)})),e(this,"_onAttitudeFromBrowser",(t=>{this._absAttitudeFromBrowser=t,this._lastForcedHeadingEvent||this._forceHeadingForRelative(t)})),e(this,"_onAttitudeFromVps",(t=>{this._forceHeadingForRelative(t)}))}availability(){return I.some([Ct.getAvailability(),Ft.getAvailability()])}start(){this.fromBrowserProviderId=Ct.addEventListener(this._onAttitudeFromBrowser,(t=>{this._attitudeFromBrowserErrored=!0,this._onError(t)})),this._vpsProviderId=Lt.addEventListener((t=>this._onAttitudeFromVps(t.absoluteAttitude)),(t=>this.notifyError(t)),!1),this.relativeAttitudeProviderId=Ft.addEventListener(this._onRelativeAttitudeEvent,(t=>{this._attitudeFromRelativeErrored=!0,this._onError(t)})),this.inclinationProviderId=At.addEventListener(),this.highRotationProviderId=it.addEventListener()}stop(){Ct.removeEventListener(this.fromBrowserProviderId),Ft.removeEventListener(this.relativeAttitudeProviderId),At.removeEventListener(this.inclinationProviderId),it.removeEventListener(this.highRotationProviderId),Lt.removeEventListener(this._vpsProviderId)}_setCallbackMagCalibration(t){this._callbackMagCalibration=t}feed(t){if(t instanceof i.AbsoluteHeading){if(null===t.time)throw Error("the time of the absolute heading is not defined");if(null===t.accuracy)throw Error("the accuracy of the absolute heading is not defined");this._forceHeadingForRelative(t)}else{if(!(t instanceof u))throw new Error("data is nor an AbsoluteHeading or an Attitude object");if(null===t.time)throw Error("the time of the attitude is not defined");if(null===t.accuracy)throw Error("the accuracy of the attitude is not defined");this._forceHeadingForRelative(t)}}};e(Ot,"REL_ABS_DIVERGENCE_ANGLE_THRESHOLD",s.deg2rad(25)),e(Ot,"REL_ABS_DIVERGENCE_TIME_THRESHOLD",2.5),e(Ot,"REL_ABS_DIVERGENCE_INCLINATION_THRESHOLD",s.deg2rad(15));const xt=new Ot,Ut=class t extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"slidingWindow",[]),e(this,"getName",(()=>"Turn")),e(this,"availability",(()=>Ft.getAvailability())),e(this,"_parseRelativeAttitude",(e=>{const{heading:i}=e,r=e.time;this.slidingWindow=this.slidingWindow.filter((e=>e[0]>=r-t.SLIDING_WINDOW_TIME)),this.slidingWindow.push([r,i]);s.std(this.slidingWindow.map((t=>t[1])))>t.STD_THRESHOLD&&this.notify({timestamp:r})}))}start(){this.providerId=Ft.addEventListener(this._parseRelativeAttitude,this.notifyError)}stop(){Ft.removeEventListener(this.providerId)}isTurning(){if(!this.lastEvent||!Ft.lastEvent)return!1;return Ft.lastEvent.time-this.lastEvent.timestamp<t.CONSIDER_TURN_UNTIL}};e(Ut,"SLIDING_WINDOW_TIME",.3),e(Ut,"STD_THRESHOLD",.075),e(Ut,"CONSIDER_TURN_UNTIL",1);const Ht=new Ut,Bt=class t extends A{constructor(){super(...arguments),e(this,"_turnProviderId"),e(this,"_stepProviderId"),e(this,"_countSteps",0),e(this,"_stepsConsideredForStraightLine",t.DEFAULT_STEPS_CONSIDERED_FOR_STRAIGHT_LINE),e(this,"getName",(()=>"StraightLine")),e(this,"_onTurn",(()=>{this._countSteps>=this._stepsConsideredForStraightLine&&this.notify(!1),this._countSteps=0})),e(this,"_onStep",(()=>{this._countSteps++,this._countSteps===this._stepsConsideredForStraightLine&&this.notify(!0)}))}availability(){return I.every([Ht.getAvailability(),Et.getAvailability()])}start(){this._turnProviderId=Ht.addEventListener(this._onTurn),this._stepProviderId=Et.addEventListener(this._onStep)}stop(){Ht.removeEventListener(this._turnProviderId),Et.removeEventListener(this._stepProviderId)}isStraight(){return this._countSteps>=this._stepsConsideredForStraightLine}get numStepsDetectedFromLastTurn(){return this._countSteps}get stepsConsideredForStraightLine(){return this._stepsConsideredForStraightLine}set stepsConsideredForStraightLine(t){this._stepsConsideredForStraightLine=t}};e(Bt,"DEFAULT_STEPS_CONSIDERED_FOR_STRAIGHT_LINE",2);const Wt=new Bt,Vt=class t extends A{constructor(){super(...arguments),e(this,"_mapMatchingMaxDistance",t.DEFAULT_MM_MAX_DIST),e(this,"_mapMatchingMinDistance",t.DEFAULT_MM_MIN_DIST),e(this,"_mapMatchingMaxAngleBearing",t.DEFAULT_MM_MAX_ANGLE),e(this,"_useItineraryStartAsPosition",t.DEFAULT_USE_ITINERARY_START_AS_POSITION),e(this,"_useOrientationMatching",t.DEFAULT_USE_ORIENTATION_MATCHING),e(this,"_hugeJumpDistance",t.DEFAULT_MM_HUGE_JUMP_DISTANCE),e(this,"_disableMMCloseToATurnDistance",t.DEFAULT_DISABLE_MM_CLOSE_TO_A_TURN_DISTANCE),e(this,"_minStepsBetweenOrientationMatching",t.DEFAULT_MIN_STEPS_BETWEEN_ORIENTATION_MATCHING),e(this,"_minStepsForOrientationMatching",t.DEFAULT_MIN_STEPS_FOR_ORIENTATION_MATCHING),e(this,"_lastProjectionsWindowSize",t.DEFAULT_LAST_PROJECTIONS_WINDOW_SIZE),e(this,"_lastProjectionsEdgeAngleThreshold",t.DEFAULT_LAST_PROJECTIONS_EDGE_ANGLE_THRESHOLD),e(this,"_graph",null),e(this,"_internalProvidersStarted",!1),e(this,"_straightLineProviderId"),e(this,"_turnProviderId"),e(this,"_stepProviderId"),e(this,"_projectionsWithAbsAndWithoutRelAttitudeInARow",[]),e(this,"_countStepsFromLastMatching",0),e(this,"_lastProjections",[]),e(this,"_itineraryInfoManager",null),e(this,"getName",(()=>"MapMatchingHandler")),e(this,"availability",(()=>Promise.resolve())),e(this,"_manageStartStop",(()=>{this.graph&&!this._internalProvidersStarted?this._startInternalProviders():!this.graph&&this._internalProvidersStarted&&this._stopInternalProviders()}))}start(){this.graph&&this._startInternalProviders()}stop(){this._stopInternalProviders()}_startInternalProviders(){this.enabled&&this._internalProvidersStarted||(this._straightLineProviderId=Wt.addEventListener(),this._turnProviderId=Ht.addEventListener(),this._stepProviderId=Et.addEventListener((()=>this._countStepsFromLastMatching++)),this._internalProvidersStarted=!0)}_stopInternalProviders(){this.enabled&&!this._internalProvidersStarted||(Wt.removeEventListener(this._straightLineProviderId),Ht.removeEventListener(this._turnProviderId),Et.removeEventListener(this._stepProviderId),this._internalProvidersStarted=!1)}get enabled(){return E.useMapMatching}get graph(){return this._graph}set graph(t){this._graph=t,this._itineraryInfoManager=null,this.notify({...t&&{graph:t}}),this._manageStartStop(),this.canUseMapMatching()}set itinerary(t){this._graph=t?t.toGraph():null,this._itineraryInfoManager=new r.ItineraryInfoManager(t),this.notify({...t&&{itinerary:t}}),this._manageStartStop(),this.canUseMapMatching()&&t&&this._notifyPositionFromItineraryInput(t)}canUseMapMatching(){return this.enabled&&this.graph}_notifyPositionFromItineraryInput(t){if(!this._useItineraryStartAsPosition||!t.origin)return;const e=Nt.lastEvent||null,s=i.UserPosition.fromCoordinates(t.origin);if(e)s.alt=e.alt,s.time=e.time,s.accuracy=e.accuracy+s.distanceTo(e),s.bearing=e.bearing;else{if(!(t.coords.length>=2))return;s.alt=D,s.time=n.TimeUtils.preciseTime(),s.accuracy=0,s.bearing=t.coords[0].bearingTo(t.coords[1])}const r=this.getProjection(s,!0);r?Nt.notify(r.coords):Nt.notify(s)}notifyPositionFromFeed(t){const e=this.getProjection(t,!0,!1);e?Nt.notify(e.coords):Nt.notify(t)}notifyPositionFromAbsolute(t){let e=null;if(null!==t.bearing&&(e=this.getProjection(t,!0,!0)),!e)return Nt.notify(t),!0;const i=e.distanceFromNearestElement>this._hugeJumpDistance;return!(i&&!Wt.isStraight())&&((!i||!this._detectWrongBigJump(e))&&(Nt.notify(e.coords),this.tryOrientationMatching(e),!0))}notifyPositionFromRelative(t){var e;if(Ht.isTurning())return this._projectionsWithAbsAndWithoutRelAttitudeInARow=[],this._lastProjections=[],Nt.notify(t),!0;const i=this.getProjection(t,!0,!0);if(i){this._projectionsWithAbsAndWithoutRelAttitudeInARow=[],this._lastProjections.push(i),this._lastProjections.length>this._lastProjectionsWindowSize&&this._lastProjections.shift();const e=i.distanceFromNearestElement>this._hugeJumpDistance;return e&&!Wt.isStraight()||e&&this._detectWrongBigJump(i)?(Nt.notify(t),!0):this._areLastProjectionsInTheSameDirection()?this._disableMMCloseToATurnDistance>0&&this._hasTurnInCircle(i.coords,this._disableMMCloseToATurnDistance)?(Nt.notify(t),!0):(Nt.notify(i.coords),this.tryOrientationMatching(i),!0):(Nt.notify(t),!0)}if(Wt.isStraight()){const i=t.clone();i.bearing=(null==(e=Ct.lastEvent)?void 0:e.heading)||null;const s=this.getProjection(i,!0,!0);if(s)return this._projectionsWithAbsAndWithoutRelAttitudeInARow.push(s),this._projectionsWithAbsAndWithoutRelAttitudeInARow.length<3?(Nt.notify(t),!0):(this._lastProjections.push(s),this._lastProjections.length>this._lastProjectionsWindowSize&&this._lastProjections.shift(),this._areLastProjectionsInTheSameDirection()?(Nt.notify(s.coords),this.tryOrientationMatching(s),!0):(Nt.notify(t),!0))}return this._projectionsWithAbsAndWithoutRelAttitudeInARow=[],this._lastProjections=[],Nt.notify(t),!0}_detectWrongBigJump(t){if(this._itineraryInfoManager&&Nt.lastEvent){const e=this._itineraryInfoManager.getInfo(Nt.lastEvent),i=this._itineraryInfoManager.getInfo(t.coords);if(e&&i&&e.traveledDistance>i.traveledDistance&&e.traveledDistance-i.traveledDistance>t.origin.accuracy&&t.distanceFromNearestElement>t.origin.accuracy&&t.origin.distanceTo(Nt.lastEvent)<t.origin.accuracy+Nt.lastEvent.accuracy)return!0}return!1}_areLastProjectionsInTheSameDirection(){if(0===this._lastProjections.length)return!1;const t=this._lastProjections[0];return!this._lastProjections.some((e=>!(e.nearestElement instanceof r.Edge)||!(t.nearestElement instanceof r.Edge)||s.diffAngleLines(e.nearestElement.bearing,t.nearestElement.bearing)>this._lastProjectionsEdgeAngleThreshold))}_nodeHasTurn(e){if(!this._graph)return;const i=this._graph.edges.filter((t=>t.vertex1===e||t.vertex2===e));for(let r=0;r<i.length;r++)for(let e=r+1;e<i.length;e++){if(s.diffAngleLines(i[r].bearing,i[e].bearing)>t.DEFAULT_MM_MAX_ANGLE)return!0}return!1}_hasTurnInCircle(t,e){const s=this._graph;return!!s&&s.vertices.filter((s=>s.coords.distanceTo(t)<=e&&i.Level.intersect(s.coords.level,t.level))).some((t=>this._nodeHasTurn(t)))}tryOrientationMatching(t){if(!this._useOrientationMatching)return;if("started"!==this.state||this._countStepsFromLastMatching<this._minStepsBetweenOrientationMatching||Wt.numStepsDetectedFromLastTurn<this._minStepsForOrientationMatching)return;const{nearestElement:e,origin:n}=t;if(!(e instanceof r.Edge))return;let o;const a=s.diffAngle(e.bearing,n.bearing),l=s.diffAngle(e.bearing+Math.PI,n.bearing);o=Math.abs(a)<Math.abs(l)?e.bearing:(e.bearing+Math.PI)%(2*Math.PI);const h=new i.AbsoluteHeading(o,n.time,0);xt._forceHeadingForRelative(h),this._countStepsFromLastMatching=0}getProjection(t,e,i){var s;const r={...e&&{maxDistance:this._mapMatchingMaxDistance},...i&&{maxBearingAngle:this._mapMatchingMaxAngleBearing}};return null==(s=this._graph)?void 0:s.getProjection(t,r)}get maxDistance(){return this._mapMatchingMaxDistance}set maxDistance(t){this._mapMatchingMaxDistance=t}get minDistance(){return this._mapMatchingMinDistance}set minDistance(t){this._mapMatchingMinDistance=t}get maxAngleBearing(){return this._mapMatchingMaxAngleBearing}set maxAngleBearing(t){this._mapMatchingMaxAngleBearing=t}get useItineraryStartAsPosition(){return this._useItineraryStartAsPosition}set useItineraryStartAsPosition(t){this._useItineraryStartAsPosition=t}get useOrientationMatching(){return this._useOrientationMatching}set useOrientationMatching(t){this._useOrientationMatching=t}get hugeJumpDistance(){return this._hugeJumpDistance}set hugeJumpDistance(t){this._hugeJumpDistance=t}get disableMMCloseToATurnDistance(){return this._disableMMCloseToATurnDistance}set disableMMCloseToATurnDistance(t){this._disableMMCloseToATurnDistance=t}get minStepsBetweenOrientationMatching(){return this._minStepsBetweenOrientationMatching}set minStepsBetweenOrientationMatching(t){this._minStepsBetweenOrientationMatching=t}get minStepsForOrientationMatching(){return this._minStepsForOrientationMatching}set minStepsForOrientationMatching(t){this._minStepsForOrientationMatching=t}get lastProjectionsWindowSize(){return this._lastProjectionsWindowSize}set lastProjectionsWindowSize(t){this._lastProjectionsWindowSize=t}get lastProjectionsEdgeAngleThreshold(){return this._lastProjectionsEdgeAngleThreshold}set lastProjectionsEdgeAngleThreshold(t){this._lastProjectionsEdgeAngleThreshold=t}};e(Vt,"DEFAULT_MM_MAX_ANGLE",s.deg2rad(30)),e(Vt,"DEFAULT_MM_MAX_DIST",30),e(Vt,"DEFAULT_MM_MIN_DIST",0),e(Vt,"DEFAULT_USE_ITINERARY_START_AS_POSITION",!1),e(Vt,"DEFAULT_USE_ORIENTATION_MATCHING",!0),e(Vt,"DEFAULT_MM_HUGE_JUMP_DISTANCE",3),e(Vt,"DEFAULT_DISABLE_MM_CLOSE_TO_A_TURN_DISTANCE",2),e(Vt,"DEFAULT_MIN_STEPS_BETWEEN_ORIENTATION_MATCHING",3),e(Vt,"DEFAULT_MIN_STEPS_FOR_ORIENTATION_MATCHING",5),e(Vt,"DEFAULT_LAST_PROJECTIONS_WINDOW_SIZE",3),e(Vt,"DEFAULT_LAST_PROJECTIONS_EDGE_ANGLE_THRESHOLD",s.deg2rad(3));const Gt=new Vt,kt=class t{constructor(i,s=t.DEFAULT_FREQUENCY){e(this,"positionsQueue",[]),e(this,"previousPosition",null),e(this,"timeoutNotify"),e(this,"_notifyNext",(()=>{var t;this.positionsQueue.length&&(null==(t=this.callback)||t.call(this,this.positionsQueue.shift()),0!==this.positionsQueue.length?this.timeoutNotify=setTimeout(this._notifyNext,1e3/this.frequency):delete this.timeoutNotify)})),this.callback=i,this.frequency=s}feed(e,s=t.DEFAULT_FLYBY_TIME){if(!(e instanceof i.UserPosition))throw new TypeError("newPosition is not instance of UserPosition");if(null===e.time)throw new Error("newPosition does not have time property");let r;if(0!==this.positionsQueue.length?(r=this.positionsQueue[0],this.positionsQueue=[]):r=this.previousPosition,r){const t=e.time,n=r.distanceTo(e),o=r.bearingTo(e);let a=1;const l=this.frequency*s+1,h=i.Level.clone(e.level);for(;a<l+1;){const i=r.destinationPoint(n*a/l,o);i.time=t+(a-1)/this.frequency,i.level=h,i.bearing=e.bearing,i.accuracy=Math.max(i.accuracy+(e.accuracy-i.accuracy)*a/l,0),this.positionsQueue.push(i),a++}this.timeoutNotify&&clearTimeout(this.timeoutNotify)}else this.positionsQueue.push(e.clone());this.previousPosition=e,this._notifyNext()}clear(){clearTimeout(this.timeoutNotify),delete this.timeoutNotify,this.positionsQueue=[]}};e(kt,"DEFAULT_FREQUENCY",60),e(kt,"DEFAULT_FLYBY_TIME",1);let Qt=kt;const qt=class t{constructor(t){e(this,"_previousAttitude"),e(this,"_smoothing",null),this.callback=t}feed(e){if(null===e.time)throw new Error("newAttitude does not have time property");const{_previousAttitude:r}=this;if(this._previousAttitude=e,r){if(t.isJump(r,e)){const n=null===this._smoothing?r:this._smoothing.interpAttitude(r),o=n.heading,a=e.heading,l=s.diffAngle(a,o),h=Math.abs(l)<t.HIGH_JUMP_THRESHOLD?t.ROTATION_SPEED_CONVERGENCE:t.ROTATION_SPEED_HIGH_JUMP_CONVERGENCE,c=n.time,d=Math.abs(l)/h,u=l<0?-1:1;this._smoothing={toTime:c+d,interpAttitude:t=>{const e=h*(t.time-c),r=o+e*u,n=s.Quaternion.fromAxisAngle([0,0,1],a-r),l=s.Quaternion.multiply(n,t.quaternion);return new i.Attitude(l,t.time,t.accuracy)}}}if(null!==this._smoothing){if(!(e.time>=this._smoothing.toTime)){const t=this._smoothing.interpAttitude(e);return void this.callback(t)}this._smoothing=null}this.callback(e)}else this.callback(e)}static isJump(e,i){const r=e.heading,n=i.heading,o=s.diffAngle(n,r),a=i.time-e.time,[l,h,c,d]=i.quaternion;return!(Math.abs(Math.asin(2*(l*h+c*d))-Math.PI/4)<t.PITCH_UNCERTAINITY_HEADING_THRESHOLD)&&Math.abs(o)>t.ROTATION_SPEED_JUMP_THRESHOLD*a}};e(qt,"ROTATION_SPEED_JUMP_THRESHOLD",s.deg2rad(180)),e(qt,"ROTATION_SPEED_CONVERGENCE",s.deg2rad(10)),e(qt,"HIGH_JUMP_THRESHOLD",s.deg2rad(20)),e(qt,"ROTATION_SPEED_HIGH_JUMP_CONVERGENCE",s.deg2rad(100)),e(qt,"PITCH_UNCERTAINITY_HEADING_THRESHOLD",s.deg2rad(5));let jt=qt;const zt=new class extends A{constructor(){super(),e(this,"getName",(()=>"MagnetometerCalibrationProvider")),e(this,"availability",(()=>xt.getAvailability())),xt._setCallbackMagCalibration((t=>"started"===this.state&&this.notify(t)))}start(){}stop(){}},Jt=class t extends Error{constructor(e){super(e||t.DEFAULT_MESSAGE)}};e(Jt,"DEFAULT_MESSAGE","IP Resolver failed");let Yt=Jt;const Xt=new class extends A{constructor(){super(...arguments),e(this,"getName",(()=>"Ip")),e(this,"availability",(()=>Promise.resolve()))}async start(){const t=await fetch("https://ipinfo.io/geo?token=24a7ca2f3b489d");if(!t)return void this.notifyError(new Yt);const e=n.TimeUtils.preciseTime()/1e3,s=(await t.json()).loc.split(","),r=new i.UserPosition(parseFloat(s[0]),parseFloat(s[1]),null,null,e,1e5);this.notify(r)}stop(){}};const Kt=new class extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"getName",(()=>"Barcode")),e(this,"availability",(()=>W.getAvailability()))}start(){W.enableBarcodeScanner(),this.providerId=W.addEventListener((t=>t.barcode&&this.notify(t.barcode)),this.notifyError)}stop(){W.disableBarcodeScanner(),W.removeEventListener(this.providerId)}};const Zt=new class extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"getName",(()=>"CameraNative")),e(this,"availability",(()=>Promise.resolve()))}start(){"stopped"!==W.state&&this.notify("started"),this.providerId=W.addMonitoringListener((()=>this.notify("started")),(()=>this.notify("stopped")))}stop(){W.removeMonitoringListener(this.providerId)}};const $t=new class extends A{constructor(){super(...arguments),e(this,"providerId"),e(this,"getName",(()=>"CameraProjectionMatrix")),e(this,"availability",(()=>W.getAvailability()))}start(){this.providerId=W.addEventListener((t=>t.cameraProjection&&this.notify(t.cameraProjection)),this.notifyError)}stop(){W.removeEventListener(this.providerId)}};exports.AbsoluteAttitude=u,exports.AbsoluteAttitudeFromBrowserProvider=Ct,exports.AbsoluteAttitudeProvider=xt,exports.AbsolutePosition=v,exports.AbsolutePositionProvider=Nt,exports.AccelerometerProvider=J,exports.ArCoreProvider=W,exports.AttitudeSmoother=jt,exports.BarcodeProvider=Kt,exports.CameraNativeProvider=Zt,exports.CameraProjectionMatrixProvider=$t,exports.GeoRelativePositionFromArCoreProvider=V,exports.GeoRelativePositionProvider=mt,exports.GnssWifiProvider=F,exports.GyroscopeProvider=X,exports.HighRotationsProvider=it,exports.ImageRelocalization=Tt,exports.ImuProvider=q,exports.InclinationFromAccProvider=pt,exports.InclinationFromRelativeAttitudeProvider=gt,exports.InclinationProvider=At,exports.IpProvider=Xt,exports.MagnetometerCalibrationProvider=zt,exports.MapMatchingHandler=Gt,exports.PdrProvider=_t,exports.PoleStarProvider=bt,exports.PositionSmoother=Qt,exports.ProvidersLoggerOld=_,exports.ProvidersOptions=E,exports.RelativeAttitude=d,exports.RelativeAttitudeFromBrowserProvider=tt,exports.RelativeAttitudeFromEkfProvider=Z,exports.RelativeAttitudeFromInertialProvider=rt,exports.RelativeAttitudeProvider=Ft,exports.RelativeRotationCalc=St,exports.StepDetectionMinMaxPeaks2=ct,exports.StepDetectionMinMaxPeaks3=ut,exports.StepProvider=Et,exports.StraightLineProvider=Wt,exports.TurnProvider=Ht,exports.VpsMetadata=It,exports.VpsProvider=Lt,exports.VpsRequest=ft,exports.VpsResponse=Pt;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => {
|
|
5
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
+
return value;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
9
|
+
const geo = require("@wemap/geo");
|
|
10
|
+
const maths = require("@wemap/maths");
|
|
11
|
+
const routers = require("@wemap/routers");
|
|
12
|
+
const utils = require("@wemap/utils");
|
|
13
|
+
const Logger = require("@wemap/logger");
|
|
14
|
+
const geomag = require("geomag");
|
|
15
|
+
const camera = require("@wemap/camera");
|
|
16
|
+
function _interopNamespaceDefault(e) {
|
|
17
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
18
|
+
if (e) {
|
|
19
|
+
for (const k in e) {
|
|
20
|
+
if (k !== "default") {
|
|
21
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
22
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: () => e[k]
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
n.default = e;
|
|
30
|
+
return Object.freeze(n);
|
|
31
|
+
}
|
|
32
|
+
const geomag__namespace = /* @__PURE__ */ _interopNamespaceDefault(geomag);
|
|
33
|
+
class RelativeAttitude extends geo.Attitude {
|
|
34
|
+
}
|
|
35
|
+
class AbsoluteAttitude extends geo.Attitude {
|
|
36
|
+
}
|
|
37
|
+
class AbsolutePosition extends geo.UserPosition {
|
|
38
|
+
}
|
|
39
|
+
const ProvidersOptions = {
|
|
40
|
+
/**
|
|
41
|
+
* Does provider will use map to
|
|
42
|
+
*/
|
|
43
|
+
useMapMatching: true,
|
|
44
|
+
/**
|
|
45
|
+
* Providers listed here will not be used by the system
|
|
46
|
+
* List of {@link Provider#pname}
|
|
47
|
+
*/
|
|
48
|
+
ignoreProviders: [],
|
|
49
|
+
/**
|
|
50
|
+
* Some providers are not used by default (i.e. PoleStar) because they
|
|
51
|
+
* require data from an optional external service or because they drain more
|
|
52
|
+
* battery. They can be added to this list to be used
|
|
53
|
+
* List of {@link Provider#pname}
|
|
54
|
+
*/
|
|
55
|
+
optionalProviders: [],
|
|
56
|
+
stopOnError: true,
|
|
57
|
+
checkAvailabilityOnStart: true,
|
|
58
|
+
get hasPoleStar() {
|
|
59
|
+
return this.optionalProviders.includes("PoleStar");
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
class ProvidersLoggerOld {
|
|
63
|
+
constructor() {
|
|
64
|
+
__publicField(this, "_enabled", false);
|
|
65
|
+
__publicField(this, "currentId", 0);
|
|
66
|
+
__publicField(this, "objectsIdMap", /* @__PURE__ */ new WeakMap());
|
|
67
|
+
__publicField(this, "pushEvents", {});
|
|
68
|
+
__publicField(this, "pushEventsRef", {});
|
|
69
|
+
__publicField(this, "interval");
|
|
70
|
+
__publicField(this, "initDate");
|
|
71
|
+
}
|
|
72
|
+
get enabled() {
|
|
73
|
+
return this._enabled;
|
|
74
|
+
}
|
|
75
|
+
set enabled(_newVal) {
|
|
76
|
+
this._enabled = _newVal;
|
|
77
|
+
}
|
|
78
|
+
initializeInterval() {
|
|
79
|
+
if (this.interval) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.interval = window.setInterval(() => {
|
|
83
|
+
for (const [key, value] of Object.entries(this.pushEvents)) {
|
|
84
|
+
Logger.debug("Received " + value + " notifications from " + this.pushEventsRef[Number(key)].getName() + " last second");
|
|
85
|
+
}
|
|
86
|
+
this.pushEvents = {};
|
|
87
|
+
this.pushEventsRef = {};
|
|
88
|
+
}, 1e3);
|
|
89
|
+
}
|
|
90
|
+
getObjectId(object) {
|
|
91
|
+
if (!this.objectsIdMap.has(object)) {
|
|
92
|
+
this.objectsIdMap.set(object, ++this.currentId);
|
|
93
|
+
}
|
|
94
|
+
return this.objectsIdMap.get(object);
|
|
95
|
+
}
|
|
96
|
+
addEvent(object, method) {
|
|
97
|
+
if (!this.enabled) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!this.initDate) {
|
|
101
|
+
this.initDate = Date.now();
|
|
102
|
+
}
|
|
103
|
+
this.initializeInterval();
|
|
104
|
+
const objectId = this.getObjectId(object);
|
|
105
|
+
const objectClassName = object.getName();
|
|
106
|
+
Logger.debug(objectClassName + "[" + objectId + "]." + method);
|
|
107
|
+
}
|
|
108
|
+
incrementNotifications(object) {
|
|
109
|
+
if (!this.enabled) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const objectId = this.getObjectId(object);
|
|
113
|
+
let counter = this.pushEvents[objectId];
|
|
114
|
+
if (!counter) {
|
|
115
|
+
counter = 0;
|
|
116
|
+
this.pushEventsRef[objectId] = object;
|
|
117
|
+
}
|
|
118
|
+
this.pushEvents[objectId] = counter + 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const ProvidersLoggerOld$1 = new ProvidersLoggerOld();
|
|
122
|
+
const _ContainsIgnoredProviderError = class _ContainsIgnoredProviderError extends Error {
|
|
123
|
+
constructor(message) {
|
|
124
|
+
super(message || _ContainsIgnoredProviderError.DEFAULT_MESSAGE);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
__publicField(_ContainsIgnoredProviderError, "DEFAULT_MESSAGE", "Contains ignored provider");
|
|
128
|
+
let ContainsIgnoredProviderError = _ContainsIgnoredProviderError;
|
|
129
|
+
const _Provider = class _Provider {
|
|
130
|
+
/**
|
|
131
|
+
* Provider constructor
|
|
132
|
+
*/
|
|
133
|
+
constructor() {
|
|
134
|
+
__publicField(this, "id");
|
|
135
|
+
__publicField(this, "state", "stopped");
|
|
136
|
+
__publicField(this, "_lastEvent", null);
|
|
137
|
+
__publicField(this, "_eventsCallbacks", []);
|
|
138
|
+
__publicField(this, "_monitoringCallbacks", []);
|
|
139
|
+
/**
|
|
140
|
+
* Notify the subscriber defined in {@link addEventListener}
|
|
141
|
+
*/
|
|
142
|
+
__publicField(this, "notify", (event) => {
|
|
143
|
+
ProvidersLoggerOld$1.incrementNotifications(this);
|
|
144
|
+
this._eventsCallbacks.forEach((cb) => {
|
|
145
|
+
var _a;
|
|
146
|
+
return (_a = cb.onEvent) == null ? void 0 : _a.call(cb, event);
|
|
147
|
+
});
|
|
148
|
+
this._lastEvent = event;
|
|
149
|
+
});
|
|
150
|
+
/**
|
|
151
|
+
* Notify the subscriber defined in {@link addEventListener}
|
|
152
|
+
*/
|
|
153
|
+
__publicField(this, "notifyError", (error) => {
|
|
154
|
+
this._eventsCallbacks.forEach(({
|
|
155
|
+
id,
|
|
156
|
+
onError
|
|
157
|
+
}) => {
|
|
158
|
+
if (ProvidersOptions.stopOnError) {
|
|
159
|
+
this.removeEventListener(id);
|
|
160
|
+
}
|
|
161
|
+
onError == null ? void 0 : onError(error);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
this.id = _Provider._uniqueId++;
|
|
165
|
+
ProvidersLoggerOld$1.addEvent(this, "constructor");
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Resolve with an error if the provider is not available
|
|
169
|
+
*/
|
|
170
|
+
getAvailability() {
|
|
171
|
+
if (ProvidersOptions.ignoreProviders.includes(this.getName())) {
|
|
172
|
+
return Promise.resolve(new ContainsIgnoredProviderError());
|
|
173
|
+
}
|
|
174
|
+
return this.availability();
|
|
175
|
+
}
|
|
176
|
+
get hasNativeInterface() {
|
|
177
|
+
return Boolean(this.nativeInterface);
|
|
178
|
+
}
|
|
179
|
+
get nativeInterface() {
|
|
180
|
+
return typeof window !== "undefined" && window.__nativeProviders || null;
|
|
181
|
+
}
|
|
182
|
+
get nativeJsInterface() {
|
|
183
|
+
if (typeof window === "undefined") {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
if (!window.__nativeJsProviders) {
|
|
187
|
+
window.__nativeJsProviders = {};
|
|
188
|
+
}
|
|
189
|
+
return window.__nativeJsProviders;
|
|
190
|
+
}
|
|
191
|
+
get useCameraNatively() {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
addEventListener(onEvent = null, onError = null, startIfNecessary = true) {
|
|
195
|
+
const id = ++_Provider._callbackUniqueId;
|
|
196
|
+
this._eventsCallbacks.push({
|
|
197
|
+
id,
|
|
198
|
+
onEvent: onEvent || (() => {
|
|
199
|
+
}),
|
|
200
|
+
onError: onError || (() => {
|
|
201
|
+
}),
|
|
202
|
+
optional: !startIfNecessary
|
|
203
|
+
});
|
|
204
|
+
if (!startIfNecessary) {
|
|
205
|
+
return id;
|
|
206
|
+
}
|
|
207
|
+
if (this.state !== "stopped") {
|
|
208
|
+
return id;
|
|
209
|
+
}
|
|
210
|
+
this.state = "starting";
|
|
211
|
+
let availabilityPromise = Promise.resolve();
|
|
212
|
+
if (ProvidersOptions.checkAvailabilityOnStart) {
|
|
213
|
+
availabilityPromise = this.getAvailability();
|
|
214
|
+
}
|
|
215
|
+
(async () => {
|
|
216
|
+
const error = await availabilityPromise;
|
|
217
|
+
if (error) {
|
|
218
|
+
this.state = "stopped";
|
|
219
|
+
this.notifyError(error);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
ProvidersLoggerOld$1.addEvent(this, "start");
|
|
223
|
+
this.start();
|
|
224
|
+
this.state = "started";
|
|
225
|
+
this._monitoringCallbacks.forEach((cb) => {
|
|
226
|
+
var _a;
|
|
227
|
+
return (_a = cb.onStarted) == null ? void 0 : _a.call(cb);
|
|
228
|
+
});
|
|
229
|
+
})();
|
|
230
|
+
return id;
|
|
231
|
+
}
|
|
232
|
+
removeEventListener(callbackUniqueId) {
|
|
233
|
+
const callback = this._eventsCallbacks.find((_callback) => _callback.id === callbackUniqueId);
|
|
234
|
+
if (!callback) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
this._eventsCallbacks = this._eventsCallbacks.filter((_callback) => _callback !== callback);
|
|
238
|
+
if (callback.optional) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (this._eventsCallbacks.find((_callback) => !_callback.optional)) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (this.state === "stopped") {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
ProvidersLoggerOld$1.addEvent(this, "stop");
|
|
248
|
+
this.stop();
|
|
249
|
+
this.state = "stopped";
|
|
250
|
+
this._monitoringCallbacks.forEach((cb) => {
|
|
251
|
+
var _a;
|
|
252
|
+
return (_a = cb.onStopped) == null ? void 0 : _a.call(cb);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
addMonitoringListener(onStarted, onStopped) {
|
|
256
|
+
const id = _Provider._callbackUniqueId++;
|
|
257
|
+
this._monitoringCallbacks.push({
|
|
258
|
+
id,
|
|
259
|
+
onStarted: onStarted || null,
|
|
260
|
+
onStopped: onStopped || null
|
|
261
|
+
});
|
|
262
|
+
return id;
|
|
263
|
+
}
|
|
264
|
+
removeMonitoringListener(callbackUniqueId) {
|
|
265
|
+
this._monitoringCallbacks = this._monitoringCallbacks.filter(
|
|
266
|
+
(_callback) => _callback.id !== callbackUniqueId
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
get lastEvent() {
|
|
270
|
+
return this._lastEvent;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
__publicField(_Provider, "_callbackUniqueId", 0);
|
|
274
|
+
__publicField(_Provider, "_uniqueId", 1);
|
|
275
|
+
let Provider = _Provider;
|
|
276
|
+
class AvailabilityHelper {
|
|
277
|
+
static async every(availabilityPromises) {
|
|
278
|
+
for (const aPr of availabilityPromises) {
|
|
279
|
+
const error = await aPr;
|
|
280
|
+
if (error) {
|
|
281
|
+
return error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
static async some(availabilityPromises) {
|
|
287
|
+
let firstError;
|
|
288
|
+
for (const aPr of availabilityPromises) {
|
|
289
|
+
const error = await aPr;
|
|
290
|
+
if (!error) {
|
|
291
|
+
return null;
|
|
292
|
+
} else if (!firstError) {
|
|
293
|
+
firstError = error;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return firstError || null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const _AskImuOnDesktopError = class _AskImuOnDesktopError extends Error {
|
|
300
|
+
constructor(message) {
|
|
301
|
+
super(message || _AskImuOnDesktopError.DEFAULT_MESSAGE);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
__publicField(_AskImuOnDesktopError, "DEFAULT_MESSAGE", "It seems that you ask for IMU events on a desktop browser");
|
|
305
|
+
let AskImuOnDesktopError = _AskImuOnDesktopError;
|
|
306
|
+
const _MissingSensorError = class _MissingSensorError extends Error {
|
|
307
|
+
constructor(message) {
|
|
308
|
+
super(message || _MissingSensorError.DEFAULT_MESSAGE);
|
|
309
|
+
}
|
|
310
|
+
from(fromMessage) {
|
|
311
|
+
this.message += " from " + fromMessage;
|
|
312
|
+
return this;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
__publicField(_MissingSensorError, "DEFAULT_MESSAGE", "Impossible to retrieve events, a sensor is missing");
|
|
316
|
+
let MissingSensorError = _MissingSensorError;
|
|
317
|
+
class MissingMagnetometerError extends MissingSensorError {
|
|
318
|
+
constructor(message) {
|
|
319
|
+
super(message);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const _GeolocationApiMissingError = class _GeolocationApiMissingError extends Error {
|
|
323
|
+
constructor(message) {
|
|
324
|
+
super(message || _GeolocationApiMissingError.DEFAULT_MESSAGE);
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
__publicField(_GeolocationApiMissingError, "DEFAULT_MESSAGE", "Geolocation api is missing");
|
|
328
|
+
let GeolocationApiMissingError = _GeolocationApiMissingError;
|
|
329
|
+
const _GeolocationPermissionDeniedError = class _GeolocationPermissionDeniedError extends Error {
|
|
330
|
+
constructor(message) {
|
|
331
|
+
super(message || _GeolocationPermissionDeniedError.DEFAULT_MESSAGE);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
__publicField(_GeolocationPermissionDeniedError, "DEFAULT_MESSAGE", "Geolocation permission denied");
|
|
335
|
+
let GeolocationPermissionDeniedError = _GeolocationPermissionDeniedError;
|
|
336
|
+
const _GeolocationPositionUnavailableError = class _GeolocationPositionUnavailableError extends Error {
|
|
337
|
+
constructor(message) {
|
|
338
|
+
super(message || _GeolocationPositionUnavailableError.DEFAULT_MESSAGE);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
__publicField(_GeolocationPositionUnavailableError, "DEFAULT_MESSAGE", "Geolocation position unavailable");
|
|
342
|
+
let GeolocationPositionUnavailableError = _GeolocationPositionUnavailableError;
|
|
343
|
+
const Constants = {
|
|
344
|
+
DEFAULT_ALTITUDE: 1.6
|
|
345
|
+
};
|
|
346
|
+
const _GnssWifiProvider = class _GnssWifiProvider extends Provider {
|
|
347
|
+
constructor() {
|
|
348
|
+
super(...arguments);
|
|
349
|
+
__publicField(this, "discardPositionsAbove", _GnssWifiProvider.DEFAULT_DISCARD_POSITIONS_ABOVE);
|
|
350
|
+
__publicField(this, "enableHighAccuracy", true);
|
|
351
|
+
__publicField(this, "geoLocationId");
|
|
352
|
+
__publicField(this, "getName", () => "GnssWifi");
|
|
353
|
+
__publicField(this, "onNewPosition", (geolocation) => {
|
|
354
|
+
const { coords } = geolocation;
|
|
355
|
+
if (!coords) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
let bearing;
|
|
359
|
+
if (coords.heading) {
|
|
360
|
+
bearing = maths.deg2rad(coords.heading);
|
|
361
|
+
}
|
|
362
|
+
const timestamp = utils.TimeUtils.unixTimestampToPreciseTime(geolocation.timestamp) / 1e3;
|
|
363
|
+
const position = new geo.UserPosition(
|
|
364
|
+
coords.latitude,
|
|
365
|
+
coords.longitude,
|
|
366
|
+
Constants.DEFAULT_ALTITUDE,
|
|
367
|
+
null,
|
|
368
|
+
timestamp,
|
|
369
|
+
coords.accuracy,
|
|
370
|
+
bearing
|
|
371
|
+
);
|
|
372
|
+
if (this.enableHighAccuracy && typeof this.discardPositionsAbove === "number" && coords.accuracy > this.discardPositionsAbove) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
this.notify(position);
|
|
376
|
+
});
|
|
377
|
+
__publicField(this, "onPositionError", (error) => {
|
|
378
|
+
Logger.warn(`[Providers] watchPosition error: [${error.code}] ${error.message}`);
|
|
379
|
+
let customError;
|
|
380
|
+
switch (error.code) {
|
|
381
|
+
case 1:
|
|
382
|
+
customError = new GeolocationPermissionDeniedError(error.message);
|
|
383
|
+
break;
|
|
384
|
+
case 2:
|
|
385
|
+
customError = new GeolocationPositionUnavailableError(error.message);
|
|
386
|
+
break;
|
|
387
|
+
default:
|
|
388
|
+
customError = new Error(error.message);
|
|
389
|
+
}
|
|
390
|
+
this.notifyError(customError);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
get positionOptions() {
|
|
394
|
+
return {
|
|
395
|
+
enableHighAccuracy: this.enableHighAccuracy,
|
|
396
|
+
timeout: Infinity,
|
|
397
|
+
maximumAge: 0
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
availability() {
|
|
401
|
+
return typeof navigator === "object" && navigator.geolocation ? Promise.resolve() : Promise.resolve(new GeolocationApiMissingError());
|
|
402
|
+
}
|
|
403
|
+
start() {
|
|
404
|
+
navigator.geolocation.getCurrentPosition(
|
|
405
|
+
this.onNewPosition,
|
|
406
|
+
this.onPositionError,
|
|
407
|
+
this.positionOptions
|
|
408
|
+
);
|
|
409
|
+
setTimeout(() => {
|
|
410
|
+
this.geoLocationId = navigator.geolocation.watchPosition(
|
|
411
|
+
this.onNewPosition,
|
|
412
|
+
this.onPositionError,
|
|
413
|
+
this.positionOptions
|
|
414
|
+
);
|
|
415
|
+
}, 150);
|
|
416
|
+
}
|
|
417
|
+
stop() {
|
|
418
|
+
if (typeof this.geoLocationId !== "undefined") {
|
|
419
|
+
navigator.geolocation.clearWatch(this.geoLocationId);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
__publicField(_GnssWifiProvider, "DEFAULT_DISCARD_POSITIONS_ABOVE", 50);
|
|
424
|
+
let GnssWifiProvider = _GnssWifiProvider;
|
|
425
|
+
const GnssWifiProvider$1 = new GnssWifiProvider();
|
|
426
|
+
const _MissingArCoreError = class _MissingArCoreError extends Error {
|
|
427
|
+
constructor(message) {
|
|
428
|
+
super(message || _MissingArCoreError.DEFAULT_MESSAGE);
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
__publicField(_MissingArCoreError, "DEFAULT_MESSAGE", "ARCore is missing");
|
|
432
|
+
let MissingArCoreError = _MissingArCoreError;
|
|
433
|
+
const _MissingNativeInterfaceError = class _MissingNativeInterfaceError extends Error {
|
|
434
|
+
constructor(message) {
|
|
435
|
+
super(message || _MissingNativeInterfaceError.DEFAULT_MESSAGE);
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
__publicField(_MissingNativeInterfaceError, "DEFAULT_MESSAGE", "Native interface is missing. You are maybe trying to execute a code which is not available in a web browser");
|
|
439
|
+
let MissingNativeInterfaceError = _MissingNativeInterfaceError;
|
|
440
|
+
const _ArCoreProvider = class _ArCoreProvider extends Provider {
|
|
441
|
+
constructor() {
|
|
442
|
+
super(...arguments);
|
|
443
|
+
__publicField(this, "_nativeProvider");
|
|
444
|
+
__publicField(this, "previousPosition", [0, 0, 0]);
|
|
445
|
+
__publicField(this, "getName", () => "ArCore");
|
|
446
|
+
__publicField(this, "pullDataLoop", () => {
|
|
447
|
+
if (this.state === "stopped") {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const payload = JSON.parse(this.nativeProvider.getInfo());
|
|
451
|
+
if (payload.length > 1) {
|
|
452
|
+
this.parsePayload(payload);
|
|
453
|
+
}
|
|
454
|
+
requestAnimationFrame(this.pullDataLoop);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
availability() {
|
|
458
|
+
try {
|
|
459
|
+
const nativeProvider = this.nativeProvider;
|
|
460
|
+
if (!nativeProvider.checkAvailability()) {
|
|
461
|
+
return Promise.resolve(new MissingArCoreError());
|
|
462
|
+
}
|
|
463
|
+
} catch (e) {
|
|
464
|
+
return Promise.resolve(e);
|
|
465
|
+
}
|
|
466
|
+
return Promise.resolve();
|
|
467
|
+
}
|
|
468
|
+
start() {
|
|
469
|
+
var _a;
|
|
470
|
+
(_a = this.nativeProvider) == null ? void 0 : _a.start();
|
|
471
|
+
this.pullDataLoop();
|
|
472
|
+
}
|
|
473
|
+
stop() {
|
|
474
|
+
var _a;
|
|
475
|
+
(_a = this.nativeProvider) == null ? void 0 : _a.stop();
|
|
476
|
+
}
|
|
477
|
+
parsePayload(payload) {
|
|
478
|
+
const ref = payload[0];
|
|
479
|
+
let bufferIndex = 1;
|
|
480
|
+
let attitude, position, cameraProjection, barcode;
|
|
481
|
+
const time = utils.TimeUtils.preciseTime() / 1e3;
|
|
482
|
+
if (ref & _ArCoreProvider.Payload.Pose.ref) {
|
|
483
|
+
attitude = new RelativeAttitude(
|
|
484
|
+
payload.slice(bufferIndex, bufferIndex + 4),
|
|
485
|
+
time,
|
|
486
|
+
_ArCoreProvider.RELATIVE_ATTITUDE_DRIFT
|
|
487
|
+
);
|
|
488
|
+
const newPosition = [
|
|
489
|
+
payload[bufferIndex + 4],
|
|
490
|
+
payload[bufferIndex + 5],
|
|
491
|
+
payload[bufferIndex + 6]
|
|
492
|
+
];
|
|
493
|
+
position = new geo.RelativePosition(
|
|
494
|
+
newPosition[0] - this.previousPosition[0],
|
|
495
|
+
newPosition[1] - this.previousPosition[1],
|
|
496
|
+
newPosition[2] - this.previousPosition[2],
|
|
497
|
+
time,
|
|
498
|
+
1e-4
|
|
499
|
+
);
|
|
500
|
+
this.previousPosition = newPosition;
|
|
501
|
+
bufferIndex += _ArCoreProvider.Payload.Pose.size;
|
|
502
|
+
}
|
|
503
|
+
if (ref & _ArCoreProvider.Payload.Barcode.ref) {
|
|
504
|
+
barcode = payload[bufferIndex];
|
|
505
|
+
bufferIndex += _ArCoreProvider.Payload.Barcode.size;
|
|
506
|
+
}
|
|
507
|
+
if (ref & _ArCoreProvider.Payload.ProjMat.ref) {
|
|
508
|
+
cameraProjection = payload.slice(bufferIndex, bufferIndex + _ArCoreProvider.Payload.ProjMat.size);
|
|
509
|
+
bufferIndex += _ArCoreProvider.Payload.ProjMat.size;
|
|
510
|
+
}
|
|
511
|
+
this.notify({
|
|
512
|
+
relativePosition: position,
|
|
513
|
+
relativeAttitude: attitude,
|
|
514
|
+
...barcode && { barcode },
|
|
515
|
+
...cameraProjection && { cameraProjection }
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
get nativeProvider() {
|
|
519
|
+
if (!this._nativeProvider) {
|
|
520
|
+
if (!this.nativeInterface) {
|
|
521
|
+
throw new MissingNativeInterfaceError();
|
|
522
|
+
}
|
|
523
|
+
this._nativeProvider = this.nativeInterface.getArCoreProvider();
|
|
524
|
+
if (!this._nativeProvider) {
|
|
525
|
+
throw new MissingArCoreError();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return this._nativeProvider;
|
|
529
|
+
}
|
|
530
|
+
enableBarcodeScanner() {
|
|
531
|
+
try {
|
|
532
|
+
this.nativeProvider.enableBarcodeScanner();
|
|
533
|
+
} catch (e) {
|
|
534
|
+
this.notifyError(e);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
disableBarcodeScanner() {
|
|
538
|
+
try {
|
|
539
|
+
this.nativeProvider.disableBarcodeScanner();
|
|
540
|
+
} catch (e) {
|
|
541
|
+
this.notifyError(e);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
get useCameraNatively() {
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
__publicField(_ArCoreProvider, "Payload", {
|
|
549
|
+
Pose: {
|
|
550
|
+
ref: 2 ** 0,
|
|
551
|
+
size: 7
|
|
552
|
+
},
|
|
553
|
+
Barcode: {
|
|
554
|
+
ref: 2 ** 1,
|
|
555
|
+
size: 1
|
|
556
|
+
},
|
|
557
|
+
ProjMat: {
|
|
558
|
+
ref: 2 ** 2,
|
|
559
|
+
size: 16
|
|
560
|
+
},
|
|
561
|
+
ImageRef: {
|
|
562
|
+
ref: 2 ** 3,
|
|
563
|
+
size: 1
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
/**
|
|
567
|
+
* default relative attitude drift in rad.second-1
|
|
568
|
+
*/
|
|
569
|
+
__publicField(_ArCoreProvider, "RELATIVE_ATTITUDE_DRIFT", maths.deg2rad(3) / 60);
|
|
570
|
+
let ArCoreProvider = _ArCoreProvider;
|
|
571
|
+
const ArCoreProvider$1 = new ArCoreProvider();
|
|
572
|
+
class GeoRelativePositionFromArCoreProvider extends Provider {
|
|
573
|
+
constructor() {
|
|
574
|
+
super(...arguments);
|
|
575
|
+
__publicField(this, "absoluteAttitudeProviderId");
|
|
576
|
+
__publicField(this, "arCoreProviderId");
|
|
577
|
+
__publicField(this, "absoluteAttitudeEvent");
|
|
578
|
+
__publicField(this, "getName", () => "GeoRelativePositionFromArCore");
|
|
579
|
+
__publicField(this, "onArCoreEvents", (event) => {
|
|
580
|
+
const relativeAttitudeEvent = event.relativeAttitude;
|
|
581
|
+
const relativePositionEvent = event.relativePosition;
|
|
582
|
+
if (relativeAttitudeEvent && relativePositionEvent && this.absoluteAttitudeEvent) {
|
|
583
|
+
this.compute(relativePositionEvent, relativeAttitudeEvent, this.absoluteAttitudeEvent);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
availability() {
|
|
588
|
+
return AvailabilityHelper.every([
|
|
589
|
+
ArCoreProvider$1.getAvailability(),
|
|
590
|
+
AbsoluteAttitudeProvider$1.getAvailability()
|
|
591
|
+
]);
|
|
592
|
+
}
|
|
593
|
+
start() {
|
|
594
|
+
this.arCoreProviderId = ArCoreProvider$1.addEventListener(
|
|
595
|
+
this.onArCoreEvents,
|
|
596
|
+
this.notifyError
|
|
597
|
+
);
|
|
598
|
+
this.absoluteAttitudeProviderId = AbsoluteAttitudeProvider$1.addEventListener(
|
|
599
|
+
(event) => this.absoluteAttitudeEvent = event,
|
|
600
|
+
this.notifyError
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
stop() {
|
|
604
|
+
ArCoreProvider$1.removeEventListener(this.arCoreProviderId);
|
|
605
|
+
AbsoluteAttitudeProvider$1.removeEventListener(this.absoluteAttitudeProviderId);
|
|
606
|
+
}
|
|
607
|
+
compute(relativePosition, relativeAttitude, absoluteAttitude) {
|
|
608
|
+
const rotation = absoluteAttitude.heading - relativeAttitude.heading;
|
|
609
|
+
const east = Math.cos(rotation) * relativePosition.x - Math.sin(rotation) * relativePosition.z;
|
|
610
|
+
const north = -Math.sin(rotation) * relativePosition.x - Math.cos(rotation) * relativePosition.z;
|
|
611
|
+
const up = relativePosition.y;
|
|
612
|
+
const position = new geo.GeoRelativePosition(
|
|
613
|
+
east,
|
|
614
|
+
north,
|
|
615
|
+
up,
|
|
616
|
+
relativePosition.time,
|
|
617
|
+
0,
|
|
618
|
+
absoluteAttitude.heading
|
|
619
|
+
);
|
|
620
|
+
this.notify(position);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
const GeoRelativePositionFromArCoreProvider$1 = new GeoRelativePositionFromArCoreProvider();
|
|
624
|
+
const DEFAULT_RELATIVE_NOISES = {
|
|
625
|
+
acc: 0.5,
|
|
626
|
+
gyr: 0.3
|
|
627
|
+
};
|
|
628
|
+
const DEFAULT_ABSOLUTE_NOISES = {
|
|
629
|
+
acc: 0.5,
|
|
630
|
+
gyr: 0.3,
|
|
631
|
+
yc: 2
|
|
632
|
+
};
|
|
633
|
+
class EkfAttitude {
|
|
634
|
+
constructor(accRef = [0, 0, 1], ycRef = [-1, 0, 0]) {
|
|
635
|
+
__publicField(this, "P");
|
|
636
|
+
__publicField(this, "accRef");
|
|
637
|
+
__publicField(this, "cRef");
|
|
638
|
+
__publicField(this, "noises");
|
|
639
|
+
__publicField(this, "quaternion");
|
|
640
|
+
this.accRef = accRef;
|
|
641
|
+
this.cRef = ycRef;
|
|
642
|
+
this.P = maths.Matrix4.fromDiagVector(Array(4).fill(0.1 ** 2));
|
|
643
|
+
this.quaternion = null;
|
|
644
|
+
this.noises = {};
|
|
645
|
+
this.setRelativeNoises(DEFAULT_RELATIVE_NOISES);
|
|
646
|
+
this.setAbsoluteNoises(DEFAULT_ABSOLUTE_NOISES);
|
|
647
|
+
}
|
|
648
|
+
setRelativeNoises(relativeNoises) {
|
|
649
|
+
this.noises.relative = {
|
|
650
|
+
acc: maths.Matrix3.diag(Array(3).fill(relativeNoises.acc ** 2)),
|
|
651
|
+
gyr: maths.Matrix3.diag(Array(3).fill(relativeNoises.gyr ** 2))
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
setAbsoluteNoises(absoluteNoises) {
|
|
655
|
+
this.noises.absolute = {
|
|
656
|
+
acc: maths.Matrix3.diag(Array(3).fill(absoluteNoises.acc ** 2)),
|
|
657
|
+
gyr: maths.Matrix3.diag(Array(3).fill(absoluteNoises.gyr ** 2)),
|
|
658
|
+
yc: maths.Matrix3.diag(Array(3).fill(absoluteNoises.yc ** 2))
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Try to initialize filter.
|
|
663
|
+
* To initialize, we need at least current acceleration (acc)
|
|
664
|
+
*/
|
|
665
|
+
tryInitialize(acc, mag) {
|
|
666
|
+
const accNormalized = maths.Vector3.normalize(acc);
|
|
667
|
+
if (mag) {
|
|
668
|
+
const magNormalized = maths.Vector3.normalize(mag);
|
|
669
|
+
const H = maths.Vector3.normalize(maths.Vector3.cross(magNormalized, accNormalized));
|
|
670
|
+
const M = maths.Vector3.cross(accNormalized, H);
|
|
671
|
+
const R = [
|
|
672
|
+
[H[0], M[0], accNormalized[0]],
|
|
673
|
+
[H[1], M[1], accNormalized[1]],
|
|
674
|
+
[H[2], M[2], accNormalized[2]]
|
|
675
|
+
];
|
|
676
|
+
this.quaternion = maths.Quaternion.fromMatrix3Matlab(R);
|
|
677
|
+
} else {
|
|
678
|
+
const r = maths.Vector3.dot(accNormalized, this.accRef) + 1;
|
|
679
|
+
const v = maths.Vector3.cross(accNormalized, this.accRef);
|
|
680
|
+
let quaternion = [r, v[0], v[1], v[2]];
|
|
681
|
+
quaternion = maths.Quaternion.normalize(quaternion);
|
|
682
|
+
this.quaternion = quaternion;
|
|
683
|
+
}
|
|
684
|
+
return this.quaternion;
|
|
685
|
+
}
|
|
686
|
+
update(diffTime, acc, gyr, mag) {
|
|
687
|
+
if (!this.quaternion) {
|
|
688
|
+
return this.tryInitialize(acc, mag);
|
|
689
|
+
}
|
|
690
|
+
let q = this.quaternion;
|
|
691
|
+
const qArray = q;
|
|
692
|
+
const gyrInt = maths.Vector3.multiplyScalar(gyr, 0.5 * diffTime);
|
|
693
|
+
const F = this.computeC([1, gyrInt[0], gyrInt[1], gyrInt[2]]);
|
|
694
|
+
const qAPriori = maths.Matrix4.multiplyVector(F, q);
|
|
695
|
+
const E1 = maths.Matrix3.diag([qArray[0], qArray[0], qArray[0]]);
|
|
696
|
+
const eSkew = maths.Matrix3.skew([qArray[1], qArray[2], qArray[3]]);
|
|
697
|
+
const qPart = [-1 * qArray[1], -1 * qArray[2], -1 * qArray[3]];
|
|
698
|
+
const E = maths.Matrix.concatRow([qPart], maths.Matrix3.sum(eSkew, E1));
|
|
699
|
+
const Qk = maths.Matrix4.multiplyScalar(
|
|
700
|
+
maths.Matrix.multiply(
|
|
701
|
+
maths.Matrix.multiply(E, this.noises[mag ? "absolute" : "relative"].gyr),
|
|
702
|
+
maths.Matrix.transpose(E)
|
|
703
|
+
),
|
|
704
|
+
(diffTime / 2) ** 2
|
|
705
|
+
);
|
|
706
|
+
const pAPriori = maths.Matrix4.sum(
|
|
707
|
+
maths.Matrix4.multiply(
|
|
708
|
+
maths.Matrix4.multiply(F, this.P),
|
|
709
|
+
maths.Matrix4.transpose(F)
|
|
710
|
+
),
|
|
711
|
+
Qk
|
|
712
|
+
);
|
|
713
|
+
const accNormalized = maths.Vector3.normalize(acc);
|
|
714
|
+
let dz, K, H;
|
|
715
|
+
if (mag) {
|
|
716
|
+
const magNormalized = maths.Vector3.normalize(mag);
|
|
717
|
+
const yc = maths.Vector3.cross(accNormalized, magNormalized);
|
|
718
|
+
const ycNormalized = maths.Vector3.normalize(yc);
|
|
719
|
+
const dzYc = maths.Vector3.subtract(ycNormalized, maths.Quaternion.rotateMatlab(qAPriori, this.cRef));
|
|
720
|
+
const dzAcc = maths.Vector3.subtract(accNormalized, maths.Quaternion.rotateMatlab(qAPriori, this.accRef));
|
|
721
|
+
dz = maths.Vector.concat(dzYc, dzAcc);
|
|
722
|
+
const HYc = this.jacobianES(qAPriori, this.cRef);
|
|
723
|
+
const HAcc = this.jacobianES(qAPriori, this.accRef);
|
|
724
|
+
H = maths.Matrix.concatRow(HYc, HAcc);
|
|
725
|
+
const RYc = maths.Matrix.concatLine(this.noises.absolute.yc, maths.Matrix3.zeros);
|
|
726
|
+
const RAcc = maths.Matrix.concatLine(maths.Matrix3.zeros, this.noises.absolute.acc);
|
|
727
|
+
const R = maths.Matrix.concatRow(RYc, RAcc);
|
|
728
|
+
K = maths.Matrix.multiply(
|
|
729
|
+
maths.Matrix.multiply(pAPriori, maths.Matrix.transpose(H)),
|
|
730
|
+
maths.Matrix.inverse(
|
|
731
|
+
maths.Matrix.sum(
|
|
732
|
+
maths.Matrix.multiply(
|
|
733
|
+
maths.Matrix.multiply(H, pAPriori),
|
|
734
|
+
maths.Matrix.transpose(H)
|
|
735
|
+
),
|
|
736
|
+
R
|
|
737
|
+
)
|
|
738
|
+
)
|
|
739
|
+
);
|
|
740
|
+
} else {
|
|
741
|
+
dz = maths.Vector3.subtract(accNormalized, maths.Quaternion.rotateMatlab(qAPriori, this.accRef));
|
|
742
|
+
H = this.jacobianES(qAPriori, this.accRef);
|
|
743
|
+
const R = this.noises.relative.acc;
|
|
744
|
+
K = maths.Matrix.multiply(
|
|
745
|
+
maths.Matrix.multiply(pAPriori, maths.Matrix.transpose(H)),
|
|
746
|
+
maths.Matrix3.inverse(
|
|
747
|
+
maths.Matrix3.sum(
|
|
748
|
+
maths.Matrix.multiply(
|
|
749
|
+
maths.Matrix.multiply(H, pAPriori),
|
|
750
|
+
maths.Matrix.transpose(H)
|
|
751
|
+
),
|
|
752
|
+
R
|
|
753
|
+
)
|
|
754
|
+
)
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
q = maths.Quaternion.sum(
|
|
758
|
+
qAPriori,
|
|
759
|
+
maths.Matrix.multiplyVector(K, dz)
|
|
760
|
+
);
|
|
761
|
+
const P = maths.Matrix4.multiply(
|
|
762
|
+
maths.Matrix4.subtract(
|
|
763
|
+
maths.Matrix4.identity,
|
|
764
|
+
maths.Matrix.multiply(K, H)
|
|
765
|
+
),
|
|
766
|
+
pAPriori
|
|
767
|
+
);
|
|
768
|
+
q = maths.Quaternion.normalize(q);
|
|
769
|
+
this.quaternion = q;
|
|
770
|
+
this.P = P;
|
|
771
|
+
return q;
|
|
772
|
+
}
|
|
773
|
+
computeC(b) {
|
|
774
|
+
return [
|
|
775
|
+
[b[0], -b[1], -b[2], -b[3]],
|
|
776
|
+
[b[1], b[0], b[3], -b[2]],
|
|
777
|
+
[b[2], -b[3], b[0], b[1]],
|
|
778
|
+
[b[3], b[2], -b[1], b[0]]
|
|
779
|
+
];
|
|
780
|
+
}
|
|
781
|
+
jacobianES(q, v) {
|
|
782
|
+
const [qw, qx, qy, qz] = q;
|
|
783
|
+
const [vx, vy, vz] = v;
|
|
784
|
+
return [
|
|
785
|
+
[2 * qz * vy - 2 * qy * vz, 2 * qy * vy + 2 * qz * vz, 2 * qx * vy - 2 * qw * vz - 4 * qy * vx, 2 * qw * vy + 2 * qx * vz - 4 * qz * vx],
|
|
786
|
+
[2 * qx * vz - 2 * qz * vx, 2 * qw * vz - 4 * qx * vy + 2 * qy * vx, 2 * qx * vx + 2 * qz * vz, 2 * qy * vz - 2 * qw * vx - 4 * qz * vy],
|
|
787
|
+
[2 * qy * vx - 2 * qx * vy, 2 * qz * vx - 4 * qx * vz - 2 * qw * vy, 2 * qw * vx - 4 * qy * vz + 2 * qz * vy, 2 * qx * vx + 2 * qy * vy]
|
|
788
|
+
];
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
class ImuProvider extends Provider {
|
|
792
|
+
constructor() {
|
|
793
|
+
super(...arguments);
|
|
794
|
+
__publicField(this, "getName", () => "IMU");
|
|
795
|
+
/**
|
|
796
|
+
* devicemotion callback
|
|
797
|
+
*/
|
|
798
|
+
__publicField(this, "parseDeviceMotionEvent", (e) => {
|
|
799
|
+
const timestamp = e.timeStamp / 1e3;
|
|
800
|
+
let acc;
|
|
801
|
+
if (e.accelerationIncludingGravity) {
|
|
802
|
+
const {
|
|
803
|
+
x,
|
|
804
|
+
y,
|
|
805
|
+
z
|
|
806
|
+
} = e.accelerationIncludingGravity;
|
|
807
|
+
if (typeof x === "number" && typeof y === "number" && typeof z === "number") {
|
|
808
|
+
acc = [x, y, z];
|
|
809
|
+
if (utils.BrowserUtils.getName() === utils.Browser.SAFARI || utils.BrowserUtils.getName() === utils.Browser.IOS_WEBVIEW) {
|
|
810
|
+
acc[0] *= -1;
|
|
811
|
+
acc[1] *= -1;
|
|
812
|
+
acc[2] *= -1;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
let gyr;
|
|
817
|
+
if (e.rotationRate) {
|
|
818
|
+
const {
|
|
819
|
+
alpha,
|
|
820
|
+
beta,
|
|
821
|
+
gamma
|
|
822
|
+
} = e.rotationRate;
|
|
823
|
+
if (typeof alpha === "number" && typeof beta === "number" && typeof gamma === "number") {
|
|
824
|
+
gyr = [maths.deg2rad(alpha), maths.deg2rad(beta), maths.deg2rad(gamma)];
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (acc || gyr) {
|
|
828
|
+
this.notify({
|
|
829
|
+
...acc && { acceleration: { timestamp, values: acc } },
|
|
830
|
+
...gyr && { angularRate: { timestamp, values: gyr } }
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
availability() {
|
|
836
|
+
return utils.BrowserUtils.isMobile ? Promise.resolve() : Promise.resolve(new AskImuOnDesktopError());
|
|
837
|
+
}
|
|
838
|
+
start() {
|
|
839
|
+
const subscribe = () => window.addEventListener("devicemotion", this.parseDeviceMotionEvent, true);
|
|
840
|
+
const requestPermission = DeviceMotionEvent.requestPermission || void 0;
|
|
841
|
+
if (requestPermission) {
|
|
842
|
+
requestPermission().then((response) => {
|
|
843
|
+
if (response !== "granted") {
|
|
844
|
+
throw new Error("Permission not granted");
|
|
845
|
+
}
|
|
846
|
+
subscribe();
|
|
847
|
+
}).catch(this.notifyError);
|
|
848
|
+
} else {
|
|
849
|
+
subscribe();
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
stop() {
|
|
853
|
+
window.removeEventListener("devicemotion", this.parseDeviceMotionEvent, true);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
const ImuProvider$1 = new ImuProvider();
|
|
857
|
+
const _MissingAccelerometerError = class _MissingAccelerometerError extends MissingSensorError {
|
|
858
|
+
constructor(message) {
|
|
859
|
+
super(message || _MissingAccelerometerError.DEFAULT_MESSAGE);
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
__publicField(_MissingAccelerometerError, "DEFAULT_MESSAGE", "Impossible to retrieve Acceleration data");
|
|
863
|
+
let MissingAccelerometerError = _MissingAccelerometerError;
|
|
864
|
+
class AccelerometerProvider extends Provider {
|
|
865
|
+
constructor() {
|
|
866
|
+
super(...arguments);
|
|
867
|
+
__publicField(this, "imuProviderId");
|
|
868
|
+
__publicField(this, "getName", () => "Accelerometer");
|
|
869
|
+
__publicField(this, "availability", () => ImuProvider$1.getAvailability());
|
|
870
|
+
}
|
|
871
|
+
start() {
|
|
872
|
+
this.imuProviderId = ImuProvider$1.addEventListener((event) => {
|
|
873
|
+
event.acceleration ? this.notify(event.acceleration) : this.notifyError(new MissingAccelerometerError().from("devicemotion"));
|
|
874
|
+
}, this.notifyError);
|
|
875
|
+
}
|
|
876
|
+
stop() {
|
|
877
|
+
ImuProvider$1.removeEventListener(this.imuProviderId);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
const AccelerometerProvider$1 = new AccelerometerProvider();
|
|
881
|
+
class MissingGyroscopeError extends MissingSensorError {
|
|
882
|
+
constructor(message) {
|
|
883
|
+
super(message || MissingSensorError.DEFAULT_MESSAGE);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
__publicField(MissingGyroscopeError, "DEFAULT_MESSAGE", "Impossible to retrieve Angular Rate data");
|
|
887
|
+
class GyroscopeProvider extends Provider {
|
|
888
|
+
constructor() {
|
|
889
|
+
super(...arguments);
|
|
890
|
+
__publicField(this, "imuProviderId");
|
|
891
|
+
__publicField(this, "getName", () => "Gyroscope");
|
|
892
|
+
__publicField(this, "availability", () => ImuProvider$1.getAvailability());
|
|
893
|
+
}
|
|
894
|
+
start() {
|
|
895
|
+
this.imuProviderId = ImuProvider$1.addEventListener((event) => {
|
|
896
|
+
event.angularRate ? this.notify(event.angularRate) : this.notifyError(new MissingGyroscopeError().from("devicemotion"));
|
|
897
|
+
}, this.notifyError);
|
|
898
|
+
}
|
|
899
|
+
stop() {
|
|
900
|
+
ImuProvider$1.removeEventListener(this.imuProviderId);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
const GyroscopeProvider$1 = new GyroscopeProvider();
|
|
904
|
+
const _RelativeAttitudeFromEkf = class _RelativeAttitudeFromEkf extends Provider {
|
|
905
|
+
constructor() {
|
|
906
|
+
super(...arguments);
|
|
907
|
+
__publicField(this, "accelerometerProviderId");
|
|
908
|
+
__publicField(this, "ekfAttitude", new EkfAttitude());
|
|
909
|
+
__publicField(this, "gyroscopeEvent");
|
|
910
|
+
__publicField(this, "gyroscopeProviderId");
|
|
911
|
+
__publicField(this, "lastTimestamp", 0);
|
|
912
|
+
__publicField(this, "getName", () => "RelativeAttitudeFromEkf");
|
|
913
|
+
__publicField(this, "onAccelerometerEvent", (accelerationEvent) => {
|
|
914
|
+
if (!this.gyroscopeEvent) {
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const {
|
|
918
|
+
values: acceleration,
|
|
919
|
+
timestamp
|
|
920
|
+
} = accelerationEvent;
|
|
921
|
+
if (this.lastTimestamp === 0) {
|
|
922
|
+
this.lastTimestamp = timestamp;
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
const diffTime = timestamp - this.lastTimestamp;
|
|
926
|
+
this.lastTimestamp = timestamp;
|
|
927
|
+
const quaternion = this.ekfAttitude.update(
|
|
928
|
+
diffTime,
|
|
929
|
+
acceleration,
|
|
930
|
+
this.gyroscopeEvent.values
|
|
931
|
+
);
|
|
932
|
+
if (quaternion) {
|
|
933
|
+
const attitude = new RelativeAttitude(
|
|
934
|
+
quaternion,
|
|
935
|
+
timestamp,
|
|
936
|
+
_RelativeAttitudeFromEkf.DEFAULT_DRIFT
|
|
937
|
+
);
|
|
938
|
+
this.notify(attitude);
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
availability() {
|
|
943
|
+
return AvailabilityHelper.every([
|
|
944
|
+
AccelerometerProvider$1.getAvailability(),
|
|
945
|
+
GyroscopeProvider$1.getAvailability()
|
|
946
|
+
]);
|
|
947
|
+
}
|
|
948
|
+
start() {
|
|
949
|
+
this.accelerometerProviderId = AccelerometerProvider$1.addEventListener(
|
|
950
|
+
(event) => this.onAccelerometerEvent(event),
|
|
951
|
+
(error) => this.notifyError(error)
|
|
952
|
+
);
|
|
953
|
+
this.gyroscopeProviderId = GyroscopeProvider$1.addEventListener(
|
|
954
|
+
(event) => this.gyroscopeEvent = event,
|
|
955
|
+
(error) => this.notifyError(error)
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
stop() {
|
|
959
|
+
AccelerometerProvider$1.removeEventListener(this.accelerometerProviderId);
|
|
960
|
+
GyroscopeProvider$1.removeEventListener(this.gyroscopeProviderId);
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
/**
|
|
964
|
+
* default relative attitude drift in rad.second-1
|
|
965
|
+
*/
|
|
966
|
+
__publicField(_RelativeAttitudeFromEkf, "DEFAULT_DRIFT", maths.deg2rad(5) / 60);
|
|
967
|
+
let RelativeAttitudeFromEkf = _RelativeAttitudeFromEkf;
|
|
968
|
+
const RelativeAttitudeFromEkfProvider = new RelativeAttitudeFromEkf();
|
|
969
|
+
const _RelativeAttitudeFromBrowser = class _RelativeAttitudeFromBrowser extends Provider {
|
|
970
|
+
constructor() {
|
|
971
|
+
super(...arguments);
|
|
972
|
+
__publicField(this, "getName", () => "RelativeAttitudeFromBrowser");
|
|
973
|
+
__publicField(this, "onDeviceOrientationEvent", (e) => {
|
|
974
|
+
if (typeof e.alpha !== "number" || typeof e.beta !== "number" || typeof e.gamma !== "number") {
|
|
975
|
+
this.notifyError(new MissingSensorError().from("deviceorientation"));
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const quaternion = maths.Rotations.eulerToQuaternionZXYDegrees([e.alpha, e.beta, e.gamma]);
|
|
979
|
+
const attitude = new RelativeAttitude(
|
|
980
|
+
quaternion,
|
|
981
|
+
e.timeStamp / 1e3,
|
|
982
|
+
_RelativeAttitudeFromBrowser.DEFAULT_DRIFT
|
|
983
|
+
);
|
|
984
|
+
this.notify(attitude);
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
availability() {
|
|
988
|
+
return utils.BrowserUtils.isMobile ? Promise.resolve() : Promise.resolve(new AskImuOnDesktopError());
|
|
989
|
+
}
|
|
990
|
+
start() {
|
|
991
|
+
const subscribe = () => window.addEventListener("deviceorientation", this.onDeviceOrientationEvent, true);
|
|
992
|
+
const requestPermission = DeviceOrientationEvent.requestPermission || void 0;
|
|
993
|
+
if (requestPermission) {
|
|
994
|
+
requestPermission().then((response) => {
|
|
995
|
+
if (response !== "granted") {
|
|
996
|
+
throw new Error("Permission not granted");
|
|
997
|
+
}
|
|
998
|
+
subscribe();
|
|
999
|
+
}).catch((error) => this.notifyError(error));
|
|
1000
|
+
} else {
|
|
1001
|
+
subscribe();
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
stop() {
|
|
1005
|
+
window.removeEventListener("deviceorientation", this.onDeviceOrientationEvent, true);
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
/**
|
|
1009
|
+
* default relative attitude drift in rad.second-1
|
|
1010
|
+
*/
|
|
1011
|
+
__publicField(_RelativeAttitudeFromBrowser, "DEFAULT_DRIFT", maths.deg2rad(5) / 60);
|
|
1012
|
+
let RelativeAttitudeFromBrowser = _RelativeAttitudeFromBrowser;
|
|
1013
|
+
const RelativeAttitudeFromBrowser$1 = new RelativeAttitudeFromBrowser();
|
|
1014
|
+
const _HighRotationsProvider = class _HighRotationsProvider extends Provider {
|
|
1015
|
+
constructor() {
|
|
1016
|
+
super(...arguments);
|
|
1017
|
+
// in seconds
|
|
1018
|
+
__publicField(this, "gyroscopeProviderId");
|
|
1019
|
+
__publicField(this, "getName", () => "HighRotationsProvider");
|
|
1020
|
+
__publicField(this, "availability", () => GyroscopeProvider$1.getAvailability());
|
|
1021
|
+
__publicField(this, "_parseGyroscopeEvent", (gyroscopeEvent) => {
|
|
1022
|
+
const { values, timestamp } = gyroscopeEvent;
|
|
1023
|
+
const speed = maths.Vector3.norm(values);
|
|
1024
|
+
if (speed > _HighRotationsProvider.THRESHOLD) {
|
|
1025
|
+
this.notify({ timestamp });
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
start() {
|
|
1030
|
+
this.gyroscopeProviderId = GyroscopeProvider$1.addEventListener(
|
|
1031
|
+
this._parseGyroscopeEvent,
|
|
1032
|
+
this.notifyError
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
stop() {
|
|
1036
|
+
GyroscopeProvider$1.removeEventListener(this.gyroscopeProviderId);
|
|
1037
|
+
}
|
|
1038
|
+
isInProgress() {
|
|
1039
|
+
if (!this.lastEvent || !GyroscopeProvider$1.lastEvent) {
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
const diffTime = GyroscopeProvider$1.lastEvent.timestamp - this.lastEvent.timestamp;
|
|
1043
|
+
return diffTime < _HighRotationsProvider.DELAY_CONSIDERATION;
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
__publicField(_HighRotationsProvider, "THRESHOLD", 10);
|
|
1047
|
+
// in radians by second
|
|
1048
|
+
__publicField(_HighRotationsProvider, "DELAY_CONSIDERATION", 3);
|
|
1049
|
+
let HighRotationsProvider = _HighRotationsProvider;
|
|
1050
|
+
const HighRotationsProvider$1 = new HighRotationsProvider();
|
|
1051
|
+
const _RelativeAttitudeFromInertial = class _RelativeAttitudeFromInertial extends Provider {
|
|
1052
|
+
constructor() {
|
|
1053
|
+
super(...arguments);
|
|
1054
|
+
__publicField(this, "_highRotationsProviderId");
|
|
1055
|
+
__publicField(this, "listenerId");
|
|
1056
|
+
__publicField(this, "provider");
|
|
1057
|
+
__publicField(this, "getName", () => "RelativeAttitudeFromInertial");
|
|
1058
|
+
}
|
|
1059
|
+
availability() {
|
|
1060
|
+
return AvailabilityHelper.some([
|
|
1061
|
+
RelativeAttitudeFromEkfProvider.getAvailability(),
|
|
1062
|
+
RelativeAttitudeFromBrowser$1.getAvailability()
|
|
1063
|
+
]);
|
|
1064
|
+
}
|
|
1065
|
+
start() {
|
|
1066
|
+
RelativeAttitudeFromEkfProvider.getAvailability().then((availabilityError) => {
|
|
1067
|
+
this.provider = !availabilityError ? RelativeAttitudeFromEkfProvider : RelativeAttitudeFromBrowser$1;
|
|
1068
|
+
this.listenerId = this.provider.addEventListener(
|
|
1069
|
+
(event) => this._parseEvent(event),
|
|
1070
|
+
this.notifyError
|
|
1071
|
+
);
|
|
1072
|
+
this._highRotationsProviderId = HighRotationsProvider$1.addEventListener(
|
|
1073
|
+
null,
|
|
1074
|
+
this.notifyError
|
|
1075
|
+
);
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
_parseEvent(event) {
|
|
1079
|
+
const relativeAttitude = event.clone();
|
|
1080
|
+
if (HighRotationsProvider$1.isInProgress()) {
|
|
1081
|
+
let accuracy = (relativeAttitude.accuracy || 0) + _RelativeAttitudeFromInertial.DEFAULT_DRIFT * 100;
|
|
1082
|
+
accuracy = Math.min(accuracy, Math.PI);
|
|
1083
|
+
relativeAttitude.accuracy = accuracy;
|
|
1084
|
+
}
|
|
1085
|
+
this.notify(relativeAttitude);
|
|
1086
|
+
}
|
|
1087
|
+
stop() {
|
|
1088
|
+
if (this.provider) {
|
|
1089
|
+
this.provider.removeEventListener(this.listenerId);
|
|
1090
|
+
delete this.provider;
|
|
1091
|
+
}
|
|
1092
|
+
HighRotationsProvider$1.removeEventListener(this._highRotationsProviderId);
|
|
1093
|
+
}
|
|
1094
|
+
};
|
|
1095
|
+
/**
|
|
1096
|
+
* default relative attitude drift in rad.second-1
|
|
1097
|
+
*/
|
|
1098
|
+
__publicField(_RelativeAttitudeFromInertial, "DEFAULT_DRIFT", maths.deg2rad(5) / 60);
|
|
1099
|
+
let RelativeAttitudeFromInertial = _RelativeAttitudeFromInertial;
|
|
1100
|
+
const RelativeAttitudeFromInertialProvider = new RelativeAttitudeFromInertial();
|
|
1101
|
+
const _StepDetectionLadetto = class _StepDetectionLadetto {
|
|
1102
|
+
constructor() {
|
|
1103
|
+
// in m.s-2
|
|
1104
|
+
__publicField(this, "frequency", 0);
|
|
1105
|
+
__publicField(this, "lastVerticalAcc", 0);
|
|
1106
|
+
__publicField(this, "maxAcceleration", 0);
|
|
1107
|
+
__publicField(this, "lastStepTimestamp", -_StepDetectionLadetto.MIN_TIME_BETWEEN_STEPS);
|
|
1108
|
+
}
|
|
1109
|
+
compute(timestamp, linearAcc) {
|
|
1110
|
+
let stepDetected = false;
|
|
1111
|
+
const verticalAcc = linearAcc[2];
|
|
1112
|
+
const timeInterval = timestamp - this.lastStepTimestamp;
|
|
1113
|
+
const upfront = verticalAcc > this.lastVerticalAcc;
|
|
1114
|
+
if (upfront) {
|
|
1115
|
+
if (verticalAcc > this.maxAcceleration) {
|
|
1116
|
+
this.maxAcceleration = verticalAcc;
|
|
1117
|
+
}
|
|
1118
|
+
} else if (this.maxAcceleration > _StepDetectionLadetto.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD && timeInterval > _StepDetectionLadetto.MIN_TIME_BETWEEN_STEPS) {
|
|
1119
|
+
this.maxAcceleration = 0;
|
|
1120
|
+
const diffTime = timestamp - this.lastStepTimestamp;
|
|
1121
|
+
this.frequency = Math.min(Math.max(1 / diffTime, _StepDetectionLadetto.MIN_FRENQUENCY), _StepDetectionLadetto.MAX_FRENQUENCY);
|
|
1122
|
+
stepDetected = true;
|
|
1123
|
+
this.lastStepTimestamp = timestamp;
|
|
1124
|
+
} else {
|
|
1125
|
+
this.maxAcceleration = 0;
|
|
1126
|
+
}
|
|
1127
|
+
this.lastVerticalAcc = verticalAcc;
|
|
1128
|
+
return stepDetected;
|
|
1129
|
+
}
|
|
1130
|
+
get lastStepSize() {
|
|
1131
|
+
if (!this.frequency) {
|
|
1132
|
+
return 0;
|
|
1133
|
+
}
|
|
1134
|
+
const kParamA = 0.45;
|
|
1135
|
+
const kParamB = 0.2;
|
|
1136
|
+
return kParamA + kParamB * this.frequency;
|
|
1137
|
+
}
|
|
1138
|
+
get speed() {
|
|
1139
|
+
return this.lastStepTimestamp ? this.lastStepSize * this.frequency : 0;
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
__publicField(_StepDetectionLadetto, "MIN_TIME_BETWEEN_STEPS", 0.4);
|
|
1143
|
+
// in seconds
|
|
1144
|
+
__publicField(_StepDetectionLadetto, "MAX_FRENQUENCY", 4);
|
|
1145
|
+
// in Hz
|
|
1146
|
+
__publicField(_StepDetectionLadetto, "MIN_FRENQUENCY", 1);
|
|
1147
|
+
// in Hz
|
|
1148
|
+
__publicField(_StepDetectionLadetto, "VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD", 1);
|
|
1149
|
+
let StepDetectionLadetto = _StepDetectionLadetto;
|
|
1150
|
+
const _StepDetectionMinMaxPeaks = class _StepDetectionMinMaxPeaks {
|
|
1151
|
+
constructor() {
|
|
1152
|
+
// in m.s-2
|
|
1153
|
+
__publicField(this, "frequency", 0);
|
|
1154
|
+
__publicField(this, "lastStepTimestamp", -_StepDetectionMinMaxPeaks.MIN_TIME_BETWEEN_STEPS);
|
|
1155
|
+
__publicField(this, "slidingWindow", []);
|
|
1156
|
+
}
|
|
1157
|
+
compute(timestamp, linearAcc) {
|
|
1158
|
+
if (this.lastStepTimestamp && this.lastStepTimestamp + _StepDetectionMinMaxPeaks.MIN_TIME_BETWEEN_STEPS > timestamp) {
|
|
1159
|
+
return false;
|
|
1160
|
+
}
|
|
1161
|
+
let maxValue = Number.MIN_SAFE_INTEGER;
|
|
1162
|
+
let minValue = Number.MAX_SAFE_INTEGER;
|
|
1163
|
+
const windowTime = _StepDetectionMinMaxPeaks.WINDOW_TIME;
|
|
1164
|
+
this.slidingWindow.forEach((item, index, object) => {
|
|
1165
|
+
if (item.timestamp < timestamp - windowTime) {
|
|
1166
|
+
object.splice(index, 1);
|
|
1167
|
+
} else {
|
|
1168
|
+
maxValue = Math.max(item.verticalAcc, maxValue);
|
|
1169
|
+
minValue = Math.min(item.verticalAcc, minValue);
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
this.slidingWindow.push({
|
|
1173
|
+
timestamp,
|
|
1174
|
+
verticalAcc: linearAcc[2]
|
|
1175
|
+
});
|
|
1176
|
+
if (maxValue > _StepDetectionMinMaxPeaks.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD && minValue < _StepDetectionMinMaxPeaks.VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD) {
|
|
1177
|
+
const timeInterval = this.lastStepTimestamp ? timestamp - this.lastStepTimestamp : 1;
|
|
1178
|
+
this.frequency = Math.min(Math.max(1 / timeInterval, _StepDetectionMinMaxPeaks.MIN_FRENQUENCY), _StepDetectionMinMaxPeaks.MAX_FRENQUENCY);
|
|
1179
|
+
this.lastStepTimestamp = timestamp;
|
|
1180
|
+
return true;
|
|
1181
|
+
}
|
|
1182
|
+
return false;
|
|
1183
|
+
}
|
|
1184
|
+
get lastStepSize() {
|
|
1185
|
+
if (!this.frequency) {
|
|
1186
|
+
return 0;
|
|
1187
|
+
}
|
|
1188
|
+
const kParamA = 0.45;
|
|
1189
|
+
const kParamB = 0.2;
|
|
1190
|
+
return kParamA + kParamB * this.frequency;
|
|
1191
|
+
}
|
|
1192
|
+
get speed() {
|
|
1193
|
+
return this.lastStepTimestamp ? this.lastStepSize * this.frequency : 0;
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
__publicField(_StepDetectionMinMaxPeaks, "WINDOW_TIME", 0.3);
|
|
1197
|
+
// in seconds
|
|
1198
|
+
__publicField(_StepDetectionMinMaxPeaks, "MIN_TIME_BETWEEN_STEPS", 0.4);
|
|
1199
|
+
// in seconds
|
|
1200
|
+
__publicField(_StepDetectionMinMaxPeaks, "MAX_FRENQUENCY", 4);
|
|
1201
|
+
// in Hz
|
|
1202
|
+
__publicField(_StepDetectionMinMaxPeaks, "MIN_FRENQUENCY", 1);
|
|
1203
|
+
// in Hz
|
|
1204
|
+
__publicField(_StepDetectionMinMaxPeaks, "VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD", 1.5);
|
|
1205
|
+
// in m.s-2
|
|
1206
|
+
__publicField(_StepDetectionMinMaxPeaks, "VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD", -1);
|
|
1207
|
+
let StepDetectionMinMaxPeaks = _StepDetectionMinMaxPeaks;
|
|
1208
|
+
const _StepDetectionMinMaxPeaks2 = class _StepDetectionMinMaxPeaks2 {
|
|
1209
|
+
constructor() {
|
|
1210
|
+
// in m.s-2
|
|
1211
|
+
__publicField(this, "frequency", 0);
|
|
1212
|
+
__publicField(this, "influence", 0.2);
|
|
1213
|
+
__publicField(this, "slidingWindow", []);
|
|
1214
|
+
__publicField(this, "lastStepTimestamp", -_StepDetectionMinMaxPeaks2.MIN_TIME_BETWEEN_STEPS);
|
|
1215
|
+
__publicField(this, "previousVerticalAcc", 0);
|
|
1216
|
+
}
|
|
1217
|
+
compute(timestamp, linearAcc, angularRate) {
|
|
1218
|
+
const verticalAcc = this.influence * (linearAcc[2] * 2) + (1 - this.influence) * this.previousVerticalAcc;
|
|
1219
|
+
this.previousVerticalAcc = verticalAcc;
|
|
1220
|
+
if (Math.sqrt(angularRate[0] ** 2 + angularRate[1] ** 2 + angularRate[2] ** 2) > 0.75) {
|
|
1221
|
+
return false;
|
|
1222
|
+
}
|
|
1223
|
+
if (this.lastStepTimestamp && this.lastStepTimestamp + _StepDetectionMinMaxPeaks2.MIN_TIME_BETWEEN_STEPS > timestamp) {
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
let maxValue = Number.MIN_SAFE_INTEGER;
|
|
1227
|
+
let minValue = Number.MAX_SAFE_INTEGER;
|
|
1228
|
+
this.slidingWindow.forEach((item, index, object) => {
|
|
1229
|
+
if (item.timestamp < timestamp - _StepDetectionMinMaxPeaks2.WINDOW_TIME) {
|
|
1230
|
+
object.splice(index, 1);
|
|
1231
|
+
} else {
|
|
1232
|
+
maxValue = Math.max(item.verticalAcc, maxValue);
|
|
1233
|
+
minValue = Math.min(item.verticalAcc, minValue);
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
this.slidingWindow.push({
|
|
1237
|
+
timestamp,
|
|
1238
|
+
verticalAcc
|
|
1239
|
+
});
|
|
1240
|
+
if (maxValue > _StepDetectionMinMaxPeaks2.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD && minValue < _StepDetectionMinMaxPeaks2.VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD) {
|
|
1241
|
+
const timeInterval = this.lastStepTimestamp ? timestamp - this.lastStepTimestamp : 1;
|
|
1242
|
+
this.frequency = Math.min(Math.max(1 / timeInterval, _StepDetectionMinMaxPeaks2.MIN_FRENQUENCY), _StepDetectionMinMaxPeaks2.MAX_FRENQUENCY);
|
|
1243
|
+
this.lastStepTimestamp = timestamp;
|
|
1244
|
+
return true;
|
|
1245
|
+
}
|
|
1246
|
+
return false;
|
|
1247
|
+
}
|
|
1248
|
+
get lastStepSize() {
|
|
1249
|
+
if (!this.frequency) {
|
|
1250
|
+
return 0;
|
|
1251
|
+
}
|
|
1252
|
+
const kParamA = 0.45;
|
|
1253
|
+
const kParamB = 0.2;
|
|
1254
|
+
return kParamA + kParamB * this.frequency;
|
|
1255
|
+
}
|
|
1256
|
+
get speed() {
|
|
1257
|
+
return this.lastStepSize && this.frequency ? this.lastStepSize * this.frequency : 0;
|
|
1258
|
+
}
|
|
1259
|
+
mean(data) {
|
|
1260
|
+
let sum = 0, mean = 0;
|
|
1261
|
+
for (let i = 0; i < data.length; ++i) {
|
|
1262
|
+
sum += data[i].verticalAcc;
|
|
1263
|
+
}
|
|
1264
|
+
mean = sum / data.length;
|
|
1265
|
+
return mean;
|
|
1266
|
+
}
|
|
1267
|
+
stddev(data) {
|
|
1268
|
+
const theMean = this.mean(data);
|
|
1269
|
+
let standardDeviation = 0;
|
|
1270
|
+
for (let i = 0; i < data.length; ++i) {
|
|
1271
|
+
standardDeviation += (data[i].verticalAcc - theMean) ** 2;
|
|
1272
|
+
}
|
|
1273
|
+
return Math.sqrt(standardDeviation / data.length);
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
__publicField(_StepDetectionMinMaxPeaks2, "WINDOW_TIME", 0.3);
|
|
1277
|
+
// in seconds
|
|
1278
|
+
__publicField(_StepDetectionMinMaxPeaks2, "MIN_TIME_BETWEEN_STEPS", 0.4);
|
|
1279
|
+
// in seconds
|
|
1280
|
+
__publicField(_StepDetectionMinMaxPeaks2, "MAX_FRENQUENCY", 4);
|
|
1281
|
+
// in Hz
|
|
1282
|
+
__publicField(_StepDetectionMinMaxPeaks2, "MIN_FRENQUENCY", 1);
|
|
1283
|
+
// in Hz
|
|
1284
|
+
__publicField(_StepDetectionMinMaxPeaks2, "VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD", 0.75);
|
|
1285
|
+
// in m.s-2
|
|
1286
|
+
__publicField(_StepDetectionMinMaxPeaks2, "VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD", -0.3);
|
|
1287
|
+
let StepDetectionMinMaxPeaks2 = _StepDetectionMinMaxPeaks2;
|
|
1288
|
+
const _StepDetectionMinMaxPeaks3 = class _StepDetectionMinMaxPeaks3 {
|
|
1289
|
+
constructor() {
|
|
1290
|
+
// in m.s-2
|
|
1291
|
+
__publicField(this, "frequency", 0);
|
|
1292
|
+
__publicField(this, "influence", 0.05);
|
|
1293
|
+
__publicField(this, "slidingWindow", []);
|
|
1294
|
+
__publicField(this, "lastStepTimestamp", -_StepDetectionMinMaxPeaks3.MIN_TIME_BETWEEN_STEPS);
|
|
1295
|
+
__publicField(this, "previousVerticalAcc", 0);
|
|
1296
|
+
__publicField(this, "previousHorizontalAcc", 0);
|
|
1297
|
+
}
|
|
1298
|
+
compute(timestamp, linearAcc) {
|
|
1299
|
+
const verticalAcc = this.influence * linearAcc[2] + (1 - this.influence) * this.previousVerticalAcc;
|
|
1300
|
+
this.previousVerticalAcc = verticalAcc;
|
|
1301
|
+
this.slidingWindow = this.slidingWindow.filter(
|
|
1302
|
+
(item) => item.timestamp >= timestamp - _StepDetectionMinMaxPeaks3.WINDOW_TIME
|
|
1303
|
+
);
|
|
1304
|
+
this.slidingWindow.push({ timestamp, verticalAcc });
|
|
1305
|
+
const isTooEarlyForANewStep = this.lastStepTimestamp && this.lastStepTimestamp + _StepDetectionMinMaxPeaks3.MIN_TIME_BETWEEN_STEPS > timestamp;
|
|
1306
|
+
if (isTooEarlyForANewStep) {
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
let maxValue = Number.MIN_VALUE;
|
|
1310
|
+
let maxValueIdx = -1;
|
|
1311
|
+
let foundMaxPeakHigherThanThreshold = false;
|
|
1312
|
+
this.slidingWindow.forEach((item, idx) => {
|
|
1313
|
+
if (item.verticalAcc > maxValue && item.verticalAcc >= _StepDetectionMinMaxPeaks3.VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD) {
|
|
1314
|
+
maxValue = item.verticalAcc;
|
|
1315
|
+
maxValueIdx = idx;
|
|
1316
|
+
foundMaxPeakHigherThanThreshold = true;
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
if (!foundMaxPeakHigherThanThreshold) {
|
|
1320
|
+
return false;
|
|
1321
|
+
}
|
|
1322
|
+
let hasLowNegativeValueBeforeMaxPeak = false;
|
|
1323
|
+
let minValueBeforeMaxPeak = Number.MAX_VALUE;
|
|
1324
|
+
for (let i = 0; i < maxValueIdx; i++) {
|
|
1325
|
+
const curValue = this.slidingWindow[i].verticalAcc;
|
|
1326
|
+
minValueBeforeMaxPeak = Math.min(minValueBeforeMaxPeak, curValue);
|
|
1327
|
+
if (curValue < _StepDetectionMinMaxPeaks3.VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD) {
|
|
1328
|
+
hasLowNegativeValueBeforeMaxPeak = true;
|
|
1329
|
+
break;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
if (!hasLowNegativeValueBeforeMaxPeak) {
|
|
1333
|
+
return false;
|
|
1334
|
+
}
|
|
1335
|
+
const diffMinMax = maxValue - minValueBeforeMaxPeak;
|
|
1336
|
+
const targetValue = maxValue - 0.5 * diffMinMax;
|
|
1337
|
+
let targetValueFoundAfterMaxPeak = false;
|
|
1338
|
+
for (let i = maxValueIdx + 1; i < this.slidingWindow.length; i++) {
|
|
1339
|
+
if (this.slidingWindow[i].verticalAcc <= targetValue) {
|
|
1340
|
+
targetValueFoundAfterMaxPeak = true;
|
|
1341
|
+
break;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
if (!targetValueFoundAfterMaxPeak) {
|
|
1345
|
+
return false;
|
|
1346
|
+
}
|
|
1347
|
+
const timeInterval = this.lastStepTimestamp ? timestamp - this.lastStepTimestamp : 1;
|
|
1348
|
+
this.frequency = Math.min(Math.max(1 / timeInterval, _StepDetectionMinMaxPeaks3.MIN_FRENQUENCY), _StepDetectionMinMaxPeaks3.MAX_FRENQUENCY);
|
|
1349
|
+
this.lastStepTimestamp = timestamp;
|
|
1350
|
+
return true;
|
|
1351
|
+
}
|
|
1352
|
+
get lastStepSize() {
|
|
1353
|
+
if (!this.frequency) {
|
|
1354
|
+
return 0;
|
|
1355
|
+
}
|
|
1356
|
+
const kParamA = 0.45;
|
|
1357
|
+
const kParamB = 0.2;
|
|
1358
|
+
return kParamA + kParamB * this.frequency;
|
|
1359
|
+
}
|
|
1360
|
+
get speed() {
|
|
1361
|
+
return this.lastStepSize && this.frequency ? this.lastStepSize * this.frequency : 0;
|
|
1362
|
+
}
|
|
1363
|
+
mean(data) {
|
|
1364
|
+
let sum = 0, mean = 0;
|
|
1365
|
+
for (let i = 0; i < data.length; ++i) {
|
|
1366
|
+
sum += data[i];
|
|
1367
|
+
}
|
|
1368
|
+
mean = sum / data.length;
|
|
1369
|
+
return mean;
|
|
1370
|
+
}
|
|
1371
|
+
stddev(data) {
|
|
1372
|
+
const theMean = this.mean(data);
|
|
1373
|
+
let standardDeviation = 0;
|
|
1374
|
+
for (let i = 0; i < data.length; ++i) {
|
|
1375
|
+
standardDeviation += (data[i] - theMean) ** 2;
|
|
1376
|
+
}
|
|
1377
|
+
return Math.sqrt(standardDeviation / data.length);
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
__publicField(_StepDetectionMinMaxPeaks3, "WINDOW_TIME", 0.6);
|
|
1381
|
+
// in seconds
|
|
1382
|
+
__publicField(_StepDetectionMinMaxPeaks3, "MIN_TIME_BETWEEN_STEPS", 0.6);
|
|
1383
|
+
// in seconds
|
|
1384
|
+
__publicField(_StepDetectionMinMaxPeaks3, "MAX_FRENQUENCY", 4);
|
|
1385
|
+
// in Hz
|
|
1386
|
+
__publicField(_StepDetectionMinMaxPeaks3, "MIN_FRENQUENCY", 1);
|
|
1387
|
+
// in Hz
|
|
1388
|
+
__publicField(_StepDetectionMinMaxPeaks3, "VERTICAL_ACC_POSITIVE_PEAK_THRESHOLD", 0.2);
|
|
1389
|
+
// in m.s-2
|
|
1390
|
+
__publicField(_StepDetectionMinMaxPeaks3, "VERTICAL_ACC_NEGATIVE_PEAK_THRESHOLD", -0.1);
|
|
1391
|
+
let StepDetectionMinMaxPeaks3 = _StepDetectionMinMaxPeaks3;
|
|
1392
|
+
const _StepProvider = class _StepProvider extends Provider {
|
|
1393
|
+
constructor() {
|
|
1394
|
+
super();
|
|
1395
|
+
__publicField(this, "accelerometerProviderId");
|
|
1396
|
+
__publicField(this, "attitudeProviderId");
|
|
1397
|
+
__publicField(this, "gyroscopeProviderId");
|
|
1398
|
+
__publicField(this, "angularRateEvent");
|
|
1399
|
+
__publicField(this, "attitudeEvent");
|
|
1400
|
+
__publicField(this, "numOfSteps", 0);
|
|
1401
|
+
__publicField(this, "stepDetector");
|
|
1402
|
+
__publicField(this, "_stepSizeMultiplier", _StepProvider.DEFAULT_STEP_SIZE_MULTIPLIER);
|
|
1403
|
+
__publicField(this, "_algorithm", _StepProvider.DEFAULT_ALGORITHM);
|
|
1404
|
+
__publicField(this, "_accValues", []);
|
|
1405
|
+
__publicField(this, "getName", () => "StepDetector");
|
|
1406
|
+
__publicField(this, "onAccelerometerEvent", (accelerationEvent) => {
|
|
1407
|
+
if (!this.attitudeEvent || !this.angularRateEvent) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
const {
|
|
1411
|
+
values: acceleration,
|
|
1412
|
+
timestamp
|
|
1413
|
+
} = accelerationEvent;
|
|
1414
|
+
const linearAcc = _StepProvider.computeLinearAcceleration(
|
|
1415
|
+
this.attitudeEvent.quaternion,
|
|
1416
|
+
acceleration
|
|
1417
|
+
);
|
|
1418
|
+
const stepDetected = this.stepDetector.compute(timestamp, linearAcc, this.angularRateEvent.values);
|
|
1419
|
+
if (stepDetected) {
|
|
1420
|
+
const size = this.stepDetector.lastStepSize * this._stepSizeMultiplier;
|
|
1421
|
+
this.numOfSteps++;
|
|
1422
|
+
this.notify({ size, number: this.numOfSteps });
|
|
1423
|
+
}
|
|
1424
|
+
});
|
|
1425
|
+
this.algorithm = this._algorithm;
|
|
1426
|
+
}
|
|
1427
|
+
availability() {
|
|
1428
|
+
return AvailabilityHelper.every([
|
|
1429
|
+
AccelerometerProvider$1.getAvailability(),
|
|
1430
|
+
GyroscopeProvider$1.getAvailability(),
|
|
1431
|
+
RelativeAttitudeFromInertialProvider.getAvailability()
|
|
1432
|
+
]);
|
|
1433
|
+
}
|
|
1434
|
+
start() {
|
|
1435
|
+
this.numOfSteps = 0;
|
|
1436
|
+
this.accelerometerProviderId = AccelerometerProvider$1.addEventListener(
|
|
1437
|
+
this.onAccelerometerEvent,
|
|
1438
|
+
this.notifyError
|
|
1439
|
+
);
|
|
1440
|
+
this.gyroscopeProviderId = GyroscopeProvider$1.addEventListener(
|
|
1441
|
+
(event) => this.angularRateEvent = event,
|
|
1442
|
+
this.notifyError
|
|
1443
|
+
);
|
|
1444
|
+
this.attitudeProviderId = RelativeAttitudeFromInertialProvider.addEventListener(
|
|
1445
|
+
(event) => this.attitudeEvent = event,
|
|
1446
|
+
this.notifyError
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
stop() {
|
|
1450
|
+
AccelerometerProvider$1.removeEventListener(this.accelerometerProviderId);
|
|
1451
|
+
GyroscopeProvider$1.removeEventListener(this.gyroscopeProviderId);
|
|
1452
|
+
RelativeAttitudeFromInertialProvider.removeEventListener(this.attitudeProviderId);
|
|
1453
|
+
}
|
|
1454
|
+
// Linear acceleration in ENU
|
|
1455
|
+
static computeLinearAcceleration(quaternion, acc) {
|
|
1456
|
+
const linearAcc = maths.Quaternion.rotateMatlab(maths.Quaternion.inverse(quaternion), acc);
|
|
1457
|
+
linearAcc[2] -= geo.Constants.EARTH_GRAVITY;
|
|
1458
|
+
return linearAcc;
|
|
1459
|
+
}
|
|
1460
|
+
set stepSizeMultiplier(stepSizeMultiplier) {
|
|
1461
|
+
this._stepSizeMultiplier = stepSizeMultiplier;
|
|
1462
|
+
}
|
|
1463
|
+
get stepSizeMultiplier() {
|
|
1464
|
+
return this._stepSizeMultiplier;
|
|
1465
|
+
}
|
|
1466
|
+
set algorithm(algorithm) {
|
|
1467
|
+
switch (algorithm) {
|
|
1468
|
+
case "ladetto":
|
|
1469
|
+
this.stepDetector = new StepDetectionLadetto();
|
|
1470
|
+
break;
|
|
1471
|
+
case "minMaxPeaks":
|
|
1472
|
+
this.stepDetector = new StepDetectionMinMaxPeaks();
|
|
1473
|
+
break;
|
|
1474
|
+
case "minMaxPeaks2":
|
|
1475
|
+
this.stepDetector = new StepDetectionMinMaxPeaks2();
|
|
1476
|
+
break;
|
|
1477
|
+
case "minMaxPeaks3":
|
|
1478
|
+
default:
|
|
1479
|
+
algorithm = "minMaxPeaks3";
|
|
1480
|
+
this.stepDetector = new StepDetectionMinMaxPeaks3();
|
|
1481
|
+
break;
|
|
1482
|
+
}
|
|
1483
|
+
this._algorithm = algorithm;
|
|
1484
|
+
}
|
|
1485
|
+
get algorithm() {
|
|
1486
|
+
return this._algorithm;
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
__publicField(_StepProvider, "DEFAULT_STEP_SIZE_MULTIPLIER", 1);
|
|
1490
|
+
__publicField(_StepProvider, "DEFAULT_ALGORITHM", "minMaxPeaks3");
|
|
1491
|
+
let StepProvider = _StepProvider;
|
|
1492
|
+
const StepProvider$1 = new StepProvider();
|
|
1493
|
+
class PdrProvider extends Provider {
|
|
1494
|
+
constructor() {
|
|
1495
|
+
super(...arguments);
|
|
1496
|
+
__publicField(this, "absoluteAttitudeProviderId");
|
|
1497
|
+
__publicField(this, "stepDetectionProviderId");
|
|
1498
|
+
__publicField(this, "attitudeEvent");
|
|
1499
|
+
// https://ieeexplore.ieee.org/document/7346766
|
|
1500
|
+
// private misalignment = [1, 0, 0, 0];
|
|
1501
|
+
__publicField(this, "misalignmentError", maths.deg2rad(3));
|
|
1502
|
+
__publicField(this, "getName", () => "Pdr");
|
|
1503
|
+
__publicField(this, "onStepEvent", (stepEvent) => {
|
|
1504
|
+
if (!this.attitudeEvent) {
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
const stepSize = stepEvent.size;
|
|
1508
|
+
const deviceAttitude = this.attitudeEvent;
|
|
1509
|
+
const deviceDirection = deviceAttitude.heading;
|
|
1510
|
+
const deviceDirectionAccuracy = deviceAttitude.accuracy + this.misalignmentError;
|
|
1511
|
+
const accuracy = stepSize / 2 * Math.sin(deviceDirectionAccuracy / 2);
|
|
1512
|
+
const timestamp = deviceAttitude.time;
|
|
1513
|
+
const position = new geo.GeoRelativePosition(
|
|
1514
|
+
stepSize * Math.sin(deviceDirection),
|
|
1515
|
+
stepSize * Math.cos(deviceDirection),
|
|
1516
|
+
0,
|
|
1517
|
+
timestamp,
|
|
1518
|
+
accuracy,
|
|
1519
|
+
deviceDirection
|
|
1520
|
+
);
|
|
1521
|
+
this.notify(position);
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
availability() {
|
|
1525
|
+
return AvailabilityHelper.every([
|
|
1526
|
+
StepProvider$1.getAvailability(),
|
|
1527
|
+
AbsoluteAttitudeProvider$1.getAvailability()
|
|
1528
|
+
]);
|
|
1529
|
+
}
|
|
1530
|
+
start() {
|
|
1531
|
+
this.stepDetectionProviderId = StepProvider$1.addEventListener(
|
|
1532
|
+
this.onStepEvent,
|
|
1533
|
+
this.notifyError
|
|
1534
|
+
);
|
|
1535
|
+
this.absoluteAttitudeProviderId = AbsoluteAttitudeProvider$1.addEventListener(
|
|
1536
|
+
(event) => this.attitudeEvent = event,
|
|
1537
|
+
this.notifyError
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
stop() {
|
|
1541
|
+
StepProvider$1.removeEventListener(this.stepDetectionProviderId);
|
|
1542
|
+
AbsoluteAttitudeProvider$1.removeEventListener(this.absoluteAttitudeProviderId);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
const PdrProvider$1 = new PdrProvider();
|
|
1546
|
+
class GeoRelativePositionProvider extends Provider {
|
|
1547
|
+
constructor() {
|
|
1548
|
+
super(...arguments);
|
|
1549
|
+
__publicField(this, "providerId");
|
|
1550
|
+
__publicField(this, "geoRelativeProvider");
|
|
1551
|
+
__publicField(this, "getName", () => "GeoRelativePosition");
|
|
1552
|
+
}
|
|
1553
|
+
availability() {
|
|
1554
|
+
return AvailabilityHelper.some([
|
|
1555
|
+
PdrProvider$1.getAvailability(),
|
|
1556
|
+
GeoRelativePositionFromArCoreProvider$1.getAvailability()
|
|
1557
|
+
]);
|
|
1558
|
+
}
|
|
1559
|
+
async start() {
|
|
1560
|
+
const availabilityError = await GeoRelativePositionFromArCoreProvider$1.getAvailability();
|
|
1561
|
+
this.geoRelativeProvider = availabilityError ? PdrProvider$1 : GeoRelativePositionFromArCoreProvider$1;
|
|
1562
|
+
this.providerId = this.geoRelativeProvider.addEventListener(this.notify, this.notifyError);
|
|
1563
|
+
}
|
|
1564
|
+
stop() {
|
|
1565
|
+
var _a;
|
|
1566
|
+
(_a = this.geoRelativeProvider) == null ? void 0 : _a.removeEventListener(this.providerId);
|
|
1567
|
+
delete this.geoRelativeProvider;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
const GeoRelativePositionProvider$1 = new GeoRelativePositionProvider();
|
|
1571
|
+
class InclinationFromAccProvider extends Provider {
|
|
1572
|
+
constructor() {
|
|
1573
|
+
super(...arguments);
|
|
1574
|
+
__publicField(this, "providerId");
|
|
1575
|
+
__publicField(this, "getName", () => "InclinationFromAcc");
|
|
1576
|
+
__publicField(this, "availability", () => AccelerometerProvider$1.getAvailability());
|
|
1577
|
+
__publicField(this, "onAccelerometerEvent", (accelerometerEvent) => {
|
|
1578
|
+
const acc = accelerometerEvent.values;
|
|
1579
|
+
const screenOrientation = window.orientation || 0;
|
|
1580
|
+
const sizeAcc = Math.sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
|
|
1581
|
+
const accNormalized = [acc[0] / sizeAcc, acc[1] / sizeAcc, acc[2] / sizeAcc];
|
|
1582
|
+
const q = [accNormalized[2] + 1, accNormalized[1], -accNormalized[0], 0];
|
|
1583
|
+
const qSize = Math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
|
|
1584
|
+
const qNormalized = [q[0] / qSize, q[1] / qSize, q[2] / qSize, 0];
|
|
1585
|
+
let inclination;
|
|
1586
|
+
if (screenOrientation === 0) {
|
|
1587
|
+
inclination = Math.asin(2 * qNormalized[1] * qNormalized[0]);
|
|
1588
|
+
} else if (screenOrientation === 90) {
|
|
1589
|
+
inclination = -Math.asin(2 * qNormalized[2] * qNormalized[0]);
|
|
1590
|
+
} else if (screenOrientation === -90) {
|
|
1591
|
+
inclination = Math.asin(2 * qNormalized[2] * qNormalized[0]);
|
|
1592
|
+
} else {
|
|
1593
|
+
inclination = -Math.asin(2 * qNormalized[1] * qNormalized[0]);
|
|
1594
|
+
}
|
|
1595
|
+
this.notify(inclination);
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
start() {
|
|
1599
|
+
this.providerId = AccelerometerProvider$1.addEventListener(
|
|
1600
|
+
this.onAccelerometerEvent,
|
|
1601
|
+
this.notifyError
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
stop() {
|
|
1605
|
+
AccelerometerProvider$1.removeEventListener(this.providerId);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
const InclinationFromAccProvider$1 = new InclinationFromAccProvider();
|
|
1609
|
+
class InclinationFromRelativeAttitudeProvider extends Provider {
|
|
1610
|
+
constructor() {
|
|
1611
|
+
super(...arguments);
|
|
1612
|
+
__publicField(this, "providerId");
|
|
1613
|
+
__publicField(this, "getName", () => "InclinationFromRelativeAttitude");
|
|
1614
|
+
__publicField(this, "availability", () => RelativeAttitudeFromInertialProvider.getAvailability());
|
|
1615
|
+
}
|
|
1616
|
+
start() {
|
|
1617
|
+
this.providerId = RelativeAttitudeFromInertialProvider.addEventListener(
|
|
1618
|
+
(attitudeEvent) => {
|
|
1619
|
+
const inclination = this.enuQuatToInclination(attitudeEvent.quaternion);
|
|
1620
|
+
this.notify(inclination);
|
|
1621
|
+
},
|
|
1622
|
+
this.notifyError
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
stop() {
|
|
1626
|
+
RelativeAttitudeFromInertialProvider.removeEventListener(this.providerId);
|
|
1627
|
+
}
|
|
1628
|
+
enuQuatToInclination(q) {
|
|
1629
|
+
const screenOrientation = window.orientation || 0;
|
|
1630
|
+
if (screenOrientation === 0) {
|
|
1631
|
+
return Math.asin(2 * (q[2] * q[3] + q[1] * q[0]));
|
|
1632
|
+
} else if (screenOrientation === 90) {
|
|
1633
|
+
return Math.asin(2 * (q[1] * q[3] - q[2] * q[0]));
|
|
1634
|
+
} else if (screenOrientation === -90) {
|
|
1635
|
+
return Math.asin(2 * (q[2] * q[0] - q[1] * q[3]));
|
|
1636
|
+
}
|
|
1637
|
+
return -Math.asin(2 * (q[2] * q[3] + q[1] * q[0]));
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
const InclinationFromRelativeAttitudeProvider$1 = new InclinationFromRelativeAttitudeProvider();
|
|
1641
|
+
class InclinationProvider extends Provider {
|
|
1642
|
+
constructor() {
|
|
1643
|
+
super(...arguments);
|
|
1644
|
+
__publicField(this, "provider");
|
|
1645
|
+
__publicField(this, "providerId");
|
|
1646
|
+
__publicField(this, "getName", () => "Inclination");
|
|
1647
|
+
}
|
|
1648
|
+
availability() {
|
|
1649
|
+
return AvailabilityHelper.some([
|
|
1650
|
+
InclinationFromAccProvider$1.getAvailability(),
|
|
1651
|
+
InclinationFromRelativeAttitudeProvider$1.getAvailability()
|
|
1652
|
+
]);
|
|
1653
|
+
}
|
|
1654
|
+
async start() {
|
|
1655
|
+
const startInclinationFromAcc = () => {
|
|
1656
|
+
this.provider = InclinationFromAccProvider$1;
|
|
1657
|
+
this.providerId = this.provider.addEventListener(
|
|
1658
|
+
this.notify,
|
|
1659
|
+
this.notifyError
|
|
1660
|
+
);
|
|
1661
|
+
};
|
|
1662
|
+
if (await InclinationFromRelativeAttitudeProvider$1.getAvailability()) {
|
|
1663
|
+
this.provider = InclinationFromRelativeAttitudeProvider$1;
|
|
1664
|
+
this.providerId = this.provider.addEventListener(
|
|
1665
|
+
this.notify,
|
|
1666
|
+
() => {
|
|
1667
|
+
InclinationFromRelativeAttitudeProvider$1.removeEventListener(this.providerId);
|
|
1668
|
+
startInclinationFromAcc();
|
|
1669
|
+
}
|
|
1670
|
+
);
|
|
1671
|
+
} else {
|
|
1672
|
+
startInclinationFromAcc();
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
stop() {
|
|
1676
|
+
if (this.provider) {
|
|
1677
|
+
this.provider.removeEventListener(this.providerId);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
const InclinationProvider$1 = new InclinationProvider();
|
|
1682
|
+
class VpsMetadata {
|
|
1683
|
+
constructor(size, calibration = null, coarse = null, device = null) {
|
|
1684
|
+
this.size = size;
|
|
1685
|
+
this.calibration = calibration;
|
|
1686
|
+
this.coarse = coarse;
|
|
1687
|
+
this.device = device;
|
|
1688
|
+
}
|
|
1689
|
+
toJson() {
|
|
1690
|
+
return {
|
|
1691
|
+
size: [this.size.width, this.size.height],
|
|
1692
|
+
...this.calibration && { calibration: this.calibration },
|
|
1693
|
+
...this.coarse && {
|
|
1694
|
+
coarse: {
|
|
1695
|
+
...this.coarse.attitude && { attitude: this.coarse.attitude.toJson() },
|
|
1696
|
+
...this.coarse.position && { position: this.coarse.position.toJson() }
|
|
1697
|
+
}
|
|
1698
|
+
},
|
|
1699
|
+
...typeof this.device === "object" && { device: this.device }
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
static fromJson(json) {
|
|
1703
|
+
var _a, _b;
|
|
1704
|
+
return new VpsMetadata(
|
|
1705
|
+
{
|
|
1706
|
+
width: json.size[0],
|
|
1707
|
+
height: json.size[1]
|
|
1708
|
+
},
|
|
1709
|
+
json.calibration,
|
|
1710
|
+
{
|
|
1711
|
+
...((_a = json.coarse) == null ? void 0 : _a.position) && { position: geo.UserPosition.fromJson(json.coarse.position) },
|
|
1712
|
+
...((_b = json.coarse) == null ? void 0 : _b.attitude) && { attitude: geo.Attitude.fromJson(json.coarse.attitude) }
|
|
1713
|
+
},
|
|
1714
|
+
json.device
|
|
1715
|
+
);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
class VpsRequest {
|
|
1719
|
+
constructor(metadata, image) {
|
|
1720
|
+
this.metadata = metadata;
|
|
1721
|
+
this.image = image;
|
|
1722
|
+
}
|
|
1723
|
+
toJson() {
|
|
1724
|
+
const base64Image = camera.canvasToBase64(this.image);
|
|
1725
|
+
return {
|
|
1726
|
+
image: base64Image,
|
|
1727
|
+
...this.metadata.toJson()
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
static fromJson(json) {
|
|
1731
|
+
return new VpsRequest(
|
|
1732
|
+
VpsMetadata.fromJson(json),
|
|
1733
|
+
camera.base64ToCanvas(json.image)
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
class VpsResponse {
|
|
1738
|
+
constructor(success, attitude = null, position = null) {
|
|
1739
|
+
this.success = success;
|
|
1740
|
+
this.attitude = attitude;
|
|
1741
|
+
this.position = position;
|
|
1742
|
+
}
|
|
1743
|
+
toJson() {
|
|
1744
|
+
var _a, _b;
|
|
1745
|
+
return {
|
|
1746
|
+
success: this.success,
|
|
1747
|
+
attitude: (_a = this.attitude) == null ? void 0 : _a.toJson(),
|
|
1748
|
+
position: (_b = this.position) == null ? void 0 : _b.toJson()
|
|
1749
|
+
};
|
|
1750
|
+
}
|
|
1751
|
+
static fromJson(json, imageRecordTime = null) {
|
|
1752
|
+
let attitude = null;
|
|
1753
|
+
if (json.attitude) {
|
|
1754
|
+
attitude = geo.Attitude.fromJson(json.attitude);
|
|
1755
|
+
attitude.time = imageRecordTime;
|
|
1756
|
+
}
|
|
1757
|
+
let position = null;
|
|
1758
|
+
if (json.position) {
|
|
1759
|
+
position = geo.UserPosition.fromJson(json.position);
|
|
1760
|
+
position.time = imageRecordTime;
|
|
1761
|
+
}
|
|
1762
|
+
return new VpsResponse(json.success, attitude, position);
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
class ImageRelocalization {
|
|
1766
|
+
static _prepareRequest(imageCanvas, calibration = null, coarsePose = null) {
|
|
1767
|
+
camera.convertToGrayscale(imageCanvas);
|
|
1768
|
+
const reducedImage = camera.reduceImageSize(imageCanvas, 1280);
|
|
1769
|
+
const metadata = new VpsMetadata(
|
|
1770
|
+
{ width: reducedImage.width, height: reducedImage.height },
|
|
1771
|
+
calibration,
|
|
1772
|
+
coarsePose,
|
|
1773
|
+
utils.UserAgentUtils.getDeviceFromUserAgent()
|
|
1774
|
+
);
|
|
1775
|
+
return new VpsRequest(metadata, reducedImage);
|
|
1776
|
+
}
|
|
1777
|
+
static async relocalize(endpointUrl, imageCanvas, calibration = null, coarsePose = null, customHeaders = null) {
|
|
1778
|
+
const timeBeforeRequest = utils.TimeUtils.preciseTime() / 1e3;
|
|
1779
|
+
const vpsRequest = this._prepareRequest(imageCanvas, calibration, coarsePose);
|
|
1780
|
+
let serverResponse;
|
|
1781
|
+
try {
|
|
1782
|
+
const body = JSON.stringify(vpsRequest.toJson());
|
|
1783
|
+
Logger.debug(`[VPS] Request (${(body.length / 1024).toFixed(0)} kB) sent to server ${endpointUrl}`);
|
|
1784
|
+
serverResponse = await fetch(endpointUrl, {
|
|
1785
|
+
method: "POST",
|
|
1786
|
+
body,
|
|
1787
|
+
headers: Object.assign(
|
|
1788
|
+
{
|
|
1789
|
+
"Content-Type": "application/json",
|
|
1790
|
+
"Accept": "application/vnd.geopose+json; version=1"
|
|
1791
|
+
},
|
|
1792
|
+
customHeaders ? customHeaders : {}
|
|
1793
|
+
)
|
|
1794
|
+
});
|
|
1795
|
+
} catch (e) {
|
|
1796
|
+
Logger.debug("[VPS] Server respond error");
|
|
1797
|
+
return null;
|
|
1798
|
+
}
|
|
1799
|
+
if (serverResponse.status !== 200) {
|
|
1800
|
+
Logger.debug("[VPS] Server respond error");
|
|
1801
|
+
return null;
|
|
1802
|
+
}
|
|
1803
|
+
const json = await serverResponse.json();
|
|
1804
|
+
const res = VpsResponse.fromJson(json, timeBeforeRequest);
|
|
1805
|
+
Logger.debug(`[VPS] Server respond ${res.success ? "success" : "not found"}`);
|
|
1806
|
+
return res;
|
|
1807
|
+
}
|
|
1808
|
+
static getHeadingFromQuaternion(quaternion) {
|
|
1809
|
+
const [qw, qx, qy, qz] = quaternion;
|
|
1810
|
+
const s = Math.sqrt(2) / 2;
|
|
1811
|
+
const C = [s * (qw - qx), s * (qw + qx), s * (qy + qz), s * (qz - qy)];
|
|
1812
|
+
return -Math.atan2(2 * C[3] * C[0] - 2 * C[2] * C[1], 1 - 2 * C[1] ** 2 - 2 * C[3] ** 2);
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
class RelativeRotationCalc {
|
|
1816
|
+
constructor() {
|
|
1817
|
+
__publicField(this, "_providerId");
|
|
1818
|
+
__publicField(this, "_isRunning", false);
|
|
1819
|
+
__publicField(this, "_dataOnStart", null);
|
|
1820
|
+
}
|
|
1821
|
+
tickStart() {
|
|
1822
|
+
this._dataOnStart = null;
|
|
1823
|
+
if (this._isRunning) {
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
this._isRunning = true;
|
|
1827
|
+
this._providerId = RelativeAttitudeFromBrowser$1.addEventListener((event) => {
|
|
1828
|
+
if (!this._dataOnStart) {
|
|
1829
|
+
this._dataOnStart = event;
|
|
1830
|
+
}
|
|
1831
|
+
});
|
|
1832
|
+
}
|
|
1833
|
+
tickEnd() {
|
|
1834
|
+
if (!this._isRunning) {
|
|
1835
|
+
Logger.warn("You have to call tickStart before tickEnd");
|
|
1836
|
+
return null;
|
|
1837
|
+
}
|
|
1838
|
+
this._internalStop();
|
|
1839
|
+
if (!this._dataOnStart) {
|
|
1840
|
+
Logger.warn("Delay was too short between tickStart and tickEnd or RelativeAttitudeProvider cannot be retrieved.");
|
|
1841
|
+
return null;
|
|
1842
|
+
}
|
|
1843
|
+
const dataOnEnd = RelativeAttitudeFromBrowser$1.lastEvent;
|
|
1844
|
+
return geo.Attitude.diff(this._dataOnStart, dataOnEnd);
|
|
1845
|
+
}
|
|
1846
|
+
_internalStop() {
|
|
1847
|
+
RelativeAttitudeFromBrowser$1.removeEventListener(this._providerId);
|
|
1848
|
+
delete this._providerId;
|
|
1849
|
+
this._isRunning = false;
|
|
1850
|
+
}
|
|
1851
|
+
release() {
|
|
1852
|
+
if (this._isRunning) {
|
|
1853
|
+
this._internalStop();
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
const _MissingPoleStarError = class _MissingPoleStarError extends Error {
|
|
1858
|
+
constructor(message) {
|
|
1859
|
+
super(message || _MissingPoleStarError.DEFAULT_MESSAGE);
|
|
1860
|
+
}
|
|
1861
|
+
};
|
|
1862
|
+
__publicField(_MissingPoleStarError, "DEFAULT_MESSAGE", "PoleStar is missing");
|
|
1863
|
+
let MissingPoleStarError = _MissingPoleStarError;
|
|
1864
|
+
class PoleStarProvider extends Provider {
|
|
1865
|
+
constructor() {
|
|
1866
|
+
super();
|
|
1867
|
+
__publicField(this, "getName", () => "PoleStar");
|
|
1868
|
+
this.addMethodsToNativeJsProvider();
|
|
1869
|
+
}
|
|
1870
|
+
availability() {
|
|
1871
|
+
try {
|
|
1872
|
+
this.nativeProvider.checkAvailability();
|
|
1873
|
+
return Promise.resolve();
|
|
1874
|
+
} catch (e) {
|
|
1875
|
+
return Promise.resolve(e);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
setApiKey(apiKey) {
|
|
1879
|
+
this.nativeProvider.setApiKey(apiKey);
|
|
1880
|
+
}
|
|
1881
|
+
start() {
|
|
1882
|
+
this.nativeProvider.start();
|
|
1883
|
+
}
|
|
1884
|
+
stop() {
|
|
1885
|
+
this.nativeProvider.stop();
|
|
1886
|
+
}
|
|
1887
|
+
get nativeProvider() {
|
|
1888
|
+
if (!this.nativeInterface) {
|
|
1889
|
+
throw new MissingNativeInterfaceError();
|
|
1890
|
+
}
|
|
1891
|
+
const nativeProvider = this.nativeInterface.getPoleStarProvider();
|
|
1892
|
+
if (!nativeProvider) {
|
|
1893
|
+
throw new MissingPoleStarError();
|
|
1894
|
+
}
|
|
1895
|
+
return nativeProvider;
|
|
1896
|
+
}
|
|
1897
|
+
addMethodsToNativeJsProvider() {
|
|
1898
|
+
if (!this.nativeJsInterface) {
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
this.nativeJsInterface.polestar = {
|
|
1902
|
+
callbackError: (errorMessage) => this.notifyError(new Error(errorMessage)),
|
|
1903
|
+
callbackPosition: (jsonString) => {
|
|
1904
|
+
const json = JSON.parse(jsonString);
|
|
1905
|
+
const timestamp = utils.TimeUtils.unixTimestampToPreciseTime(json.time) / 1e3;
|
|
1906
|
+
const position = new AbsolutePosition(
|
|
1907
|
+
json.lat,
|
|
1908
|
+
json.lng,
|
|
1909
|
+
Constants.DEFAULT_ALTITUDE,
|
|
1910
|
+
json.alt / 5,
|
|
1911
|
+
timestamp,
|
|
1912
|
+
json.accuracy,
|
|
1913
|
+
maths.deg2rad(json.bearing)
|
|
1914
|
+
);
|
|
1915
|
+
this.notify(position);
|
|
1916
|
+
}
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
const PoleStarProvider$1 = new PoleStarProvider();
|
|
1921
|
+
const _VpsProvider = class _VpsProvider extends Provider {
|
|
1922
|
+
constructor() {
|
|
1923
|
+
super(...arguments);
|
|
1924
|
+
__publicField(this, "_relativeRotationCalc");
|
|
1925
|
+
__publicField(this, "_serverError", false);
|
|
1926
|
+
__publicField(this, "_cameraError", false);
|
|
1927
|
+
__publicField(this, "_camera", null);
|
|
1928
|
+
__publicField(this, "_endpoint", null);
|
|
1929
|
+
__publicField(this, "_inclinationProviderId");
|
|
1930
|
+
__publicField(this, "_minInclinationForRequest", _VpsProvider.DEFAULT_MIN_INCLINATION_FOR_REQUEST);
|
|
1931
|
+
__publicField(this, "_waitTimeMinInclinationForRequest", _VpsProvider.DEFAULT_WAIT_TIME_MIN_INCLINATION_FOR_REQUEST);
|
|
1932
|
+
__publicField(this, "_useCoarsePose", _VpsProvider.DEFAULT_USE_COARSE_POSE);
|
|
1933
|
+
__publicField(this, "getName", () => "Vps");
|
|
1934
|
+
__publicField(this, "availability", () => camera.Camera.checkAvailability());
|
|
1935
|
+
__publicField(this, "_onCameraDetected", ({ camera: camera2 }) => {
|
|
1936
|
+
if (this._camera) {
|
|
1937
|
+
Logger.warn("It seems that more than 1 camera has been detected for VPS. Taking the first...");
|
|
1938
|
+
}
|
|
1939
|
+
this._useCamera(camera2);
|
|
1940
|
+
});
|
|
1941
|
+
__publicField(this, "_onCameraRemoved", () => {
|
|
1942
|
+
if (this._camera) {
|
|
1943
|
+
this._camera.off("started", this._internalStart);
|
|
1944
|
+
this._camera.off("stopped", this._internalStop);
|
|
1945
|
+
} else {
|
|
1946
|
+
Logger.warn("There is no previously detected camera but once has stopped");
|
|
1947
|
+
}
|
|
1948
|
+
this._camera = null;
|
|
1949
|
+
});
|
|
1950
|
+
__publicField(this, "_internalStart", async () => {
|
|
1951
|
+
var _a, _b;
|
|
1952
|
+
if (!this._endpoint) {
|
|
1953
|
+
this.notifyError(new Error("VPS endpoint has not been set before calling start()"));
|
|
1954
|
+
return;
|
|
1955
|
+
}
|
|
1956
|
+
let lastRequestTime = null;
|
|
1957
|
+
const isProviderStopped = () => this.state === "stopped";
|
|
1958
|
+
while (!isProviderStopped()) {
|
|
1959
|
+
if (lastRequestTime !== null) {
|
|
1960
|
+
const diffTime = utils.TimeUtils.preciseTime() - lastRequestTime;
|
|
1961
|
+
const timeToWait = Math.max(0, _VpsProvider.MIN_TIME_BETWEEN_TWO_REQUESTS - diffTime);
|
|
1962
|
+
await new Promise((resolve) => setTimeout(resolve, timeToWait));
|
|
1963
|
+
}
|
|
1964
|
+
lastRequestTime = utils.TimeUtils.preciseTime();
|
|
1965
|
+
if (isProviderStopped() || !this._camera || this._camera.state !== "started") {
|
|
1966
|
+
break;
|
|
1967
|
+
}
|
|
1968
|
+
const inclination = InclinationProvider$1.lastEvent ? InclinationProvider$1.lastEvent : null;
|
|
1969
|
+
if (inclination !== null && inclination < this._minInclinationForRequest) {
|
|
1970
|
+
await new Promise((resolve) => setTimeout(resolve, this._waitTimeMinInclinationForRequest));
|
|
1971
|
+
continue;
|
|
1972
|
+
}
|
|
1973
|
+
(_a = this._relativeRotationCalc) == null ? void 0 : _a.tickStart();
|
|
1974
|
+
const image = await this._camera.currentImage;
|
|
1975
|
+
if (!image) {
|
|
1976
|
+
continue;
|
|
1977
|
+
}
|
|
1978
|
+
let coarsePose = null;
|
|
1979
|
+
const bestCoarsePosition = AbsolutePositionProvider$1.getBestPositionEvent(GnssWifiProvider$1.lastEvent, PoleStarProvider$1.lastEvent);
|
|
1980
|
+
if (this._useCoarsePose && (bestCoarsePosition || AbsoluteAttitudeProvider$1.lastEvent)) {
|
|
1981
|
+
coarsePose = {
|
|
1982
|
+
...bestCoarsePosition && { position: bestCoarsePosition },
|
|
1983
|
+
...AbsoluteAttitudeProvider$1.lastEvent && { attitude: AbsoluteAttitudeProvider$1.lastEvent }
|
|
1984
|
+
};
|
|
1985
|
+
}
|
|
1986
|
+
const res = await ImageRelocalization.relocalize(this._endpoint, image, null, coarsePose);
|
|
1987
|
+
if (!res || !res.success) {
|
|
1988
|
+
continue;
|
|
1989
|
+
}
|
|
1990
|
+
const enuToCameraRot = res.attitude.quaternion;
|
|
1991
|
+
const enuToSmartphoneRot = maths.Quaternion.multiply(
|
|
1992
|
+
enuToCameraRot,
|
|
1993
|
+
_VpsProvider.CAMERA_TO_SMARTPHONE_ROT
|
|
1994
|
+
);
|
|
1995
|
+
const deviceQuaternion = maths.Quaternion.multiply(
|
|
1996
|
+
maths.Quaternion.fromAxisAngle([0, 0, 1], maths.deg2rad(window.orientation || 0)),
|
|
1997
|
+
enuToSmartphoneRot
|
|
1998
|
+
);
|
|
1999
|
+
const diffAttitude = ((_b = this._relativeRotationCalc) == null ? void 0 : _b.tickEnd()) || new geo.Attitude([1, 0, 0, 0]);
|
|
2000
|
+
const deviceQuaternionWithRelOffset = maths.Quaternion.multiply(
|
|
2001
|
+
deviceQuaternion,
|
|
2002
|
+
diffAttitude.quaternion
|
|
2003
|
+
);
|
|
2004
|
+
const attitude = new AbsoluteAttitude(
|
|
2005
|
+
deviceQuaternionWithRelOffset,
|
|
2006
|
+
res.attitude.time,
|
|
2007
|
+
res.attitude.accuracy
|
|
2008
|
+
);
|
|
2009
|
+
const devicePosition = res.position.clone();
|
|
2010
|
+
if (devicePosition.accuracy === null) {
|
|
2011
|
+
devicePosition.accuracy = 5;
|
|
2012
|
+
}
|
|
2013
|
+
if (isProviderStopped()) {
|
|
2014
|
+
break;
|
|
2015
|
+
}
|
|
2016
|
+
this.notify({
|
|
2017
|
+
absoluteAttitude: attitude,
|
|
2018
|
+
absolutePosition: devicePosition
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
});
|
|
2022
|
+
__publicField(this, "_internalStop", () => {
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
2025
|
+
start() {
|
|
2026
|
+
this._inclinationProviderId = InclinationProvider$1.addEventListener();
|
|
2027
|
+
this._relativeRotationCalc = new RelativeRotationCalc();
|
|
2028
|
+
camera.SharedCameras.on("added", this._onCameraDetected);
|
|
2029
|
+
camera.SharedCameras.on("removed", this._onCameraRemoved);
|
|
2030
|
+
if (camera.SharedCameras.list.length) {
|
|
2031
|
+
if (camera.SharedCameras.list.length > 1) {
|
|
2032
|
+
Logger.warn("It seems that more than 1 camera has been detected for VPS. Taking the first...");
|
|
2033
|
+
}
|
|
2034
|
+
this._useCamera(camera.SharedCameras.list[0].camera);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
stop() {
|
|
2038
|
+
var _a;
|
|
2039
|
+
InclinationProvider$1.removeEventListener(this._inclinationProviderId);
|
|
2040
|
+
(_a = this._relativeRotationCalc) == null ? void 0 : _a.release();
|
|
2041
|
+
camera.SharedCameras.off("added", this._onCameraDetected);
|
|
2042
|
+
camera.SharedCameras.off("removed", this._onCameraRemoved);
|
|
2043
|
+
this._camera = null;
|
|
2044
|
+
}
|
|
2045
|
+
_useCamera(camera2) {
|
|
2046
|
+
this._camera = camera2;
|
|
2047
|
+
camera2.on("started", this._internalStart);
|
|
2048
|
+
camera2.on("stopped", this._internalStop);
|
|
2049
|
+
if (camera2.state === "started") {
|
|
2050
|
+
this._internalStart();
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
get endpoint() {
|
|
2054
|
+
return this._endpoint;
|
|
2055
|
+
}
|
|
2056
|
+
set endpoint(endpoint) {
|
|
2057
|
+
this._endpoint = endpoint;
|
|
2058
|
+
}
|
|
2059
|
+
get minInclinationForRequest() {
|
|
2060
|
+
return this._minInclinationForRequest;
|
|
2061
|
+
}
|
|
2062
|
+
set minInclinationForRequest(minInclinationForRequest) {
|
|
2063
|
+
this._minInclinationForRequest = minInclinationForRequest;
|
|
2064
|
+
}
|
|
2065
|
+
get waitTimeMinInclinationForRequest() {
|
|
2066
|
+
return this._waitTimeMinInclinationForRequest;
|
|
2067
|
+
}
|
|
2068
|
+
set waitTimeMinInclinationForRequest(waitTimeMinInclinationForRequest) {
|
|
2069
|
+
this._waitTimeMinInclinationForRequest = waitTimeMinInclinationForRequest;
|
|
2070
|
+
}
|
|
2071
|
+
get useCoarsePose() {
|
|
2072
|
+
return this._useCoarsePose;
|
|
2073
|
+
}
|
|
2074
|
+
set useCoarsePose(useCoarsePose) {
|
|
2075
|
+
this._useCoarsePose = useCoarsePose;
|
|
2076
|
+
}
|
|
2077
|
+
};
|
|
2078
|
+
__publicField(_VpsProvider, "MIN_TIME_BETWEEN_TWO_REQUESTS", 1e3);
|
|
2079
|
+
// in ms
|
|
2080
|
+
__publicField(_VpsProvider, "DEFAULT_MIN_INCLINATION_FOR_REQUEST", maths.deg2rad(60));
|
|
2081
|
+
// in radians
|
|
2082
|
+
__publicField(_VpsProvider, "DEFAULT_WAIT_TIME_MIN_INCLINATION_FOR_REQUEST", 200);
|
|
2083
|
+
// in ms
|
|
2084
|
+
__publicField(_VpsProvider, "DEFAULT_USE_COARSE_POSE", true);
|
|
2085
|
+
__publicField(_VpsProvider, "CAMERA_TO_SMARTPHONE_ROT", maths.Quaternion.fromAxisAngle([1, 0, 0], Math.PI));
|
|
2086
|
+
let VpsProvider = _VpsProvider;
|
|
2087
|
+
const VpsProvider$1 = new VpsProvider();
|
|
2088
|
+
const _AbsolutePositionProvider = class _AbsolutePositionProvider extends Provider {
|
|
2089
|
+
constructor() {
|
|
2090
|
+
super(...arguments);
|
|
2091
|
+
__publicField(this, "_polestarProviderId");
|
|
2092
|
+
__publicField(this, "_vpsProviderId");
|
|
2093
|
+
__publicField(this, "_gnssWifiProviderId");
|
|
2094
|
+
__publicField(this, "_relativePositionProviderId");
|
|
2095
|
+
__publicField(this, "_mapMatchingHandlerId");
|
|
2096
|
+
__publicField(this, "useAllAbsolutePositions", false);
|
|
2097
|
+
__publicField(this, "_waitUntilNextVpsPosition", false);
|
|
2098
|
+
__publicField(this, "_lastPolestarFix", null);
|
|
2099
|
+
__publicField(this, "getName", () => "AbsolutePosition");
|
|
2100
|
+
}
|
|
2101
|
+
availability() {
|
|
2102
|
+
return AvailabilityHelper.some([
|
|
2103
|
+
GeoRelativePositionProvider$1.getAvailability(),
|
|
2104
|
+
GnssWifiProvider$1.getAvailability(),
|
|
2105
|
+
...ProvidersOptions.hasPoleStar ? [PoleStarProvider$1.getAvailability()] : [],
|
|
2106
|
+
VpsProvider$1.getAvailability()
|
|
2107
|
+
]);
|
|
2108
|
+
}
|
|
2109
|
+
start() {
|
|
2110
|
+
GeoRelativePositionProvider$1.getAvailability().then((error) => {
|
|
2111
|
+
if (!error) {
|
|
2112
|
+
this._relativePositionProviderId = GeoRelativePositionProvider$1.addEventListener(
|
|
2113
|
+
(e) => this._onRelativePosition(e)
|
|
2114
|
+
);
|
|
2115
|
+
}
|
|
2116
|
+
});
|
|
2117
|
+
this._gnssWifiProviderId = GnssWifiProvider$1.addEventListener(
|
|
2118
|
+
(event) => {
|
|
2119
|
+
const clone = event.clone();
|
|
2120
|
+
clone.bearing = null;
|
|
2121
|
+
this._onAbsolutePosition(clone, false);
|
|
2122
|
+
}
|
|
2123
|
+
);
|
|
2124
|
+
this._vpsProviderId = VpsProvider$1.addEventListener(
|
|
2125
|
+
(event) => this._onAbsolutePosition(event.absolutePosition),
|
|
2126
|
+
this.notifyError,
|
|
2127
|
+
false
|
|
2128
|
+
);
|
|
2129
|
+
if (ProvidersOptions.hasPoleStar) {
|
|
2130
|
+
this._polestarProviderId = PoleStarProvider$1.addEventListener((polestarPositionEvent) => {
|
|
2131
|
+
var _a;
|
|
2132
|
+
this._lastPolestarFix = utils.TimeUtils.preciseTime();
|
|
2133
|
+
const psPositionUsed = this._onAbsolutePosition(polestarPositionEvent);
|
|
2134
|
+
if (!psPositionUsed && ((_a = this.lastEvent) == null ? void 0 : _a.level) === null) {
|
|
2135
|
+
const lastPositionWithLevel = this.lastEvent.clone();
|
|
2136
|
+
lastPositionWithLevel.level = polestarPositionEvent.level;
|
|
2137
|
+
this.notify(lastPositionWithLevel);
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
this._mapMatchingHandlerId = MapMatchingHandler$1.addEventListener();
|
|
2142
|
+
}
|
|
2143
|
+
/**
|
|
2144
|
+
* @override
|
|
2145
|
+
*/
|
|
2146
|
+
stop() {
|
|
2147
|
+
if (this._relativePositionProviderId) {
|
|
2148
|
+
GeoRelativePositionProvider$1.removeEventListener(this._relativePositionProviderId);
|
|
2149
|
+
delete this._relativePositionProviderId;
|
|
2150
|
+
}
|
|
2151
|
+
if (this._gnssWifiProviderId) {
|
|
2152
|
+
GnssWifiProvider$1.removeEventListener(this._gnssWifiProviderId);
|
|
2153
|
+
delete this._gnssWifiProviderId;
|
|
2154
|
+
}
|
|
2155
|
+
if (this._vpsProviderId) {
|
|
2156
|
+
VpsProvider$1.removeEventListener(this._vpsProviderId);
|
|
2157
|
+
delete this._vpsProviderId;
|
|
2158
|
+
}
|
|
2159
|
+
if (this._polestarProviderId) {
|
|
2160
|
+
PoleStarProvider$1.removeEventListener(this._polestarProviderId);
|
|
2161
|
+
delete this._polestarProviderId;
|
|
2162
|
+
}
|
|
2163
|
+
MapMatchingHandler$1.removeEventListener(this._mapMatchingHandlerId);
|
|
2164
|
+
}
|
|
2165
|
+
_shouldTakeIntoAccountNewAbsolutePosition(newPositionEvent, canContainLevel = true) {
|
|
2166
|
+
const newPosition = newPositionEvent;
|
|
2167
|
+
const lastPosition = this.lastEvent || null;
|
|
2168
|
+
if (!lastPosition) {
|
|
2169
|
+
return true;
|
|
2170
|
+
}
|
|
2171
|
+
const isBetterEnough = newPosition.accuracy * _AbsolutePositionProvider.ACCURACY_RELOC_RATIO <= lastPosition.accuracy;
|
|
2172
|
+
if (isBetterEnough) {
|
|
2173
|
+
return true;
|
|
2174
|
+
}
|
|
2175
|
+
const isFarEnough = lastPosition.distanceTo(newPosition) > lastPosition.accuracy + newPosition.accuracy;
|
|
2176
|
+
if (isFarEnough) {
|
|
2177
|
+
return true;
|
|
2178
|
+
}
|
|
2179
|
+
const isFarEnoughAndAccuracyIsBetter = isFarEnough && newPosition.accuracy <= lastPosition.accuracy;
|
|
2180
|
+
if (isBetterEnough && isFarEnoughAndAccuracyIsBetter) {
|
|
2181
|
+
return true;
|
|
2182
|
+
}
|
|
2183
|
+
const isChangingLevel = canContainLevel && !geo.Level.equals(newPosition.level, lastPosition.level);
|
|
2184
|
+
if (isChangingLevel) {
|
|
2185
|
+
return true;
|
|
2186
|
+
}
|
|
2187
|
+
return false;
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* @returns if input position is used by the system (true = used, false = discarded)
|
|
2191
|
+
*/
|
|
2192
|
+
_onAbsolutePosition(positionEvent, canContainLevel = true) {
|
|
2193
|
+
if (!this._shouldTakeIntoAccountNewAbsolutePosition(positionEvent, canContainLevel) && !this.useAllAbsolutePositions) {
|
|
2194
|
+
return false;
|
|
2195
|
+
}
|
|
2196
|
+
const newPosition = positionEvent.clone();
|
|
2197
|
+
const lastPosition = this.lastEvent ? this.lastEvent : null;
|
|
2198
|
+
if (lastPosition) {
|
|
2199
|
+
if (!canContainLevel) {
|
|
2200
|
+
newPosition.level = lastPosition.level;
|
|
2201
|
+
}
|
|
2202
|
+
if (newPosition.bearing === null) {
|
|
2203
|
+
newPosition.bearing = lastPosition.bearing;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
if (!MapMatchingHandler$1.canUseMapMatching()) {
|
|
2207
|
+
this.notify(newPosition);
|
|
2208
|
+
return true;
|
|
2209
|
+
}
|
|
2210
|
+
return MapMatchingHandler$1.notifyPositionFromAbsolute(newPosition);
|
|
2211
|
+
}
|
|
2212
|
+
/**
|
|
2213
|
+
* @returns if input position is used by the system (true = used, false = discarded)
|
|
2214
|
+
*/
|
|
2215
|
+
_onRelativePosition(relativeEvent) {
|
|
2216
|
+
if (!this.lastEvent || this._waitUntilNextVpsPosition) {
|
|
2217
|
+
return false;
|
|
2218
|
+
}
|
|
2219
|
+
const lastPosition = this.lastEvent;
|
|
2220
|
+
const offsetPos = relativeEvent;
|
|
2221
|
+
const dist = Math.sqrt(offsetPos.x ** 2 + offsetPos.y ** 2);
|
|
2222
|
+
const bearing = Math.atan2(offsetPos.x, offsetPos.y);
|
|
2223
|
+
const alt = lastPosition.alt !== null ? offsetPos.z : null;
|
|
2224
|
+
const newPosition = lastPosition.destinationPoint(dist, bearing, alt);
|
|
2225
|
+
newPosition.bearing = offsetPos.bearing;
|
|
2226
|
+
newPosition.time = offsetPos.time;
|
|
2227
|
+
newPosition.accuracy += offsetPos.accuracy;
|
|
2228
|
+
if (!MapMatchingHandler$1.canUseMapMatching()) {
|
|
2229
|
+
this.notify(newPosition);
|
|
2230
|
+
return true;
|
|
2231
|
+
}
|
|
2232
|
+
return MapMatchingHandler$1.notifyPositionFromRelative(newPosition);
|
|
2233
|
+
}
|
|
2234
|
+
feed(data) {
|
|
2235
|
+
let newPositionEvent;
|
|
2236
|
+
if (data instanceof geo.UserPosition) {
|
|
2237
|
+
if (data.time === null) {
|
|
2238
|
+
throw Error("the time of the position is not defined");
|
|
2239
|
+
}
|
|
2240
|
+
if (data.accuracy === null) {
|
|
2241
|
+
throw Error("the accuracy of the position is not defined");
|
|
2242
|
+
}
|
|
2243
|
+
newPositionEvent = data;
|
|
2244
|
+
} else {
|
|
2245
|
+
throw new Error("data is nor an UserPosition or an AbsolutePositionEvent");
|
|
2246
|
+
}
|
|
2247
|
+
if (!_AbsolutePositionProvider.USE_MM_FOR_FEED || !MapMatchingHandler$1.canUseMapMatching()) {
|
|
2248
|
+
this.notify(newPositionEvent);
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
MapMatchingHandler$1.notifyPositionFromFeed(newPositionEvent);
|
|
2252
|
+
}
|
|
2253
|
+
getBestPositionEvent(...absolutePositionEvents) {
|
|
2254
|
+
return absolutePositionEvents.reduce((best, value) => {
|
|
2255
|
+
if (!best) {
|
|
2256
|
+
return value;
|
|
2257
|
+
}
|
|
2258
|
+
if (!value || value.accuracy === null || value.time === null) {
|
|
2259
|
+
return best;
|
|
2260
|
+
}
|
|
2261
|
+
const { accuracy: curAccuracy, time: curTime } = value;
|
|
2262
|
+
const { accuracy: bestAccuracy, time: bestTime } = best;
|
|
2263
|
+
return curAccuracy < bestAccuracy + 1.3888 * (curTime - bestTime) ? value : best;
|
|
2264
|
+
}, null);
|
|
2265
|
+
}
|
|
2266
|
+
};
|
|
2267
|
+
// Use the new absolute position if its accuracy is at least x times better than the last one.
|
|
2268
|
+
__publicField(_AbsolutePositionProvider, "ACCURACY_RELOC_RATIO", 1);
|
|
2269
|
+
// or 1.5
|
|
2270
|
+
__publicField(_AbsolutePositionProvider, "USE_MM_FOR_FEED", true);
|
|
2271
|
+
let AbsolutePositionProvider = _AbsolutePositionProvider;
|
|
2272
|
+
const AbsolutePositionProvider$1 = new AbsolutePositionProvider();
|
|
2273
|
+
class AbsoluteAttitudeFromBrowser extends Provider {
|
|
2274
|
+
constructor() {
|
|
2275
|
+
super(...arguments);
|
|
2276
|
+
// from http://tyrex.inria.fr/mobile/benchmarks-attitude/
|
|
2277
|
+
__publicField(this, "DEFAULT_ACCURACY", maths.deg2rad(15));
|
|
2278
|
+
__publicField(this, "absolutePositionProviderId");
|
|
2279
|
+
__publicField(this, "absolutePositionEvent");
|
|
2280
|
+
__publicField(this, "declinationQuaternion");
|
|
2281
|
+
__publicField(this, "magQuaternion");
|
|
2282
|
+
__publicField(this, "magQuaternionTimestamp");
|
|
2283
|
+
__publicField(this, "iosPreviousQuat");
|
|
2284
|
+
__publicField(this, "iosIsSkyMode", null);
|
|
2285
|
+
__publicField(this, "getName", () => "AbsoluteAttitudeFromBrowser");
|
|
2286
|
+
__publicField(this, "onDeviceOrientationChromeEvent", (e) => {
|
|
2287
|
+
this.magQuaternionTimestamp = e.timeStamp / 1e3;
|
|
2288
|
+
if (typeof e.alpha !== "number" || typeof e.beta !== "number" || typeof e.gamma !== "number") {
|
|
2289
|
+
this.notifyError(new MissingSensorError().from("deviceorientationabsolute"));
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
this.magQuaternion = maths.Rotations.eulerToQuaternionZXYDegrees(
|
|
2293
|
+
[e.alpha, e.beta, e.gamma]
|
|
2294
|
+
);
|
|
2295
|
+
this.compute();
|
|
2296
|
+
});
|
|
2297
|
+
__publicField(this, "onDeviceOrientationSafariEvent", (e) => {
|
|
2298
|
+
this.magQuaternionTimestamp = e.timeStamp / 1e3;
|
|
2299
|
+
if (typeof e.beta !== "number" || typeof e.gamma !== "number") {
|
|
2300
|
+
this.notifyError(new MissingSensorError().from("deviceorientation"));
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
if (typeof e.webkitCompassHeading !== "number") {
|
|
2304
|
+
this.notifyError(new MissingMagnetometerError().from("deviceorientation"));
|
|
2305
|
+
return;
|
|
2306
|
+
}
|
|
2307
|
+
let alpha;
|
|
2308
|
+
const [qw, qx, qy, qz] = maths.Rotations.eulerToQuaternionZXYDegrees([e.webkitCompassHeading, e.beta, e.gamma]);
|
|
2309
|
+
const groundAngle = maths.rad2deg(Math.acos(qw ** 2 - qx ** 2 - qy ** 2 + qz ** 2));
|
|
2310
|
+
let isSkyMode = null;
|
|
2311
|
+
if (groundAngle > 136) {
|
|
2312
|
+
isSkyMode = true;
|
|
2313
|
+
} else if (groundAngle < 134) {
|
|
2314
|
+
isSkyMode = false;
|
|
2315
|
+
} else if (this.iosPreviousQuat && this.iosIsSkyMode !== null) {
|
|
2316
|
+
isSkyMode = maths.Quaternion.distance([qw, qx, qy, qz], this.iosPreviousQuat) < 0.5 ? this.iosIsSkyMode : !this.iosIsSkyMode;
|
|
2317
|
+
}
|
|
2318
|
+
this.iosPreviousQuat = [qw, qx, qy, qz];
|
|
2319
|
+
this.iosIsSkyMode = isSkyMode;
|
|
2320
|
+
if (typeof isSkyMode === "undefined") {
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
if (isSkyMode) {
|
|
2324
|
+
alpha = 180 - e.webkitCompassHeading;
|
|
2325
|
+
} else {
|
|
2326
|
+
alpha = AbsoluteAttitudeFromBrowser.webkitCompassToHeading(
|
|
2327
|
+
e.webkitCompassHeading,
|
|
2328
|
+
e.beta,
|
|
2329
|
+
e.gamma
|
|
2330
|
+
);
|
|
2331
|
+
}
|
|
2332
|
+
this.magQuaternion = maths.Rotations.eulerToQuaternionZXYDegrees([alpha, e.beta, e.gamma]);
|
|
2333
|
+
this.compute();
|
|
2334
|
+
});
|
|
2335
|
+
/**
|
|
2336
|
+
* Initialized declination quaternion using current position.
|
|
2337
|
+
* This method should be theoretically called every time the user moves.
|
|
2338
|
+
* But in reality declination does not change as much.
|
|
2339
|
+
*/
|
|
2340
|
+
__publicField(this, "onAbsolutePositionEvent", (position) => {
|
|
2341
|
+
this.absolutePositionEvent = position;
|
|
2342
|
+
const wmmResult = geomag__namespace.field(position.lat, position.lng);
|
|
2343
|
+
this.declinationQuaternion = maths.Quaternion.fromAxisAngle([0, 0, 1], -maths.deg2rad(wmmResult.declination));
|
|
2344
|
+
AbsolutePositionProvider$1.removeEventListener(this.absolutePositionProviderId);
|
|
2345
|
+
delete this.absolutePositionProviderId;
|
|
2346
|
+
this.compute();
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
availability() {
|
|
2350
|
+
return utils.BrowserUtils.isMobile ? Promise.resolve() : Promise.resolve(new AskImuOnDesktopError());
|
|
2351
|
+
}
|
|
2352
|
+
start() {
|
|
2353
|
+
const subscribe = () => {
|
|
2354
|
+
switch (utils.BrowserUtils.getName()) {
|
|
2355
|
+
case utils.Browser.CHROME:
|
|
2356
|
+
window.addEventListener(
|
|
2357
|
+
"deviceorientationabsolute",
|
|
2358
|
+
this.onDeviceOrientationChromeEvent,
|
|
2359
|
+
true
|
|
2360
|
+
);
|
|
2361
|
+
break;
|
|
2362
|
+
case utils.Browser.SAFARI:
|
|
2363
|
+
case utils.Browser.IOS_WEBVIEW:
|
|
2364
|
+
window.addEventListener(
|
|
2365
|
+
"deviceorientation",
|
|
2366
|
+
this.onDeviceOrientationSafariEvent,
|
|
2367
|
+
true
|
|
2368
|
+
);
|
|
2369
|
+
break;
|
|
2370
|
+
}
|
|
2371
|
+
};
|
|
2372
|
+
const requestPermission = DeviceOrientationEvent.requestPermission || void 0;
|
|
2373
|
+
if (requestPermission) {
|
|
2374
|
+
requestPermission().then((response) => {
|
|
2375
|
+
if (response !== "granted") {
|
|
2376
|
+
throw new Error("Permission not granted");
|
|
2377
|
+
}
|
|
2378
|
+
subscribe();
|
|
2379
|
+
}).catch(this.notifyError);
|
|
2380
|
+
} else {
|
|
2381
|
+
subscribe();
|
|
2382
|
+
}
|
|
2383
|
+
const lastAbsolutePosition = AbsolutePositionProvider$1.lastEvent;
|
|
2384
|
+
if (lastAbsolutePosition) {
|
|
2385
|
+
this.onAbsolutePositionEvent(lastAbsolutePosition);
|
|
2386
|
+
} else {
|
|
2387
|
+
this.absolutePositionProviderId = AbsolutePositionProvider$1.addEventListener(
|
|
2388
|
+
this.onAbsolutePositionEvent,
|
|
2389
|
+
this.notifyError,
|
|
2390
|
+
false
|
|
2391
|
+
);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
stop() {
|
|
2395
|
+
switch (utils.BrowserUtils.getName()) {
|
|
2396
|
+
case utils.Browser.CHROME:
|
|
2397
|
+
window.removeEventListener(
|
|
2398
|
+
"deviceorientationabsolute",
|
|
2399
|
+
this.onDeviceOrientationChromeEvent,
|
|
2400
|
+
true
|
|
2401
|
+
);
|
|
2402
|
+
break;
|
|
2403
|
+
case utils.Browser.SAFARI:
|
|
2404
|
+
case utils.Browser.IOS_WEBVIEW:
|
|
2405
|
+
window.removeEventListener(
|
|
2406
|
+
"deviceorientation",
|
|
2407
|
+
this.onDeviceOrientationSafariEvent,
|
|
2408
|
+
true
|
|
2409
|
+
);
|
|
2410
|
+
break;
|
|
2411
|
+
}
|
|
2412
|
+
AbsolutePositionProvider$1.removeEventListener(this.absolutePositionProviderId);
|
|
2413
|
+
}
|
|
2414
|
+
compute() {
|
|
2415
|
+
if (!this.declinationQuaternion || !this.magQuaternion || !this.absolutePositionEvent) {
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
const trueQuaternion = maths.Quaternion.multiply(this.declinationQuaternion, this.magQuaternion);
|
|
2419
|
+
const attitude = new AbsoluteAttitude(trueQuaternion, this.magQuaternionTimestamp, this.DEFAULT_ACCURACY);
|
|
2420
|
+
this.notify(attitude);
|
|
2421
|
+
}
|
|
2422
|
+
static webkitCompassToHeading(_webkitCompassHeading, _beta, _gamma) {
|
|
2423
|
+
const webkitCompassHeading = maths.deg2rad(_webkitCompassHeading);
|
|
2424
|
+
const beta = maths.deg2rad(_beta);
|
|
2425
|
+
const gamma = maths.deg2rad(_gamma);
|
|
2426
|
+
const c1 = Math.cos(webkitCompassHeading / 2);
|
|
2427
|
+
const c2 = Math.cos(beta / 2);
|
|
2428
|
+
const c3 = Math.cos(gamma / 2);
|
|
2429
|
+
const s1 = Math.sin(webkitCompassHeading / 2);
|
|
2430
|
+
const s2 = Math.sin(beta / 2);
|
|
2431
|
+
const s3 = Math.sin(gamma / 2);
|
|
2432
|
+
const qw = c1 * c2 * c3 - s1 * s2 * s3;
|
|
2433
|
+
const qz = s1 * c2 * c3 + c1 * s2 * s3;
|
|
2434
|
+
return maths.rad2deg(-2 * Math.atan(qz / qw));
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
const AbsoluteAttitudeFromBrowser$1 = new AbsoluteAttitudeFromBrowser();
|
|
2438
|
+
class RelativeAttitudeProvider extends Provider {
|
|
2439
|
+
constructor() {
|
|
2440
|
+
super(...arguments);
|
|
2441
|
+
__publicField(this, "arCoreMonitoringId");
|
|
2442
|
+
__publicField(this, "arCoreProviderId");
|
|
2443
|
+
__publicField(this, "inertialProviderId");
|
|
2444
|
+
__publicField(this, "getName", () => "RelativeAttitude");
|
|
2445
|
+
__publicField(this, "availability", () => RelativeAttitudeFromInertialProvider.getAvailability());
|
|
2446
|
+
__publicField(this, "listenInertial", () => {
|
|
2447
|
+
this.inertialProviderId = RelativeAttitudeFromInertialProvider.addEventListener(
|
|
2448
|
+
this.notify,
|
|
2449
|
+
this.notifyError
|
|
2450
|
+
);
|
|
2451
|
+
});
|
|
2452
|
+
__publicField(this, "unlistenInertial", () => {
|
|
2453
|
+
RelativeAttitudeFromInertialProvider.removeEventListener(this.inertialProviderId);
|
|
2454
|
+
});
|
|
2455
|
+
__publicField(this, "listenArCore", () => {
|
|
2456
|
+
this.arCoreProviderId = ArCoreProvider$1.addEventListener(
|
|
2457
|
+
(event) => this.notify(event.relativeAttitude),
|
|
2458
|
+
null,
|
|
2459
|
+
false
|
|
2460
|
+
);
|
|
2461
|
+
});
|
|
2462
|
+
__publicField(this, "unlistenArCore", () => {
|
|
2463
|
+
ArCoreProvider$1.removeEventListener(this.arCoreProviderId);
|
|
2464
|
+
});
|
|
2465
|
+
}
|
|
2466
|
+
start() {
|
|
2467
|
+
this.arCoreMonitoringId = ArCoreProvider$1.addMonitoringListener(
|
|
2468
|
+
() => {
|
|
2469
|
+
this.listenArCore();
|
|
2470
|
+
this.unlistenInertial();
|
|
2471
|
+
},
|
|
2472
|
+
() => {
|
|
2473
|
+
this.unlistenArCore();
|
|
2474
|
+
this.listenInertial();
|
|
2475
|
+
}
|
|
2476
|
+
);
|
|
2477
|
+
if (ArCoreProvider$1.state === "started") {
|
|
2478
|
+
this.listenArCore();
|
|
2479
|
+
} else {
|
|
2480
|
+
this.listenInertial();
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
/**
|
|
2484
|
+
* @override
|
|
2485
|
+
*/
|
|
2486
|
+
stop() {
|
|
2487
|
+
ArCoreProvider$1.removeMonitoringListener(this.arCoreMonitoringId);
|
|
2488
|
+
this.unlistenArCore();
|
|
2489
|
+
this.unlistenInertial();
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
const RelativeAttitudeProvider$1 = new RelativeAttitudeProvider();
|
|
2493
|
+
const _AbsoluteAttitudeProvider = class _AbsoluteAttitudeProvider extends Provider {
|
|
2494
|
+
constructor() {
|
|
2495
|
+
super(...arguments);
|
|
2496
|
+
// in radians;
|
|
2497
|
+
__publicField(this, "_absAttitudeFromBrowser");
|
|
2498
|
+
__publicField(this, "_vpsProviderId");
|
|
2499
|
+
__publicField(this, "fromBrowserProviderId");
|
|
2500
|
+
__publicField(this, "highRotationProviderId");
|
|
2501
|
+
__publicField(this, "inclinationProviderId");
|
|
2502
|
+
__publicField(this, "relativeAttitudeProviderId");
|
|
2503
|
+
__publicField(this, "_attitudeFromBrowserErrored", false);
|
|
2504
|
+
__publicField(this, "_attitudeFromRelativeErrored", false);
|
|
2505
|
+
/*
|
|
2506
|
+
* RELATIVE
|
|
2507
|
+
*/
|
|
2508
|
+
__publicField(this, "_relativeAttitude", null);
|
|
2509
|
+
__publicField(this, "_relativeAccuracy", 0);
|
|
2510
|
+
// in radians/s
|
|
2511
|
+
__publicField(this, "_lastForcedHeadingEvent");
|
|
2512
|
+
__publicField(this, "_relAbsQuat");
|
|
2513
|
+
__publicField(this, "_wasHighRotationInProgress", false);
|
|
2514
|
+
__publicField(this, "_timeFirstDivergence", null);
|
|
2515
|
+
__publicField(this, "_callbackMagCalibration");
|
|
2516
|
+
__publicField(this, "getName", () => "AbsoluteAttitude");
|
|
2517
|
+
__publicField(this, "_onError", (error) => {
|
|
2518
|
+
if (this._attitudeFromBrowserErrored && this._attitudeFromRelativeErrored) {
|
|
2519
|
+
this.notifyError(error);
|
|
2520
|
+
}
|
|
2521
|
+
});
|
|
2522
|
+
__publicField(this, "_forceHeadingForRelative", (absoluteHeadingEvent) => {
|
|
2523
|
+
if (this.lastEvent && absoluteHeadingEvent.accuracy > this.lastEvent.accuracy) {
|
|
2524
|
+
return;
|
|
2525
|
+
}
|
|
2526
|
+
const calcForceHeading = (relativeAttitude) => {
|
|
2527
|
+
const currentRelativeHeading = relativeAttitude.heading;
|
|
2528
|
+
this._relAbsQuat = maths.Quaternion.fromAxisAngle(
|
|
2529
|
+
[0, 0, 1],
|
|
2530
|
+
currentRelativeHeading - absoluteHeadingEvent.heading
|
|
2531
|
+
);
|
|
2532
|
+
this._relativeAccuracy = 0;
|
|
2533
|
+
this._lastForcedHeadingEvent = absoluteHeadingEvent;
|
|
2534
|
+
};
|
|
2535
|
+
if (this._relativeAttitude) {
|
|
2536
|
+
calcForceHeading(this._relativeAttitude);
|
|
2537
|
+
return;
|
|
2538
|
+
}
|
|
2539
|
+
const providerId = RelativeAttitudeProvider$1.addEventListener(
|
|
2540
|
+
(event) => {
|
|
2541
|
+
calcForceHeading(event);
|
|
2542
|
+
RelativeAttitudeProvider$1.removeEventListener(providerId);
|
|
2543
|
+
}
|
|
2544
|
+
);
|
|
2545
|
+
});
|
|
2546
|
+
__publicField(this, "_onRelativeAttitudeEvent", (event) => {
|
|
2547
|
+
var _a;
|
|
2548
|
+
const { quaternion, accuracy, time } = event;
|
|
2549
|
+
if (this._relativeAttitude) {
|
|
2550
|
+
this._relativeAccuracy += (time - this._relativeAttitude.time) * accuracy;
|
|
2551
|
+
}
|
|
2552
|
+
this._relativeAttitude = event;
|
|
2553
|
+
if (!this._lastForcedHeadingEvent || !this._relAbsQuat) {
|
|
2554
|
+
return;
|
|
2555
|
+
}
|
|
2556
|
+
const accuracyWithRelative = Math.min(
|
|
2557
|
+
(this._lastForcedHeadingEvent.accuracy || 0) + this._relativeAccuracy,
|
|
2558
|
+
Math.PI
|
|
2559
|
+
);
|
|
2560
|
+
const highRotationInProgress = HighRotationsProvider$1.isInProgress();
|
|
2561
|
+
let divergenceDetected = false;
|
|
2562
|
+
if (this._absAttitudeFromBrowser) {
|
|
2563
|
+
const {
|
|
2564
|
+
accuracy: accuracyWithAbsolute,
|
|
2565
|
+
heading: headingFromAbsolute
|
|
2566
|
+
} = this._absAttitudeFromBrowser;
|
|
2567
|
+
if (this._wasHighRotationInProgress && !highRotationInProgress) {
|
|
2568
|
+
this._forceHeadingForRelative(this._absAttitudeFromBrowser);
|
|
2569
|
+
} else if (accuracyWithAbsolute < accuracyWithRelative) {
|
|
2570
|
+
const relativeQuaternion = maths.Quaternion.multiply(this._relAbsQuat, quaternion);
|
|
2571
|
+
const relativeAttitude = new geo.Attitude(relativeQuaternion);
|
|
2572
|
+
const angle = Math.abs(maths.diffAngle(relativeAttitude.heading, headingFromAbsolute));
|
|
2573
|
+
const inclination = InclinationProvider$1.lastEvent;
|
|
2574
|
+
if (angle > _AbsoluteAttitudeProvider.REL_ABS_DIVERGENCE_ANGLE_THRESHOLD && inclination !== null && Math.abs(inclination - Math.PI / 4) > _AbsoluteAttitudeProvider.REL_ABS_DIVERGENCE_INCLINATION_THRESHOLD) {
|
|
2575
|
+
divergenceDetected = true;
|
|
2576
|
+
if (this._timeFirstDivergence !== null && time - this._timeFirstDivergence > _AbsoluteAttitudeProvider.REL_ABS_DIVERGENCE_TIME_THRESHOLD) {
|
|
2577
|
+
this._forceHeadingForRelative(this._absAttitudeFromBrowser);
|
|
2578
|
+
(_a = this._callbackMagCalibration) == null ? void 0 : _a.call(this, { angle });
|
|
2579
|
+
this._timeFirstDivergence = null;
|
|
2580
|
+
} else if (this._timeFirstDivergence === null) {
|
|
2581
|
+
this._timeFirstDivergence = time;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
if (!divergenceDetected) {
|
|
2587
|
+
this._timeFirstDivergence = null;
|
|
2588
|
+
}
|
|
2589
|
+
this._wasHighRotationInProgress = highRotationInProgress;
|
|
2590
|
+
const absoluteQuat = maths.Quaternion.multiply(this._relAbsQuat, quaternion);
|
|
2591
|
+
const attitude = new AbsoluteAttitude(absoluteQuat, time, accuracyWithRelative);
|
|
2592
|
+
this.notify(attitude);
|
|
2593
|
+
});
|
|
2594
|
+
__publicField(this, "_onAttitudeFromBrowser", (event) => {
|
|
2595
|
+
this._absAttitudeFromBrowser = event;
|
|
2596
|
+
if (!this._lastForcedHeadingEvent) {
|
|
2597
|
+
this._forceHeadingForRelative(event);
|
|
2598
|
+
return;
|
|
2599
|
+
}
|
|
2600
|
+
});
|
|
2601
|
+
__publicField(this, "_onAttitudeFromVps", (event) => {
|
|
2602
|
+
this._forceHeadingForRelative(event);
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
availability() {
|
|
2606
|
+
return AvailabilityHelper.some([
|
|
2607
|
+
AbsoluteAttitudeFromBrowser$1.getAvailability(),
|
|
2608
|
+
RelativeAttitudeProvider$1.getAvailability()
|
|
2609
|
+
]);
|
|
2610
|
+
}
|
|
2611
|
+
start() {
|
|
2612
|
+
this.fromBrowserProviderId = AbsoluteAttitudeFromBrowser$1.addEventListener(
|
|
2613
|
+
this._onAttitudeFromBrowser,
|
|
2614
|
+
(error) => {
|
|
2615
|
+
this._attitudeFromBrowserErrored = true;
|
|
2616
|
+
this._onError(error);
|
|
2617
|
+
}
|
|
2618
|
+
);
|
|
2619
|
+
this._vpsProviderId = VpsProvider$1.addEventListener(
|
|
2620
|
+
(event) => this._onAttitudeFromVps(event.absoluteAttitude),
|
|
2621
|
+
(error) => this.notifyError(error),
|
|
2622
|
+
false
|
|
2623
|
+
);
|
|
2624
|
+
this.relativeAttitudeProviderId = RelativeAttitudeProvider$1.addEventListener(
|
|
2625
|
+
this._onRelativeAttitudeEvent,
|
|
2626
|
+
(error) => {
|
|
2627
|
+
this._attitudeFromRelativeErrored = true;
|
|
2628
|
+
this._onError(error);
|
|
2629
|
+
}
|
|
2630
|
+
);
|
|
2631
|
+
this.inclinationProviderId = InclinationProvider$1.addEventListener();
|
|
2632
|
+
this.highRotationProviderId = HighRotationsProvider$1.addEventListener();
|
|
2633
|
+
}
|
|
2634
|
+
stop() {
|
|
2635
|
+
AbsoluteAttitudeFromBrowser$1.removeEventListener(this.fromBrowserProviderId);
|
|
2636
|
+
RelativeAttitudeProvider$1.removeEventListener(this.relativeAttitudeProviderId);
|
|
2637
|
+
InclinationProvider$1.removeEventListener(this.inclinationProviderId);
|
|
2638
|
+
HighRotationsProvider$1.removeEventListener(this.highRotationProviderId);
|
|
2639
|
+
VpsProvider$1.removeEventListener(this._vpsProviderId);
|
|
2640
|
+
}
|
|
2641
|
+
_setCallbackMagCalibration(cb) {
|
|
2642
|
+
this._callbackMagCalibration = cb;
|
|
2643
|
+
}
|
|
2644
|
+
feed(data) {
|
|
2645
|
+
if (data instanceof geo.AbsoluteHeading) {
|
|
2646
|
+
if (data.time === null) {
|
|
2647
|
+
throw Error("the time of the absolute heading is not defined");
|
|
2648
|
+
}
|
|
2649
|
+
if (data.accuracy === null) {
|
|
2650
|
+
throw Error("the accuracy of the absolute heading is not defined");
|
|
2651
|
+
}
|
|
2652
|
+
this._forceHeadingForRelative(data);
|
|
2653
|
+
} else if (data instanceof AbsoluteAttitude) {
|
|
2654
|
+
if (data.time === null) {
|
|
2655
|
+
throw Error("the time of the attitude is not defined");
|
|
2656
|
+
}
|
|
2657
|
+
if (data.accuracy === null) {
|
|
2658
|
+
throw Error("the accuracy of the attitude is not defined");
|
|
2659
|
+
}
|
|
2660
|
+
this._forceHeadingForRelative(data);
|
|
2661
|
+
} else {
|
|
2662
|
+
throw new Error("data is nor an AbsoluteHeading or an Attitude object");
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
};
|
|
2666
|
+
__publicField(_AbsoluteAttitudeProvider, "REL_ABS_DIVERGENCE_ANGLE_THRESHOLD", maths.deg2rad(25));
|
|
2667
|
+
// in radians;
|
|
2668
|
+
__publicField(_AbsoluteAttitudeProvider, "REL_ABS_DIVERGENCE_TIME_THRESHOLD", 2.5);
|
|
2669
|
+
// in seconds
|
|
2670
|
+
__publicField(_AbsoluteAttitudeProvider, "REL_ABS_DIVERGENCE_INCLINATION_THRESHOLD", maths.deg2rad(15));
|
|
2671
|
+
let AbsoluteAttitudeProvider = _AbsoluteAttitudeProvider;
|
|
2672
|
+
const AbsoluteAttitudeProvider$1 = new AbsoluteAttitudeProvider();
|
|
2673
|
+
const _TurnProvider = class _TurnProvider extends Provider {
|
|
2674
|
+
constructor() {
|
|
2675
|
+
super(...arguments);
|
|
2676
|
+
// in seconds
|
|
2677
|
+
__publicField(this, "providerId");
|
|
2678
|
+
__publicField(this, "slidingWindow", []);
|
|
2679
|
+
__publicField(this, "getName", () => "Turn");
|
|
2680
|
+
__publicField(this, "availability", () => RelativeAttitudeProvider$1.getAvailability());
|
|
2681
|
+
__publicField(this, "_parseRelativeAttitude", (relativeAttitudeEvent) => {
|
|
2682
|
+
const { heading } = relativeAttitudeEvent;
|
|
2683
|
+
const timestamp = relativeAttitudeEvent.time;
|
|
2684
|
+
this.slidingWindow = this.slidingWindow.filter((item) => item[0] >= timestamp - _TurnProvider.SLIDING_WINDOW_TIME);
|
|
2685
|
+
this.slidingWindow.push([timestamp, heading]);
|
|
2686
|
+
const stdVal = maths.std(this.slidingWindow.map((item) => item[1]));
|
|
2687
|
+
if (stdVal > _TurnProvider.STD_THRESHOLD) {
|
|
2688
|
+
this.notify({ timestamp });
|
|
2689
|
+
}
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
start() {
|
|
2693
|
+
this.providerId = RelativeAttitudeProvider$1.addEventListener(
|
|
2694
|
+
this._parseRelativeAttitude,
|
|
2695
|
+
this.notifyError
|
|
2696
|
+
);
|
|
2697
|
+
}
|
|
2698
|
+
stop() {
|
|
2699
|
+
RelativeAttitudeProvider$1.removeEventListener(this.providerId);
|
|
2700
|
+
}
|
|
2701
|
+
isTurning() {
|
|
2702
|
+
if (!this.lastEvent || !RelativeAttitudeProvider$1.lastEvent) {
|
|
2703
|
+
return false;
|
|
2704
|
+
}
|
|
2705
|
+
const diffTime = RelativeAttitudeProvider$1.lastEvent.time - this.lastEvent.timestamp;
|
|
2706
|
+
return diffTime < _TurnProvider.CONSIDER_TURN_UNTIL;
|
|
2707
|
+
}
|
|
2708
|
+
};
|
|
2709
|
+
__publicField(_TurnProvider, "SLIDING_WINDOW_TIME", 0.3);
|
|
2710
|
+
// in seconds
|
|
2711
|
+
__publicField(_TurnProvider, "STD_THRESHOLD", 0.075);
|
|
2712
|
+
__publicField(_TurnProvider, "CONSIDER_TURN_UNTIL", 1);
|
|
2713
|
+
let TurnProvider = _TurnProvider;
|
|
2714
|
+
const TurnProvider$1 = new TurnProvider();
|
|
2715
|
+
const _StraightLineProvider = class _StraightLineProvider extends Provider {
|
|
2716
|
+
constructor() {
|
|
2717
|
+
super(...arguments);
|
|
2718
|
+
__publicField(this, "_turnProviderId");
|
|
2719
|
+
__publicField(this, "_stepProviderId");
|
|
2720
|
+
__publicField(this, "_countSteps", 0);
|
|
2721
|
+
__publicField(this, "_stepsConsideredForStraightLine", _StraightLineProvider.DEFAULT_STEPS_CONSIDERED_FOR_STRAIGHT_LINE);
|
|
2722
|
+
__publicField(this, "getName", () => "StraightLine");
|
|
2723
|
+
__publicField(this, "_onTurn", () => {
|
|
2724
|
+
if (this._countSteps >= this._stepsConsideredForStraightLine) {
|
|
2725
|
+
this.notify(false);
|
|
2726
|
+
}
|
|
2727
|
+
this._countSteps = 0;
|
|
2728
|
+
});
|
|
2729
|
+
__publicField(this, "_onStep", () => {
|
|
2730
|
+
this._countSteps++;
|
|
2731
|
+
if (this._countSteps === this._stepsConsideredForStraightLine) {
|
|
2732
|
+
this.notify(true);
|
|
2733
|
+
}
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
availability() {
|
|
2737
|
+
return AvailabilityHelper.every([
|
|
2738
|
+
TurnProvider$1.getAvailability(),
|
|
2739
|
+
StepProvider$1.getAvailability()
|
|
2740
|
+
]);
|
|
2741
|
+
}
|
|
2742
|
+
start() {
|
|
2743
|
+
this._turnProviderId = TurnProvider$1.addEventListener(this._onTurn);
|
|
2744
|
+
this._stepProviderId = StepProvider$1.addEventListener(this._onStep);
|
|
2745
|
+
}
|
|
2746
|
+
stop() {
|
|
2747
|
+
TurnProvider$1.removeEventListener(this._turnProviderId);
|
|
2748
|
+
StepProvider$1.removeEventListener(this._stepProviderId);
|
|
2749
|
+
}
|
|
2750
|
+
isStraight() {
|
|
2751
|
+
return this._countSteps >= this._stepsConsideredForStraightLine;
|
|
2752
|
+
}
|
|
2753
|
+
get numStepsDetectedFromLastTurn() {
|
|
2754
|
+
return this._countSteps;
|
|
2755
|
+
}
|
|
2756
|
+
get stepsConsideredForStraightLine() {
|
|
2757
|
+
return this._stepsConsideredForStraightLine;
|
|
2758
|
+
}
|
|
2759
|
+
set stepsConsideredForStraightLine(stepsConsideredForStraightLine) {
|
|
2760
|
+
this._stepsConsideredForStraightLine = stepsConsideredForStraightLine;
|
|
2761
|
+
}
|
|
2762
|
+
};
|
|
2763
|
+
__publicField(_StraightLineProvider, "DEFAULT_STEPS_CONSIDERED_FOR_STRAIGHT_LINE", 2);
|
|
2764
|
+
let StraightLineProvider = _StraightLineProvider;
|
|
2765
|
+
const StraightLineProvider$1 = new StraightLineProvider();
|
|
2766
|
+
const _MapMatchingHandler = class _MapMatchingHandler extends Provider {
|
|
2767
|
+
constructor() {
|
|
2768
|
+
super(...arguments);
|
|
2769
|
+
// radians
|
|
2770
|
+
__publicField(this, "_mapMatchingMaxDistance", _MapMatchingHandler.DEFAULT_MM_MAX_DIST);
|
|
2771
|
+
__publicField(this, "_mapMatchingMinDistance", _MapMatchingHandler.DEFAULT_MM_MIN_DIST);
|
|
2772
|
+
__publicField(this, "_mapMatchingMaxAngleBearing", _MapMatchingHandler.DEFAULT_MM_MAX_ANGLE);
|
|
2773
|
+
__publicField(this, "_useItineraryStartAsPosition", _MapMatchingHandler.DEFAULT_USE_ITINERARY_START_AS_POSITION);
|
|
2774
|
+
__publicField(this, "_useOrientationMatching", _MapMatchingHandler.DEFAULT_USE_ORIENTATION_MATCHING);
|
|
2775
|
+
__publicField(this, "_hugeJumpDistance", _MapMatchingHandler.DEFAULT_MM_HUGE_JUMP_DISTANCE);
|
|
2776
|
+
__publicField(this, "_disableMMCloseToATurnDistance", _MapMatchingHandler.DEFAULT_DISABLE_MM_CLOSE_TO_A_TURN_DISTANCE);
|
|
2777
|
+
__publicField(this, "_minStepsBetweenOrientationMatching", _MapMatchingHandler.DEFAULT_MIN_STEPS_BETWEEN_ORIENTATION_MATCHING);
|
|
2778
|
+
__publicField(this, "_minStepsForOrientationMatching", _MapMatchingHandler.DEFAULT_MIN_STEPS_FOR_ORIENTATION_MATCHING);
|
|
2779
|
+
__publicField(this, "_lastProjectionsWindowSize", _MapMatchingHandler.DEFAULT_LAST_PROJECTIONS_WINDOW_SIZE);
|
|
2780
|
+
__publicField(this, "_lastProjectionsEdgeAngleThreshold", _MapMatchingHandler.DEFAULT_LAST_PROJECTIONS_EDGE_ANGLE_THRESHOLD);
|
|
2781
|
+
__publicField(this, "_graph", null);
|
|
2782
|
+
__publicField(this, "_internalProvidersStarted", false);
|
|
2783
|
+
__publicField(this, "_straightLineProviderId");
|
|
2784
|
+
__publicField(this, "_turnProviderId");
|
|
2785
|
+
__publicField(this, "_stepProviderId");
|
|
2786
|
+
__publicField(this, "_projectionsWithAbsAndWithoutRelAttitudeInARow", []);
|
|
2787
|
+
__publicField(this, "_countStepsFromLastMatching", 0);
|
|
2788
|
+
__publicField(this, "_lastProjections", []);
|
|
2789
|
+
__publicField(this, "_itineraryInfoManager", null);
|
|
2790
|
+
__publicField(this, "getName", () => "MapMatchingHandler");
|
|
2791
|
+
__publicField(this, "availability", () => Promise.resolve());
|
|
2792
|
+
__publicField(this, "_manageStartStop", () => {
|
|
2793
|
+
if (this.graph && !this._internalProvidersStarted) {
|
|
2794
|
+
this._startInternalProviders();
|
|
2795
|
+
} else if (!this.graph && this._internalProvidersStarted) {
|
|
2796
|
+
this._stopInternalProviders();
|
|
2797
|
+
}
|
|
2798
|
+
});
|
|
2799
|
+
}
|
|
2800
|
+
start() {
|
|
2801
|
+
if (this.graph) {
|
|
2802
|
+
this._startInternalProviders();
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
stop() {
|
|
2806
|
+
this._stopInternalProviders();
|
|
2807
|
+
}
|
|
2808
|
+
_startInternalProviders() {
|
|
2809
|
+
if (this.enabled && this._internalProvidersStarted) {
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2812
|
+
this._straightLineProviderId = StraightLineProvider$1.addEventListener();
|
|
2813
|
+
this._turnProviderId = TurnProvider$1.addEventListener();
|
|
2814
|
+
this._stepProviderId = StepProvider$1.addEventListener(() => this._countStepsFromLastMatching++);
|
|
2815
|
+
this._internalProvidersStarted = true;
|
|
2816
|
+
}
|
|
2817
|
+
_stopInternalProviders() {
|
|
2818
|
+
if (this.enabled && !this._internalProvidersStarted) {
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
StraightLineProvider$1.removeEventListener(this._straightLineProviderId);
|
|
2822
|
+
TurnProvider$1.removeEventListener(this._turnProviderId);
|
|
2823
|
+
StepProvider$1.removeEventListener(this._stepProviderId);
|
|
2824
|
+
this._internalProvidersStarted = false;
|
|
2825
|
+
}
|
|
2826
|
+
get enabled() {
|
|
2827
|
+
return ProvidersOptions.useMapMatching;
|
|
2828
|
+
}
|
|
2829
|
+
get graph() {
|
|
2830
|
+
return this._graph;
|
|
2831
|
+
}
|
|
2832
|
+
set graph(graph) {
|
|
2833
|
+
this._graph = graph;
|
|
2834
|
+
this._itineraryInfoManager = null;
|
|
2835
|
+
this.notify({ ...graph && { graph } });
|
|
2836
|
+
this._manageStartStop();
|
|
2837
|
+
if (this.canUseMapMatching())
|
|
2838
|
+
;
|
|
2839
|
+
}
|
|
2840
|
+
set itinerary(itinerary) {
|
|
2841
|
+
this._graph = itinerary ? itinerary.toGraph() : null;
|
|
2842
|
+
this._itineraryInfoManager = new routers.ItineraryInfoManager(itinerary);
|
|
2843
|
+
this.notify({ ...itinerary && { itinerary } });
|
|
2844
|
+
this._manageStartStop();
|
|
2845
|
+
if (this.canUseMapMatching() && itinerary) {
|
|
2846
|
+
this._notifyPositionFromItineraryInput(itinerary);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
canUseMapMatching() {
|
|
2850
|
+
return this.enabled && this.graph;
|
|
2851
|
+
}
|
|
2852
|
+
_notifyPositionFromItineraryInput(itinerary) {
|
|
2853
|
+
if (!this._useItineraryStartAsPosition || !itinerary.origin) {
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
const lastPosition = AbsolutePositionProvider$1.lastEvent || null;
|
|
2857
|
+
const newPosition = geo.UserPosition.fromCoordinates(itinerary.origin);
|
|
2858
|
+
if (lastPosition) {
|
|
2859
|
+
newPosition.alt = lastPosition.alt;
|
|
2860
|
+
newPosition.time = lastPosition.time;
|
|
2861
|
+
newPosition.accuracy = lastPosition.accuracy + newPosition.distanceTo(lastPosition);
|
|
2862
|
+
newPosition.bearing = lastPosition.bearing;
|
|
2863
|
+
} else if (itinerary.coords.length >= 2) {
|
|
2864
|
+
newPosition.alt = Constants.DEFAULT_ALTITUDE;
|
|
2865
|
+
newPosition.time = utils.TimeUtils.preciseTime();
|
|
2866
|
+
newPosition.accuracy = 0;
|
|
2867
|
+
newPosition.bearing = itinerary.coords[0].bearingTo(itinerary.coords[1]);
|
|
2868
|
+
} else {
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
const projection = this.getProjection(newPosition, true);
|
|
2872
|
+
if (projection) {
|
|
2873
|
+
AbsolutePositionProvider$1.notify(projection.coords);
|
|
2874
|
+
} else {
|
|
2875
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2876
|
+
}
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2879
|
+
notifyPositionFromFeed(newPositionEvent) {
|
|
2880
|
+
const projection = this.getProjection(newPositionEvent, true, false);
|
|
2881
|
+
if (!projection) {
|
|
2882
|
+
AbsolutePositionProvider$1.notify(newPositionEvent);
|
|
2883
|
+
return;
|
|
2884
|
+
}
|
|
2885
|
+
AbsolutePositionProvider$1.notify(projection.coords);
|
|
2886
|
+
}
|
|
2887
|
+
/**
|
|
2888
|
+
* @returns if input position is used by the system (true = used, false = discarded)
|
|
2889
|
+
*/
|
|
2890
|
+
notifyPositionFromAbsolute(newPosition) {
|
|
2891
|
+
let projectionWithBearing = null;
|
|
2892
|
+
if (newPosition.bearing !== null) {
|
|
2893
|
+
projectionWithBearing = this.getProjection(newPosition, true, true);
|
|
2894
|
+
}
|
|
2895
|
+
if (!projectionWithBearing) {
|
|
2896
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2897
|
+
return true;
|
|
2898
|
+
}
|
|
2899
|
+
const thisWillBeAHugeJump = projectionWithBearing.distanceFromNearestElement > this._hugeJumpDistance;
|
|
2900
|
+
if (thisWillBeAHugeJump && !StraightLineProvider$1.isStraight()) {
|
|
2901
|
+
return false;
|
|
2902
|
+
}
|
|
2903
|
+
if (thisWillBeAHugeJump && this._detectWrongBigJump(projectionWithBearing)) {
|
|
2904
|
+
return false;
|
|
2905
|
+
}
|
|
2906
|
+
AbsolutePositionProvider$1.notify(projectionWithBearing.coords);
|
|
2907
|
+
this.tryOrientationMatching(projectionWithBearing);
|
|
2908
|
+
return true;
|
|
2909
|
+
}
|
|
2910
|
+
/**
|
|
2911
|
+
* @returns if input position is used by the system (true = used, false = discarded)
|
|
2912
|
+
*/
|
|
2913
|
+
notifyPositionFromRelative(newPosition) {
|
|
2914
|
+
var _a;
|
|
2915
|
+
if (TurnProvider$1.isTurning()) {
|
|
2916
|
+
this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
|
|
2917
|
+
this._lastProjections = [];
|
|
2918
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2919
|
+
return true;
|
|
2920
|
+
}
|
|
2921
|
+
const projection = this.getProjection(newPosition, true, true);
|
|
2922
|
+
if (projection) {
|
|
2923
|
+
this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
|
|
2924
|
+
this._lastProjections.push(projection);
|
|
2925
|
+
if (this._lastProjections.length > this._lastProjectionsWindowSize) {
|
|
2926
|
+
this._lastProjections.shift();
|
|
2927
|
+
}
|
|
2928
|
+
const thisWillBeAHugeJump = projection.distanceFromNearestElement > this._hugeJumpDistance;
|
|
2929
|
+
if (thisWillBeAHugeJump && !StraightLineProvider$1.isStraight()) {
|
|
2930
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2931
|
+
return true;
|
|
2932
|
+
}
|
|
2933
|
+
if (thisWillBeAHugeJump && this._detectWrongBigJump(projection)) {
|
|
2934
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2935
|
+
return true;
|
|
2936
|
+
}
|
|
2937
|
+
if (!this._areLastProjectionsInTheSameDirection()) {
|
|
2938
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2939
|
+
return true;
|
|
2940
|
+
}
|
|
2941
|
+
if (this._disableMMCloseToATurnDistance > 0 && this._hasTurnInCircle(projection.coords, this._disableMMCloseToATurnDistance)) {
|
|
2942
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2943
|
+
return true;
|
|
2944
|
+
}
|
|
2945
|
+
AbsolutePositionProvider$1.notify(projection.coords);
|
|
2946
|
+
this.tryOrientationMatching(projection);
|
|
2947
|
+
return true;
|
|
2948
|
+
}
|
|
2949
|
+
if (StraightLineProvider$1.isStraight()) {
|
|
2950
|
+
const testedPosition = newPosition.clone();
|
|
2951
|
+
testedPosition.bearing = ((_a = AbsoluteAttitudeFromBrowser$1.lastEvent) == null ? void 0 : _a.heading) || null;
|
|
2952
|
+
const projectionWithAbs = this.getProjection(testedPosition, true, true);
|
|
2953
|
+
if (projectionWithAbs) {
|
|
2954
|
+
this._projectionsWithAbsAndWithoutRelAttitudeInARow.push(projectionWithAbs);
|
|
2955
|
+
if (this._projectionsWithAbsAndWithoutRelAttitudeInARow.length < 3) {
|
|
2956
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2957
|
+
return true;
|
|
2958
|
+
}
|
|
2959
|
+
this._lastProjections.push(projectionWithAbs);
|
|
2960
|
+
if (this._lastProjections.length > this._lastProjectionsWindowSize) {
|
|
2961
|
+
this._lastProjections.shift();
|
|
2962
|
+
}
|
|
2963
|
+
if (!this._areLastProjectionsInTheSameDirection()) {
|
|
2964
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2965
|
+
return true;
|
|
2966
|
+
}
|
|
2967
|
+
AbsolutePositionProvider$1.notify(projectionWithAbs.coords);
|
|
2968
|
+
this.tryOrientationMatching(projectionWithAbs);
|
|
2969
|
+
return true;
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
this._projectionsWithAbsAndWithoutRelAttitudeInARow = [];
|
|
2973
|
+
this._lastProjections = [];
|
|
2974
|
+
AbsolutePositionProvider$1.notify(newPosition);
|
|
2975
|
+
return true;
|
|
2976
|
+
}
|
|
2977
|
+
_detectWrongBigJump(projection) {
|
|
2978
|
+
if (this._itineraryInfoManager && AbsolutePositionProvider$1.lastEvent) {
|
|
2979
|
+
const infoPrevious = this._itineraryInfoManager.getInfo(AbsolutePositionProvider$1.lastEvent);
|
|
2980
|
+
const infoProjection = this._itineraryInfoManager.getInfo(projection.coords);
|
|
2981
|
+
if (infoPrevious && infoProjection && infoPrevious.traveledDistance > infoProjection.traveledDistance && infoPrevious.traveledDistance - infoProjection.traveledDistance > projection.origin.accuracy && projection.distanceFromNearestElement > projection.origin.accuracy && projection.origin.distanceTo(AbsolutePositionProvider$1.lastEvent) < projection.origin.accuracy + AbsolutePositionProvider$1.lastEvent.accuracy) {
|
|
2982
|
+
return true;
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
return false;
|
|
2986
|
+
}
|
|
2987
|
+
_areLastProjectionsInTheSameDirection() {
|
|
2988
|
+
if (this._lastProjections.length === 0) {
|
|
2989
|
+
return false;
|
|
2990
|
+
}
|
|
2991
|
+
const firstProjection = this._lastProjections[0];
|
|
2992
|
+
return !this._lastProjections.some(
|
|
2993
|
+
(projection) => !(projection.nearestElement instanceof routers.Edge) || !(firstProjection.nearestElement instanceof routers.Edge) || maths.diffAngleLines(projection.nearestElement.bearing, firstProjection.nearestElement.bearing) > this._lastProjectionsEdgeAngleThreshold
|
|
2994
|
+
);
|
|
2995
|
+
}
|
|
2996
|
+
_nodeHasTurn(vertex) {
|
|
2997
|
+
if (!this._graph)
|
|
2998
|
+
return;
|
|
2999
|
+
const edges = this._graph.edges.filter((e) => e.vertex1 === vertex || e.vertex2 === vertex);
|
|
3000
|
+
for (let i = 0; i < edges.length; i++) {
|
|
3001
|
+
for (let j = i + 1; j < edges.length; j++) {
|
|
3002
|
+
const angle = maths.diffAngleLines(edges[i].bearing, edges[j].bearing);
|
|
3003
|
+
if (angle > _MapMatchingHandler.DEFAULT_MM_MAX_ANGLE) {
|
|
3004
|
+
return true;
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
return false;
|
|
3009
|
+
}
|
|
3010
|
+
_hasTurnInCircle(center, radius) {
|
|
3011
|
+
const graph = this._graph;
|
|
3012
|
+
if (!graph) {
|
|
3013
|
+
return false;
|
|
3014
|
+
}
|
|
3015
|
+
return graph.vertices.filter(
|
|
3016
|
+
(vertex) => vertex.coords.distanceTo(center) <= radius && geo.Level.intersect(vertex.coords.level, center.level)
|
|
3017
|
+
).some((it) => this._nodeHasTurn(it));
|
|
3018
|
+
}
|
|
3019
|
+
tryOrientationMatching(projection) {
|
|
3020
|
+
if (!this._useOrientationMatching) {
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
if (this.state !== "started" || this._countStepsFromLastMatching < this._minStepsBetweenOrientationMatching || StraightLineProvider$1.numStepsDetectedFromLastTurn < this._minStepsForOrientationMatching) {
|
|
3024
|
+
return;
|
|
3025
|
+
}
|
|
3026
|
+
const { nearestElement, origin } = projection;
|
|
3027
|
+
if (!(nearestElement instanceof routers.Edge)) {
|
|
3028
|
+
return;
|
|
3029
|
+
}
|
|
3030
|
+
let matchingDirection;
|
|
3031
|
+
const matchingDirectionAngle1 = maths.diffAngle(nearestElement.bearing, origin.bearing);
|
|
3032
|
+
const matchingDirectionAngle2 = maths.diffAngle(nearestElement.bearing + Math.PI, origin.bearing);
|
|
3033
|
+
if (Math.abs(matchingDirectionAngle1) < Math.abs(matchingDirectionAngle2)) {
|
|
3034
|
+
matchingDirection = nearestElement.bearing;
|
|
3035
|
+
} else {
|
|
3036
|
+
matchingDirection = (nearestElement.bearing + Math.PI) % (2 * Math.PI);
|
|
3037
|
+
}
|
|
3038
|
+
const matchedHeading = new geo.AbsoluteHeading(
|
|
3039
|
+
matchingDirection,
|
|
3040
|
+
origin.time,
|
|
3041
|
+
0
|
|
3042
|
+
// Math.min(Math.abs(matchingDirectionAngle1), Math.abs(matchingDirectionAngle2))
|
|
3043
|
+
);
|
|
3044
|
+
AbsoluteAttitudeProvider$1._forceHeadingForRelative(matchedHeading);
|
|
3045
|
+
this._countStepsFromLastMatching = 0;
|
|
3046
|
+
}
|
|
3047
|
+
getProjection(position, useDistance, useBearing) {
|
|
3048
|
+
var _a;
|
|
3049
|
+
const projectionsOptions = {
|
|
3050
|
+
...useDistance && { maxDistance: this._mapMatchingMaxDistance },
|
|
3051
|
+
...useBearing && { maxBearingAngle: this._mapMatchingMaxAngleBearing }
|
|
3052
|
+
};
|
|
3053
|
+
return (_a = this._graph) == null ? void 0 : _a.getProjection(position, projectionsOptions);
|
|
3054
|
+
}
|
|
3055
|
+
get maxDistance() {
|
|
3056
|
+
return this._mapMatchingMaxDistance;
|
|
3057
|
+
}
|
|
3058
|
+
set maxDistance(maxDistance) {
|
|
3059
|
+
this._mapMatchingMaxDistance = maxDistance;
|
|
3060
|
+
}
|
|
3061
|
+
get minDistance() {
|
|
3062
|
+
return this._mapMatchingMinDistance;
|
|
3063
|
+
}
|
|
3064
|
+
set minDistance(minDistance) {
|
|
3065
|
+
this._mapMatchingMinDistance = minDistance;
|
|
3066
|
+
}
|
|
3067
|
+
get maxAngleBearing() {
|
|
3068
|
+
return this._mapMatchingMaxAngleBearing;
|
|
3069
|
+
}
|
|
3070
|
+
set maxAngleBearing(maxAngleBearing) {
|
|
3071
|
+
this._mapMatchingMaxAngleBearing = maxAngleBearing;
|
|
3072
|
+
}
|
|
3073
|
+
get useItineraryStartAsPosition() {
|
|
3074
|
+
return this._useItineraryStartAsPosition;
|
|
3075
|
+
}
|
|
3076
|
+
set useItineraryStartAsPosition(useItineraryStartAsPosition) {
|
|
3077
|
+
this._useItineraryStartAsPosition = useItineraryStartAsPosition;
|
|
3078
|
+
}
|
|
3079
|
+
get useOrientationMatching() {
|
|
3080
|
+
return this._useOrientationMatching;
|
|
3081
|
+
}
|
|
3082
|
+
set useOrientationMatching(useOrientationMatching) {
|
|
3083
|
+
this._useOrientationMatching = useOrientationMatching;
|
|
3084
|
+
}
|
|
3085
|
+
get hugeJumpDistance() {
|
|
3086
|
+
return this._hugeJumpDistance;
|
|
3087
|
+
}
|
|
3088
|
+
set hugeJumpDistance(hugeJumpDistance) {
|
|
3089
|
+
this._hugeJumpDistance = hugeJumpDistance;
|
|
3090
|
+
}
|
|
3091
|
+
get disableMMCloseToATurnDistance() {
|
|
3092
|
+
return this._disableMMCloseToATurnDistance;
|
|
3093
|
+
}
|
|
3094
|
+
set disableMMCloseToATurnDistance(disableMMCloseToATurnDistance) {
|
|
3095
|
+
this._disableMMCloseToATurnDistance = disableMMCloseToATurnDistance;
|
|
3096
|
+
}
|
|
3097
|
+
get minStepsBetweenOrientationMatching() {
|
|
3098
|
+
return this._minStepsBetweenOrientationMatching;
|
|
3099
|
+
}
|
|
3100
|
+
set minStepsBetweenOrientationMatching(minStepsBetweenOrientationMatching) {
|
|
3101
|
+
this._minStepsBetweenOrientationMatching = minStepsBetweenOrientationMatching;
|
|
3102
|
+
}
|
|
3103
|
+
get minStepsForOrientationMatching() {
|
|
3104
|
+
return this._minStepsForOrientationMatching;
|
|
3105
|
+
}
|
|
3106
|
+
set minStepsForOrientationMatching(minStepsForOrientationMatching) {
|
|
3107
|
+
this._minStepsForOrientationMatching = minStepsForOrientationMatching;
|
|
3108
|
+
}
|
|
3109
|
+
get lastProjectionsWindowSize() {
|
|
3110
|
+
return this._lastProjectionsWindowSize;
|
|
3111
|
+
}
|
|
3112
|
+
set lastProjectionsWindowSize(lastProjectionsWindowSize) {
|
|
3113
|
+
this._lastProjectionsWindowSize = lastProjectionsWindowSize;
|
|
3114
|
+
}
|
|
3115
|
+
get lastProjectionsEdgeAngleThreshold() {
|
|
3116
|
+
return this._lastProjectionsEdgeAngleThreshold;
|
|
3117
|
+
}
|
|
3118
|
+
set lastProjectionsEdgeAngleThreshold(lastProjectionsEdgeAngleThreshold) {
|
|
3119
|
+
this._lastProjectionsEdgeAngleThreshold = lastProjectionsEdgeAngleThreshold;
|
|
3120
|
+
}
|
|
3121
|
+
};
|
|
3122
|
+
__publicField(_MapMatchingHandler, "DEFAULT_MM_MAX_ANGLE", maths.deg2rad(30));
|
|
3123
|
+
// radians
|
|
3124
|
+
__publicField(_MapMatchingHandler, "DEFAULT_MM_MAX_DIST", 30);
|
|
3125
|
+
// meters
|
|
3126
|
+
__publicField(_MapMatchingHandler, "DEFAULT_MM_MIN_DIST", 0);
|
|
3127
|
+
// meters
|
|
3128
|
+
__publicField(_MapMatchingHandler, "DEFAULT_USE_ITINERARY_START_AS_POSITION", false);
|
|
3129
|
+
__publicField(_MapMatchingHandler, "DEFAULT_USE_ORIENTATION_MATCHING", true);
|
|
3130
|
+
__publicField(_MapMatchingHandler, "DEFAULT_MM_HUGE_JUMP_DISTANCE", 3);
|
|
3131
|
+
// meters
|
|
3132
|
+
__publicField(_MapMatchingHandler, "DEFAULT_DISABLE_MM_CLOSE_TO_A_TURN_DISTANCE", 2);
|
|
3133
|
+
// meters
|
|
3134
|
+
__publicField(_MapMatchingHandler, "DEFAULT_MIN_STEPS_BETWEEN_ORIENTATION_MATCHING", 3);
|
|
3135
|
+
__publicField(_MapMatchingHandler, "DEFAULT_MIN_STEPS_FOR_ORIENTATION_MATCHING", 5);
|
|
3136
|
+
__publicField(_MapMatchingHandler, "DEFAULT_LAST_PROJECTIONS_WINDOW_SIZE", 3);
|
|
3137
|
+
__publicField(_MapMatchingHandler, "DEFAULT_LAST_PROJECTIONS_EDGE_ANGLE_THRESHOLD", maths.deg2rad(3));
|
|
3138
|
+
let MapMatchingHandler = _MapMatchingHandler;
|
|
3139
|
+
const MapMatchingHandler$1 = new MapMatchingHandler();
|
|
3140
|
+
const _PositionSmoother = class _PositionSmoother {
|
|
3141
|
+
// can be number if web or NodeJS.Timer
|
|
3142
|
+
/**
|
|
3143
|
+
* @param frequency in Hz
|
|
3144
|
+
*/
|
|
3145
|
+
constructor(callback, frequency = _PositionSmoother.DEFAULT_FREQUENCY) {
|
|
3146
|
+
__publicField(this, "positionsQueue", []);
|
|
3147
|
+
__publicField(this, "previousPosition", null);
|
|
3148
|
+
__publicField(this, "timeoutNotify");
|
|
3149
|
+
__publicField(this, "_notifyNext", () => {
|
|
3150
|
+
var _a;
|
|
3151
|
+
if (!this.positionsQueue.length)
|
|
3152
|
+
return;
|
|
3153
|
+
(_a = this.callback) == null ? void 0 : _a.call(this, this.positionsQueue.shift());
|
|
3154
|
+
if (this.positionsQueue.length !== 0) {
|
|
3155
|
+
this.timeoutNotify = setTimeout(this._notifyNext, 1e3 / this.frequency);
|
|
3156
|
+
} else {
|
|
3157
|
+
delete this.timeoutNotify;
|
|
3158
|
+
}
|
|
3159
|
+
});
|
|
3160
|
+
this.callback = callback;
|
|
3161
|
+
this.frequency = frequency;
|
|
3162
|
+
}
|
|
3163
|
+
/**
|
|
3164
|
+
* @param flybyTime in seconds
|
|
3165
|
+
*/
|
|
3166
|
+
feed(newPosition, flybyTime = _PositionSmoother.DEFAULT_FLYBY_TIME) {
|
|
3167
|
+
if (!(newPosition instanceof geo.UserPosition)) {
|
|
3168
|
+
throw new TypeError("newPosition is not instance of UserPosition");
|
|
3169
|
+
}
|
|
3170
|
+
if (newPosition.time === null) {
|
|
3171
|
+
throw new Error("newPosition does not have time property");
|
|
3172
|
+
}
|
|
3173
|
+
let previousPosition;
|
|
3174
|
+
if (this.positionsQueue.length !== 0) {
|
|
3175
|
+
previousPosition = this.positionsQueue[0];
|
|
3176
|
+
this.positionsQueue = [];
|
|
3177
|
+
} else {
|
|
3178
|
+
previousPosition = this.previousPosition;
|
|
3179
|
+
}
|
|
3180
|
+
if (previousPosition) {
|
|
3181
|
+
const refTimestamp = newPosition.time;
|
|
3182
|
+
const distance = previousPosition.distanceTo(newPosition);
|
|
3183
|
+
const azimuth = previousPosition.bearingTo(newPosition);
|
|
3184
|
+
let i = 1;
|
|
3185
|
+
const nSamples = this.frequency * flybyTime + 1;
|
|
3186
|
+
const newPositionLevel = geo.Level.clone(newPosition.level);
|
|
3187
|
+
while (i < nSamples + 1) {
|
|
3188
|
+
const smoothedPosition = previousPosition.destinationPoint(distance * i / nSamples, azimuth);
|
|
3189
|
+
smoothedPosition.time = refTimestamp + (i - 1) / this.frequency;
|
|
3190
|
+
smoothedPosition.level = newPositionLevel;
|
|
3191
|
+
smoothedPosition.bearing = newPosition.bearing;
|
|
3192
|
+
smoothedPosition.accuracy = Math.max(
|
|
3193
|
+
smoothedPosition.accuracy + (newPosition.accuracy - smoothedPosition.accuracy) * i / nSamples,
|
|
3194
|
+
0
|
|
3195
|
+
);
|
|
3196
|
+
this.positionsQueue.push(smoothedPosition);
|
|
3197
|
+
i++;
|
|
3198
|
+
}
|
|
3199
|
+
if (this.timeoutNotify) {
|
|
3200
|
+
clearTimeout(this.timeoutNotify);
|
|
3201
|
+
}
|
|
3202
|
+
} else {
|
|
3203
|
+
this.positionsQueue.push(newPosition.clone());
|
|
3204
|
+
}
|
|
3205
|
+
this.previousPosition = newPosition;
|
|
3206
|
+
this._notifyNext();
|
|
3207
|
+
}
|
|
3208
|
+
clear() {
|
|
3209
|
+
clearTimeout(this.timeoutNotify);
|
|
3210
|
+
delete this.timeoutNotify;
|
|
3211
|
+
this.positionsQueue = [];
|
|
3212
|
+
}
|
|
3213
|
+
};
|
|
3214
|
+
// Generated positions by second
|
|
3215
|
+
__publicField(_PositionSmoother, "DEFAULT_FREQUENCY", 60);
|
|
3216
|
+
// flyby (in second)
|
|
3217
|
+
__publicField(_PositionSmoother, "DEFAULT_FLYBY_TIME", 1);
|
|
3218
|
+
let PositionSmoother = _PositionSmoother;
|
|
3219
|
+
const _AttitudeSmoother = class _AttitudeSmoother {
|
|
3220
|
+
constructor(callback) {
|
|
3221
|
+
// in radians/s
|
|
3222
|
+
__publicField(this, "_previousAttitude");
|
|
3223
|
+
__publicField(this, "_smoothing", null);
|
|
3224
|
+
this.callback = callback;
|
|
3225
|
+
}
|
|
3226
|
+
feed(newAttitude) {
|
|
3227
|
+
if (newAttitude.time === null) {
|
|
3228
|
+
throw new Error("newAttitude does not have time property");
|
|
3229
|
+
}
|
|
3230
|
+
const { _previousAttitude: previousAttitude } = this;
|
|
3231
|
+
this._previousAttitude = newAttitude;
|
|
3232
|
+
if (!previousAttitude) {
|
|
3233
|
+
this.callback(newAttitude);
|
|
3234
|
+
return;
|
|
3235
|
+
}
|
|
3236
|
+
if (_AttitudeSmoother.isJump(previousAttitude, newAttitude)) {
|
|
3237
|
+
const fromAttitude = this._smoothing === null ? previousAttitude : this._smoothing.interpAttitude(previousAttitude);
|
|
3238
|
+
const fromHeading = fromAttitude.heading;
|
|
3239
|
+
const toHeading = newAttitude.heading;
|
|
3240
|
+
const diffAngleHeading = maths.diffAngle(toHeading, fromHeading);
|
|
3241
|
+
const isHighJump = Math.abs(diffAngleHeading) < _AttitudeSmoother.HIGH_JUMP_THRESHOLD;
|
|
3242
|
+
const rotationSpeedConvergence = isHighJump ? _AttitudeSmoother.ROTATION_SPEED_CONVERGENCE : _AttitudeSmoother.ROTATION_SPEED_HIGH_JUMP_CONVERGENCE;
|
|
3243
|
+
const fromTime = fromAttitude.time;
|
|
3244
|
+
const timeToConsume = Math.abs(diffAngleHeading) / rotationSpeedConvergence;
|
|
3245
|
+
const multiplier = diffAngleHeading < 0 ? -1 : 1;
|
|
3246
|
+
this._smoothing = {
|
|
3247
|
+
toTime: fromTime + timeToConsume,
|
|
3248
|
+
interpAttitude: (attitude) => {
|
|
3249
|
+
const angle = rotationSpeedConvergence * (attitude.time - fromTime);
|
|
3250
|
+
const interpHeading = fromHeading + angle * multiplier;
|
|
3251
|
+
const offsetQuat = maths.Quaternion.fromAxisAngle([0, 0, 1], toHeading - interpHeading);
|
|
3252
|
+
const interpQuat = maths.Quaternion.multiply(offsetQuat, attitude.quaternion);
|
|
3253
|
+
return new geo.Attitude(interpQuat, attitude.time, attitude.accuracy);
|
|
3254
|
+
}
|
|
3255
|
+
};
|
|
3256
|
+
}
|
|
3257
|
+
if (this._smoothing !== null) {
|
|
3258
|
+
if (newAttitude.time >= this._smoothing.toTime) {
|
|
3259
|
+
this._smoothing = null;
|
|
3260
|
+
} else {
|
|
3261
|
+
const interpAttitude = this._smoothing.interpAttitude(newAttitude);
|
|
3262
|
+
this.callback(interpAttitude);
|
|
3263
|
+
return;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
this.callback(newAttitude);
|
|
3267
|
+
}
|
|
3268
|
+
/**
|
|
3269
|
+
* @param {Attitude} previousAttitude
|
|
3270
|
+
* @param {Attitude} newAttitude
|
|
3271
|
+
* @returns {boolean}
|
|
3272
|
+
*/
|
|
3273
|
+
static isJump(previousAttitude, newAttitude) {
|
|
3274
|
+
const fromHeading = previousAttitude.heading;
|
|
3275
|
+
const toHeading = newAttitude.heading;
|
|
3276
|
+
const diffAngleHeading = maths.diffAngle(toHeading, fromHeading);
|
|
3277
|
+
const diffTime = newAttitude.time - previousAttitude.time;
|
|
3278
|
+
const [qw, qx, qy, qz] = newAttitude.quaternion;
|
|
3279
|
+
const distToPitchThreshold = Math.abs(Math.asin(2 * (qw * qx + qy * qz)) - Math.PI / 4);
|
|
3280
|
+
if (distToPitchThreshold < _AttitudeSmoother.PITCH_UNCERTAINITY_HEADING_THRESHOLD) {
|
|
3281
|
+
return false;
|
|
3282
|
+
}
|
|
3283
|
+
return Math.abs(diffAngleHeading) > _AttitudeSmoother.ROTATION_SPEED_JUMP_THRESHOLD * diffTime;
|
|
3284
|
+
}
|
|
3285
|
+
};
|
|
3286
|
+
__publicField(_AttitudeSmoother, "ROTATION_SPEED_JUMP_THRESHOLD", maths.deg2rad(180));
|
|
3287
|
+
// in radians/s
|
|
3288
|
+
__publicField(_AttitudeSmoother, "ROTATION_SPEED_CONVERGENCE", maths.deg2rad(10));
|
|
3289
|
+
// in radians/s
|
|
3290
|
+
__publicField(_AttitudeSmoother, "HIGH_JUMP_THRESHOLD", maths.deg2rad(20));
|
|
3291
|
+
// in radians/s
|
|
3292
|
+
__publicField(_AttitudeSmoother, "ROTATION_SPEED_HIGH_JUMP_CONVERGENCE", maths.deg2rad(100));
|
|
3293
|
+
// in radians/s
|
|
3294
|
+
__publicField(_AttitudeSmoother, "PITCH_UNCERTAINITY_HEADING_THRESHOLD", maths.deg2rad(5));
|
|
3295
|
+
let AttitudeSmoother = _AttitudeSmoother;
|
|
3296
|
+
class MagnetometerCalibrationProvider extends Provider {
|
|
3297
|
+
constructor() {
|
|
3298
|
+
super();
|
|
3299
|
+
__publicField(this, "getName", () => "MagnetometerCalibrationProvider");
|
|
3300
|
+
__publicField(this, "availability", () => AbsoluteAttitudeProvider$1.getAvailability());
|
|
3301
|
+
AbsoluteAttitudeProvider$1._setCallbackMagCalibration((e) => this.state === "started" && this.notify(e));
|
|
3302
|
+
}
|
|
3303
|
+
start() {
|
|
3304
|
+
}
|
|
3305
|
+
stop() {
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
const MagnetometerCalibrationProvider$1 = new MagnetometerCalibrationProvider();
|
|
3309
|
+
const _IpResolveServerError = class _IpResolveServerError extends Error {
|
|
3310
|
+
constructor(message) {
|
|
3311
|
+
super(message || _IpResolveServerError.DEFAULT_MESSAGE);
|
|
3312
|
+
}
|
|
3313
|
+
};
|
|
3314
|
+
__publicField(_IpResolveServerError, "DEFAULT_MESSAGE", "IP Resolver failed");
|
|
3315
|
+
let IpResolveServerError = _IpResolveServerError;
|
|
3316
|
+
class IpProvider extends Provider {
|
|
3317
|
+
constructor() {
|
|
3318
|
+
super(...arguments);
|
|
3319
|
+
__publicField(this, "getName", () => "Ip");
|
|
3320
|
+
__publicField(this, "availability", () => Promise.resolve());
|
|
3321
|
+
}
|
|
3322
|
+
async start() {
|
|
3323
|
+
const response = await fetch("https://ipinfo.io/geo?token=24a7ca2f3b489d");
|
|
3324
|
+
if (!response) {
|
|
3325
|
+
this.notifyError(new IpResolveServerError());
|
|
3326
|
+
return;
|
|
3327
|
+
}
|
|
3328
|
+
const timestamp = utils.TimeUtils.preciseTime() / 1e3;
|
|
3329
|
+
const latLngStr = (await response.json()).loc.split(",");
|
|
3330
|
+
const position = new geo.UserPosition(
|
|
3331
|
+
parseFloat(latLngStr[0]),
|
|
3332
|
+
parseFloat(latLngStr[1]),
|
|
3333
|
+
null,
|
|
3334
|
+
null,
|
|
3335
|
+
timestamp,
|
|
3336
|
+
1e5
|
|
3337
|
+
);
|
|
3338
|
+
this.notify(position);
|
|
3339
|
+
}
|
|
3340
|
+
stop() {
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
const IpProvider$1 = new IpProvider();
|
|
3344
|
+
class BarcodePoleStarProvider extends Provider {
|
|
3345
|
+
constructor() {
|
|
3346
|
+
super(...arguments);
|
|
3347
|
+
__publicField(this, "providerId");
|
|
3348
|
+
__publicField(this, "getName", () => "Barcode");
|
|
3349
|
+
__publicField(this, "availability", () => ArCoreProvider$1.getAvailability());
|
|
3350
|
+
}
|
|
3351
|
+
start() {
|
|
3352
|
+
ArCoreProvider$1.enableBarcodeScanner();
|
|
3353
|
+
this.providerId = ArCoreProvider$1.addEventListener(
|
|
3354
|
+
(event) => event.barcode && this.notify(event.barcode),
|
|
3355
|
+
this.notifyError
|
|
3356
|
+
);
|
|
3357
|
+
}
|
|
3358
|
+
stop() {
|
|
3359
|
+
ArCoreProvider$1.disableBarcodeScanner();
|
|
3360
|
+
ArCoreProvider$1.removeEventListener(this.providerId);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
const BarcodeProvider = new BarcodePoleStarProvider();
|
|
3364
|
+
class CameraNativeProvider extends Provider {
|
|
3365
|
+
constructor() {
|
|
3366
|
+
super(...arguments);
|
|
3367
|
+
__publicField(this, "providerId");
|
|
3368
|
+
__publicField(this, "getName", () => "CameraNative");
|
|
3369
|
+
__publicField(this, "availability", () => Promise.resolve());
|
|
3370
|
+
}
|
|
3371
|
+
start() {
|
|
3372
|
+
if (ArCoreProvider$1.state !== "stopped") {
|
|
3373
|
+
this.notify("started");
|
|
3374
|
+
}
|
|
3375
|
+
this.providerId = ArCoreProvider$1.addMonitoringListener(
|
|
3376
|
+
() => this.notify("started"),
|
|
3377
|
+
() => this.notify("stopped")
|
|
3378
|
+
);
|
|
3379
|
+
}
|
|
3380
|
+
stop() {
|
|
3381
|
+
ArCoreProvider$1.removeMonitoringListener(this.providerId);
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
const CameraNativeProvider$1 = new CameraNativeProvider();
|
|
3385
|
+
class CameraProjectionMatrixProvider extends Provider {
|
|
3386
|
+
constructor() {
|
|
3387
|
+
super(...arguments);
|
|
3388
|
+
__publicField(this, "providerId");
|
|
3389
|
+
__publicField(this, "getName", () => "CameraProjectionMatrix");
|
|
3390
|
+
__publicField(this, "availability", () => ArCoreProvider$1.getAvailability());
|
|
3391
|
+
}
|
|
3392
|
+
start() {
|
|
3393
|
+
this.providerId = ArCoreProvider$1.addEventListener(
|
|
3394
|
+
(event) => event.cameraProjection && this.notify(event.cameraProjection),
|
|
3395
|
+
this.notifyError
|
|
3396
|
+
);
|
|
3397
|
+
}
|
|
3398
|
+
stop() {
|
|
3399
|
+
ArCoreProvider$1.removeEventListener(this.providerId);
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
const CameraProjectionMatrixProvider$1 = new CameraProjectionMatrixProvider();
|
|
3403
|
+
exports.AbsoluteAttitude = AbsoluteAttitude;
|
|
3404
|
+
exports.AbsoluteAttitudeFromBrowserProvider = AbsoluteAttitudeFromBrowser$1;
|
|
3405
|
+
exports.AbsoluteAttitudeProvider = AbsoluteAttitudeProvider$1;
|
|
3406
|
+
exports.AbsolutePosition = AbsolutePosition;
|
|
3407
|
+
exports.AbsolutePositionProvider = AbsolutePositionProvider$1;
|
|
3408
|
+
exports.AccelerometerProvider = AccelerometerProvider$1;
|
|
3409
|
+
exports.ArCoreProvider = ArCoreProvider$1;
|
|
3410
|
+
exports.AttitudeSmoother = AttitudeSmoother;
|
|
3411
|
+
exports.BarcodeProvider = BarcodeProvider;
|
|
3412
|
+
exports.CameraNativeProvider = CameraNativeProvider$1;
|
|
3413
|
+
exports.CameraProjectionMatrixProvider = CameraProjectionMatrixProvider$1;
|
|
3414
|
+
exports.GeoRelativePositionFromArCoreProvider = GeoRelativePositionFromArCoreProvider$1;
|
|
3415
|
+
exports.GeoRelativePositionProvider = GeoRelativePositionProvider$1;
|
|
3416
|
+
exports.GnssWifiProvider = GnssWifiProvider$1;
|
|
3417
|
+
exports.GyroscopeProvider = GyroscopeProvider$1;
|
|
3418
|
+
exports.HighRotationsProvider = HighRotationsProvider$1;
|
|
3419
|
+
exports.ImageRelocalization = ImageRelocalization;
|
|
3420
|
+
exports.ImuProvider = ImuProvider$1;
|
|
3421
|
+
exports.InclinationFromAccProvider = InclinationFromAccProvider$1;
|
|
3422
|
+
exports.InclinationFromRelativeAttitudeProvider = InclinationFromRelativeAttitudeProvider$1;
|
|
3423
|
+
exports.InclinationProvider = InclinationProvider$1;
|
|
3424
|
+
exports.IpProvider = IpProvider$1;
|
|
3425
|
+
exports.MagnetometerCalibrationProvider = MagnetometerCalibrationProvider$1;
|
|
3426
|
+
exports.MapMatchingHandler = MapMatchingHandler$1;
|
|
3427
|
+
exports.PdrProvider = PdrProvider$1;
|
|
3428
|
+
exports.PoleStarProvider = PoleStarProvider$1;
|
|
3429
|
+
exports.PositionSmoother = PositionSmoother;
|
|
3430
|
+
exports.ProvidersLoggerOld = ProvidersLoggerOld$1;
|
|
3431
|
+
exports.ProvidersOptions = ProvidersOptions;
|
|
3432
|
+
exports.RelativeAttitude = RelativeAttitude;
|
|
3433
|
+
exports.RelativeAttitudeFromBrowserProvider = RelativeAttitudeFromBrowser$1;
|
|
3434
|
+
exports.RelativeAttitudeFromEkfProvider = RelativeAttitudeFromEkfProvider;
|
|
3435
|
+
exports.RelativeAttitudeFromInertialProvider = RelativeAttitudeFromInertialProvider;
|
|
3436
|
+
exports.RelativeAttitudeProvider = RelativeAttitudeProvider$1;
|
|
3437
|
+
exports.RelativeRotationCalc = RelativeRotationCalc;
|
|
3438
|
+
exports.StepDetectionMinMaxPeaks2 = StepDetectionMinMaxPeaks2;
|
|
3439
|
+
exports.StepDetectionMinMaxPeaks3 = StepDetectionMinMaxPeaks3;
|
|
3440
|
+
exports.StepProvider = StepProvider$1;
|
|
3441
|
+
exports.StraightLineProvider = StraightLineProvider$1;
|
|
3442
|
+
exports.TurnProvider = TurnProvider$1;
|
|
3443
|
+
exports.VpsMetadata = VpsMetadata;
|
|
3444
|
+
exports.VpsProvider = VpsProvider$1;
|
|
3445
|
+
exports.VpsRequest = VpsRequest;
|
|
3446
|
+
exports.VpsResponse = VpsResponse;
|
|
2
3447
|
//# sourceMappingURL=index.js.map
|