src/node/random-direction-position.cc
changeset 1575 cbc37ce4b91d
child 1579 a4187ed1e45e
equal deleted inserted replaced
1574:cf1ff5bfac1e 1575:cbc37ce4b91d
       
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2007 INRIA
       
     4  * All rights reserved.
       
     5  *
       
     6  * This program is free software; you can redistribute it and/or modify
       
     7  * it under the terms of the GNU General Public License version 2 as
       
     8  * published by the Free Software Foundation;
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License
       
    16  * along with this program; if not, write to the Free Software
       
    17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    18  *
       
    19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    20  */
       
    21 #include "ns3/random-variable-default-value.h"
       
    22 #include "ns3/rectangle-default-value.h"
       
    23 #include "ns3/simulator.h"
       
    24 #include <algorithm>
       
    25 #include <cmath>
       
    26 #include "random-direction-position.h"
       
    27 
       
    28 namespace ns3 {
       
    29 
       
    30 const double RandomDirectionPosition::PI = 3.1415;
       
    31 const InterfaceId RandomDirectionPosition::iid = 
       
    32   MakeInterfaceId ("RandomDirectionPosition", Position::iid);
       
    33 const ClassId RandomDirectionPosition::cid = 
       
    34   MakeClassId<RandomDirectionPosition,double,double> ("RandomDirectionPosition",
       
    35 						      RandomDirectionPosition::iid);
       
    36 
       
    37 
       
    38 static RandomVariableDefaultValue 
       
    39   g_speedVariable ("RandomDirectionSpeed",
       
    40 		   "A random variable to control the speed of a RandomDirection mobility model.",
       
    41 		   "Uniform:1:2");
       
    42 
       
    43 static RandomVariableDefaultValue
       
    44   g_pauseVariable ("RandomDirectionPause",
       
    45 		   "A random variable to control the duration of of the pause of a RandomDiretion mobility model.",
       
    46 		   "Constant:2");
       
    47 
       
    48 static RectangleDefaultValue
       
    49   g_rectangle ("RandomDirectionArea",
       
    50 	       "The bounding area for the RandomDirection model.",
       
    51 	       -100, 100, -100, 100);
       
    52 
       
    53 
       
    54 RandomDirectionParameters::RandomDirectionParameters ()
       
    55   : m_xMin (g_rectangle.GetMinX ()),
       
    56     m_xMax (g_rectangle.GetMaxX ()),
       
    57     m_yMin (g_rectangle.GetMinY ()),
       
    58     m_yMax (g_rectangle.GetMaxY ()),
       
    59     m_speedVariable (g_speedVariable.GetCopy ()),
       
    60     m_pauseVariable (g_pauseVariable.GetCopy ())
       
    61 {}
       
    62 RandomDirectionParameters::RandomDirectionParameters (double xMin, double xMax, double yMin, double yMax)
       
    63   : m_xMin (xMin),
       
    64     m_xMax (xMax),
       
    65     m_yMin (yMin),
       
    66     m_yMax (yMax),
       
    67     m_speedVariable (g_speedVariable.GetCopy ()),
       
    68     m_pauseVariable (g_pauseVariable.GetCopy ())
       
    69 {}
       
    70 RandomDirectionParameters::RandomDirectionParameters (double xMin, double xMax, double yMin, double yMax,
       
    71 						      const RandomVariable &speedVariable,
       
    72 						      const RandomVariable &pauseVariable)
       
    73   : m_xMin (xMin),
       
    74     m_xMax (xMax),
       
    75     m_yMin (yMin),
       
    76     m_yMax (yMax),
       
    77     m_speedVariable (speedVariable.Copy ()),
       
    78     m_pauseVariable (pauseVariable.Copy ())
       
    79 {}
       
    80 
       
    81 RandomDirectionParameters::~RandomDirectionParameters ()
       
    82 {
       
    83   delete m_speedVariable;
       
    84   delete m_pauseVariable;
       
    85   m_speedVariable = 0;
       
    86   m_pauseVariable = 0;
       
    87 }
       
    88 
       
    89 void 
       
    90 RandomDirectionParameters::SetSpeed (const RandomVariable &speedVariable)
       
    91 {
       
    92   delete m_speedVariable;
       
    93   m_speedVariable = speedVariable.Copy ();
       
    94 }
       
    95 void 
       
    96 RandomDirectionParameters::SetPause (const RandomVariable &pauseVariable)
       
    97 {
       
    98   delete m_pauseVariable;
       
    99   m_pauseVariable = pauseVariable.Copy ();
       
   100 }
       
   101 void 
       
   102 RandomDirectionParameters::SetBounds (double xMin, double xMax, double yMin, double yMax)
       
   103 {
       
   104   m_xMin = xMin;
       
   105   m_yMin = yMin;
       
   106   m_xMax = xMax;
       
   107   m_yMax = yMax;
       
   108 }
       
   109 
       
   110 Ptr<RandomDirectionParameters> 
       
   111 RandomDirectionPosition::GetDefaultParameters (void)
       
   112 {
       
   113   static Ptr<RandomDirectionParameters> parameters = Create<RandomDirectionParameters> ();
       
   114   if (parameters->m_xMin != g_rectangle.GetMinX () ||
       
   115       parameters->m_yMin != g_rectangle.GetMinY () ||
       
   116       parameters->m_xMax != g_rectangle.GetMaxX () ||
       
   117       parameters->m_yMax != g_rectangle.GetMaxY () ||
       
   118       g_speedVariable.IsDirty () ||
       
   119       g_pauseVariable.IsDirty ())
       
   120     {
       
   121       parameters = Create<RandomDirectionParameters> ();
       
   122       g_speedVariable.ClearDirtyFlag ();
       
   123       g_pauseVariable.ClearDirtyFlag ();
       
   124     }
       
   125   return parameters;
       
   126 }
       
   127 
       
   128 
       
   129 RandomDirectionPosition::RandomDirectionPosition ()
       
   130   : m_parameters (GetDefaultParameters ()),
       
   131     m_x (0.0),
       
   132     m_y (0.0),
       
   133     m_dx (0.0),
       
   134     m_dy (0.0),
       
   135     m_prevTime (Simulator::Now ()),
       
   136     m_pauseStart (Simulator::Now ())
       
   137 {
       
   138   SetInterfaceId (RandomDirectionPosition::iid);
       
   139   InitializeDirectionAndSpeed ();
       
   140 }
       
   141 bool
       
   142 RandomDirectionPosition::CheckPosition (void) const
       
   143 {
       
   144   return 
       
   145     m_x <= m_parameters->m_xMax && 
       
   146     m_x >= m_parameters->m_xMin &&
       
   147     m_y <= m_parameters->m_yMax && 
       
   148     m_y >= m_parameters->m_yMin;
       
   149 }
       
   150 
       
   151 RandomDirectionPosition::RandomDirectionPosition (double x, double y)
       
   152   : m_parameters (GetDefaultParameters ()),
       
   153     m_x (x),
       
   154     m_y (y),
       
   155     m_dx (0.0),
       
   156     m_dy (0.0),
       
   157     m_prevTime (Simulator::Now ()),
       
   158     m_pauseStart (Simulator::Now ())
       
   159 {
       
   160   SetInterfaceId (RandomDirectionPosition::iid);
       
   161   NS_ASSERT (CheckPosition ());
       
   162   InitializeDirectionAndSpeed ();
       
   163 }
       
   164 RandomDirectionPosition::RandomDirectionPosition (Ptr<RandomDirectionParameters> parameters)
       
   165   : m_parameters (parameters),
       
   166     m_x (0.0),
       
   167     m_y (0.0),
       
   168     m_dx (0.0),
       
   169     m_dy (0.0),
       
   170     m_prevTime (Simulator::Now ()),
       
   171     m_pauseStart (Simulator::Now ())
       
   172 {
       
   173   SetInterfaceId (RandomDirectionPosition::iid);
       
   174   InitializeDirectionAndSpeed ();
       
   175   NS_ASSERT (CheckPosition ());
       
   176 }
       
   177 RandomDirectionPosition::RandomDirectionPosition (Ptr<RandomDirectionParameters> parameters,
       
   178 						  double x, double y)
       
   179   : m_parameters (parameters),
       
   180     m_x (x),
       
   181     m_y (y),
       
   182     m_dx (0.0),
       
   183     m_dy (0.0),
       
   184     m_prevTime (Simulator::Now ()),
       
   185     m_pauseStart (Simulator::Now ())
       
   186 {
       
   187   SetInterfaceId (RandomDirectionPosition::iid);
       
   188   InitializeDirectionAndSpeed ();
       
   189   NS_ASSERT (CheckPosition ());
       
   190 }
       
   191 void 
       
   192 RandomDirectionPosition::DoDispose (void)
       
   193 {
       
   194   m_parameters = 0;
       
   195   // chain up.
       
   196   Position::DoDispose ();
       
   197 }
       
   198 enum RandomDirectionPosition::Side
       
   199 RandomDirectionPosition::CalculateIntersection (double &x, double &y)
       
   200 {
       
   201   double xMin = m_parameters->m_xMin;
       
   202   double xMax = m_parameters->m_xMax;
       
   203   double yMin = m_parameters->m_yMin;
       
   204   double yMax = m_parameters->m_yMax;
       
   205   double xMaxY = m_y + (xMax - m_x) / m_dx * m_dy;
       
   206   double xMinY = m_y + (xMin - m_x) / m_dx * m_dy;
       
   207   double yMaxX = m_x + (yMax - m_y) / m_dy * m_dx;
       
   208   double yMinX = m_x + (yMin - m_y) / m_dy * m_dx;
       
   209   bool xMaxOk = xMaxY <= yMax && xMaxY >= yMin;
       
   210   bool xMinOk = xMinY <= yMax && xMinY >= yMin;
       
   211   bool yMaxOk = yMaxX <= xMax && yMaxX >= xMin;
       
   212   bool yMinOk = yMinX <= xMax && yMinX >= xMin;
       
   213   if (xMaxOk && m_dx >= 0)
       
   214     {
       
   215       x = xMax;
       
   216       y = xMaxY;
       
   217       return RandomDirectionPosition::RIGHT;
       
   218     }
       
   219   else if (xMinOk && m_dx <= 0)
       
   220     {
       
   221       x = xMin;
       
   222       y = xMinY;
       
   223       return RandomDirectionPosition::LEFT;
       
   224     }
       
   225   else if (yMaxOk && m_dy >= 0)
       
   226     {
       
   227       x = yMaxX;
       
   228       y = yMax;
       
   229       return RandomDirectionPosition::TOP;
       
   230     }
       
   231   else if (yMinOk && m_dy <= 0)
       
   232     {
       
   233       x = yMinX;
       
   234       y = yMin;
       
   235       return RandomDirectionPosition::BOTTOM;
       
   236     }
       
   237   else
       
   238     {
       
   239       NS_ASSERT (false);
       
   240       // quiet compiler
       
   241       return RandomDirectionPosition::RIGHT;
       
   242     }
       
   243 }
       
   244 void
       
   245 RandomDirectionPosition::InitializeDirectionAndSpeed (void)
       
   246 {
       
   247   double direction = UniformVariable::GetSingleValue (0, 2 * PI);
       
   248   SetDirectionAndSpeed (direction);
       
   249 }
       
   250 void
       
   251 RandomDirectionPosition::SetDirectionAndSpeed (double direction)
       
   252 {
       
   253   double speed = m_parameters->m_speedVariable->GetValue ();
       
   254   m_dx = std::cos (direction) * speed;
       
   255   m_dy = std::sin (direction) * speed;
       
   256   double x, y;
       
   257   m_side = CalculateIntersection (x, y);
       
   258   double deltaX = x - m_x;
       
   259   double deltaY = y - m_y;
       
   260   double distance = sqrt (deltaX * deltaX + deltaY * deltaY);
       
   261   double seconds = distance / speed;
       
   262   double pause = m_parameters->m_pauseVariable->GetValue ();
       
   263   m_pauseStart = Simulator::Now () + Seconds (seconds);
       
   264   m_prevTime = Simulator::Now ();
       
   265   m_event = Simulator::Schedule (Seconds (seconds + pause),
       
   266 				 &RandomDirectionPosition::ResetDirectionAndSpeed, this);
       
   267 }
       
   268 void
       
   269 RandomDirectionPosition::ResetDirectionAndSpeed (void)
       
   270 {
       
   271   Update ();
       
   272   double direction = UniformVariable::GetSingleValue (0, PI);
       
   273   switch (m_side)
       
   274     {
       
   275     case RandomDirectionPosition::RIGHT:
       
   276       direction += PI / 2;
       
   277       break;
       
   278     case RandomDirectionPosition::LEFT:
       
   279       direction += - PI / 2;
       
   280       break;
       
   281     case RandomDirectionPosition::TOP:
       
   282       direction += PI;
       
   283       break;
       
   284     case RandomDirectionPosition::BOTTOM:
       
   285       direction += 0.0;
       
   286       break;
       
   287     }
       
   288   SetDirectionAndSpeed (direction);
       
   289   NotifyCourseChange ();
       
   290 }
       
   291 void
       
   292 RandomDirectionPosition::Update (void) const
       
   293 {
       
   294   Time end = std::min (Simulator::Now (), m_pauseStart);
       
   295   if (m_prevTime >= end)
       
   296     {
       
   297       return;
       
   298     }
       
   299   Time deltaTime = end - m_prevTime;
       
   300   m_prevTime = Simulator::Now ();
       
   301   double deltaS = deltaTime.GetSeconds ();
       
   302   NS_ASSERT (CheckPosition ());
       
   303   m_x += m_dx * deltaS;
       
   304   m_y += m_dy * deltaS;
       
   305   // round to closest boundaries.
       
   306   m_x = std::min (m_x, m_parameters->m_xMax);
       
   307   m_x = std::max (m_x, m_parameters->m_xMin);
       
   308   m_y = std::min (m_y, m_parameters->m_yMax);
       
   309   m_y = std::max (m_y, m_parameters->m_yMin);
       
   310   NS_ASSERT (CheckPosition ());
       
   311 }
       
   312 void 
       
   313 RandomDirectionPosition::DoGet (double &x, double &y, double &z) const
       
   314 {
       
   315   Update ();
       
   316   x = m_x;
       
   317   y = m_y;
       
   318   z = 0;
       
   319 }
       
   320 void
       
   321 RandomDirectionPosition::DoSet (double x, double y, double z)
       
   322 {
       
   323   bool changed = false;
       
   324   if (m_x != x || m_y != y)
       
   325     {
       
   326       changed = true;
       
   327     }
       
   328   m_x = x;
       
   329   m_y = y;
       
   330   m_prevTime = Simulator::Now ();
       
   331   m_pauseStart = Simulator::Now ();
       
   332   Simulator::Remove (m_event);
       
   333   InitializeDirectionAndSpeed ();
       
   334   NotifyCourseChange ();
       
   335 }
       
   336 
       
   337 
       
   338 
       
   339 } // namespace ns3