Obtener datos de los satélites que utiliza el GPS



Como sabéis las coordenadas que establece el GPS de vuestro dispositivo son el resultado de complejos cálculos matemáticos que se realizan en función de la señal de los satélites que capta, estas coordenadas pueden tener una precisión de centímetros (si se utiliza GPS diferencial) aunque lo normal es que la precisión para uso civil sea de varios metros.

Para calcular la posición se necesita como mínimo la información de 3 satélites, para ello cada uno envía su id y la hora de su reloj interno y en base a estos datos el GPS calcula el tiempo que tarda en llegar la señal; posteriormente utilizando un método matemático llamado trilateración inversa calcula la latitud y longitud de tu posición.

Android nos proporciona una serie de procedimientos que nos informan de los parámetros de cada satélite: elevación, azimut, nivel de ruido de la señal, etc...
Realmente no es tan sencillo como pudiera parecer inicialmente llegar a estos datos ya que además de utilizar el servicio del sistema "LOCATION_SERVICE" hay que configurar la clase tGPSListener que automáticamente genera eventos que nos avisan del instante en el que el GPS se activa, se desactiva, del tiempo del primer "fix", y -lo que nos interesa en este caso- cada vez que se recopile información de los satélites, que se hace mediante el disparo del evento "GPS_EVENT_SATELLITE_STATUS".

Una vez que se dispare capturaremos los datos de esta forma:
 
 satelites := FLocationManager.getGpsStatus(NIL).getSatellites;

Después recorreremos "satelites" para obtener la información asociada a cada uno de ellos tecleando lo siguiente:


satelite := tjgpssatellite.wrap((Objeto AS ILocalObject).GetObjectID);

con lo que obtendremos:

satelite.getAzimut()  : el azimut del satélite en grados
satelite.getElevation()  :  la elevacion en grados
satelite.getPrn: Un número pseudo aleatorio
satelite.getSnr: El ruido de la señal
satelite.hasAlmanac(): si tiene datos de almanaque
satelie.hasEphemeris(): si tiene datos de efemérides
satelite.usedInFix(): si se usa para fijar la posición

El procedimiento que he utilizado es el siguiente:


....

tform1 = class(tform)

   ..VARIABLES..;  

PROCEDURE onGpsStatusChanged(event: Integer);
PROCEDURE IniciarGPS;

PUBLIC
 { Public declarations }
PRIVATE
 { Private declarations }
    satelites: jIterable;
    FLocationManager: JLocationManager;
    locationListener: TLocationListener;
    LocationManagerService: JObject;
END; //tform1

// Definimos la clase TGpsListener

TGpsListener = CLASS(TJavaLocal, JGpsStatus_Listener)
  PRIVATE
    FParent: Tform1;
  PUBLIC
    CONSTRUCTOR Create(AParent: Tform1);
    PROCEDURE onGpsStatusChanged(event: Integer); CDECL;
END;

CONSTRUCTOR TGpsListener.Create(AParent: TfGPS);
BEGIN
  INHERITED Create;
  FParent := AParent;
END;

PROCEDURE TGpsListener.onGpsStatusChanged(event: Integer);
BEGIN
    FParent.onGpsStatusChanged(event);
END;
....


PROCEDURE tform1.IniciarGPS;
BEGIN
  LocationManagerService := tAndroidHelper.context.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);
  FLocationManager := TJLocationManager.wrap((LocationManagerService AS ILocalObject).GetObjectID);
  GPSListener := TGpsListener.Create(self);
END;

PROCEDURE tform1.onGpsStatusChanged(event: Integer);
VAR
  satelite: jgpssatellite;
  Objeto: JObject;
  iter: jiterator;

BEGIN


  //SI SE DISPARA EL EVENTO gps_event_satellite_status...
  IF event = tjgpsstatus.JavaClass.GPS_EVENT_SATELLITE_STATUS THEN
    BEGIN

      IF assigned(FLocationManager) THEN
        BEGIN

            //OBTENGO LOS DATOS DE TODOS LOS SATELITES
            satelites := FLocationManager.getGpsStatus(NIL).getSatellites;
            iter := form1.satelites.iterator;
            
            // RECORRO LA LISTA UNO A UNO PARA OBTENER SUS CARACTERISTICAS  
            Objeto := NIL;
            WHILE iter.hasnext DO
              BEGIN
                Objeto := iter.next;
                IF assigned(Objeto) THEN
                  BEGIN
                      
                      //OBTENGO UN SATELITE DE LA LISTA

                      satelite := tjgpssatellite.wrap((Objeto AS ILocalObject).GetObjectID);
                      //Ojo, no confundir la variable satelites:JIterable con satelite: jgpssatellite
                      // LEO SUS CARACTERISTICAS
                      Label1.text := satelite.getSnr; // 'Ruido        '
                      Label2.text := satelite.getPrn;
                      Label3.text := satelite.getAzimuth.Tostring; // 'Azimuth      '
                      label4.text := satelite.getElevation.Tostring; // 'Elevación    '

                      { 
                        OTROS PARAMETROS DEL SATELITE
                        satelite.hasAlmanac
                        satelite.HasEphemeris
                        satelite.usedInFix
                      }               

                  END;

              END;
        END;
    END;
END;

En la app GPS TOTAL RUN  en el menú "Satélites" tenéis un ejemplo de como quedaría todo lo expuesto anteriormente.



Quizás te pueda interesar:

Cómo añadir gráficos a vuestra app
Programación paralela con Delphi
Rotaciones en 3D
Obtener la elevación en un punto del mapa
Un app para mostrar moléculas en 3D

No hay comentarios:

Publicar un comentario