Este es un problema que golpeo al intentar implementar un juego usando el motor LÖVE, que cubre box2d con secuencias de comandos Lua.programación de juegos de física box2d - orientación de un objeto parecido a una torreta usando torques
El objetivo es simple: un objeto tipo torre (visto desde la parte superior, en un entorno 2D) necesita orientarse para apuntar a un objetivo.
La torre está en las coordenadas x, y, y el objetivo está en tx, ty. Podemos considerar que x, y son fijas, pero tx, ty tienden a variar de un instante a otro (es decir, serían el cursor del mouse).
La torreta tiene un rotor que puede aplicar una fuerza de rotación (torque) en cualquier momento dado, en sentido horario o antihorario. La magnitud de esa fuerza tiene un límite superior llamado maxTorque.
La torreta también tiene cierta inercia de rotación, que actúa para el movimiento angular de la misma manera que la masa actúa para el movimiento lineal. No hay fricción de ningún tipo, por lo que la torreta seguirá girando si tiene una velocidad angular.
La torreta tiene una pequeña función AI que reevalúa su orientación para verificar que apunta en la dirección correcta y activa el rotador. Esto sucede cada dt (~ 60 veces por segundo). Se ve así ahora:
function Turret:update(dt)
local x,y = self:getPositon()
local tx,ty = self:getTarget()
local maxTorque = self:getMaxTorque() -- max force of the turret rotor
local inertia = self:getInertia() -- the rotational inertia
local w = self:getAngularVelocity() -- current angular velocity of the turret
local angle = self:getAngle() -- the angle the turret is facing currently
-- the angle of the like that links the turret center with the target
local targetAngle = math.atan2(oy-y,ox-x)
local differenceAngle = _normalizeAngle(targetAngle - angle)
if(differenceAngle <= math.pi) then -- counter-clockwise is the shortest path
self:applyTorque(maxTorque)
else -- clockwise is the shortest path
self:applyTorque(-maxTorque)
end
end
... falla. Permítanme explicarlo con dos situaciones ilustrativas:
- La torreta "oscila" alrededor del ángulo de destino.
- Si el objetivo está "justo detrás de la torreta, solo un poco en el sentido de las agujas del reloj", la torreta comenzará a aplicar torques en sentido horario y seguirá aplicándolos hasta el instante en que supere el ángulo deseado. En ese momento comenzará a aplicar pares en la dirección opuesta. Pero habrá ganado una velocidad angular significativa, por lo que seguirá funcionando en el sentido de las agujas del reloj durante algún tiempo ... hasta que el objetivo quede "justo detrás, pero un poco en sentido contrario a las agujas del reloj". Y comenzará de nuevo. Entonces la torreta oscilará o incluso irá en círculos redondos.
Creo que mi torreta debería comenzar a aplicar pares en la "dirección opuesta a la ruta más corta" antes de que alcance el ángulo objetivo (como un frenado de automóvil antes de detenerse).
Intuitivamente, creo que la torreta debería "comenzar a aplicar pares en la dirección opuesta de la ruta más corta cuando está a mitad de camino del objetivo objetivo". Mi intuición me dice que tiene algo que ver con la velocidad angular. Y luego está el hecho de que el objetivo es móvil: no sé si debería tomar eso en cuenta de alguna manera o simplemente ignorarlo.
¿Cómo calculo cuándo la torreta debe "comenzar a frenar"?
El problema con este enfoque es que está diseñado para cosas como sistemas de calefacción, donde lo que controlas es energía, que es la primera derivada de temperatura; egarcia controla el torque, que es el segundo. P rebasará violentamente porque su objetivo es a = 0, no w = 0, I no ayuda con la oscilación, D podría funcionar pero hará que el proceso LENTO. – Beta
Tiene razón, el ejemplo que doy no trata directamente con el par de torsión. Sin embargo, 'maxAngleMomentum' es proporcional a' maxTorque' cuando se considera la fricción en el 'mecanismo' de rotación de la torreta, se pueden considerar intercambiables cuando se usan unidades arbitrarias. – Brendan
La implementación se ve bien. La idea de "conservar el momento angular" es interesante. Sin embargo, esto no es lo que estaba pidiendo, quería aplicar pares, mientras que al final está configurando el ángulo usted mismo. Pero +1 por hacer una demostración y elegancia de código. – kikito