Tengo problemas para calcular mis elementos orbitales clásicos y no sé dónde buscar

Estoy usando el motor Unity y C#, y estoy tratando de encontrar una forma de trazar futuras trayectorias orbitales 2D. Actualmente tengo una configuración de dos cuerpos. El planeta tiene una masa de 1000000, el satélite una masa de 1.

ingrese la descripción de la imagen aquí

En la imagen de arriba, puede ver una línea rosa que indica el camino orbital (PASADO, NO FUTURO) creado por un renderizador de senderos, lo que indica que las matemáticas son incorrectas ya que la excentricidad no está entre 0 y 1.

También he notado que el AP y el PE son incorrectos ya que el PE se muestra como -AP. Sé que mis matemáticas están mal en alguna parte, pero no tengo idea de dónde.

Si alguien mucho más inteligente que yo es capaz de resolverlo/arreglar esto, sería genial si también pudiera indicarme cómo usar esto para trazar una trayectoria futura en tiempo real.

void JustKeplerThings(Vector3 curPos, Vector3 shipCurVel, GameObject orbiting) {        
    //Gravitational Constant
    float G = 6.67408f * Mathf.Pow(10, -11);

    //Mass of ship
    float m1 = thisShip.mass;

    //Mass of the larger body
    float m2 = -orbiting.GetComponent<PointEffector2D>().forceMagnitude;
    float M = m2;

    //Standard Gravitational Parameter
    float µ = G * (m1 + m2);
    //float µ = G * M;

    //Relative Position Vector
    Vector3 r = FindRelativePosition(transform, orbitee.transform.position);

    //Relative Velocity Vector
    Vector3 v = shipCurVel - new Vector3(orbitee.GetComponent<Rigidbody2D>().velocity.x, orbitee.GetComponent<Rigidbody2D>().velocity.y, 0);

    //Specific Angular Momentum
    Vector3 h = Vector3.Cross(r, v);

    //Eccentricity Vector
    Vector3 evec = (Vector3.Cross(v, h) / µ) - (r / Vector3.Magnitude(r));

    //Eccentricity
    float e = Vector3.Magnitude(evec);

    //Mechanical Energy
    float E = (Mathf.Pow(Vector3.Magnitude(v), 2) / 2) - (µ / Vector3.Magnitude(r));

    //Semi-Major Axis
    float a = µ / (2 * E);
    if (Mathf.Abs(e - 1.0f) <= Mathf.Epsilon)
        a = Mathf.Infinity;

    //Semi-Latus Rectum Check
    float p = a * (1 - Mathf.Pow(e, 2));
    if (Mathf.Abs(e - 1.0f) <= Mathf.Epsilon)
        p = Mathf.Pow(Vector3.Magnitude(h), 2) / µ;

    //Inclination (2D)
    float i = 0;

    //Longitude of Ascending Node (2D)
    float Ω = 0;

    //Argument of Periapsis
    float ω = Mathf.Atan2(evec.y, evec.x);
    //ω = (2 * Mathf.PI) - ω;

    //True Anomaly
    float t = Mathf.Acos((Vector3.Dot(evec, r)) / (e * Vector3.Magnitude(r)));
    if (Vector3.Dot(r, v) < 0)
        t = (2 * Mathf.PI) - t;

    //Apoapsis
    float ap = a * (1 + e);

    //Periapsis
    float pe = a * (1 - e);

    //Orbital Period
    float T = (2 * Mathf.PI) * Mathf.Sqrt(Mathf.Pow(a, 3) / µ);
}

-

public static Vector3 FindRelativePosition(Transform origin, Vector3 position) {
    Vector3 distance = position - origin.position;
    Vector3 relativePosition = Vector3.zero;
    relativePosition.x = Vector3.Dot(distance, origin.right.normalized);
    relativePosition.y = Vector3.Dot(distance, origin.up.normalized);
    relativePosition.z = Vector3.Dot(distance, origin.forward.normalized);
    return relativePosition;
}
No sé el idioma que estás usando, así que solo estoy adivinando. ¿Tiene un momento angular específico como r X v? Tal vez debería ser (2 * r X v)/(período de órbita).
Tuve que mover las cosas para calcular incluso las cosas que dependían entre sí, pero esto no funciona ya que T (período orbital) se devuelve como NaN.
Por favor, ¿podría indicar el idioma que ha utilizado?
Sí, lo siento, edité mi pregunta pero también olvidé agregarla al comentario, C# en Unity.
Parece que u es su etiqueta para GM o el parámetro gravitacional. El lenguaje es opaco, por lo que no puedo decir si ha definido un eje semi-mayor. El período orbital T se puede expresar como 2 pi * sqrt (a^3 / u)
Gracias, actualicé mi script, cambiando la legibilidad, los nombres de las variables y algunas cosas. µ es, de hecho, mi etiqueta para GM. He definido el semieje mayor (a) como flotante a = -µ / (2 * E)que encontré en algún lugar de Internet. Agregué su cálculo del período orbital T como T = (2 * Mathf.PI) * Mathf.Sqrt(Mathf.Pow(a, 3) / µ)resultado de un NaN todavía.
Primero, debe conquistar los NaN: envenenan cualquier cálculo posterior. Después de cada cálculo, imprima el resultado en la consola con una línea como Debug.Log( "x = "+x); -- ataca el primer resultado obviamente incorrecto que obtengas, una y otra vez, hasta que todo parezca correcto. Hay métodos de depuración más sofisticados, pero este es el que más sigo usando.
También estoy un poco preocupado por su uso de PointEffector2D aquí; Unity tiende a introducir límites y términos de escala arbitrarios y mal documentados en su sistema de física 2D, por lo que si espera que la física de Unity le proporcione una órbita que corresponda a sus valores calculados, es posible que se sienta decepcionado.
El NaNs está en el período orbital que todavía no estoy usando para nada más. Así que los problemas que estoy teniendo no son relevantes todavía. ¿Qué haría para agregar gravedad correctamente sin usar un efector de punto? ¿Aplicaría esto una atracción gravitacional adecuada: answers.unity3d.com/questions/596202/… ?
Creo que está aplicando una fuerza de cuadrado inverso al igual que el efector de punto de la unidad.
Si T es NaN, lo más probable es que mu sea 0 oa sea NaN o negativo. Regístrelos y descubra cuáles.
De acuerdo, mu estaba resultando negativo porque estaba tirando de la magnitud de la fuerza directamente, pero es un valor negativo en el cuerpo rígido, así que cambié orbiting.GetComponent<PointEffector2D>().forceMagnitude;a -orbiting.GetComponent<PointEffector2D>().forceMagnitude;Sin embargo, la ecuación que estoy usando para calcular a es -a = µ / (2 * E)que resulta negativa ahora que mu es positivo. Así que tentativamente lo cambié a = µ / (2 * E)y ahora estoy viendo un Período Orbital.
Actualicé la imagen en mi publicación para proporcionar la información que deseaba encontrar para imprimir/depurar registro.

Respuestas (1)

El cálculo que está haciendo es para un cuerpo de 1 millón de kg con un satélite a 150 metros de su centro moviéndose a 83 metros por segundo. 1 millón de kg es casi nada en términos gravitatorios; Masas terrestres 6e24 kg. Entonces el satélite se mueve más rápido que la velocidad de escape. Esto significa que la energía orbital es positiva por convención, por lo que el eje semi-mayor "aparece" negativo, y no hay una solución posible para el período orbital, porque no regresa.

La simulación física de Unity utiliza una fuerza (tal vez expresada en newtons si asume que las unidades de distancia de Unity son metros, pero tal vez no, porque es Unity), no una masa; lo estás tratando como una masa, lo cual no tiene sentido.

Dado que Unity limita las velocidades de movimiento 2D en su sistema de física y no documenta la distancia base en la que la fuerza PointEffector2D es igual al valor especificado, será problemático alinear sus cálculos con el resultado de la simulación de Unity, por lo que Recomiendo escribir su propia simulación gravitacional, es bastante sencillo. Tendrá que ser consciente de la escala de su simulación, es decir, decidir cuántos metros representa una unidad de distancia de Unity y ceñirse a ella.

Con respecto a trazar el camino futuro de un cuerpo, tiene un par de opciones.

Uno, una vez que tenga su propio simulador de gravedad funcionando, es simplemente recordar las últimas N posiciones del simulador, y colocar el cuerpo en órbita en la ubicación de los resultados de N pasos anteriores, y dibujar líneas de trayectoria futura hasta la última posición. Tendrás que ejecutar la simulación N veces antes de mostrar el cuerpo, por supuesto.

La opción dos, si solo tiene uno o dos cuerpos masivos en juego, es abordar las ecuaciones aquí o aquí para traducir entre sus vectores de estado orbital y coordenadas de tiempo futuro. Con más de dos cuerpos, no puedes resolverlo de esta manera. (Puedes tener un cuerpo masivo y cualquier número de infinitesimales que no se afecten gravitatoriamente entre sí, por supuesto).

Entonces, ¿debería mantener mi ecuación calculando a como -a = µ / (2 * E)pero arreglar la escala en mis valores? Entonces tendré que escribir mi propia gravedad, ya que la masa del planeta es actualmente el máximo de pointeffector2D.
Unity limita las velocidades de movimiento 2D en su sistema de física y no documenta la distancia base en la que la fuerza PointEffector2D es igual al valor especificado. Es posible que pueda resolverlo por prueba y error, pero escribiría mi propia gravedad si fuera usted. Tendrá que ser consciente de la escala de su simulación, es decir, decidir cuántos metros representa una unidad de distancia de Unity y ceñirse a ella.
Seguí adelante y traté de simular mi propia gravedad, usé la ISS en órbita terrestre y reduje las cosas en 100. Pero por alguna razón que aún no he resuelto, se ve afectado por la velocidad de fotogramas y la escala de tiempo. También necesitaba hacer cambios masivos en la constante gravitacional cambiándola manualmente hasta que los números funcionaran. Esto es lo que obtuve con Radio de la Tierra: 63.71, Masa de la Tierra: 5.972E+22, Masa de la Nave: 4194.55, Velocidad de la Nave: 76.5, Altitud de la Nave: 4, Constante Gravitacional: 1.59508e-21.
¿Está utilizando Time.deltaTime para obtener el tiempo transcurrido por cuadro? (¿O el equivalente de actualización fija?) Debe tener en cuenta el tiempo transcurrido y decidir cuánto tiempo real desea que le tome a su ISS simulada hacer una órbita para establecer una escala de tiempo. Tu v está en unidades de 100 m/s, pero tus dimensiones lineales están en unidades de 100 km.