Longitud/latitud terrestre bajo un satélite (coordenadas cartesianas) en una época específica

El script que quiero desarrollar usa las coordenadas cartesianas (XYZ) de un satélite y, junto con el rango, la elevación y el acimut de una ubicación, luego tomo la información orbital de un satélite y obtengo la longitud/latitud del terreno debajo de ese satélite. en un momento dado.

Un paso más allá de esto: imagina la señal de un satélite perforando la atmósfera exactamente a 300 km sobre el nivel del mar. En este punto en particular, cuando la altitud es de 300 km, necesito calcular la longitud/latitud del suelo.

En el módulo pyephem parece que ya hay un método (ephem.readtle) que puede lograr esto, pero solo para datos TLE (elemento de dos líneas). Me gustaría usar las coordenadas cartesianas de un satélite para desarrollar esto. ¿Ya existe tal método? O tal vez alguien con experiencia en este dominio pueda indicarme la dirección correcta.

Ya existe una pregunta similar que se refiere a ECEF de Azimuth, Elevation, Range y Observer Lat,Lon,Alt , pero no es el mismo problema.

Esto es lo que ya he desarrollado:

  • coordenadas cartesianas del satélite, XYZ
  • acimut, elevación y alcance del satélite desde la estación terrestre
  • coordenadas de la estación terrestre en latitud, longitud y altura sobre el nivel del mar

Esto es lo que necesito: longitud/latitud del suelo debajo de un satélite en una época específica, y en particular donde el punto de perforación en la atmósfera (el punto en el que la señal del satélite perfora la atmósfera) está a 300 km de altitud.


Ok, todavía no resolví el problema de cómo resolver las huellas terrestres para altitudes de 300 km, pero creo que el método que escribí para convertir XYZ en elipsoidal está completo:

 def cartesian_to_ellipsoidal(self):
    x = 4433469.9438
    y = 362672.7267
    z = 4556211.6409
    r = np.sqrt(x**2 + y**2 + z**2)

    # WGS-84 PARAMETERS, semimajor and semiminor axis
    a = 6378137.0
    b = 6356752.314 

    # Eccentricity
    e_squared = (a**2 - b**2) / a**2

    # Auxiliary quantities
    p = np.sqrt(x**2 + y**2)

    # Latitude (phi) & Longitude (lam)
    phi = np.rad2deg(np.arctan(z / ((1- e_squared) * p)))
    lam = np.rad2deg(np.arctan(y/x))

    # Radius of curvature in prime vertical               
    N = a / np.sqrt(1 - e_squared * (np.sin(np.deg2rad(phi)))**2)

    # Altitude
    h = (p / np.cos(np.deg2rad(phi))) - N

    return lam, phi, h

Las coordenadas XYZ se toman como muestra de este ejemplo trabajado de Matlab Ejemplo trabajado de Matlab . Los resultados tienen una precisión con la que estoy satisfecho. Lo que no entiendo y tal vez sea una pregunta tonta, pero cuando se calcula una pista terrestre junto con la altitud, ¿por qué la altitud no es cero? Uno esperaría que, dado que una pista de tierra se asigna a la superficie de la tierra, la altitud debería ser cero.

Un último punto: la pista terrestre deseada era donde la línea entre el satélite y la estación terrestre atraviesa la atmósfera a 300 km sobre la tierra. Teniendo en cuenta distancias de 20000 km (26000 km de radio), ¿un ajuste en mi código, solo para compensar el escenario de altitud deseado de 300 km, haría una gran diferencia en el resultado? De lo contrario, los datos de seguimiento en tierra pueden ser suficientes.

Cuando dices cartesiano, ¿te refieres a coordenadas inerciales centradas en la Tierra? ¿Y quiere encontrar la latitud/longitud directamente debajo del satélite? Simplemente dibujando una línea desde el centro de la tierra hasta el satélite, averigüe dónde la línea se cruza con la superficie (y 300 km por encima de la superficie). Si XYZ proviene de los TLE, ¿para qué sirve la estación terrestre?
Consulte las preguntas sobre Skyfield aquí y aquí y también en el sitio web . ¡Es fácil de usar!
@uhoh, sí ECEF. Me gustaría encontrar la trayectoria terrestre del satélite en el marco lon/lat, pero en lugar del satélite mismo, el punto donde la línea del satélite a la recepción se cruza a 300 km sobre la Tierra. XYZ no proviene de los TLE, sino de mi propio script en Python a modo de efemérides satelitales.
Oh, ahora entiendo, donde la línea del satélite a la estación terrestre atraviesa una altitud de 300 km. Entonces, ¿el XYZ del satélite está en coordenadas terrestres centradas en la Tierra fijas (ECEF = rotación) o inerciales centradas en la Tierra (ECI = sin rotación)?
ECEF. ya tengo una coordenada XYZ del satélite, además de elevación, acimut y rango. Me imagino que esto requerirá algo de trigonometría para obtener el resultado deseado.
Es algo así como +/- 10 km de precisión OK (Tierra esférica) o necesita tener en cuenta la oblación: aproximadamente 20 km de diferencia de polo a ecuador. Las matemáticas se vuelven un poco más difíciles cuando las líneas de latitud y longitud están en una esfera achatada. También puede encontrar cosas realmente útiles en http://gis.stackexchange.com/ ; eche un vistazo allí.
@uhoh, vea mi pregunta modificada arriba.
¿Puedes tratar de convertir esto en una pregunta más corta y bien definida (estrechamente) que pueda tener una respuesta clara? Puede haber demasiadas cosas aquí para encajar en el formato de preguntas y respuestas de stackexchange. Al menos para mí esto se parece más a "pensar en voz alta",
Las coordenadas del satélite (sv) se dan en XYZ, y el radio desde la Tierra es de aproximadamente 26000 km. Las pistas de tierra se calculan a partir del XYZ del satélite. Ahora imagine una línea desde el sv hasta el suelo. En lugar de que el sv esté aproximadamente a 20000 (26000 menos el radio de la Tierra) km de distancia sobre esta línea, supongamos que el sv está en la misma línea, pero a 300 km de altitud (llamaremos a esto el punto de perforación de la atmósfera). Esto significa que el sv tiene un alcance de (300 / sen e) km de distancia, donde 'e' es el ángulo de elevación. Lo que me gustaría saber es la trayectoria terrestre de este satélite ubicado en este rango (300 km sobre la Tierra).

Respuestas (1)

Desde el punto en que te encuentras, necesitas:

  1. Calcula las coordenadas XYZ de tu estación terrestre
  2. Encuentre la línea en el espacio entre el satélite y la estación terrestre
  3. Encuentre las coordenadas XYZ del punto en la intersección de esa línea con el elipsoide definido por todos los puntos con elevaciones de 300 km
  4. Encuentra la latitud y la longitud de ese punto.

Para (1) puede usar esta función de matlab:

function [X,Y,Z] = ll2xyz(lat,lon,alt)
    b=6356752.3141;
    a=6378137.0;
    lat=lat*pi/180;
    %transformation between geografic and geocentric latitude
    gclat=atan(b^2*tan(lat)/a^2);
    lon=lon*pi/180;
    R=sqrt(1./(tan(gclat).^2/b^2 + 1/a^2));
    Z=R.*tan(gclat);
    Z=Z+alt.*sin(lat);
    R=R+alt.*cos(lat);
    X=R.*cos(lon);
    Y=R.*sin(lon);

Para (2) y (3) esta función hará el truco

function [X Y Z] = rectaxelip(x1,x2,y1,y2,z1,z2,alt)
%rectaxelip calculates the point XYZ were a straight line that pass by points P1
%and P2, intersects a ellipsoid alt meters bigger than WGS84 
%ellispsoid (on each axis)

%The director cosines of the line are 
    d=sqrt((x1-x2).^2.*(y1-y2).^2.*(z1-z2).^2);
    L=(x1-x2)./d;
    M=(y1-y2)./d;
    N=(z1-z2)./d;
    %its parametric  for is
    %x = x1 + L * t
    %y = y1 + M * t
    %z = z1 + N * t
    %Now we look for the intersection
    %the ellipsoid would have axes bp and ap

    b=6356752.3141; 
    a=6378137.0;
    bp=b+alt; 
    ap=a+alt;

    %The equation of such ellipsod would be
    %  x^2/ap^2+y^2/ap^2+z^2/bp^2=1
    %subtituting and reorganizng you get a quadratic equation like
    %   A x^2 + B x + C = 0
    %with
    A=(L./ap).^2+(M./ap).^2+(N./bp).^2;
    B=2*((x1.*L./(ap.^2))+(y1.*M./(ap.^2))+(z1.*N./(bp.^2)));
    C=((x1./ap).^2+(y1./ap).^2+(z1./bp).^2)-1;
    ta=(-B+sqrt(B.^2 - (4*A.*C)))./(2*A);
    tb=(-B-sqrt(B.^2 - (4*A.*C)))./(2*A);

    %then
    x1a = x1 + L .* ta;
    y1a = y1 + M .* ta;
    z1a = z1 + N .* ta;
    x1b = x1 + L .* tb;
    y1b = y1 + M .* tb;
    z1b = z1 + N .* tb;
    %Now the distance from each point to the satellite is
    da=sqrt((x1a-x2).^2+(y1a-y2).^2+(z1a-z2).^2);
    db=sqrt((x1b-x2).^2+(y1b-y2).^2+(z1b-z2).^2);
    ESta=da<db;
    t=ta.*ESta+tb.*(~ESta);

    %then
    X = x1 + L .* t;
    Y = y1 + M .* t;
    Z = z1 + N .* t;

Y para (4) solo necesita una función que calcule las coordenadas de latitud y longitud desde las posiciones XYZ, y esta lo haría:

function [lat,lon,alt] = xyz2ll(x,y,z1)
%For some reason the error spikes at +-45
a=6356752.3141; 
b=6378137.0;

signos=sign(z1);
z1=-abs(z1);

lon=atan2(y,x)*180/pi; %Longitude
d1=sqrt(x.^2+y.^2);
z2=-sqrt(1./((1/(a^2))+(1./(b^2*(z1./d1).^2))));
d2=z2./(z1./d1);
p2=-a*d2./(b^2*sqrt(1-(d2.^2/(b^2)))); %slope of the tangent to the ellipse in the point
for i=1:5
    %points in the palne
    dp=(z1-z2-(d1./p2)+(p2.*d2))./(p2-(1./p2));
    zp=(p2.*dp)+z2-(p2.*d2);
    %points in the ellipse
    z2=-sqrt(1./((1/(a^2))+(1./(b^2*(zp./dp).^2))));
    d2=z2./(zp./dp);
    p2=-a*d2./(b^2*sqrt(1-(d2.^2/(b^2))));
end
lat=-90-(atan(p2)*180/pi);   %geographic latitude
lat=abs(lat).*signos;
ecuador=find(abs(z1)<0.001);
lat(ecuador)=0;
alt=sqrt(d1.^2+z1.^2)-sqrt(d2.^2+z2.^2);
alt(ecuador)=d1(ecuador)-a;

Y luego está listo y tiene la posición en el suelo del punto donde la señal GPS que llega a la estación base cruza la altitud de 300 km.

Escribí estas funciones yo mismo y las probé extensamente, así que sé que funcionan, pero tenga en cuenta que la última función, a pesar de que tiene muy buena precisión, por una razón que no he investigado mucho, parece producir grandes errores en latitudes. de +-45°.

Lo último a tener en cuenta. Si quieres más precisión y evitar calcular las coordenadas XYZ de los satélites GPS, puedes utilizar los archivos de efemérides sp3. Son fáciles de descargar desde aquí . Hay un archivo por día, y cada archivo tiene las posiciones XYZ de cada satélite tabuladas cada 15 minutos. Para obtener posiciones en cualquier momento, la interpolación spline brinda una muy buena solución, más o menos lo mismo que la interpolación polinomial de Neville recomendada.

Cuando dice "el elipsoide definido por todos los puntos con elevaciones de 300 km", ¿cómo "hace crecer" el elipsoide WGS84 en 300 km de altitud? Lo que tengo curiosidad es si cada punto en WGS84 se mueve en un elipsoide local normal, o radialmente alejándose del centro de la Tierra, o a lo largo de un gradiente de gravedad local ("hacia arriba"). Además, si desea agregar una respuesta a ¿Qué es el elipsoide de mercurio de Fischer 1960 y por qué se llama así? Con alguna perspectiva histórica, ¡eso sería genial! ¡Me encantan tus respuestas, y su historia es bastante interesante!
@uhoh Como puede ver en el código, solo agregará los 300 km a los ejes semi-mayor y semi-menor que definen el elipsoide de referencia. Y creo que el elipsoide resultante es equivalente a la superficie definida por todos los puntos a 300 km de elevación elipsoidal con respecto al primer elipsoide. Las elevaciones elipsoidales, a su vez, se miden perpendicularmente a la superficie del elipsoide (es decir, distancia mínima), NO radialmente desde el centro del elipsoide NI considerando los gradientes de gravedad de ninguna manera. ¡Interesante pregunta que apuntaste! Pero me abstendré de responder esta vez solo por falta de tiempo libre para hacerlo. Salud
¡Ay! Finalmente me di cuenta de qué es lo que me sigue desconcertando acerca de esto. "...con el elipsoide definido por..." La superficie resultante no es un elipsoide. Para pequeños cambios, probablemente se vería como uno, pero no se puede llamar uno. La forma más rápida de verificar sería tomar el elipsoide de referencia, agregar 300 km a los radios mayor y menor, calcular la forma de un elipsoide adecuado con esos radios y luego comparar la diferencia. Probablemente solo unas pocas decenas de metros. Aún así, es mejor no llamarlo elipsoide si no lo es.