src/node/mobility-model-helper.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 19 Jul 2007 10:01:42 +0200
changeset 1619 82612ea8b2a7
parent 1591 4a1f822fe9aa
permissions -rw-r--r--
move delay calculation code from helper to random walk class

#include <cmath>
#include "ns3/simulator.h"
#include "mobility-model-helper.h"

namespace ns3 {

Position2D::Position2D (double _x, double _y)
  : x (_x),
    y (_y)
{}
Position2D::Position2D ()
  : x (0.0),
    y (0.0)
{}

Speed2D::Speed2D (double _dx, double _dy)  
  : dx (_dx),
    dy (_dy)
{}

Speed2D::Speed2D ()  
  : dx (0.0),
    dy (0.0)
{}

MobilityModelHelper::MobilityModelHelper ()
{}
void 
MobilityModelHelper::InitializePosition (const struct Position2D &position)
{
  m_position = position;
  m_speed.dx = 0.0;
  m_speed.dy = 0.0;
  m_lastUpdate = Simulator::Now ();
  m_pauseEnd = Simulator::Now ();
}
void
MobilityModelHelper::Update (const struct AreaBounds &bounds) const
{
  Time now = Simulator::Now ();
  if (m_pauseEnd > now)
    {
      return;
    }
  Time last = std::max (now, m_pauseEnd);
  if (m_lastUpdate >= last)
    {
      return;
    }
  Time deltaTime = now - last;
  m_lastUpdate = now;
  double deltaS = deltaTime.GetSeconds ();
  m_position.x += m_speed.dx * deltaS;
  m_position.y += m_speed.dy * deltaS;
  m_position.x = std::min (m_position.x, bounds.xMax);
  m_position.y = std::min (m_position.y, bounds.yMax);
  m_position.x = std::max (m_position.x, bounds.xMin);
  m_position.y = std::max (m_position.y, bounds.yMin);
}
Position2D 
MobilityModelHelper::CalculateIntersection (const struct AreaBounds &bounds) const
{
  double xMaxY = m_position.y + (bounds.xMax - m_position.x) / m_speed.dx * m_speed.dy;
  double xMinY = m_position.y + (bounds.xMin - m_position.x) / m_speed.dx * m_speed.dy;
  double yMaxX = m_position.x + (bounds.yMax - m_position.y) / m_speed.dy * m_speed.dx;
  double yMinX = m_position.x + (bounds.yMin - m_position.y) / m_speed.dy * m_speed.dx;
  bool xMaxOk = xMaxY <= bounds.yMax && xMaxY >= bounds.yMin;
  bool xMinOk = xMinY <= bounds.yMax && xMinY >= bounds.yMin;
  bool yMaxOk = yMaxX <= bounds.xMax && yMaxX >= bounds.xMin;
  bool yMinOk = yMinX <= bounds.xMax && yMinX >= bounds.xMin;
  if (xMaxOk && m_speed.dx >= 0)
    {
      return Position2D (bounds.xMax, xMaxY);
    }
  else if (xMinOk && m_speed.dx <= 0)
    {
      return Position2D (bounds.xMin, xMinY);
    }
  else if (yMaxOk && m_speed.dy >= 0)
    {
      return Position2D (yMaxX, bounds.yMax);
    }
  else if (yMinOk && m_speed.dy <= 0)
    {
      return Position2D (yMinX, bounds.yMin);
    }
  else
    {
      NS_ASSERT (false);
      // quiet compiler
      return Position2D (0.0, 0.0);
    }
}
double 
MobilityModelHelper::Distance (const Position2D &a, const Position2D &b) const
{
  double dx = a.x - b.x;
  double dy = a.y - b.y;
  return sqrt (dx * dx + dy * dy);
}
			       
Time
MobilityModelHelper::Reset (const struct AreaBounds &bounds,
			    double direction,
			    double speed,
			    const Time &maxMovementDelay,
			    const Time &pauseDelay)
{
  Update (bounds);
  m_pauseEnd = Simulator::Now () + pauseDelay;
  m_speed.dx = std::cos (direction) * speed;
  m_speed.dy = std::sin (direction) * speed;
  Position2D intersection = CalculateIntersection (bounds);
  Time seconds = Seconds (Distance (intersection, m_position) / speed);
  seconds = std::min (seconds, maxMovementDelay);
  return seconds;
}
Time
MobilityModelHelper::Reset (const struct AreaBounds &bounds,
			    double direction,
			    double speed,
			    double maxDistance,
			    const Time &pauseDelay)
{
  Update (bounds);
  m_pauseEnd = Simulator::Now () + pauseDelay;
  m_speed.dx = std::cos (direction) * speed;
  m_speed.dy = std::sin (direction) * speed;
  Position2D intersection = CalculateIntersection (bounds);
  double distance = Distance (intersection, m_position);
  distance = std::min (distance, maxDistance);
  double seconds = distance / speed;
  return Seconds (seconds);
}
Time
MobilityModelHelper::Reset (const struct AreaBounds &bounds,
			    double direction,
			    double speed,
			    const Time &pauseDelay)
{
  Update (bounds);
  m_pauseEnd = Simulator::Now () + pauseDelay;
  m_speed.dx = std::cos (direction) * speed;
  m_speed.dy = std::sin (direction) * speed;
  Position2D intersection = CalculateIntersection (bounds);
  double seconds = Distance (intersection, m_position) / speed;
  return Seconds (seconds);
}

Position2D 
MobilityModelHelper::GetCurrentPosition (const struct AreaBounds &bounds) const
{
  Update (bounds);
  return m_position;
}

Speed2D 
MobilityModelHelper::GetSpeed (void) const
{
  return m_speed;
}

enum MobilityModelHelper::Side 
MobilityModelHelper::GetSide (const struct AreaBounds &bounds) const
{
  if (m_position.x == bounds.xMin)
    {
      return MobilityModelHelper::LEFT;
    }
  if (m_position.x == bounds.xMax)
    {
      return MobilityModelHelper::RIGHT;
    }
  if (m_position.y == bounds.yMin)
    {
      return MobilityModelHelper::BOTTOM;
    }
  if (m_position.y == bounds.yMax)
    {
      return MobilityModelHelper::TOP;
    }
  return MobilityModelHelper::NONE;
}

} // namespace ns3