Rastreamento de alvo: quando acelerar e desacelerar uma torre rotativa?


24

Digamos que eu tenha uma circular móvel targetdefinida como:

Vector2 position;
Vector2 velocity;
float radius;

E uma rotação turret(montada em algum veículo em movimento) 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

(Ou algo nesse sentido. Observe que a posição e a velocidade de ambos são controladas em outros lugares - suponha que a velocidade seja constante e a posição mude com base na velocidade.)

Estou tentando escrever duas funções relacionadas à AI para determinar, em um determinado quadro:

  • Qual aceleração angular (e em qual direção) aplicar ao ângulo da torre para manter a torre apontando para o alvo?

  • Se o alvo estiver à vista no momento, ele (qualquer parte dentro do raio) pode ser mantido à vista por xsegundos, onde xfica uma fração de segundo? (Como alternativa: existe outra estratégia para garantir que o alvo esteja realmente "travado" e não simplesmente voando pelos locais?)

E eu poderia usar alguma ajuda ...


11
Você pode ter valores diferentes para aceleração e desaceleração rotacional - no mundo real, um provavelmente é um motor e o outro um freio.
e100

Respostas:


19

Primeiro, você precisa determinar a diferença de ângulo entre a direção da torre e a direção do alvo.

Vector2 turretToTarget = target.position - turret.position;
float desiredAngle = atan2(turretToTarget.y, turretToTarget.x);
float angleDiff = desiredAngle - turret.angle;

// Normalize angle to [-PI,PI] range. This ensures that the turret
// turns the shortest way.
while (angleDiff < -PI) angleDiff += 2*PI;
while (angleDiff >= PI) angleDiff -= 2*PI;

Depois de ter essas quantidades, você pode configurar uma expressão de segundo grau para o ângulo da torre. Você precisa calcular isso em cada atualização para garantir sempre o uso dos dados mais recentes de posições e velocidades.

// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;

Aqui, o primeiro termo (grau zero) na expressão de aceleração fará com que a torre comece a girar em direção ao alvo. No entanto, ele não para no tempo, mas oscila de um lado para o outro. Para fazê-lo parar, precisamos do amortecimento do segundo termo (primeiro grau), que faz com que uma alta velocidade de rotação seja oposta a uma alta aceleração.

Agora, as constantes positivas (não necessariamente constantes do programa) precisam ser determinadas e equilibradas para que o sistema se comporte bem. C0é o principal controle da velocidade do sistema. Um valor alto para C0dará uma velocidade de rotação rápida e um valor baixo dará uma velocidade de rotação baixa. O valor real depende de muitos fatores; portanto, você deve usar tentativa e erro aqui. C1controla a magnitude do amortecimento. O discriminante da equação quadrática nos diz que se C1*C1 - 4*C0 >= 0temos um sistema não-oscilante.

// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.

Você provavelmente deve escolher C1um pouco maior que isso por razões numéricas, mas não muito grande, pois pode ficar muito úmido e lento para responder. Novamente, você precisa ajustar.

Também é importante observar que esse código calcula apenas a aceleração angular. O ângulo e a velocidade angular precisam ser atualizados a partir disso em outro lugar, usando algum tipo de integrador. Da pergunta, presumo que isso tenha sido coberto.

Finalmente, há algo a dizer sobre o atraso, porque a torre provavelmente sempre estará para trás ao rastrear um alvo rápido. Uma maneira simples de resolver isso é adicionar uma previsão linear à posição do alvo, ou seja, sempre apontar um pouco à frente na direção para frente do alvo.

// Improvement of the first lines above.
const float predictionTime = 1; // One second prediction, you need to experiment.
Vector2 turretToTarget = target.position + predictionTime * target.velocity - turret.position;
/// ...

Quanto a manter a torre apontada dentro do raio do alvo por algum tempo, pode ser um requisito difícil de impor diretamente a esse tipo de sistema. Você pode ter certeza de que este controlador se esforçará para manter a torre apontada para o alvo (ou melhor, para a posição prevista) o tempo todo. Se o resultado acaba por não ser satisfatório você tem que modificar os parâmetros predictionTime, C0e C1(dentro de limites estáveis).


Não estou qualificado para dizer se isso está certo ou não, mas parece algo inteligente! Eu resolvi esses tipos de problemas no passado, prevendo antecipadamente o efeito da aceleração para descobrir quando acelerar e quando "aplicar as quebras". Isso significa que eu tenho feito errado?
Iain

O atan2 dificulta a adaptação desse método a um sistema preditivo, uma vez que os parâmetros xey para atan2 se tornam dependentes de t.
Skizz

Esta é exatamente a solução que eu estava sugerindo na minha resposta abaixo. Excelentes detalhes e apresentação!
Drxzcl 30/07/10

@ Iain: Não, não há certo e errado aqui. Embora eu ache que seu método tenha dois estados distintos: acelerar / desacelerar, esse método é inspirado por um regulador da teoria de controle, escalando a aceleração para obter uma resposta rápida e reduzindo o overshoot e as oscilações.
precisa

11
Como nos outros comentários, isso funcionará para um alvo fixo, mas provavelmente será inaceitável para qualquer alvo em movimento. Os termos C0 e C1 são material tradicional de mola amortecida, onde C0 representa a força da mola (geralmente chamada k) e C1 é o fator de amortecimento (geralmente chamado de 'B' ou 'c'). Portanto, sim, você pode minimizar a oscilação acionando o amortecimento, mas o problema é que isso não tenta antecipar onde o alvo estará , portanto está fadado a atrasar o objetivo desejado.
traço-tom-bang

3

O que você tem aqui é um problema de controle básico . A torre é o sistema, a aceleração é o controle e o sensor mede a posição / velocidade. Existem muitas maneiras de resolver esses problemas, pois é um problema muito bem estudado em engenharia.

A chave está finalizando com um sistema estável, ou seja, um sistema que não gera oscilações. Isso geralmente é feito adicionando amortecimento. A página da Wikipedia deve começar.


2

Primeiro, calcule o vetor da torre para o alvo. Em seguida, compare isso com o vetor atual da torre. Em seguida, use a diferença entre os dois para calcular a aceleração angular e a velocidade angular necessárias para fazer com que a torre gire para apontar na direção certa dentro de um determinado período de tempo.

OK, isso parecia simples. No entanto, você deve realmente tentar antecipar a posição do alvo, já que o alvo se moverá quando você girar a torre. Para fazer isso:-

Pd' = Pd + t.Vd
Ps' = Ps + t.Vs

onde P é a posição e V é a velocidade e o índice é d para o destino (alvo) es para a fonte (torre), que fornece um vetor de direção: -

Dsd' = Pd' - Ps' = Pd + t.Vd - (Ps + t.Vs) = Pd - Ps + (Vd - Vs).t

onde D é um vetor de direção e Dsd 'é a direção necessária no tempo t. Agora, calcule a direção da torre com base na posição atual e velocidade e aceleração máximas por um determinado tempo t: -

Ds' = t.Ds.Rs -> this is a vector rotation

Ds e Ds 'são as direções da fonte e Rs é a velocidade de rotação. Com tudo isso, você deseja encontrar t para quando Dsd '== Ds' e, portanto, Rs, a velocidade de rotação necessária. Não esqueça que todos os P's, D's e V's possuem componentes x e y.

Não levei em consideração a aceleração aqui - isso adiciona muito mais à complexidade. Depois de obter Rs e t, você provavelmente poderá aproximar um Rs parabólico (ou seja, acelerar e desacelerar) para obter o mesmo resultado.


Parece uma boa resposta para o cálculo de interceptação, mas infelizmente existe uma grande lacuna entre as pessoas que podem ler esse tipo de notação matemática e transformá-lo em código de programa, e a maioria das pessoas que cria jogos que ainda não sabem a resposta para a questão. Em outras palavras, acho que os desenvolvedores de jogos que podem ler essa notação matemática provavelmente já podem descobrir como programar a solução de disparo. Isso me ajudaria a entender suas fórmulas se você explicasse o que seus termos significavam.
Dronz 20/03

2

O que você provavelmente está procurando aqui é um controlador PID , semelhante à resposta aceita nesta pergunta do SO

Inicialmente, eu respondi a essa pergunta "fazendo o meu próprio", mas essa resposta é significativamente mais completa e elegante.


0

A primeira coisa a fazer é calcular o ângulo entre o turrent e o objeto rastreado.
O próximo passo é verificar se, usando a velocidade atual do torrent e aplicando a aceleração máxima para trás (interrompendo o torrent), o torrent será interrompido antes ou depois do objeto rastreado.
Se a resposta for que o torrent irá parar antes do objeto rastreado, aplique a aceleração máxima para frente (velocidade crescente).
Se a resposta for que o torrent irá parar após o objeto rastreado, aplique a aceleração máxima para trás (interrompendo o torrent).
Dessa forma, o torrent sempre chegará mais rápido e parará no ponto certo (ou uma fração depois).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.