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.
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;
}
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).
-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.
HopDavid
Oblea
Frailecillo
Oblea
HopDavid
Oblea
a = -µ / (2 * E)
que encontré en algún lugar de Internet. Agregué su cálculo del período orbital T comoT = (2 * Mathf.PI) * Mathf.Sqrt(Mathf.Pow(a, 3) / µ)
resultado de un NaN todavía.russell borogove
russell borogove
Oblea
Oblea
russell borogove
Oblea
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.Oblea