From 8597ee6592b59119d57b1c41a7f2bc4e64a2d20c Mon Sep 17 00:00:00 2001 From: Afonso Hermenegildo Date: Sat, 8 Jun 2024 00:00:40 +0100 Subject: [PATCH] fix: only calculate device heading offset is user is in a straight + some small errors fixed --- index.html | 2 ++ scripts/extras.js | 20 ++++++++++++------- scripts/map.js | 45 +++++++++++++++++++++++++++++++++++-------- scripts/navigation.js | 8 ++++---- scripts/routing.js | 12 +++++------- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/index.html b/index.html index f16b083..3bb6ae4 100644 --- a/index.html +++ b/index.html @@ -101,10 +101,12 @@
+
+
diff --git a/scripts/extras.js b/scripts/extras.js index 33b4b17..c63ae07 100644 --- a/scripts/extras.js +++ b/scripts/extras.js @@ -180,13 +180,6 @@ function toPascalCase(str) { return str.charAt(0).toUpperCase() + str.slice(1); } -function convertBbox(bbox) { - const minCoords = ol.proj.fromLonLat([bbox[0], bbox[1]]); - const maxCoords = ol.proj.fromLonLat([bbox[2], bbox[3]]); - - return [...minCoords, ...maxCoords]; -} - function htmlEncode(str) { return str .replaceAll("&", "&") @@ -215,6 +208,19 @@ function formatDistance(meters) { return meters.toFixed(0) + "m"; } +const arrayStandardDeviation = (arr, usePopulation = false) => { + // Calculate the mean of the array + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + + // Calculate the sum of squared differences from the mean + const sumOfSquaredDifferences = arr + .reduce((acc, val) => acc.concat((val - mean) ** 2), []) + .reduce((acc, val) => acc + val, 0); + + // Calculate the standard deviation + return Math.sqrt(sumOfSquaredDifferences / (arr.length - (usePopulation ? 0 : 1))); +}; + // Testing functions let onFakeTrip = false; diff --git a/scripts/map.js b/scripts/map.js index 0c18fad..0314fbb 100644 --- a/scripts/map.js +++ b/scripts/map.js @@ -10,6 +10,8 @@ let gpsHeading = null; let followLocation = false; let deviceHeadingOffset = 0; // offset between the gps heading when above 5kph and the device compass (to make the device compass reading more accurate) let watchPositionIDs = []; +let last5PositionsAngles = []; +let inStraightLine = false; async function initMap() { // Set cycleways style @@ -337,16 +339,43 @@ function getLocation(zoom = true) { // Location update handler const locationUpdateHandler = async position => { // Convert to the OpenLayers format - pos = [position.coords.longitude, position.coords.latitude]; + new_pos = [position.coords.longitude, position.coords.latitude]; + + // Get the differences between new and old positions + if (pos) { + const diffLat = new_pos[1] - pos[1]; + const diffLon = new_pos[0] - pos[0]; + + // Get the angle between new and old positions (corrected from clockwise east to clockwise north) + last5PositionsAngles.push(-90 * (Math.PI / 180) + Math.atan2(diffLat, diffLon)); + if (last5PositionsAngles.length > 5) last5PositionsAngles.shift(); + } + arrayStandardDeviation(last5PositionsAngles) < 0.15 ? (inStraightLine = true) : (inStraightLine = false); + document.querySelectorAll("#posAngles").forEach(elem => { + if (inStraightLine) { + elem.innerHTML = "in straight"; + elem.style.backgroundColor = "green"; + } else { + elem.innerHTML = "not straight"; + elem.style.backgroundColor = "red"; + } + }); + + // Now update to current pos to new pos, since we don't need the old value + pos = new_pos; + + // Get speed speed = position.coords.speed ?? 0; + if (document.getElementById("speedMS")) document.getElementById("speedMS").innerHTML = speed.toFixed(0) + "m/s"; // Update gps heading gpsHeading = (Math.PI / 180) * position.coords.heading; // adjusted to radians // Update speed on landscape const speedKMH = (speed * 60 * 60) / 1000; - const speedElem = document.getElementById("speed"); - if (speedElem) speedElem.innerHTML = speedKMH.toFixed(0); // convert m/s to km/h + for (const speedElem of document.querySelectorAll("#speed")) { + speedElem.innerHTML = speedKMH.toFixed(0); // convert m/s to km/h + } // Update distance to open station if (lastStationObj) { @@ -390,8 +419,8 @@ function getLocation(zoom = true) { //map.getView().setCenter(ol.proj.fromLonLat(pos)); } - // Use GPS heading above certain speed (12kph) (testing for more accurate heading) - if (gpsHeading && speed >= (12 * 1000) / (60 * 60)) { + // Use GPS heading if user is ruffly in a straight line for the last 5 seconds + if (gpsHeading && inStraightLine) { // Calculate offset between gps heading and compass heading deviceHeadingOffset = Math.PI - Math.abs(Math.abs(gpsHeading - compassHeading) - Math.PI); @@ -474,15 +503,15 @@ function startLocationDotRotation() { if (!pos) return; - // Reset offset if there is no gps heading - if (!gpsHeading) { + // Reset offset if there is not using gps heading + /*if (!(gpsHeading && inStraightLine)) { // Reset offset deviceHeadingOffset = 0; // Dev info document.getElementById("headingSource").innerHTML = "Compass"; document.getElementById("headingSource").style.backgroundColor = "lightblue"; - } + }*/ // Calculate final heading heading = compassHeading + deviceHeadingOffset; diff --git a/scripts/navigation.js b/scripts/navigation.js index 7b69544..27bd963 100644 --- a/scripts/navigation.js +++ b/scripts/navigation.js @@ -24,7 +24,7 @@ async function startNavigation(walkingOnly = false) { } // Navigation on-foot from user location to nearest station - navigationMode === "foot"; + navigationMode = "foot"; // Set rotation mode rotationMode = "route"; @@ -123,7 +123,7 @@ async function finalOnFootNavigation() { const navigationElements = Array.from(document.querySelectorAll("*")).filter( e => getComputedStyle(e).zIndex === "16" ); - for (element of navigationElements) { + for (const element of navigationElements) { element.remove(); } @@ -166,7 +166,7 @@ async function stopNavigation() { e => getComputedStyle(e).zIndex === "11" || getComputedStyle(e).zIndex === "16" || getComputedStyle(e).zIndex === "20" ); - for (element of navigationElements) { + for (const element of navigationElements) { element.remove(); } @@ -486,7 +486,7 @@ function exitLandscapeNavigationUI() { const navigationElements = Array.from(document.querySelectorAll("*")).filter( e => getComputedStyle(e).zIndex === "16" || getComputedStyle(e).zIndex === "20" ); - for (element of navigationElements) { + for (const element of navigationElements) { element.remove(); } diff --git a/scripts/routing.js b/scripts/routing.js index e132f72..e755125 100644 --- a/scripts/routing.js +++ b/scripts/routing.js @@ -44,8 +44,8 @@ async function calculateFullRoute(fromCoordinates, toCoordinates) { let grabStation; let dropoffStationInternal; - for (stationStart of nearestStationsStart) { - for (stationEnd of nearestStationsEnd) { + for (const stationStart of nearestStationsStart) { + for (const stationEnd of nearestStationsEnd) { const walkingDistanceToStartStation = distance(fromCoordinates, [stationStart.longitude, stationStart.latitude]); const cyclingDistanceFromStartToEnd = distance( [stationStart.longitude, stationStart.latitude], @@ -227,8 +227,8 @@ async function recalculateFullRoute(fromCoordinates, toCoordinates) { let grabStation; let dropoffStationInternal; - for (stationStart of nearestStationsStart) { - for (stationEnd of nearestStationsEnd) { + for (const stationStart of nearestStationsStart) { + for (const stationEnd of nearestStationsEnd) { const walkingDistanceToStartStation = distance(fromCoordinates, [stationStart.longitude, stationStart.latitude]); const cyclingDistanceFromStartToEnd = distance( [stationStart.longitude, stationStart.latitude], @@ -347,7 +347,6 @@ async function calculateRoute(fromCoordinates, toCoordinates, cycling = true) { cycling: new ol.style.Style({ stroke: new ol.style.Stroke({ color: "#79C000", - width: 8, width: 4, }), zIndex: 0, @@ -355,7 +354,6 @@ async function calculateRoute(fromCoordinates, toCoordinates, cycling = true) { walking: new ol.style.Style({ stroke: new ol.style.Stroke({ color: "#231F20", - width: 8, lineDash: [3, 9], width: 4, }), @@ -755,7 +753,7 @@ function viewRoute(toCoordinates) { getLocation(false); checkPos = function (toCoordinates) { - if (typeof pos === "undefined" || typeof pos === "null") setTimeout(() => checkPos(toCoordinates), 0); + if (typeof pos === "undefined") setTimeout(() => checkPos(toCoordinates), 0); else { // Calculate and display the route on the map when we have the user position calculateFullRoute(pos, toCoordinates);