Estou trabalhando em um problema para um jogo simulado. Quero que minha IA seja capaz de mirar em um alvo inimigo em movimento com uma determinada localização inicial, velocidade inicial e aceleração constante.
A posição do inimigo é dada por
p_e(t) = s_e + v_e * t + 0.5 * a_e * t ** 2
e a posição de um projétil disparado é dada por
v_b(theta) = spd_b * (sin(theta), cos(theta))
p_b(theta, t) = v_b(theta) * t
A tarefa é encontrar o ângulo theta
tal que haja algum t
lugar p_e(t) == p_b(t)
, se houver algum, theta
dados os valores dos vários parâmetros.
Resolvi a versão com aceleração zero usando o Sympy. A saída do Sympy pareceu logicamente correta e funcionou corretamente na simulação que estou usando. No entanto, quando tentei resolver a versão com aceleração, tive problemas:
from sympy import *
# Define variables.
#
# Note: we do not define variables for the bullet's starting position, because
# we are going to treat the player ship as a fixed frame of reference.
# Therefore, esx, esy, evx, and evy need to be modified by the controlled
# ship's relative speed and position.
esx, esy, evx, evy, eax, eay = symbols('esx esy evx evy eax eay')
bspd, theta = symbols('bspd theta')
bvx, bvy = bspd * sin(theta), bspd * cos(theta)
t = symbols('t', positive=True)
# Define the x and y positions of the bullet and the enemy.
ex = esx + evx * t + 0.5 * eax * t ** 2
ey = esy + evy * t + 0.5 * eay * t ** 2
bx = bvx * t
by = bvy * t
# Solve for the intersection time in each dimension.
tix = solve(Eq(ex, bx), t)
tiy = solve(Eq(ey, by), t)
print(tix)
print(tiy)
# Set the per-dimension intersection times equal to one another
# and solve for theta.
print(solve(Eq(tix[0], tiy[0]), theta, check=False))
A saída deste programa é:
[(bspd*sin(theta) - evx - 1.4142135623731*sqrt(0.5*bspd**2*sin(theta)**2 - bspd*evx*sin(theta) - eax*esx + 0.5*evx**2))/eax, (bspd*sin(theta) - evx + 1.4142135623731*sqrt(0.5*bspd**2*sin(theta)**2 - bspd*evx*sin(theta) - eax*esx + 0.5*evx**2))/eax]
[(bspd*cos(theta) - evy - 1.4142135623731*sqrt(0.5*bspd**2*cos(theta)**2 - bspd*evy*cos(theta) - eay*esy + 0.5*evy**2))/eay, (bspd*cos(theta) - evy + 1.4142135623731*sqrt(0.5*bspd**2*cos(theta)**2 - bspd*evy*cos(theta) - eay*esy + 0.5*evy**2))/eay]
[-oo*I, oo*I]
Quando executo este código, a impressão final mostra que a solução contém infinito vezes um número imaginário. Agora, tix
e tiy
tenho duas soluções, mas obtenho este resultado independentemente da combinação de soluções que uso.
Não sou um especialista em matemática, e é por isso que estou tentando usar o Sympy para resolver isso. Será que adicionar o termo de aceleração torna realmente impossível resolver este problema? Ou fiz algo errado ao usar o Sympy? Se fiz algo errado ao usar o Sympy, por favor, me digam o que é e como consertar.
Seja a distância do disparo R, o ângulo (anti-horário em relação ao eixo x) θ, a posição inicial do alvo (x0,y0), sua velocidade inicial (ux,uy) e sua aceleração (ax,ay). Seja a velocidade da bala W. Então, como R = Wt,
O quadrado e a adição dão
que é um polinômio de quarta ordem para t.
Um polinômio de quarta ordem pode ter qualquer coisa entre 0 e 4 raízes reais positivas. (Presumo que você não queira ser lembrado de que poderia ter atirado antes!) Se você puder encontrar um, então você obtém θ de
O código abaixo oferece duas soluções legítimas. (Você pode atirar duas vezes!) No entanto, se você diminuir a velocidade da bala para 10, não conseguirá nada.
OBSERVAÇÃO: considerei theta no sentido anti-horário em relação ao eixo x, então cos e seno serão invertidos na velocidade da bala em relação à sua.
Saída:
Seu código tenta corresponder os tempos de ocorrência x e y separadamente, mas eles precisam ocorrer ao mesmo tempo. Resolver as duas equações juntas resolve o problema.