Digamos que tengo una circular móvil target
definida como:
Vector2 position;
Vector2 velocity;
float radius;
Y una rotación turret
(montada en un vehículo en movimiento de algún tipo) definida como:
Vector2 position;
Vector2 velocity;
float angle; // radians
float angularVelocity; // radians per second
const float maxAngularVelocity; // radians per second
const float maxAngularAcceleration; // radians per second per second
(O algo por el estilo. Tenga en cuenta que la posición y la velocidad de ambas están controladas en otra parte: suponga que la velocidad es constante y que la posición cambia según la velocidad).
Estoy tratando de escribir dos funciones de IA relacionadas para determinar, en un marco dado:
¿Qué aceleración angular (y en qué dirección) aplicar al ángulo de la torreta para mantener la torre apuntando al objetivo?
Si el objetivo está actualmente a la vista, ¿se puede mantener a la vista (cualquier parte dentro de su radio) durante
x
segundos, ¿dóndex
está una fracción de segundo? (Alternativamente: ¿existe otra estrategia para garantizar que el objetivo esté realmente "bloqueado" y no simplemente volando a través de las vistas?)
Y podría usar algo de ayuda ...
Respuestas:
Primero debe determinar la diferencia de ángulo entre la dirección de la torreta y la dirección del objetivo.
Una vez que tenga estas cantidades, puede configurar una expresión de segundo grado para el ángulo de la torreta. Debe calcular esto en cada actualización para asegurarse de utilizar siempre los últimos datos de posiciones y velocidades.
Aquí, el primer término (grado cero) en la expresión de aceleración hará que la torreta comience a girar hacia el objetivo. Sin embargo, no se detendrá a tiempo sino que oscilará de un lado a otro. Para detenerlo, necesitamos el segundo término de amortiguación (primer grado) que hace que una alta velocidad de giro se oponga por una alta aceleración.
Ahora las constantes positivas (no necesariamente las constantes del programa) deben determinarse y equilibrarse para que el sistema se comporte bien.
C0
es el mayor control para la velocidad del sistema. Un valor alto paraC0
dará una velocidad de giro rápida y un valor bajo dará una velocidad de giro baja. El valor real depende de muchos factores, por lo que debe usar prueba y error aquí.C1
controla la magnitud de la amortiguación. El discriminante de la ecuación cuadrática nos dice que siC1*C1 - 4*C0 >= 0
tenemos un sistema no oscilante.Probablemente debería elegir
C1
un poco más grande que esto por razones numéricas, pero no demasiado grande, ya que en su lugar se puede amortiguar demasiado y responder lentamente. Nuevamente, necesitas modificar.También es importante tener en cuenta que este código solo calcula la aceleración angular. El ángulo y la velocidad angular deben actualizarse a partir de esto en otro lugar, utilizando un integrador de algún tipo. De la pregunta asumo que esto ha sido cubierto.
Finalmente, hay algo que decir sobre el retraso, porque la torreta probablemente siempre estará detrás cuando se rastrea un objetivo rápido. Una manera simple de abordar esto es agregar una predicción lineal a la posición del objetivo, es decir, siempre apunte un poco hacia adelante en la dirección hacia adelante del objetivo.
En cuanto a mantener la torreta apuntada dentro del radio del objetivo durante algún tiempo, este puede ser un requisito difícil de imponer directamente en este tipo de sistema. Puede estar seguro de que este controlador se esforzará por mantener la torreta apuntada al objetivo (o más bien la posición predicha) en todo momento. Si el resultado resulta no ser satisfactoria tiene que modificar los parámetros
predictionTime
,C0
yC1
(dentro de ciertos límites estables).fuente
k
) y C1 es el factor de amortiguamiento (generalmente llamado 'B' o 'c'). Entonces, sí, puede minimizar la oscilación aumentando la amortiguación, pero el problema es que esto no intenta anticipar dónde estará el objetivo , por lo que está condenado a retrasar el objetivo deseado.Lo que tienes aquí es un problema de control básico . La torreta es el sistema, la aceleración es el control y el sensor mide la posición / velocidad. Hay muchas formas de abordar estos problemas, ya que es un problema muy bien estudiado en ingeniería.
La clave está terminando con un sistema estable, es decir, un sistema que no genera oscilaciones. Esto generalmente se hace agregando amortiguación. La página de wikipedia debería ayudarlo a comenzar.
fuente
En primer lugar, calcule el vector desde la torreta hasta el objetivo. Luego compare esto con el vector actual de la torreta. Luego use la diferencia entre los dos para calcular la aceleración angular y la velocidad angular requeridas para hacer que la torreta gire para apuntar en la dirección correcta dentro de un tiempo determinado.
OK, eso parecía simple. Sin embargo, realmente deberías tratar de anticipar la posición del objetivo ya que el objetivo se moverá para cuando hayas girado la torreta. Para hacer esto:-
donde P es la posición y V es la velocidad y el subíndice es d para el destino (objetivo) ys para la fuente (torreta), lo que da un vector de dirección: -
donde D es un vector de dirección y Dsd 'es la dirección requerida en el tiempo t. Ahora, calcule la dirección de la torreta basándose en la posición actual y la velocidad y aceleración máximas para un tiempo dado t: -
Ds y Ds 'son las direcciones de origen y Rs es la velocidad de rotación. Con todo eso, desea encontrar t para cuando Dsd '== Ds' y, por lo tanto, Rs, la velocidad de rotación requerida. No olvide que todas las P, D y V tienen componentes x e y.
No he tenido en cuenta la aceleración aquí, eso agrega mucho más a la complejidad. Una vez que tenga Rs y t, probablemente podría aproximarse a un Rs parabólico (es decir, acelerar y desacelerar) para obtener el mismo resultado.
fuente
Lo que probablemente esté buscando aquí es un controlador PID , similar a la respuesta aceptada en esta pregunta SO
Inicialmente había respondido esa pregunta "rodando la mía" pero esta respuesta es significativamente más completa y elegante.
fuente
Lo primero que debe hacer es calcular el ángulo entre la torre y el objeto rastreado.
Lo siguiente es verificar si al usar la velocidad actual del torrente y aplicar la aceleración máxima hacia atrás (detener el torrent), el torrent se detendrá antes o después del objeto rastreado.
Si la respuesta es que el torrente se detendrá antes que el objeto rastreado, aplique la aceleración máxima hacia adelante (aumentando la velocidad).
Si la respuesta es que el torrente se detendrá después del objeto rastreado, aplique la aceleración máxima hacia atrás (deteniendo el torrente).
De esta manera, el torrent siempre llegará más rápido y se detendrá en el punto correcto (o una fracción después).
fuente