Go Down

Topic: comparación coordenadas (Read 2794 times) previous topic - next topic

mamumo

Hola buenas! A ver si alguien me puede dar una idea de como hacer lo que quiero. Os explico:

Tengo un módulo GPS, el cual he configurado para que sólo me muestre la Latitud y la Longitud.También tengo un módulo de SD en el que tengo guardo un documento con otra larga lista de coordenadas (de la misma forma que las anteriores).
Lo que quiero hacer es ir cogiendo las coordenadas del GPS y hacer una operación (se trataría de una resta en valor absoluto), con los datos de la SD. Con esto quiero saber cual es la coordenada que más se acerca a la que mi GPS recoge.

Mi problema viene en este paso, es una secuencia sencilla pero  no se como tratar estos datos. ¿Con que tipo de dato es con el que debería trabajar?
Ya que primero tengo que leer el número, guardarlo en una variable y luego operar con el.

Este es un ejemplo de los datos que tengo en el documento de la SD:

  42.46071,  -2.42176
  42.46070,  -2.42177
  42.46070,  -2.42177
  42.46070,  -2.42177
  42.46070,  -2.42178

Muchas gracias de antemano.
Un saludo.


jorgepl

Si estás leyendo los datos de un módulo GPS y comparandolos con otros de un fichero en una SD, supongo que estás manejando todo el rato cadenas de carácteres (por lo menos la lectura del GPS). Lo primero que tendrás que hacer es convertir esos textos a números y guardarlos en el tipo de número que más te interese.

Si siempre vas a utilizar el mismo número de decimales (por el ejemplo que has mostrado, 5 decimales), yo multiplicaría el valor por la potencia de 10 necesaria para eliminar la parte decimal (en tu ejemplo por 10^5=100.000). Como la posición GPS va desde -360 hasta 360 (es positiva y/o negativa, por lo tanto, no puedes usar un tipo unsigned), el rango de valores con el que vas a trabajar será de -36.000.000 (-360*100.000) hasta 36.000.000 (360*100.000). El tipo de datos para trabajar con ese rango es el tipo long (http://arduino.cc/en/Reference/Long).

mamumo

Muchas gracias jorgepl por tu contestación.

Tu idea es buena pero no puedo quitar el punto ya que los decimales suelen variar de un dato  a otro  y entonces la resta me saldría mal.
Si, para la lectura del gps he trabajado con el tipo char, y con la SD también he comenzado así para detectar dos números diferentes separados por la ',' . Los valores me variarán en los decimales (pueden ser 2,3,4,5 ó 6) como ya he comentado y en la unidades y decenas.
No los podría declarar como float?? Como se leería esta línea?
                                                                                    42.46100,  -2.41741

mi intención es hacer algo así:

char inByte;
float latitud;
float longitud;
inByte = gps.read();
if (inByte != ',')
{
// leo y guardo en latitud el valor 42.461
}
else
{
// leo y guardo en longitud el valor -2.41741
}
inByte = gps.read();


así continuaría con toda la lista guardando el menor de los valores en cada caso. El problema es que estoy totalmente liada con los tipos de datos y no soy capaz de guardar esos valores en una variable, estoy atascada...

curro92

Hola,
para convertir una cadena de texto a número existen varias funciones en C

- atoi() para convertir texto a int
- atol() para convertir texto a long int
- atof() para convertir texto a float, que es la que necesitas

Prueba con esto:
Code: [Select]
float valorSD, valorGPS;

char txtSD[11];
char txtGPS[11];

void setup()
{
   Serial.begin(9600);
}   
   

void loop()
{   
    strncpy(txtSD, "12.3400", 10);
    strncpy(txtGPS, "1.0000", 10);

    valorSD = atof(txtSD);
    valorGPS = atof(txtGPS);
   
    Serial.println(valorSD - valorGPS, DEC);
    delay(3333);
}

Si van a ser más decimales, define una cadena de tamaño más grande.

Engeeknyer

Buenas,

A parte del tema de conversión de datos y por lo que deduzco de lo que estas describiendo, creo que deberias darle un vistazo a la "formula del Haversine" (http://es.wikipedia.org/wiki/F%C3%B3rmula_del_Haversine). Pienso que puede ayudarte evaluar que par de coordenadas estan mas cerca.

Un saludo.

mamumo

Muchas gracias Curro92, ahora me voy a poner en ello, creo que me va a ser de gran ayuda.

Una pregunta, donde puedo encontrar documentación sobre programación con funciones más específicas como esta. Tengo que documentarme más ando un poco perdida todavía...

mamumo

hola  @Engeeknyer,
he estado echando un vistazo al link, la verdad que no conocía esta fórmula, es muy interesante. Lo único que las operaciones son mucho más complejas que las que yo pensaba usar, puesto que las mías son simplemente la suma de dos restas en valor absoluto: |Xgps-Xsd| + |Ygps-Ysd|.

Muchas gracias de todas formas.

Engeeknyer

Si, claro. Si lo único que te interesa es eso.
Pero sólo un pequeño comentario: la diferencia (medida en distáncia) de un minuto de grado, es diferente dependiendo de la latitud donde se mida.

Un saludo y feliz proyecto.


jorgepl


Tu idea es buena pero no puedo quitar el punto ya que los decimales suelen variar de un dato  a otro  y entonces la resta me saldría mal.


Siempre puedes rellenar con ceros cuando conviertes de texto a valor para igualar el número de decimales y/o trabajar con un número fijo de decimales (si decides trabajar con 5, desprecias los siguientes si hay o rellenas con ceros si faltan).

curro92

Hola,
para aprender lo básico en lenguaje C a mí me sirvió mucho la obra de los inventores del lenguaje C,
"The C Programming Language" de Kernighan & Ritchie



Engeeknyer

curoo92: Gran Libro de escritorio. Recomiendo  sin duda.

mamumo

Hola he hecho un programa de prueba para convertir cadena de caracteres a real  con la instrucción atof. No se por que razón me hace una aproximación en los dos primeros decimales y el resto los elimina.

Programilla:

double real;
char numero[]="3.9873";
void setup(){
Serial.begin(9600);
}
void loop(){
real=atof(numero);
Serial.print(real);
Serial.println();
}

El valor que me muestra es 3.99. Sabe alguien que pasa?
Gracias.

curro92

Hola,
Parece un redondeo que hace la función cuando se escribe
Serial.print(real);
sin especificar el tipo de variable. Si pones
Serial.print(real, DEC);
no hace el redondeo.


mamumo

Curro92, ya vi esa instrucción en un ejemplo que anteriormente pusiste. Y añade decimales hasta llegar a 10 e incluso si pongo 10 decimales me modifica las últimas 3, al igual que si se pones Serial.print (real,OCT) añade hasta que queden 8 decimales. No entiendo muy bien el funcionamiento de esta instrucción...
que tendría que poner si yo trabajo con 5 o 6 decimales???

mamumo

Ya he encontrado la solución, en este link viene muy bien explicado: http://arduino.cc/es/Serial/Print

en mi caso sería Serial.print(real,6)

Go Up