UNPKG

@codewithvincent/react-native-gps-filter

Version:

Kalman-based adaptive GPS filter for React Native.

91 lines (90 loc) 4.46 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LocationFilter = void 0; //@ts-ignore const kalmanjs_1 = __importDefault(require("kalmanjs")); const locationFilters_1 = require("../utils/locationFilters"); const helpers_1 = require("../utils/helpers"); class LocationFilter { constructor() { this.kalmanFilterLat = new kalmanjs_1.default(locationFilters_1.kalmanFilterOptions); this.kalmanFilterLon = new kalmanjs_1.default(locationFilters_1.kalmanFilterOptions); this.consecutiveRejectCount = 0; this.totalDistanceTraveled = 0; this.lastAcceptedPredictedLocation = null; this.currentSpeed = 0; } filterAndAddLocation(location, onPredictLocation) { const now = Date.now(); const age = now - location.timestamp; if (age > 10000) return { result: false, reason: "old" }; //@ts-ignore if (location.coords.accuracy <= 0) return { result: false, reason: "no_accuracy" }; //@ts-ignore if (location.coords.accuracy > 100) return { result: false, reason: "inaccurate" }; const speed = location.coords.speed || 0; const { minDelta, maxDelta, maxAllowedDelta, mode } = (0, locationFilters_1.getAdaptiveThresholds)(speed); const isMoving = speed > locationFilters_1.GPS_SPEED_THRESHOLD; if (!this.lastAcceptedPredictedLocation) { this.kalmanFilterLat.filter(location.coords.latitude); this.kalmanFilterLon.filter(location.coords.longitude); this.lastAcceptedPredictedLocation = location; return { result: true, acceptedLocation: location, predictedLocation: location, distanceTraveled: 0, }; } const predictedLat = this.kalmanFilterLat.filter(location.coords.latitude); const predictedLon = this.kalmanFilterLon.filter(location.coords.longitude); const predictedDelta = (0, helpers_1.getDistanceFromLatLonInMeters)(predictedLat, predictedLon, location.coords.latitude, location.coords.longitude); if (predictedDelta > maxAllowedDelta) { this.consecutiveRejectCount += 1; if (this.consecutiveRejectCount > locationFilters_1.KALMAN_REJECT_THRESHOLD) { this.kalmanFilterLat = new kalmanjs_1.default(locationFilters_1.kalmanFilterOptions); this.kalmanFilterLon = new kalmanjs_1.default(locationFilters_1.kalmanFilterOptions); this.consecutiveRejectCount = 0; } return { result: false, reason: `kalman_reject_${mode}` }; } else { this.consecutiveRejectCount = 0; } const predictedLocation = Object.assign(Object.assign({}, location), { coords: Object.assign(Object.assign({}, location.coords), { latitude: predictedLat, longitude: predictedLon }) }); const lastAccepted = this.lastAcceptedPredictedLocation; const distanceSinceLast = (0, helpers_1.getDistanceFromLatLonInMeters)(predictedLat, predictedLon, lastAccepted.coords.latitude, lastAccepted.coords.longitude); if (isMoving && distanceSinceLast > minDelta && distanceSinceLast < maxDelta) { this.totalDistanceTraveled += distanceSinceLast; this.lastAcceptedPredictedLocation = predictedLocation; this.currentSpeed = speed; if (onPredictLocation) { onPredictLocation(predictedLocation); } return { result: true, acceptedLocation: location, predictedLocation, distanceTraveled: this.totalDistanceTraveled, }; } else { return { result: false, reason: `distance_too_small_or_noise_${mode}` }; } } resetFilters() { this.kalmanFilterLat = new kalmanjs_1.default(locationFilters_1.kalmanFilterOptions); this.kalmanFilterLon = new kalmanjs_1.default(locationFilters_1.kalmanFilterOptions); this.consecutiveRejectCount = 0; this.totalDistanceTraveled = 0; this.lastAcceptedPredictedLocation = null; this.currentSpeed = 0; } } exports.LocationFilter = LocationFilter;