Encontrar coordenadas de periapsis centradas en la Tierra

Actualmente estoy escribiendo un programa que acepta un vector de estado, calcula la elipse Kepleriana correspondiente y luego dibuja la elipse.

Pero estoy atascado en el siguiente punto. Actualmente necesito algún valor para decirle al programa cuánto girar la elipse orbital. Para esto necesito un valor del ángulo desde el eje x (coordenadas ECI) hasta el periapsis.

El problema es que el argumento del periapsis no me sirve si la órbita no está inclinada.

¿Hay alguna forma de calcular este ángulo o calcular las coordenadas del periapsis para poder lograr esto?

En este momento estoy trazando la órbita usando la función matplotlib add ellipse (python) que requiere algún ángulo en el que se debe rotar la elipse, rotation_deges el ángulo que estoy buscando.

orbit = patches.Ellipse((Cx,Cy), major, minor, rotation_deg, 
                        facecolor="none", edgecolor="k", linestyle="--")

En el siguiente ejemplo, elegí cuidadosamente un vector de estado inicial con X = periapsis , y = 0 , z = 0 tal que el ángulo es cero, pero necesito generalizar para cualquier vector de estado arbitrario dentro de una órbita dada.

r = np.array([r_earth+500000,      0,   0])
v = np.array([             0,   9000,   0])

gráfico de ejemplo de órbita elíptica

Aquí está mi código hasta ahora:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

G = 6.67e-11
M_earth = 5.972e24
mu_earth = G*M_earth
r_earth = 6.3781e6

def plot_setup_earth():
    global f, ax

    f, ax = plt.subplots()
    circle = plt.Circle((0,0),r_earth,color = "b")

    ax.set_aspect("equal", "box")
    ax.add_artist(circle)
    ax.set_title("Vehicle Orbit (ECI Coordinates)")
    ax.set_xlabel("X (meters)")
    ax.set_ylabel("Y (meters)")

def elements_from_vectors(r,v,radius,mu):
    global apoapsis, periapsis, a, b, e

    K = np.array([0,0,1])

    h_vec = np.cross(r,v) #momentum vector 
    n_vec = np.cross(K,h_vec) #line of nodes vector
    e_vec = (1/mu)* np.cross(v,h_vec) - (r/np.linalg.norm(r)) #eccentricity vector
    E = ((np.linalg.norm(v)**2)/2) - (mu/np.linalg.norm(r)) #orbital energy

    e = np.linalg.norm(e_vec) #eccentricity
    a = (-1)*(mu/(2*E)) #semimajor axis
    b = a*np.sqrt(1-(e**2))
    p = ((np.linalg.norm(h_vec)**2)/mu) #????

    i = np.arccos(np.dot((h_vec/np.linalg.norm(h_vec)),K)) #Inclination (rad)
    i_deg = np.degrees(i) #Inclination (deg)

    #Right ascension of the ascending node
    if i == 0:
        raan = 0
    elif n_vec[1] >= 0:
        raan = np.arccos(n_vec[0]/np.linalg.norm(n_vec))
    elif n_vec[1] <0: 
        raan = (2*np.pi) - np.arccos(n_vec[0]/np.linalg.norm(n_vec))

    #Argument of periapsis
    if i == 0: 
        w = 0
    elif e_vec[2] >= 0:
        w = np.arccos(np.dot(n_vec,e_vec)/(np.linalg.norm(n_vec)*np.linalg.norm(e_vec)))
    elif e_vec[2] < 0: 
        w = (2*np.pi)-np.arccos(np.dot(n_vec,e_vec)/(np.linalg.norm(n_vec)*np.linalg.norm(e_vec)))

    #True anomoly
    if np.dot(r,v) >= 0:
        f = np.arccos(np.dot(r,e_vec)/(np.linalg.norm(r)*np.linalg.norm(e_vec)))
    if np.dot(r,v) < 0:
        f = (2*pi)-np.arccos(np.dot(r,e_vec)/(np.linalg.norm(r)*np.linalg.norm(e_vec)))

    periapsis = a*(1-e)
    apoapsis = a*(1+e)

def plot_orbit(apoapsis, periapsis, semimajor, semiminor, eccentricity):
    major = 2*semimajor #Aka major axis
    minor = 2*semiminor #Aka minor axis

    ae = semimajor*eccentricity #Focus to center distance (where focus 1 is center of body being orbited)
    rotation_deg = 0
    rotation_rad = np.radians(rotation_deg)

    Px = periapsis*np.cos(rotation_rad)
    Py = periapsis*np.sin(rotation_rad)

    Ax = (-1)*apoapsis*np.cos((-1)*rotation_rad)
    Ay = apoapsis*np.sin((-1)*rotation_rad)

    Cx = 0 - ae*np.cos(-1*rotation_rad)
    Cy = 0 + ae*np.sin(-1*rotation_rad)

    orbit = patches.Ellipse((Cx,Cy), major, minor, rotation_deg, facecolor = "none", edgecolor = "k", linestyle = "--")
    ax.add_artist(orbit)

    plt.scatter(Px,Py, color = "r",marker = "+")
    plt.annotate("Periapsis %f km" %round((periapsis-r_earth)/1000,1), (Px,Py), fontsize = 9)
    plt.scatter(Ax,Ay,color = "b", marker = "+")
    plt.annotate("Apoapsis %f km" %round((apoapsis-r_earth)/1000,1),(Ax,Ay), fontsize = 9)

r = np.array([r_earth+500000,0,0])
v = np.array([0,9000,0])

plot_setup_earth()
elements_from_vectors(r,v,r_earth,mu_earth)
plot_orbit(apoapsis, periapsis, a, b, e)

plt.xlim(-1.5*apoapsis,4*periapsis)
plt.ylim(-1*(b*2),1*((b*2)))

plt.show()
Si tiene vectores de estado adecuados , simplemente los traza y esa es su órbita. ¿De verdad quieres decir que tienes una mesa de X , y , z , v X , v y , v z ¿valores? Tal vez podría mostrar un ejemplo de lo que tiene que trazar para que sea más fácil entender por qué aún necesita más información.
La forma en que lo hago es convertir los vectores en elementos orbitales y trazar una elipse a partir de esos valores. Estoy usando la biblioteca matplotlib para python para hacer este trazado. No estoy seguro de cómo trazaría simplemente el vector y vería una órbita.
No creo que podamos discutir más a menos que muestres una muestra de lo que tienes. El gráfico de una órbita es en realidad una serie de segmentos de línea que conectan una secuencia de X , y , z puntos. Ver esta respuesta por ejemplo. Esa órbita es una secuencia de 201 vectores de estado, con el X , y , z parte de los vectores de estado trazados.
Actualicé mi respuesta, si quieres puedes echar un vistazo a mi código para ver lo que piensas.
¡Muchas gracias por la actualización y el script! Ajusté un poco la redacción y agregué algo de formato. Ahora veo que cada órbita es de un vector de estado inicial y no de vectores de estado (plural). ¿Puede aclarar si necesita que esto funcione para cualquier vector de estado inicial arbitrario, incluidos todos los RAAN e inclinaciones? En este momento hay una respuesta que parece útil, pero no estoy seguro de que cubra su caso. Sería genial si pudieras dejar un comentario para ese autor directamente debajo de su respuesta. ¡Gracias!

Respuestas (2)

Actualmente, la pregunta tal como está escrita es demasiado general para responderla específicamente. No obstante, proporcionaré algunos recursos útiles recomendados como un comentario ampliado.

Podría comenzar con esta explicación de la longitud del periapsis para obtener un ejemplo de un conjunto de elementos orbitales que no se comporta mal cuando la inclinación se aproxima a cero.

Y/o podría usar fórmulas para relaciones entre vectores de estado y elementos orbitales dadas en Bate, Muller y White (1971) Fundamentals of Astrodynamics , ...

o por ejemplo en AE Roy, Orbital Motion (o google para otras fuentes del mismo título).

También puede encontrar algunas de las fórmulas útiles en el Método de determinación de órbita preliminar que no tiene singularidad coplanar de RML Baker y NH Jacoby, Celestial Mechanics 15 (1977) 137-160.

Espero que eso ayude.

Este es el comienzo de una gran respuesta, pero la respuesta está en los enlaces, no aquí, lo que hace que esta sea una respuesta de solo enlace principalmente, lo que generalmente se desaconseja en Stack Exchange. Si/cuando los enlaces se pudren, no hay respuesta aquí para que la vean los futuros lectores. ¿Puede tomar un bloque, un pasaje bastante pequeño o una ecuación o dos y resumir las respuestas aquí en su publicación? ¡Gracias!
¡ Ciertamente has escrito respuestas bastante completas antes!
@uhoh: entiendo que una 'respuesta de solo enlace' es una que proporciona una URL sin identificar qué debe abordar. Aquí he dado citas a las publicaciones por título y autor, etc., de modo que incluso si los enlaces en sí mismos 'se pudren', las referencias citadas aún pueden identificarse y buscarse. Así que creo que esto no es, de hecho, una respuesta de solo enlace. La dificultad de seleccionar fórmulas para el interrogador es que se ha dicho tan poco sobre el problema que no está claro qué operaciones computacionales serían las más relevantes.
Si la pregunta es demasiado general para responderla, agregue un comentario a la pregunta pidiendo una aclaración. Estoy bastante seguro de que el término solo enlace también incluye solo cita, el punto es que la respuesta no está aquí en la respuesta, sino que está en otro lugar fuera de Stack Exchange. Modifiqué su prefacio, luego agregué un comentario a la pregunta pidiendo una aclaración.

En la situación en la que la órbita no está inclinada, la convención generalmente es que el Argumento del Periapsis es el ángulo desde la Dirección de Referencia (en su caso, el eje x) hasta el Periapsis.

El código que tiene asume que el Argumento de Periapsis siempre es cero si la inclinación es cero, lo cual no es cierto. Así es como yo reescribiría su sección Argument of Periapsis.

    #Argument of periapsis

    if i != 0 and e!= 0: # Orbit is inclined and eccentric
        w = np.arccos(np.dot(n_vec,e_vec)/(np.linalg.norm(n_vec)*np.linalg.norm(e_vec)))
        if e_vec[2] < 0:
            w = (2*np.pi) - w
    elif e != 0: # Orbit is not inclined, but is eccentric
        w = numpy.arctan2(e_vec[1], e_vec[0])
    else: #Orbit is circular.
        w = 0.0

Como tal, como se mencionó anteriormente, puede usar su argumento del valor del periapsis para rotation_deg=wrotar su elipse de la manera que desee, si su órbita es ecuatorial y prograda (inclinación = 0) y el punto de vista es desde arriba del eje Z.

He agregado algo de formato aquí. Eche un vistazo a la pregunta, se actualizó con un guión completo y con algunas aclaraciones en la redacción. Hay comentarios adicionales allí también. Me pregunto si puede ampliar esto para incluir también la inclinación. ¡Gracias!
Gracias por la aclaración. ¿Usar el argumento del periapsis como el valor de rotación no supone que la línea de nodos está a lo largo del eje x? Solo estoy luchando por entender por qué el argumento del periapsis funciona como el ángulo de rotación.
El argumento de Periapsis es el ángulo, en el plano de la órbita, medido desde la Ascensión Recta, del Nodo Ascendente, a través del centro del cuerpo que está en órbita hasta el Periapsis, en la dirección de viaje alrededor de la órbita. Entonces, si su órbita es ecuatorial y prograda (i = 0), entonces raan = 0 y, por lo tanto, el Argumento de Periapsis es el ángulo que desea.
¡Impresionante! Gracias por la explicación. ¿Y esto incluso funciona con las coordenadas ECI que estoy usando para el gráfico? ¿No tengo que graficar la órbita desde una vista perpendicular al plano de la órbita?
@GriffinJ desafortunadamente, usar el argumento de periapsis solo funciona para la órbita no inclinada vista desde el caso perpendicular, que es lo que pensé que estabas preguntando. Disculpas. No estoy personalmente familiarizado con matplotlib, por lo que realmente no puedo hacer una buena recomendación sobre cómo lidiar con hacer que dibuje una órbita elíptica desde un punto de vista arbitrario.
Eso está bien. Estoy usando esto principalmente para otro programa que estoy escribiendo que generaliza que las órbitas no estén inclinadas. Entonces, para mi uso actual, ¡está bien! Probablemente querré resolver las otras cosas en algún momento, pero por ahora he implementado tu sugerencia y está funcionando.