¿Cómo puedo interceptar un objeto con un movimiento circular?

23

Estoy creando un juego espacial en 2D y necesito hacer que la nave espacial intercepte un planeta. Tengo un código de trabajo para las intersecciones en línea recta, pero no puedo entender cómo calcular la ubicación de los planetas en una órbita circular.

El juego no es científicamente preciso, así que no me preocupa la inercia, la gravedad, las órbitas elípticas, etc.

Conozco la ubicación y la velocidad de las naves espaciales y también la órbita (radio) y la velocidad de los planetas.

ingrese la descripción de la imagen aquí

Ausa
fuente
1
No, estoy tratando de calcular el ángulo que la nave necesita moverse para interceptar el planeta.
Ausa
44
Esto probablemente funcionaría mejor en math.stackexchange.com ..
Jari Komppa
2
¿Tu nave puede cambiar la velocidad y la dirección, o son constantes? Además, esta pregunta sobre cómo evitar que los misiles rodeen un objetivo podría ser útil.
thegrinner
44
Para aclarar, ¿es la situación? dado para el planeta: centro de la órbita, radio de la órbita, velocidad angular, ubicación actual; para el barco : ubicación actual, velocidad actual; determinar la dirección del movimiento de la nave para interceptar el planeta
AakashM
66
Como nota histórica interesante: los planetas generalmente giran en la misma dirección que su órbita, por lo que también es en sentido antihorario como se ve desde arriba del hemisferio norte. De este hecho podemos deducir que los relojes de sol fueron inventados en el hemisferio norte . Si se hubieran inventado relojes de sol en el hemisferio sur, en sentido horario sería lo contrario .
Eric Lippert

Respuestas:

3

Una solución analítica para esto es difícil, pero podemos usar la búsqueda binaria para encontrar una solución dentro de la precisión requerida.

El barco puede alcanzar el punto más cercano en la órbita en el tiempo t_min :

shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;

La nave puede alcanzar CUALQUIER punto de la órbita en un tiempo menor o igual que t_max :

(Aquí, por simplicidad, supongo que el barco puede conducir a través del sol. Si desea evitar esto, entonces deberá cambiar a caminos que no sean de línea recta por al menos algunos casos. "Los círculos de besos" pueden verse bien y orbitales) mecánica-y, sin cambiar el algoritmo en más de un factor constante)

if(shipOrbitRadius > planet.orbitRadius)
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}

Si nuestro período orbital es corto, podríamos mejorar en este límite superior eligiendo t_maxser la primera vez después de t_minque el planeta se acerque más a la posición de inicio de la nave. Tome cualquiera de estos dos valores de t_maxes menor. Vea esta respuesta posterior para obtener una derivación de por qué esto funciona.

Ahora podemos usar la búsqueda binaria entre estos extremos, t_min y t_max . Buscaremos un valor t que obtenga el error cercano a cero:

error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;

(Con esta construcción, error @ t_min> = 0 y error @ t_max <= 0, por lo que debe haber al menos una intersección con error = 0 para un valor t intermedio)

donde, para completar, la función de posición es algo así como ...

Vector2 Planet.positionAtTime(float t)
{
  angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
  return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}

Tenga en cuenta que si el período orbital del planeta es muy corto en comparación con la velocidad de la nave, esta función de error puede cambiar los signos varias veces durante t_min a t_max. Simplemente haga un seguimiento del primer par + ve & -ve que encuentre y continúe buscando entre ellos hasta que el error esté lo suficientemente cerca de cero ("lo suficientemente cerca" es sensible a sus unidades y contexto de juego. El cuadrado de la mitad de la duración del cuadro puede funciona bien, eso asegura que la intercepción sea precisa dentro de un marco)

Una vez que tengas un buen t para minimizar errores, puedes apuntar la nave hacia planet.positionAtTime (t) y acelerar a fondo, seguro de que el planeta llegará a ese punto al mismo tiempo que tú.

Siempre puede encontrar una solución dentro de las iteraciones Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold). Entonces, por ejemplo, si mi nave puede atravesar la órbita en 60 cuadros, y quiero una intersección precisa dentro de un cuadro, necesitaré alrededor de 6 iteraciones.

DMGregory
fuente
1
Muchas buenas respuestas aquí, también algunas opciones alternativas interesantes, pero por lo que ya tenía, esta solución se ve mejor para mi instancia. He creado una pequeña demostración de JavaScript de mis resultados. Demostración
Ausa
11

No complicamos demasiado esto. Esta no es una solución "perfecta", pero debería funcionar para la mayoría de los juegos y cualquier imperfección debería ser invisible para el jugador.

if(!OldTargetPoint)
  TargetPoint = PlanetPosition;
else
  TargetPoint = OldTargetPoint;
Distance = CurPosition - TargetPoint;
TimeNeeded = Distance / Speed;
TargetPoint = PlanetPositionInFuture(TimeNeeded);
SteerTowards(TargetPoint);
[...repeat this every AI update, for example every second...]
  1. Calcule el tiempo necesario para alcanzar el punto objetivo.
  2. Calcule en qué posición estará el planeta en el tiempo calculado.
  3. Moverse hacia el punto calculado.
  4. Repetir

Esto funciona porque cuanto más se acerca la nave espacial, más bajo se vuelve el error. Entonces el cálculo se vuelve más estable con el tiempo.

El error es la diferencia entre el tiempo necesario calculado para llegar al planeta (TimeNeeded) y el tiempo real necesario para llegar al planeta (después de tener en cuenta el nuevo TargetPoint).

API-Bestia
fuente
1
Es posible que desee ejecutar 2 iteraciones de esto al comenzar un curso de intercepción, de lo contrario, puede ver el barco parpadear entre dos direcciones momentáneamente (la segunda suposición puede ser mucho mejor que la primera y dar como resultado un rumbo muy diferente, especialmente si la nave está cerca o dentro de la órbita del planeta)
DMGregory
1
@DMGregory ¡Oh! Podríamos simplemente tomar la posición actual del planeta en lugar del centro de órbita como punto de partida. Cuando estamos cerca, eso está mucho más cerca, si estamos lejos, no importa.
API-Beast
También vale la pena señalar que esto funciona mejor cuando el planeta se mueve lentamente en comparación con la nave. Si la velocidad del planeta es comparable o mayor que la de la nave, puede ver oscilaciones en la trayectoria de la nave. A relaciones de velocidad patológicas, la nave puede perseguir al planeta para siempre en una órbita concéntrica. Si sus planetas son rápidos y nota que esto sucede, es posible que desee planificar todo su curso de intercepción por adelantado en lugar de iterar a mitad del vuelo.
DMGregory
3

Comencemos por echar un vistazo a las matemáticas detrás del problema.

Paso 1:

Encontrar la intersección entre una línea y una forma es solo una cuestión de insertar la ecuación de la línea en la ecuación de la forma, que en este caso es un círculo.

Línea que se cruza con círculo

Toma un círculo con centro c y el radio r . Un punto p está en el círculo si

|pc|2=r2

p=p0+μv (donde v es un vector, http://en.wikipedia.org/wiki/Euclidean_vector ), inserta la línea en la fórmula del círculo y obtiene

|p0+μvc|2=r2

La distancia al cuadrado se puede reescribir como un producto de punto ( http://en.wikipedia.org/wiki/Dot_product ).

(p0+μvc)(p0+μvc)=r2

a=cp0(μva)(μva)=r2

μ2(vv)2μ(av)+aa=r2

|v|=1

μ22μ(av)+|a|2r2=0

que es una ecuación cuadrática simple, y llegamos a la solución

μ=av+sqrt((av)2a2r2)

μ<0

μ=0

μ

Paso 2:

Entonces podemos definir una línea para el barco, y de eso obtenemos 0, 1 o 2 μ valores . Si obtenemos 1 valor, use ese. Si obtenemos 2, simplemente elija uno de ellos.

¿Qué podemos hacer con esto? Bueno, ahora sabemos la distancia que debe recorrer el barco y en qué punto terminará.

p=p0+μvμv componente nos da qué tan lejos tendrá que viajar. ¡Simplemente divida este último componente con la velocidad de su nave para obtener cuánto tiempo le llevará llegar allí!

Ahora, todo lo que queda por hacer es calcular dónde debería estar el planeta cuando la nave comience a acercarse a su órbita. Esto se calcula fácilmente con los denominados coodinatos polares ( http://mathworld.wolfram.com/PolarCoordinates.html )

x=c+rcos(θ)

y=c+rsin(θ)

tangularVelocity

Resumen

Elige una línea para tu nave y ejecuta los cálculos para ver si choca con la órbita del planeta. Si lo hace, calcule el tiempo que llevará llegar a ese punto. Use este tiempo para regresar a la órbita desde este punto con el planeta para calcular dónde debería estar el planeta cuando la nave comience a moverse.

Tholle
fuente
8
Buen análisis, pero no parece responder a la pregunta (aclarado en un comentario): "No, estoy tratando de calcular el ángulo que la nave necesita moverse para interceptar el planeta". Estás tomando el ángulo de la nave como algo dado y calculando la posición del planeta, en lugar de al revés.
Chaosed0
44
No voy a rechazar esto porque es un análisis útil, pero estoy de acuerdo con @ Chaosed0 en que no responde la pregunta. En tu resumen dices "Elige una línea para tu barco ...", pero elegir esa línea es exactamente la parte difícil.
Drake
1

Aquí hay dos soluciones ligeramente "listas para usar".

La pregunta es: dado que la nave se mueve en línea recta a una velocidad dada, y el planeta se mueve en un círculo de radio dado a una velocidad angular dada, y las posiciones iniciales del planeta y la nave, determinan qué vector de dirección de la nave debe haber una línea recta para trazar un curso de intercepción

Solución uno: negar la premisa de la pregunta. La cantidad que es "deslizable" en la pregunta es el ángulo. En cambio, arregla eso. Apunte la nave directamente al centro de la órbita.

  • Calcule la posición en la que la nave se encontrará con el planeta; eso es fácil.
  • Calcule la distancia desde el barco a la posición de intercepción; También fácil.
  • Calcule el tiempo que tomará hasta que el planeta alcance la posición de intercepción. Fácil.
  • Divide la distancia desde la nave hasta la intersección por el tiempo hasta que el planeta llegue a la intersección.
  • Si eso es menor o igual que la velocidad máxima de la nave, ya está. Pon la nave en movimiento a esa velocidad directamente hacia el sol.
  • De lo contrario, agregue el período orbital del planeta al tiempo e intente nuevamente. Sigue haciéndolo hasta que obtengas una velocidad que esté dentro de lo razonable para el barco.

Solución dos: no lo hagas en piloto automático en absoluto. Haz un mini-juego en el que el jugador tenga que usar propulsores para acercarse al planeta, y si lo golpean a una velocidad relativa demasiado alta, explotan, pero también tienen combustible limitado. ¡Haz que el jugador aprenda a resolver el problema de intercepción!

Eric Lippert
fuente
1

(x,y,t)

tv=x2+y2

v

La posición del planeta en el espacio y el tiempo se puede parametrizar, p. Ej.

x=x0+rcos(wu+a)y=y0+rsin(wu+a)t=u

tu0 0wunatu

uv=(x0+rcos(wu+a))2+(y0+rsin(wu+a))2u2v2=(x0+rcos(wu+a))2+(y0+rsin(wu+a))2u2v2=x02+y02+r2+2x0rcos(wu+a)+2y0rsin(wu+a)

Esta ecuación necesita ser resuelta numéricamente. Puede tener muchas soluciones. Al mirarlo, parece que siempre tiene una solución

Toni Makkonen
fuente
1

Aquí hay parte de una solución. No pude terminarlo a tiempo. Lo intentaré más tarde.

Si entiendo correctamente, tienes la posición y velocidad de un planeta, así como la posición y velocidad de una nave. Desea obtener la dirección de movimiento del barco. Supongo que las velocidades de la nave y del planeta son constantes. También supongo, sin pérdida de generalidad, que el barco está en (0,0); para hacer esto, reste la posición de la nave de la del planeta y agregue la posición de la nave nuevamente al resultado de la operación que se describe a continuación.

Desafortunadamente, sin látex , no puedo formatear esta respuesta muy bien, pero intentaremos hacerlo. Dejar:

  • s_s = la velocidad del barco (s_s.x, s_s.y, igualmente)
  • s_a= el rumbo del barco (ángulo de movimiento, lo que queremos calcular )
  • p_p = posición inicial del planeta, coordenadas globales
  • p_r = la distancia del planeta (radio) desde el centro de la órbita, derivable de p_p
  • p_a = el ángulo inicial del planeta en radianes, en relación con el centro de la órbita
  • p_s = la velocidad angular del planeta (rad / seg)
  • t = el tiempo de colisión (esto resulta ser algo que también debemos calcular)

Aquí están las ecuaciones para la posición de los dos cuerpos, desglosadas en componentes:

ship.x = s_s.x * t * cos(s_a)
ship.y = s_s.y * t * sin(s_a)

planet.x = p_r * cos(p_a + p_s * t) + p_p.x
planet.y = p_r * sin(p_a + p_s * t) + p_p.y

Como queremos ship.x = planet.xy ship.y = planet.yen algún momento t, obtenemos esta ecuación (el ycaso es casi simétrico):

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
   s_s.y * t * sin(s_a) = p_r * sin(p_a + p_s * t) + p_p.y

Resolviendo la ecuación superior para s_a:

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
=> s_a = arccos((p_r * cos(p_a + p_s * t) + p_p.x) / (s_s.x * t))

Sustituir esto en la segunda ecuación da como resultado una ecuación bastante aterradora que Wolfram alpha no resolverá por mí . Puede haber una mejor manera de hacer esto sin involucrar coordenadas polares. Si alguien quiere probar este método, puede hacerlo; He hecho esto un wiki. De lo contrario, puede llevar esto a Math StackExchange .

Caosed0
fuente
2
Me encantaría tener TeX habilitado para este sitio. Haría que algunas cosas relacionadas con gráficos (por ejemplo, vectores, matrices, cuaterniones ...) sean más fáciles de representar.
mvw
0

Arreglaría la ubicación en la que interceptar (pastar el círculo, en el lado "saliente" de la órbita).

Ahora solo tienes que ajustar la velocidad de la nave espacial para que el planeta y la nave lleguen a ese punto al mismo tiempo.

Tenga en cuenta que la cita podría ser después de N órbitas más, dependiendo de qué tan lejos esté la nave y qué tan rápido el planeta orbita la estrella.

Elija la N que con el tiempo se acerca más a la duración del viaje del barco a la velocidad actual.

Luego, acelere o reduzca la velocidad de la nave para que coincida exactamente con la marca de tiempo de esas N órbitas.

¡En todo esto, el curso real ya se conoce! Simplemente no la velocidad.

Bram
fuente
Esto podría dar viajes innecesariamente largos. Digamos que estamos posicionados para que el planeta se acerque a nosotros y podamos alcanzar el punto de pastoreo "entrante" al mismo tiempo que el planeta. Si solo estamos viendo el punto de pastoreo "saliente", ¡podríamos terminar gastando medio año extra en tránsito!
DMGregory
Es cierto ... depende de las velocidades orbitales. Pero también minimiza la velocidad delta si siempre pastas en las salidas. En "entrante" podría quemarse en la atmósfera, mientras que en "saliente" es más probable que lo emparejen. @DMGregory
Bram