Commit 766e1fa7 authored by VAN TOLL Wouter's avatar VAN TOLL Wouter
Browse files

Added CostFunction::GetGradientFromCurrentVelocity(). This makes...

Added CostFunction::GetGradientFromCurrentVelocity(). This makes ForceBasedFunction more efficient (skipping some unnecessary math).
parent 20960efd
......@@ -35,6 +35,11 @@ Vector2D ForceBasedFunction::GetGradient(const Vector2D& velocity, Agent* agent,
return (velocity - targetV) / world->GetDeltaTime();
}
Vector2D ForceBasedFunction::GetGradientFromCurrentVelocity(Agent* agent, const WorldBase * world) const
{
return -ComputeForce(agent, world) / agent->getMass();
}
Vector2D ForceBasedFunction::GetGlobalMinimum(Agent* agent, const WorldBase* world) const
{
return ComputeTargetVelocity(agent, world);
......@@ -43,10 +48,9 @@ Vector2D ForceBasedFunction::GetGlobalMinimum(Agent* agent, const WorldBase* wor
void ForceBasedFunction::parseParameters(const CostFunctionParameters & params)
{
CostFunction::parseParameters(params);
params.ReadFloat("agentMass", agentMass);
}
Vector2D ForceBasedFunction::ComputeTargetVelocity(Agent* agent, const WorldBase* world) const
{
return agent->getVelocity() + ComputeForce(agent, world) / agentMass * world->GetDeltaTime();
return agent->getVelocity() + ComputeForce(agent, world) / agent->getMass() * world->GetDeltaTime();
}
\ No newline at end of file
......@@ -32,12 +32,6 @@
/// you can then focus on just computing the force itself, and everything else will be handled for you.</remarks>
class ForceBasedFunction : public CostFunction
{
protected:
/// <summary>The mass of the agent according to this function. Most force-based methods assume unit mass.</summary>
/// <remarks>This value is used for converting a force to a gradient.
/// The value corresponds to the XML parameter "agentMass".</remarks>
float agentMass = 1;
protected:
ForceBasedFunction() : CostFunction() {}
virtual ~ForceBasedFunction() {}
......@@ -61,6 +55,13 @@ public:
/// <returns>The gradient of the cost function, derived from the result of ComputeForce().</param>
virtual Vector2D GetGradient(const Vector2D& velocity, Agent* agent, const WorldBase * world) const override;
/// <summary>Computes the gradient of the cost at the agent's current velocity, in a way that is specific for force-based functions.</summary>
/// <remarks>In the case of ForceBasedFunction, this should simply return -F/m, and we can skip some computations from the regular GetGradient() function.</remarks>
/// <param name="agent">An agent in the simulation.</param>
/// <param name="world">The world in which the simulation takes place.</param>
/// <returns>The gradient of the cost function, derived from the result of ComputeForce().</param>
virtual Vector2D GetGradientFromCurrentVelocity(Agent* agent, const WorldBase * world) const override;
/// <summary>Computes the globally optimal velocity, in a way that is specific for force-based functions.</summary>
/// <remarks>In the case of ForceBasedFunction, this is the velocity that the agent would reach if it uses the force for one time step.</remarks>
/// <param name="agent">The agent that would use the requested velocity.</param>
......
......@@ -150,6 +150,8 @@ public:
inline float getMaximumSpeed() const { return settings_.max_speed_; };
/// <summary>Returns the agent's maximum acceleration.</summary>
inline float getMaximumAcceleration() const { return settings_.max_acceleration_; };
/// <summary>Returns the agent's mass.</summary>
inline float getMass() const { return settings_.mass_; };
/// <summary>Returns a pointer to the Policy that describes the agent's navigation behavior.</summary>
inline Policy* getPolicy() const { return settings_.policy_; }
/// <summary>Returns whether or not the agent wants to be removed from the simulation when it reaches its goal.</summary>
......
......@@ -53,6 +53,11 @@ Vector2D CostFunction::GetGradient(const Vector2D& velocity, Agent* agent, const
return Vector2D(gradientX, gradientY);
}
Vector2D CostFunction::GetGradientFromCurrentVelocity(Agent* agent, const WorldBase* world) const
{
return GetGradient(agent->getVelocity(), agent, world);
}
Vector2D CostFunction::GetGlobalMinimum(Agent* agent, const WorldBase* world) const
{
// By default, we approximate the global optimum via sampling.
......
......@@ -164,6 +164,14 @@ public:
/// <returns>A 2D vector denoting the gradient of the cost function at the given velocity.</param>
virtual Vector2D GetGradient(const Vector2D& velocity, Agent* agent, const WorldBase* world) const;
/// <summary>Computes the gradient of the cost at the agent's current velocity.</summary>
/// <remarks>By default, this function simply calls GetGradient(),
/// but a subclass might have a more efficient implementation that computes the same result.</remarks>
/// <param name="agent">An agent in the simulation.</param>
/// <param name="world">The world in which the simulation takes place.</param>
/// <returns>The gradient of the cost function, derived from the result of ComputeForce().</param>
virtual Vector2D GetGradientFromCurrentVelocity(Agent* agent, const WorldBase * world) const;
/// <summary>Computes the global minimum of the cost function, i.e. the velocity with minimum cost.</summary>
/// <remarks>By default, this method uses sampling to approximate the global minimum.
/// Subclasses of CostFunction may choose to implement a better (e.g. closed-form) solution.</remarks>
......
......@@ -74,7 +74,7 @@ Vector2D Policy::getAccelerationFromGradient(Agent* agent, WorldBase * world)
// sum up the gradient of all cost functions
Vector2D TotalGradient(0, 0);
for (auto& costFunction : cost_functions_)
TotalGradient += costFunction.second * costFunction.first->GetGradient(CurrentVelocity, agent, world);
TotalGradient += costFunction.second * costFunction.first->GetGradientFromCurrentVelocity(agent, world);
// move in the opposite direction of this gradient
return -1 * TotalGradient;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment