Steering Behaviors – Pursuit e Evade
O comportamento Pursuit faz com que um agente (perseguidor/pursuer) corra atrás de outro (fugitivo/evader), mas usa a posição futura estimada do fugitivo para calcular a trajetória que o perseguidor irá fazer. O evader é o comportamento contrário, ao invés de ir até a posição futura, o fugitivo tenta evita-la.
Não houve grande mistério na implementação desses algoritmos. O único detalhe é que dessa vez tanto o alvo, quanto o veículo são membros da classe veículo.
Abaixo, segue o código do pursuit:
namespace behavior
{
class Pursuit : public SteerForce
{
private:
const Vehicle& vehicle;
const Vehicle& evader;
public:
Pursuit(const Vehicle& _vehicle, const Vehicle& _evader)
: vehicle(_vehicle), evader(_evader)
{
}
virtual math::Vector2D calculate()
{
//if the evader is ahead and facing the agent then we can just seek
math::Vector2D toEvader =
evader.getPosition() - vehicle.getPosition();
if ((toEvader.dot(vehicle.getVelocity()) > 0) &&
(vehicle.getVelocity().dot(evader.getVelocity()) < 0.95))
return Seek<math::Vector2D>(vehicle, evader.getPosition()).
calculate();
//Not considered ahead, so we predict where the evader will be
//the look-ahead time is proportional to the distance between the
//evader and the vehicle; and it's inversely proportional to the
//sum of the agents velocities.
double lookAheadTime = toEvader.getSize() /
(vehicle.getMaxSpeed() + evader.getVelocity().getSize());
//now seek to the predicted future position of the evader
return Seek<math::Vector2D>(vehicle, evader.getPosition() +
evader.getVelocity() * lookAheadTime).calculate();
}
};
E do Evade:
namespace behavior
{
class Evade : public SteerForce
{
private:
const Vehicle& vehicle;
const Vehicle& pursuer;
public:
Evade(const Vehicle& _vehicle, const Vehicle& _pursuer)
: vehicle(_vehicle), pursuer(_pursuer)
{
}
virtual math::Vector2D calculate()
{
math::Vector2D toPursuer =
pursuer.getPosition() - vehicle.getPosition();
//the look-ahead time is proportional to the distance between the
//pursuer and the vehicle; and it's inversely proportional to the
//sum of the agents velocities.
double lookAheadTime = toPursuer.getSize() /
(vehicle.getMaxSpeed() + pursuer.getVelocity().getSize());
//now flee away from predicted future position of the pursuer
return Flee<math::Vector2D>(vehicle, pursuer.getPosition() +
pursuer.getVelocity() * lookAheadTime).calculate();
}
};
}
Uma das chaves para esses algoritmos é a função que estima a posição futura. Uma idéia interessante talvez seja parametrizar essa função, através de um functor e manter como padrão a função acima. Assim, uma implementação mais precisa poderia levar em consideração mais características físicas dos agentes envolvidos; tais como a velocidade de rotação, aceleração e frenagem; ou mesmo características do cenário, para obter-se um comportamento ainda mais convincente.
