2011-11-14 17 views
13

Estoy tratando de desarrollar mi propio motor de realidad aumentada.Calcular rodamiento entre dos ubicaciones (lat, largo)

Buscando en internet, he encontrado esto útil tutorial. Al leerlo, veo que lo importante es llevarlo entre la ubicación del usuario, la ubicación del punto y el norte.

La siguiente imagen es de ese tutorial.

enter image description here

Después, me escribió un método de Objective-C para obtener la beta:

+ (float) calculateBetaFrom:(CLLocationCoordinate2D)user to:(CLLocationCoordinate2D)destination 
{ 
    double beta = 0; 
    double a, b = 0; 

    a = destination.latitude - user.latitude; 
    b = destination.longitude - user.longitude; 

    beta = atan2(a, b) * 180.0/M_PI; 
    if (beta < 0.0) 
     beta += 360.0; 
    else if (beta > 360.0) 
     beta -= 360; 

    return beta; 
} 

Pero, cuando lo intento, no funciona muy bien.

Así que revisé iPhone AR Toolkit, para ver cómo funciona (he estado trabajando con este kit de herramientas, pero es tan grande para mí).

Y, en ARGeoCoordinate.m hay otra implementación de cómo obtener la beta:

- (float)angleFromCoordinate:(CLLocationCoordinate2D)first toCoordinate:(CLLocationCoordinate2D)second { 

    float longitudinalDifference = second.longitude - first.longitude; 
    float latitudinalDifference  = second.latitude - first.latitude; 
    float possibleAzimuth   = (M_PI * .5f) - atan(latitudinalDifference/longitudinalDifference); 

    if (longitudinalDifference > 0) 
     return possibleAzimuth; 
    else if (longitudinalDifference < 0) 
     return possibleAzimuth + M_PI; 
    else if (latitudinalDifference < 0) 
     return M_PI; 

    return 0.0f; 
} 

Utiliza esta fórmula:

float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference/longitudinalDifference); 

¿Por qué es (* M_PI .5f) en esta fórmula? No lo entiendo

Y continúo buscando, he encontrado otro page hablando de cómo calcular la distancia y el rumbo de 2 ubicaciones. En esta página hay otra aplicación:

/** 
* Returns the (initial) bearing from this point to the supplied point, in degrees 
* see http://williams.best.vwh.net/avform.htm#Crs 
* 
* @param {LatLon} point: Latitude/longitude of destination point 
* @returns {Number} Initial bearing in degrees from North 
*/ 
LatLon.prototype.bearingTo = function(point) { 
    var lat1 = this._lat.toRad(), lat2 = point._lat.toRad(); 
    var dLon = (point._lon-this._lon).toRad(); 

    var y = Math.sin(dLon) * Math.cos(lat2); 
    var x = Math.cos(lat1)*Math.sin(lat2) - 
      Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); 
    var brng = Math.atan2(y, x); 

    return (brng.toDeg()+360) % 360; 
} 

¿Cuál es la correcta?

+0

¿Alguna vez resolvió este problema? Estoy interesado en la solución que utilizó con – Craigy

+0

Sí, tengo que agregar mi propia respuesta en breve. – VansFannel

Respuesta

14

Calcular rodamiento

//Source 
JSONObject source = step.getJSONObject("start_location"); 
double lat1 = Double.parseDouble(source.getString("lat")); 
double lng1 = Double.parseDouble(source.getString("lng")); 

// destination 
JSONObject destination = step.getJSONObject("end_location"); 
double lat2 = Double.parseDouble(destination.getString("lat")); 
double lng2 = Double.parseDouble(destination.getString("lng")); 

double dLon = (lng2-lng1); 
double y = Math.sin(dLon) * Math.cos(lat2); 
double x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); 
double brng = Math.toDegrees((Math.atan2(y, x))); 
brng = (360 - ((brng + 360) % 360)); 

convertir grados a radianes

Radians = Degrees * PI/180 

Convertir radianes a grados

Degrees = Radians * 180/PI 
+0

¿Convierte el valor a grados, pero no es latitud y longitud en grados? ¿No deberías convertirlos primero a radianes? – ravemir

+0

No convierto la latitud y la longitud en radio. No creo que marque ninguna diferencia –

+0

¿Has probado la coincidencia de rodamientos en línea para las pruebas? por ej. prueba en este enlace. http://www.sunearthtools.com/tools/distance.php –

4

En la fórmula

float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference/longitudinalDifference);

el término (M_PI * .5f) significa π/2, que es de 90 °. Eso significa que es la misma fórmula que usted indicó al principio, porque con respecto a la figura anterior contiene

β = arctan (a/b) = 90 ° - arctan (b/a).

Por lo que ambas fórmulas son similares si a se refiere a la diferencia en longitud y b en la diferencia en latitud. La última fórmula calcula nuevamente lo mismo usando la primera parte de mi ecuación.

+0

Usted se refiere a 'a' como diferencia en lat y' b' como diferencia en long. Vea mi respuesta de cómo 'a' debería realmente la diferencia en long y' b' la diferencia en lat. Podría ser útil editar su respuesta para que sea coherente con el diagrama, de modo que no confundamos a los lectores futuros más de lo necesario. – Dolbz

+0

Gracias, Dolbz, tienes razón, a y b deberían cambiarse. Edité mi respuesta principal para tener una correcta. :) – Palund

2

a en el diagrama es la diferencia de longitud, b es la diferencia de latitud en lo que respecta al método que ha utilizado, lo tiene equivocado.

a = destination.latitude - user.latitude; // should be b 
b = destination.longitude - user.longitude; // should be a 

Intente cambiarlos y vea qué pasa.

Consulte la respuesta de Palund para obtener respuestas al resto de sus preguntas.

+0

Gracias, tienes razón: me he equivocado con a y b. Los cambié y obtuve beta = 9 grados. Pero, si uso LatLon.prototype.bearingTo, con las mismas ubicaciones, obtengo beta = 7 grados. Creo que el segundo es más preciso, pero no entiendo que no esté implementado en iPhone AR Toolkit. Gracias de nuevo. – VansFannel

+0

Esto resuelve el problema. Simplemente use arctan (b, a) en lugar de (a, b). –

0

Si lo deseas, puedes echar un vistazo al código utilizado en el motor de realidad aumentada mixare, está en github y también hay una versión para iPhone: github.com/mixare

+0

Gracias. Ahora veo que has trabajado con este navegador ar. ¿Podrías ayudarme a encontrar la clase que contiene cálculos de rumbo? – VansFannel

+1

Hola, no soy el desarrollador de la versión para iPhone, pero de acuerdo con la documentación de la clase disponible en: http://code.google.com/p/mixare/wiki/FileResponsibility, debería ser clase AugmentedViewController. La fuente es: https://github.com/mixare/mixare-iphone/blob/master/Classes/gui/tabbarControllers/augmentedView/AugmentedViewController.m – Daniele

7

Sé que esta pregunta es antigua, pero aquí hay una solución más fácil:

flotador rodamiento = loc1.bearingTo (loc2);

1

para probar este resultado preciso:

private static double degreeToRadians(double latLong) { 
    return (Math.PI * latLong/180.0); 
} 

private static double radiansToDegree(double latLong) { 
    return (latLong * 180.0/Math.PI); 
} 

public static double getBearing() { 

//Source 
JSONObject source = step.getJSONObject("start_location"); 
double lat1 = Double.parseDouble(source.getString("lat")); 
double lng1 = Double.parseDouble(source.getString("lng")); 

// destination 
JSONObject destination = step.getJSONObject("end_location"); 
double lat2 = Double.parseDouble(destination.getString("lat")); 
double lng2 = Double.parseDouble(destination.getString("lng")); 

    double fLat = degreeToRadians(lat1); 
    double fLong = degreeToRadians(lng1); 
    double tLat = degreeToRadians(lat2); 
    double tLong = degreeToRadians(lng2); 

    double dLon = (tLong - fLong); 

    double degree = radiansToDegree(Math.atan2(sin(dLon) * cos(tLat), 
      cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(dLon))); 

    if (degree >= 0) { 
     return degree; 
    } else { 
     return 360 + degree; 
    } 
} 

que pueda probar que lleva el resultado http://www.sunearthtools.com/tools/distance.php.

Cuestiones relacionadas