Balanceo dinámico del propulsor de la nave espacial

14

Las naves espaciales en mi juego están destinadas a ser construidas por jugadores con una cantidad arbitraria de propulsores conectados en cualquier lugar con cualquier rotación. Actualmente tengo un código sucio para rotar la nave a un ángulo determinado (acelerando y desacelerando).

Aquí hay un ejemplo de una nave simétrica orientada hacia donde apunta la línea roja, diciéndole que gire a la izquierda.

Embarcacion

Sin embargo, como se podría imaginar, dependiendo de dónde haya colocado el jugador los propulsores, a veces fuerzas lineales no deseadas están afectando a la nave. En este caso, el barco comienza a avanzar.

Estoy elaborando si es posible encontrar el empuje máximo que puede aplicar un propulsor para no causar velocidad lineal. (En el caso anterior, eso no sería ninguno, ya que no hay nada para contrarrestar las fuerzas de los propulsores traseros, y los delanteros se matan entre sí).

Lo que he encontrado hasta ahora es una fórmula para determinar la "eficiencia de giro", por ejemplo, cuánta rotación se produce en relación con el movimiento lineal.

a - vector de posición al propulsor a b - vector de posición al propulsor b v1 - fuerza del propulsor a v2 - fuerza del propulsor b

eficienciaDelta = a.cross (v1) / | v1 | - (a.cross (v1) + b.cross (v2)) / | v1 + v2 |

, básicamente "a.cross (v1 * t) / | v1 |" se supone que es la eficiencia de giro. Y luego lo restamos por la eficiencia de giro de los propulsores combinados, para ver si vale la pena disparar el nuevo propulsor.

El problema surge cuando me doy cuenta de que no se supone que los propulsores estén encendidos / apagados, sino que pueden variar su empuje de 0 a 1. Y cómo hacerlo cuando el jugador quiere que la nave avance. Por supuesto, tendría que haber un equilibrio de cuánto girar / mover.

No soy un científico de cohetes, así que espero que haya alguien que pueda decirme si es posible calcular el acelerador de cada propulsor de esta manera y darme un empujón en la dirección correcta.

¡Gracias por tomarse el tiempo! / Kim

Kim
fuente
3
Comencé en el mismo camino, pero con muchas configuraciones, es imposible rotar y no traducir. Entonces, ¿quitas la rotación? ¿O permites la traducción? En última instancia, depende del usuario diseñar la nave. Para mi demostración de esto, lo fingí. Relacionado: gamedev.stackexchange.com/questions/58216/… , gamedev.stackexchange.com/questions/40615/…
MichaelHouse
Seguí un camino similar y terminé escribiendo una demostración en esta página . A medida que mueve los propulsores (arrástrelos en el barco para establecer la posición y la potencia), dibuja tres formas. La intuición es que puedes pensar en todos los movimientos posibles como un punto en el espacio 3d (x, y, rotación), y estar limitado a 0-1 es una restricción en ese espacio. Entonces terminas con una forma 3D que contiene todos los movimientos posibles. Si no desea velocidad lineal, está mirando la línea (x = 0, y = 0) en ese espacio (Q, W, E, S, todos 0 en mi demo)
amitp

Respuestas:

7

Asumiré que tienes un movimiento físicamente correcto para tu nave, ya que de lo contrario este análisis no se mantendrá. Necesita algo más fuerte que la eficiencia para resolver este problema correctamente.

Cada propulsor producirá dos efectos sobre el movimiento de la nave: lineal y angular. Estos pueden considerarse de forma independiente. Si el propulsor produce una fuerza fen una dirección diry está desplazado del centro de masa por un vector r(¡no el centro geométrico o el centro del sprite!), Entonces el efecto sobre el componente lineal es:

t = f * dir // f is a scalar, dir is unit length

El efecto sobre la velocidad angular viene dado por el par:

tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product

tes un vector de fuerza (es decir, el empuje lineal). taues un escalar con signo que, cuando se divide por el momento de inercia de la masa, dará la aceleración angular. Es importante que diry rson a la vez en el mismo espacio de coordenadas, es decir, tanto en coordenadas locales o ambos en coordenadas mundiales.

La aceleración lineal general de la nave viene dada por la suma de los t's para cada propulsor dividido por la masa de la nave. Del mismo modo, la aceleración angular es solo la suma de los pares divididos por el momento de inercia de la masa (que es otro escalar). El barco no girará si el par total es cero. Del mismo modo, no se moverá si el empuje total es cero. El par de recuperación es escalar pero el empuje (la suma de los t's) es un vector 2D.

El punto de esta exposición es que ahora podemos escribir nuestro problema como un programa lineal . Digamos primero que queremos que nuestro barco gire sin moverse . Tenemos una variable para cada propulsor, $ x_1, x_2, ... $, que es la cantidad de empuje que proporcionará el propulsor. Un conjunto de restricciones es:

0 <= x_i < fmax_i  //for each i

¿Dónde fmaxestá la fuerza máxima para ese propulsor (esto nos permite tener más fuertes o más débiles). A continuación, decimos que ambas igualdades:

0 = Sum_i  x_i * dir_i.x
0 = Sum_i  x_i * dir_i.y

Esto codifica la restricción de que no aplicaremos una aceleración lineal, al decir que el empuje total es cero (el empuje es un vector, por lo que simplemente decimos que cada parte es cero).

Ahora queremos que nuestro barco gire. Presumiblemente, queremos hacerlo lo más rápido posible, por lo que queremos:

max (Sum_i  x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0>

Resolver los problemas x_imientras satisface las desigualdades e igualdades anteriores, mientras maximiza la suma anterior, nos dará el empuje deseado. La mayoría de los lenguajes de programación tienen una biblioteca LP disponible para ellos. Simplemente coloque el problema anterior y producirá su respuesta.

Un problema similar nos permitirá movernos sin girar. Digamos que reescribimos nuestro problema en un sistema de coordenadas en el que queremos movernos en la dirección x positiva. Entonces las restricciones son:

0 <= x_i < fmax_i  //for each i
max Sum_i  x_i * dir_i.x
0 = Sum_i  x_i * dir_i.y
0 = (Sum_i  x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0> // as before

Con la restricción de que los propulsores solo pueden producir empuje en una sola dirección, habrá límites para el tipo de rotaciones y velocidades lineales que podrá lograr. Esto se manifestará como la solución 0 = x_1 = x_2 = ... = x_n, lo que significa que nunca llegarás a ningún lado. Para mitigar esto, sugiero agregar un par de propulsores pequeños y débiles (por ejemplo, 5% o 10%) para cada jugador que coloque el propulsor a 45 grados a cada lado. Esto le dará más flexibilidad a la solución, ya que se pueden usar para contrarrestar los débiles efectos secundarios de los propulsores principales.

Finalmente, para hasta unos 100 propulsores, la solución al LP es lo suficientemente rápida como para hacerse por cuadro. Sin embargo, debido a que la solución no depende de la ubicación o el estado actual, puede calcular previamente la solución para cada combinación de entrada de controlador razonable cada vez que cambie la forma (esto incluye agregar no impulsores que cambian el momento de inercia o la masa de la nave, ¡porque entonces los propulsores están en una ubicación diferente en relación con el centro de masa!). Esto es 24 posibilidades (es decir, 8 direcciones veces {giro a la izquierda, sin rotación, giro a la derecha}).


fuente
Muy bien explicado!
Kim
1
¿Qué Sum_isignifica en este contexto?
S. Tarık Çetin
1

Mi primer pensamiento fue una solución puramente empírica, que es simular la plataforma en un entorno de caja de arena para diferentes grados de empuje para determinar cómo se comporta. En lugar de equilibrar muchas matemáticas complejas en la búsqueda de una solución determinista, puede alcanzarla numéricamente, por ejemplo, utilizando el método de newtons. Ejemplo:

El rango de empuje es de 0 a 1000 donde 1000 es MUCHO.

Paso 1

Simule con confianza (0 + 1000) / 2 = 500. Resultado: demasiada confianza

Paso 2

El rango ahora es de 0 a 500 Simular con confianza (0 + 500) / 2 = 250. Resultado: demasiada confianza

Paso 3

El rango ahora es de 0 a 250 Simular con confianza (0 + 250) / 2 = 125 Resultado: muy poca confianza

Etapa 4

El rango ahora es de 125 a 250 Simular con confianza (125 + 250) /2=187.5 Resulta demasiada confianza

Paso # 5 El rango ahora es de 125 a 187.5 Simule con confianza (125 + 187.5) /2=156.25 El resultado es muy poca confianza

Paso # 6 El rango ahora es de 156.25 a 187.5 El rango está por debajo del umbral de 35, lo que significa que es una estimación lo suficientemente buena

Resultado final = (187.5 + 156.25) / 2 = 171.875

Lennart Rolland
fuente