tipos keyframes fotogramas divididas diferencias copiar como after java android algorithm gps interpolation

java - fotogramas - keyframes after effects



Interpolar entre 2 ubicaciones de GPS basadas en la velocidad de caminata (5)

Supongo que tengo que calcular algunos deltas de tiempo, pero ¿cómo puedo tener en cuenta la velocidad de movimiento?

En la interpolación lineal, en su casema itera entre dos puntos de tiempo, usando la variable de iteración t, que se extiende desde el tiempo de inicio t1 hasta el tiempo de finalización t2, con un paso predefinido. Asume step = 1 segundo, que es bastante útil para tu aplicación.

long t1 = location1.getTimeStamp(); // in milliseconds; long t2 = location2.getTimeStamp(); double deltaLat = location2.latitude - location1.latitude; doule deltaLon = location2.longitude- location1.longtude; // remove this line if you don''t have measured speed: double deltaSpeed = location2.speed - location1.speed; long step = 1 * 1000; // 1 second in millis for (long t = t1; t1 < t2; t+= step) { // t0_1 shall run from 0.0 to (nearly) 1.0 in that loop double t0_1 = (t - t1) / (t2 - t1); double latInter = lat1 + deltaLat * t0_1; double lonInter = lon1 + deltaLon * t0_1; // remove the line below if you dont have speed double speedInter = speed1 + deltaSpeed * t0_1; Location interPolLocation = new Location(latInter, lonInter, speedInter); // add interPolLocation to list or plot. }

Problema:

Dadas dos ubicaciones:

L 1 = (latitud 1 , longitud 1 , marca de tiempo 1 ) , L 2 = (latitud 2 , longitud 2 , marca de tiempo 2 ) ,

y una velocidad de movimiento configurable, pero constante:

v = 1.39 metros por segundo (por ejemplo).

¿Cómo podemos interpolar entre estas dos ubicaciones para estimar la ubicación de un usuario mientras viaja de L 1 a L 2 ?

He estado buscando soluciones a este problema y hasta ahora he encontrado que para distancias pequeñas (lejos de los polos) se puede usar la interpolación lineal. Entonces, busqué la interpolación lineal en Wikipedia y encontré esto:

// Imprecise method which does not guarantee v = v1 when t = 1, // due to floating-point arithmetic error. float lerp(float v0, float v1, float t) { return v0 + t*(v1-v0); }

Así que estoy pensando en usar esta función lerp para interpolar latitud y longitud entre L 1 y L 2 . Esa fue la parte fácil. ¿Cómo calculo t ? Supongo que tengo que calcular algunos deltas de tiempo, pero ¿cómo puedo tener en cuenta la velocidad de movimiento?

Editar:

Estoy probando varios métodos para recopilar ubicaciones de GPS. Para este propósito, estoy registrando waypoint-locations a lo largo de una caminata. Necesito interpolar entre estos puntos de referencia, usando la velocidad de movimiento, para estimar mi posición a lo largo de la caminata. Luego, puedo comparar mis resultados con las estimaciones para ver qué tan bien les está yendo.

Ejemplo:


Sí. Interpolación linear.

L1 = (1, 2, 3) L2 = (4, 5, 6) desired_number_of_interpolation_points = 9 interpolation_points = [] lat_step = (L2[0] - L1[0]) / (desired_number_of_interpolation_points + 1) lon_step = (L2[1] - L1[1]) / (desired_number_of_interpolation_points + 1) time_step = (L2[2] - L1[2]) / (desired_number_of_interpolation_points + 1) for i in range(1, desired_number_of_interpolation_points + 1) interpolation_points.append((lat_step * i, lon_step * i, time_step * i))


Hay algunas otras estrategias de interpolación que funcionan mejor que la interpolación lineal, incluida la interpolación cinemática, que toma como entrada la velocidad inicial y final de los puntos de anclaje. Como ejemplo, ver esta comparación de un artículo reciente (Long JA (2015) interpolación cinemática de datos de movimiento. Int J Geogr Inf Sci 8816: 1-15. Doi: 10.1080 / 13658816.2015.1081909):

Hay implementaciones R y Python para la interpolación cinemática. Debería ser fácil escribir una versión de Java.


Cálculos como estos son en realidad muy simples si primero convierte sus lat / longs a n-vectores ( https://en.wikipedia.org/wiki/N-vector ). Después de la conversión puede usar la interpolación estándar, y también evitará cualquier problema con las distancias largas, los polos o la fecha.

Si marca "Enlaces externos" en la página de Wikipedia, hay una página ( http://www.navlab.net/nvector/ ) donde se resuelven diez problemas, y el problema 6 en esa página (posición interpolada) debe ser el mismo como tu pregunta Como puede ver, esa solución es exacta para cualquier distancia y también funciona en cualquier posición de la Tierra, como los polos.


Eche un vistazo de cerca a Calcular distancia, rumbo y más entre puntos de latitud / longitud

Contiene varias fórmulas y ejemplos de JavaScript que pueden ayudarte. Sé que NO es Java, pero debería ser lo suficientemente simple para portar el código. Especialmente dada la descripción detallada de la fórmula.

EDITAR:

Si bien parece correcto utilizar la interpolación lineal para distancias más cortas, de hecho puede estar bastante apagado, especialmente a medida que te acercas a los polos. Viendo por el ejemplo que estás en Hamburgo, esto ya tendrá un efecto que se puede notar en unos pocos cientos de metros. Vea esta respuesta para una buena explicación.

El problema: la distancia entre 1 grado en longitud varía mucho según tu latitud.

Esto se debe a que la tierra NO es plana, sino una esfera, en realidad un elipsoide. Por lo tanto, una línea recta en un mapa bidimensional NO es una línea recta en el globo, y viceversa.

Para evitar este problema uno puede usar el siguiente enfoque:

  1. Obtener el rumbo desde la coordenada inicial (L1) hasta la coordenada final (L2)
  2. Calcule una nueva coordenada desde la coordenada de inicio (L1) a lo largo de una trayectoria de círculo grande, dado el rumbo calculado y una distancia especificada
  3. Repita este proceso, pero usando la coordenada recién calculada como la coordenada inicial

Podemos crear algunas funciones simples que nos harán el truco:

double radius = 6371; // earth''s mean radius in km // Helper function to convert degrees to radians double DegToRad(double deg) { return (deg * Math.PI / 180); } // Helper function to convert radians to degrees double RadToDeg(double rad) { return (rad * 180 / Math.PI); } // Calculate the (initial) bearing between two points, in degrees double CalculateBearing(Location startPoint, Location endPoint) { double lat1 = DegToRad(startPoint.latitude); double lat2 = DegToRad(endPoint.latitude); double deltaLon = DegToRad(endPoint.longitude - startPoint.longitude); double y = Math.sin(deltaLon) * Math.cos(lat2); double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(deltaLon); double bearing = Math.atan2(y, x); // since atan2 returns a value between -180 and +180, we need to convert it to 0 - 360 degrees return (RadToDeg(bearing) + 360) % 360; } // Calculate the destination point from given point having travelled the given distance (in km), on the given initial bearing (bearing may vary before destination is reached) Location CalculateDestinationLocation(Location point, double bearing, double distance) { distance = distance / radius; // convert to angular distance in radians bearing = DegToRad(bearing); // convert bearing in degrees to radians double lat1 = DegToRad(point.latitude); double lon1 = DegToRad(point.logintude); double lat2 = Math.asin(Math.sin(lat1) * Math.cos(distance) + Math.cos(lat1) * Math.sin(distance) * Math.cos(bearing)); double lon2 = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(distance) * Math.cos(lat1), Math.cos(distance) - Math.sin(lat1) * Math.sin(lat2)); lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180 - + 180 degrees return new Location(RadToDeg(lat2), RadToDeg(lon2)); } // Calculate the distance between two points in km double CalculateDistanceBetweenLocations(Location startPoint, Location endPoint) { double lat1 = DegToRad(startPoint.latitude); double lon1 = DegToRad(startPoint.longitude); double lat2 = DegToRad(endPoint.latitude); double lon2 = DegToRad(endPoint.longitude); double deltaLat = lat2 - lat1; double deltaLon = lon2 - lon1; double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - 1)); return (radius * c); }

Esto usa un radio medio de tierra de 6371 km. Consulte Wikipedia para obtener una explicación de este número y su precisión.

Ahora se puede calcular una nueva ubicación intermedia entre los dos puntos, dada la distancia recorrida (en km):

double bearing = CalculateBearing(startLocation, endLocation); Location intermediaryLocation = CalculateDestinationLocation(startLocation, bearing, distanceTravelled);

Suponiendo una velocidad de v (por ejemplo, 1.39) metros por segundo, ahora se puede usar un bucle simple para obtener puntos separados por un segundo:

List<Location> locations = new ArrayList<Location>(); // assuming duration in full seconds for (int i = 0; i < duration; i++){ double bearing = CalculateBearing(startLocation, endLocation); double distanceInKm = v / 1000; Location intermediaryLocation = CalculateDestinationLocation(startLocation, bearing, distanceInKm); // add intermediary location to list locations.add(intermediaryLocation); // set intermediary location as new starting location startLocation = intermediaryLocation; }

Como una ventaja adicional, incluso puedes determinar el tiempo requerido para viajar entre dos puntos:

double distanceBetweenPoints = CalculateDistanceBetweenLocations(startPoint, endPoint) * 1000; // multiply by 1000 to get meters instead of km double timeRequired = distanceBetweenPoints / v;

Esto dará como resultado una mayor precisión sobre cualquier distancia que una simple interpolación lineal usando solo el delta de las coordenadas. Aunque este enfoque no es perfecto, tendrá un error generalmente de 0.3% o menos, lo cual es bastante aceptable. Si necesita una solución mejor, es posible que desee examinar la fórmula de Vincenty.