src/helper/ns2-mobility-helper.cc
changeset 6366 ef2e946450fe
parent 6215 617ac18757e6
child 6388 eeb9780b5580
equal deleted inserted replaced
6365:9e4fce3d1138 6366:ef2e946450fe
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     2 /*
     3  * Copyright (c) 2007 INRIA
     3  * Copyright (c) 2007 INRIA
       
     4  *               2009,2010 Contributors
     4  *
     5  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  * published by the Free Software Foundation;
     8  *
     9  *
    14  * You should have received a copy of the GNU General Public License
    15  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    20  * Contributors: Thomas Waldecker <twaldecker@rocketmail.com>
       
    21  *               Martín Giachino <martin.giachino@gmail.com>
       
    22  *
       
    23  * Brief description: Implementation of a ns2 movement trace file reader.
       
    24  *
       
    25  * This implementation is based on the ns2 movement documentation of ns2
       
    26  * as described in http://www.isi.edu/nsnam/ns/doc/node174.html
       
    27  *
       
    28  * Valid trace files use the following ns2 statements:
       
    29  *
       
    30  * $node set X_ x1
       
    31  * $node set Y_ y1
       
    32  * $node set Z_ z1
       
    33  * $ns at $time $node setdest x2 y2 speed
       
    34  * $ns at $time $node set X_ x1
       
    35  * $ns at $time $node set Y_ Y1
       
    36  * $ns at $time $node set Z_ Z1
       
    37  *
    19  */
    38  */
       
    39 
       
    40 
    20 #include <fstream>
    41 #include <fstream>
    21 #include <sstream>
    42 #include <sstream>
       
    43 #include <map>
       
    44 #include <algorithm>
    22 #include "ns3/log.h"
    45 #include "ns3/log.h"
    23 #include "ns3/simulator.h"
    46 #include "ns3/simulator.h"
    24 #include "ns3/node-list.h"
    47 #include "ns3/node-list.h"
    25 #include "ns3/node.h"
    48 #include "ns3/node.h"
    26 #include "ns3/constant-velocity-mobility-model.h"
    49 #include "ns3/constant-velocity-mobility-model.h"
       
    50 #include "ns3/test.h"
       
    51 #include "ns3/node-container.h"
       
    52 #include "ns3/names.h"
       
    53 #include "ns3/config.h"
    27 #include "ns2-mobility-helper.h"
    54 #include "ns2-mobility-helper.h"
    28 
    55 
    29 NS_LOG_COMPONENT_DEFINE ("Ns2MobilityHelper");
    56 NS_LOG_COMPONENT_DEFINE ("Ns2MobilityHelper");
    30 
    57 
       
    58 using namespace std;
       
    59 
    31 namespace ns3 {
    60 namespace ns3 {
       
    61 
       
    62 // Constants definitions
       
    63 #define  NS2_AT       "at"
       
    64 #define  NS2_X_COORD  "X_"
       
    65 #define  NS2_Y_COORD  "Y_"
       
    66 #define  NS2_Z_COORD  "Z_"
       
    67 #define  NS2_SETDEST  "setdest"
       
    68 #define  NS2_SET      "set"
       
    69 #define  NS2_NODEID   "$node_("
       
    70 #define  NS2_NS_SCH   "$ns_"
       
    71 
       
    72 
       
    73 // Type to maintain line parsed and its values
       
    74 struct ParseResult
       
    75 {
       
    76   vector<string> tokens; // tokens from a line
       
    77   vector<int> ivals;     // int values for each tokens
       
    78   vector<bool> has_ival; // points if a tokens has an int value
       
    79   vector<double> dvals;  // double values for each tokens
       
    80   vector<bool> has_dval; // points if a tokens has a double value
       
    81   vector<string> svals;  // string value for each token
       
    82 };
       
    83 
       
    84 
       
    85 // Parses a line of ns2 mobility
       
    86 static ParseResult ParseNs2Line (const string& str);
       
    87 
       
    88 // Put out blank spaces at the start and end of a line
       
    89 static string TrimNs2Line (const string& str);
       
    90 
       
    91 // Checks if a string represents a number or it has others characters than digits an point.
       
    92 static bool IsNumber (const string& s);
       
    93 
       
    94 // Check if s string represents a numeric value
       
    95 template<class T>
       
    96 static bool IsVal (const string& str, T& ret);
       
    97 
       
    98 // Checks if the value between brackets is a correct nodeId number
       
    99 static bool HasNodeIdNumber (string str);
       
   100 
       
   101 // Gets nodeId number in string format from the string like $node_(4)
       
   102 static string GetNodeIdFromToken (string str);
       
   103 
       
   104 // Get node id number in int format
       
   105 static int GetNodeIdInt (ParseResult pr);
       
   106 
       
   107 // Get node id number in string format
       
   108 static string GetNodeIdString (ParseResult pr);
       
   109 
       
   110 // Add one coord to a vector position
       
   111 static Vector SetOneInitialCoord (Vector actPos, string& coord, double value);
       
   112 
       
   113 // Check if this corresponds to a line like this: $node_(0) set X_ 123
       
   114 static bool IsSetInitialPos (ParseResult pr);
       
   115 
       
   116 // Check if this corresponds to a line like this: $ns_ at 1 "$node_(0) setdest 2 3 4"
       
   117 static bool IsSchedSetPos (ParseResult pr);
       
   118 
       
   119 // Check if this corresponds to a line like this: $ns_ at 1 "$node_(0) set X_ 2"
       
   120 static bool IsSchedMobilityPos (ParseResult pr);
       
   121 
       
   122 // Set waypoints and speed for movement.
       
   123 static Vector SetMovement (Ptr<ConstantVelocityMobilityModel> model, Vector lastPos, double at,
       
   124                            double xFinalPosition, double yFinalPosition, double speed);
       
   125 
       
   126 // Set initial position for a node
       
   127 static Vector SetInitialPosition (Ptr<ConstantVelocityMobilityModel> model, string coord, double coordVal);
       
   128 
       
   129 // Schedule a set of position for a node
       
   130 static Vector SetSchedPosition (Ptr<ConstantVelocityMobilityModel> model, double at, string coord, double coordVal);
    32 
   131 
    33 
   132 
    34 Ns2MobilityHelper::Ns2MobilityHelper (std::string filename)
   133 Ns2MobilityHelper::Ns2MobilityHelper (std::string filename)
    35   : m_filename (filename)
   134   : m_filename (filename)
    36 {}
   135 {
    37 
   136 }
    38 
       
    39 
   137 
    40 Ptr<ConstantVelocityMobilityModel>
   138 Ptr<ConstantVelocityMobilityModel>
    41 Ns2MobilityHelper::GetMobilityModel (std::string idString, const ObjectStore &store) const
   139 Ns2MobilityHelper::GetMobilityModel (std::string idString, const ObjectStore &store) const
    42 {
   140 {
    43   std::istringstream iss;
   141   std::istringstream iss;
    56       object->AggregateObject (model);
   154       object->AggregateObject (model);
    57     }
   155     }
    58   return model;
   156   return model;
    59 }
   157 }
    60 
   158 
    61 double
   159 
    62 Ns2MobilityHelper::ReadDouble (std::string valueString) const
   160 void
    63 {
   161 Ns2MobilityHelper::ConfigNodesMovements (const ObjectStore &store) const
    64   std::istringstream iss;
   162 {
    65   iss.str (valueString);
   163   map<int, Vector> last_pos;    // Vector containing lasts positions for each node
    66   double value;
   164 
    67   iss >> value;
       
    68   return value;
       
    69 }
       
    70 
       
    71 void 
       
    72 Ns2MobilityHelper::LayoutObjectStore (const ObjectStore &store) const
       
    73 {
       
    74   std::ifstream file (m_filename.c_str (), std::ios::in);
   165   std::ifstream file (m_filename.c_str (), std::ios::in);
    75   if (file.is_open())
   166   if (file.is_open ())
    76     {
   167     {
    77       while (!file.eof() )
   168       while (!file.eof () )
    78         {
   169         {
       
   170           int         iNodeId = 0;
       
   171           std::string nodeId;
    79           std::string line;
   172           std::string line;
       
   173 
    80           getline (file, line);
   174           getline (file, line);
    81           std::string::size_type startNodeId = line.find_first_of ("(");
   175 
    82           std::string::size_type endNodeId = line.find_first_of (")");
   176           // ignore empty lines
    83           if (startNodeId == std::string::npos ||
   177           if (line.empty ())
    84               endNodeId == std::string::npos)
       
    85             {
   178             {
    86               continue;
   179               continue;
    87             }
   180             }
    88           Ptr<ConstantVelocityMobilityModel> model = GetMobilityModel (line.substr (startNodeId + 1, 
   181 
    89                                                                                endNodeId - (startNodeId + 1)), 
   182           ParseResult pr = ParseNs2Line (line); // Parse line and obtain tokens
    90                                                                   store);
   183 
       
   184           // Check if the line corresponds with one of the three types of line
       
   185           if (pr.tokens.size () != 4 && pr.tokens.size () != 7 && pr.tokens.size () != 8)
       
   186             {
       
   187               NS_LOG_ERROR ("Line has not correct number of parameters (corrupted file?): " << line << "\n");
       
   188               continue;
       
   189             }
       
   190 
       
   191           // Get the node Id
       
   192           nodeId  = GetNodeIdString (pr);
       
   193           iNodeId = GetNodeIdInt (pr);
       
   194           if (iNodeId == -1)
       
   195             {
       
   196         	  NS_LOG_ERROR ("Node number couldn't be obtained (corrupted file?): " << line << "\n");
       
   197               continue;
       
   198             }
       
   199 
       
   200           // get mobility model of node
       
   201           Ptr<ConstantVelocityMobilityModel> model = GetMobilityModel (nodeId,store);
       
   202 
       
   203           // if model not exists, continue
    91           if (model == 0)
   204           if (model == 0)
    92             {
   205             {
       
   206               NS_LOG_ERROR ("Unknown node ID (corrupted file?): " << nodeId << "\n");
    93               continue;
   207               continue;
    94             }
   208             }
    95           if (startNodeId == 6)
   209 
       
   210 
       
   211           /*
       
   212            * In this case a initial position is being seted
       
   213            * line like $node_(0) set X_ 151.05190721688197
       
   214            */
       
   215           if (IsSetInitialPos (pr))
    96             {
   216             {
    97               double value = ReadDouble (line.substr (endNodeId + 9, std::string::npos));
   217               //                                            coord         coord value
    98               std::string coordinate = line.substr (endNodeId + 6, 1);
   218               last_pos[iNodeId] = SetInitialPosition (model, pr.tokens[2], pr.dvals[3]);
    99               Vector position = model->GetPosition ();
   219 
   100               if (coordinate == "X")
   220               // Log new position
       
   221               NS_LOG_DEBUG ("Positions after parse for node " << iNodeId << " " << nodeId <<
       
   222                             " x=" << last_pos[iNodeId].x << " y=" << last_pos[iNodeId].y << " z=" << last_pos[iNodeId].z);
       
   223             }
       
   224 
       
   225           else // NOW EVENTS TO BE SCHEDULED
       
   226             {
       
   227 
       
   228               // This is a scheduled event, so time at should be present
       
   229               double at;
       
   230 
       
   231               if (!IsNumber (pr.tokens[2]))
   101                 {
   232                 {
   102                   position.x = value;
   233                   NS_LOG_WARN ("Time is not a number: " << pr.tokens[2]);
   103                   NS_LOG_DEBUG ("X=" << value);
   234                   continue;
   104                 }
   235                 }
   105               else if (coordinate == "Y")
   236 
       
   237               at = pr.dvals[2]; // set time at
       
   238 
       
   239               if ( at < 0 )
   106                 {
   240                 {
   107                   position.y = value;
   241                   NS_LOG_WARN ("Time is less than cero: " << at);
   108                   NS_LOG_DEBUG ("Y=" << value);
   242                   continue;
   109                 }
   243                 }
   110               else if (coordinate == "Z")
   244 
       
   245 
       
   246 
       
   247               /*
       
   248                * In this case a new waypoint is added
       
   249                * line like $ns_ at 1 "$node_(0) setdest 2 3 4"
       
   250                */
       
   251               if (IsSchedMobilityPos (pr))
   111                 {
   252                 {
   112                   position.z = value;
   253                   //                                     last position     time  X coord     Y coord      velocity
   113                   NS_LOG_DEBUG ("Z=" << value);
   254                   last_pos[iNodeId] = SetMovement (model, last_pos[iNodeId], at, pr.dvals[5], pr.dvals[6], pr.dvals[7]);
       
   255 
       
   256                   // Log new position
       
   257                   NS_LOG_DEBUG ("Positions after parse for node " << iNodeId << " " << nodeId <<
       
   258                                 " x=" << last_pos[iNodeId].x << " y=" << last_pos[iNodeId].y << " z=" << last_pos[iNodeId].z);
       
   259                 }
       
   260 
       
   261 
       
   262               /*
       
   263                * Scheduled set position
       
   264                * line like $ns_ at 4.634906291962 "$node_(0) set X_ 28.675920486450"
       
   265                */
       
   266               else if (IsSchedSetPos (pr))
       
   267                 {
       
   268                   //                                         time  coordinate   coord value
       
   269                   last_pos[iNodeId] = SetSchedPosition (model, at, pr.tokens[5], pr.dvals[6]);
       
   270 
       
   271                   // Log new position
       
   272                   NS_LOG_DEBUG ("Positions after parse for node " << iNodeId << " " << nodeId <<
       
   273                                 " x=" << last_pos[iNodeId].x << " y=" << last_pos[iNodeId].y << " z=" << last_pos[iNodeId].z);
   114                 }
   274                 }
   115               else
   275               else
   116                 {
   276                 {
   117                   continue;
   277                   NS_LOG_WARN ("Format Line is not correct: " << line << "\n");
   118                 }
   278                 }
   119               model->SetPosition (position);
       
   120             }
       
   121           else 
       
   122             {
       
   123               std::string::size_type atEnd = line.find_first_of (" ", 8);
       
   124               std::string atStr = line.substr (8, atEnd-8);
       
   125               NS_LOG_DEBUG (atStr);
       
   126               double at = ReadDouble (atStr);
       
   127               std::string::size_type xSpeedEnd = line.find_first_of (" ", endNodeId + 10);
       
   128               std::string::size_type ySpeedEnd = line.find_first_of (" ", xSpeedEnd + 1);
       
   129               double xSpeed = ReadDouble (line.substr (endNodeId + 10, xSpeedEnd - endNodeId - 10));
       
   130               double ySpeed = ReadDouble (line.substr (xSpeedEnd + 1, ySpeedEnd - xSpeedEnd - 1));
       
   131               double zSpeed = ReadDouble (line.substr (ySpeedEnd + 1, std::string::npos));
       
   132               NS_LOG_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
       
   133               Simulator::Schedule (Seconds (at), &ConstantVelocityMobilityModel::SetVelocity, model,
       
   134                                    Vector (xSpeed, ySpeed, zSpeed));
       
   135             }
   279             }
   136         }
   280         }
   137       file.close();
   281       file.close ();
   138     }
   282     }
   139 }
   283 }
   140 
   284 
   141 void 
   285 
       
   286 ParseResult
       
   287 ParseNs2Line (const string& str)
       
   288 {
       
   289   ParseResult ret;
       
   290   istringstream s;
       
   291   string line;
       
   292 
       
   293   // ignore comments (#)
       
   294   size_t pos_sharp = str.find_first_of ('#');
       
   295   if (pos_sharp != string::npos)
       
   296     {
       
   297       line = str.substr (0, pos_sharp);
       
   298     }
       
   299   else
       
   300     {
       
   301       line = str;
       
   302     }
       
   303 
       
   304   line = TrimNs2Line (line);
       
   305 
       
   306   // If line hasn't a correct node Id
       
   307   if (!HasNodeIdNumber (line))
       
   308     {
       
   309       NS_LOG_WARN ("Line has no node Id: " << line);
       
   310       return ret;
       
   311     }
       
   312 
       
   313   s.str (line);
       
   314 
       
   315   while (!s.eof ())
       
   316     {
       
   317       string x;
       
   318       s >> x;
       
   319       ret.tokens.push_back (x);
       
   320       int ii;
       
   321       double d;
       
   322       if (HasNodeIdNumber (x))
       
   323         {
       
   324           x = GetNodeIdFromToken (x);
       
   325         }
       
   326       ret.has_ival.push_back (IsVal<int> (x, ii));
       
   327       ret.ivals.push_back (ii);
       
   328       ret.has_dval.push_back (IsVal<double> (x, d));
       
   329       ret.dvals.push_back (d);
       
   330       ret.svals.push_back (x);
       
   331     }
       
   332 
       
   333   size_t tokensLength   = ret.tokens.size ();                 // number of tokens in line
       
   334   size_t lasTokenLength = ret.tokens[tokensLength - 1].size (); // length of the last token
       
   335 
       
   336   // if it is a scheduled set _[XYZ] or a setdest I need to remove the last "
       
   337   // and re-calculate values
       
   338   if ( (tokensLength == 7 || tokensLength == 8)
       
   339        && (ret.tokens[tokensLength - 1][lasTokenLength - 1] == '"') )
       
   340     {
       
   341 
       
   342       // removes " from the last position
       
   343       ret.tokens[tokensLength - 1] = ret.tokens[tokensLength - 1].substr (0,lasTokenLength - 1);
       
   344 
       
   345       string x;
       
   346       x = ret.tokens[tokensLength - 1];
       
   347 
       
   348       if (HasNodeIdNumber (x))
       
   349         {
       
   350           x = GetNodeIdFromToken (x);
       
   351         }
       
   352 
       
   353       // Re calculate values
       
   354       int ii;
       
   355       double d;
       
   356       ret.has_ival[tokensLength - 1] = IsVal<int> (x, ii);
       
   357       ret.ivals[tokensLength - 1] = ii;
       
   358       ret.has_dval[tokensLength - 1] = IsVal<double> (x, d);
       
   359       ret.dvals[tokensLength - 1] = d;
       
   360       ret.svals[tokensLength - 1] = x;
       
   361 
       
   362     }
       
   363   else if ( (tokensLength == 9 && ret.tokens[tokensLength - 1] == "\"")
       
   364             || (tokensLength == 8 && ret.tokens[tokensLength - 1] == "\""))
       
   365     {
       
   366       // if the line has the " character in this way: $ns_ at 1 "$node_(0) setdest 2 2 1  "
       
   367       // or in this: $ns_ at 4 "$node_(0) set X_ 2  " we need to ignore this last token
       
   368 
       
   369       ret.tokens.erase (ret.tokens.begin () + tokensLength - 1);
       
   370       ret.has_ival.erase (ret.has_ival.begin () + tokensLength - 1);
       
   371       ret.ivals.erase (ret.ivals.begin () + tokensLength - 1);
       
   372       ret.has_dval.erase (ret.has_dval.begin () + tokensLength - 1);
       
   373       ret.dvals.erase (ret.dvals.begin () + tokensLength - 1);
       
   374       ret.svals.erase (ret.svals.begin () + tokensLength - 1);
       
   375 
       
   376     }
       
   377 
       
   378 
       
   379 
       
   380   return ret;
       
   381 }
       
   382 
       
   383 
       
   384 string
       
   385 TrimNs2Line (const string& s)
       
   386 {
       
   387   string ret = s;
       
   388 
       
   389   while (ret.size () > 0 && isblank (ret[0]))
       
   390     {
       
   391       ret.erase (0, 1);    // Removes blank spaces at the begining of the line
       
   392     }
       
   393 
       
   394   while (ret.size () > 0 && isblank (ret[ret.size () - 1]))
       
   395     {
       
   396       ret.erase (ret.size () - 1, 1); // Removes blank spaces from at end of line
       
   397     }
       
   398 
       
   399   return ret;
       
   400 }
       
   401 
       
   402 
       
   403 bool
       
   404 IsNumber (const string& s)
       
   405 {
       
   406   char *endp;
       
   407   double unused;
       
   408   unused = strtod (s.c_str (), &endp); // declared with warn_unused_result
       
   409   return endp == s.c_str () + s.size ();
       
   410 }
       
   411 
       
   412 
       
   413 template<class T>
       
   414 bool IsVal (const string& str, T& ret)
       
   415 {
       
   416   if (str.size () == 0)
       
   417     {
       
   418       return false;
       
   419     }
       
   420   else if (IsNumber (str))
       
   421     {
       
   422       string s2 = str;
       
   423       istringstream s (s2);
       
   424       s >> ret;
       
   425       return true;
       
   426     }
       
   427   else
       
   428     {
       
   429       return false;
       
   430     }
       
   431 }
       
   432 
       
   433 
       
   434 bool
       
   435 HasNodeIdNumber (string str)
       
   436 {
       
   437 
       
   438   // find brackets
       
   439   std::string::size_type startNodeId = str.find_first_of ("("); // index of left bracket
       
   440   std::string::size_type endNodeId   = str.find_first_of (")"); // index of right bracket
       
   441 
       
   442   // Get de nodeId in a string and in a int value
       
   443   std::string nodeId;     // node id
       
   444 
       
   445   // if no brackets, continue!
       
   446   if (startNodeId == std::string::npos || endNodeId == std::string::npos)
       
   447     {
       
   448       return false;
       
   449     }
       
   450 
       
   451   nodeId = str.substr (startNodeId + 1, endNodeId - (startNodeId + 1)); // set node id
       
   452 
       
   453   //   is number              is integer                                       is not negative
       
   454   if (IsNumber (nodeId) && (nodeId.find_first_of (".") == std::string::npos) && (nodeId[0] != '-'))
       
   455     {
       
   456       return true;
       
   457     }
       
   458   else
       
   459     {
       
   460       return false;
       
   461     }
       
   462 }
       
   463 
       
   464 
       
   465 string
       
   466 GetNodeIdFromToken (string str)
       
   467 {
       
   468   if (HasNodeIdNumber (str))
       
   469     {
       
   470       // find brackets
       
   471       std::string::size_type startNodeId = str.find_first_of ("(");     // index of left bracket
       
   472       std::string::size_type endNodeId   = str.find_first_of (")");     // index of right bracket
       
   473 
       
   474       return str.substr (startNodeId + 1, endNodeId - (startNodeId + 1)); // set node id
       
   475     }
       
   476   else
       
   477     {
       
   478       return "";
       
   479     }
       
   480 }
       
   481 
       
   482 
       
   483 int
       
   484 GetNodeIdInt (ParseResult pr)
       
   485 {
       
   486   switch (pr.tokens.size ())
       
   487     {
       
   488     case 4:   // line like $node_(0) set X_ 11
       
   489       return pr.ivals[0];
       
   490       break;
       
   491     case 7:   // line like $ns_ at 4 "$node_(0) set X_ 28"
       
   492       return pr.ivals[3];
       
   493       break;
       
   494     case 8:   // line like $ns_ at 1 "$node_(0) setdest 2 3 4"
       
   495       return pr.ivals[3];
       
   496       break;
       
   497     default:
       
   498       return -1;
       
   499     }
       
   500 }
       
   501 
       
   502 // Get node id number in string format
       
   503 string
       
   504 GetNodeIdString (ParseResult pr)
       
   505 {
       
   506   switch (pr.tokens.size ())
       
   507     {
       
   508     case 4:   // line like $node_(0) set X_ 11
       
   509       return pr.svals[0];
       
   510       break;
       
   511     case 7:   // line like $ns_ at 4 "$node_(0) set X_ 28"
       
   512       return pr.svals[3];
       
   513       break;
       
   514     case 8:   // line like $ns_ at 1 "$node_(0) setdest 2 3 4"
       
   515       return pr.svals[3];
       
   516       break;
       
   517     default:
       
   518       return "";
       
   519     }
       
   520 }
       
   521 
       
   522 
       
   523 Vector
       
   524 SetOneInitialCoord (Vector position, string& coord, double value)
       
   525 {
       
   526 
       
   527   // set the position for the coord.
       
   528   if (coord == NS2_X_COORD)
       
   529     {
       
   530       position.x = value;
       
   531       NS_LOG_DEBUG ("X=" << value);
       
   532     }
       
   533   else if (coord == NS2_Y_COORD)
       
   534     {
       
   535       position.y = value;
       
   536       NS_LOG_DEBUG ("Y=" << value);
       
   537     }
       
   538   else if (coord == NS2_Z_COORD)
       
   539     {
       
   540       position.z = value;
       
   541       NS_LOG_DEBUG ("Z=" << value);
       
   542     }
       
   543   return position;
       
   544 }
       
   545 
       
   546 
       
   547 bool
       
   548 IsSetInitialPos (ParseResult pr)
       
   549 {
       
   550   //        number of tokens         has $node_( ?                        has "set"           has doble for position?
       
   551   return pr.tokens.size () == 4 && HasNodeIdNumber (pr.tokens[0]) && pr.tokens[1] == NS2_SET && pr.has_dval[3]
       
   552          // coord name is X_, Y_ or Z_ ?
       
   553          && (pr.tokens[2] == NS2_X_COORD || pr.tokens[2] == NS2_Y_COORD || pr.tokens[2] == NS2_Z_COORD);
       
   554 
       
   555 }
       
   556 
       
   557 
       
   558 bool
       
   559 IsSchedSetPos (ParseResult pr)
       
   560 {
       
   561   //      correct number of tokens,    has $ns_                   and at
       
   562   return pr.tokens.size () == 7 && pr.tokens[0] == NS2_NS_SCH && pr.tokens[1] == NS2_AT
       
   563          && pr.tokens[4] == NS2_SET && pr.has_dval[2] && pr.has_dval[3]   // has set and double value for time and nodeid
       
   564          && ( pr.tokens[5] == NS2_X_COORD || pr.tokens[5] == NS2_Y_COORD || pr.tokens[5] == NS2_Z_COORD) // has X_, Y_ or Z_?
       
   565          && pr.has_dval[2]; // time is a number
       
   566 }
       
   567 
       
   568 bool
       
   569 IsSchedMobilityPos (ParseResult pr)
       
   570 {
       
   571   //     number of tokens      and    has $ns_                and    has at
       
   572   return pr.tokens.size () == 8 && pr.tokens[0] == NS2_NS_SCH && pr.tokens[1] == NS2_AT
       
   573          //    time             x coord          y coord          velocity are numbers?
       
   574          && pr.has_dval[2] && pr.has_dval[5] && pr.has_dval[6] && pr.has_dval[7]
       
   575          && pr.tokens[4] == NS2_SETDEST; // and has setdest
       
   576 
       
   577 }
       
   578 
       
   579 Vector
       
   580 SetMovement (Ptr<ConstantVelocityMobilityModel> model, Vector last_pos, double at,
       
   581              double xFinalPosition, double yFinalPosition, double speed)
       
   582 {
       
   583   Vector position;
       
   584   position.x = last_pos.x;
       
   585   position.y = last_pos.y;
       
   586   position.z = last_pos.z;
       
   587 
       
   588   if (speed == 0)
       
   589     {
       
   590       // We have to maintain last position, and stop the movement
       
   591       Simulator::Schedule (Seconds (at), &ConstantVelocityMobilityModel::SetVelocity, model,
       
   592                            Vector (0, 0, 0));
       
   593     }
       
   594   else if (speed > 0)
       
   595     {
       
   596       // first calculate the time; time = distance / speed
       
   597       double time = sqrt (pow (xFinalPosition - position.x, 2) + pow (yFinalPosition - position.y, 2)) / speed;
       
   598       NS_LOG_DEBUG ("at=" << at << " time=" << time);
       
   599       // now calculate the xSpeed = distance / time
       
   600       double xSpeed = (xFinalPosition - position.x) / time;
       
   601       double ySpeed = (yFinalPosition - position.y) / time; // & same with ySpeed
       
   602 
       
   603       // quick and dirty set zSpeed = 0
       
   604       double zSpeed = 0;
       
   605 
       
   606       NS_LOG_DEBUG ("Calculated Speed: X=" << xSpeed << " Y=" << ySpeed << " Z=" << zSpeed);
       
   607 
       
   608       // Set the Values
       
   609       Simulator::Schedule (Seconds (at), &ConstantVelocityMobilityModel::SetVelocity, model,
       
   610                            Vector (xSpeed, ySpeed, zSpeed));
       
   611 
       
   612       if (time >= 0)
       
   613         {
       
   614           Simulator::Schedule (Seconds (at + time), &ConstantVelocityMobilityModel::SetVelocity,
       
   615                                model, Vector (0, 0, 0));
       
   616         }
       
   617 
       
   618       position.x = xFinalPosition;
       
   619       position.y = yFinalPosition;
       
   620       position.z = 0;
       
   621     }
       
   622 
       
   623   return position;
       
   624 }
       
   625 
       
   626 
       
   627 Vector
       
   628 SetInitialPosition (Ptr<ConstantVelocityMobilityModel> model, string coord, double coordVal)
       
   629 {
       
   630   model->SetPosition (SetOneInitialCoord (model->GetPosition (), coord, coordVal));
       
   631 
       
   632   Vector position;
       
   633   position.x = model->GetPosition ().x;
       
   634   position.y = model->GetPosition ().y;
       
   635   position.z = model->GetPosition ().z;
       
   636 
       
   637   return position;
       
   638 }
       
   639 
       
   640 // Schedule a set of position for a node
       
   641 Vector
       
   642 SetSchedPosition (Ptr<ConstantVelocityMobilityModel> model, double at, string coord, double coordVal)
       
   643 {
       
   644   // update position
       
   645   model->SetPosition (SetOneInitialCoord (model->GetPosition (), coord, coordVal));
       
   646 
       
   647   Vector position;
       
   648   position.x = model->GetPosition ().x;
       
   649   position.y = model->GetPosition ().y;
       
   650   position.z = model->GetPosition ().z;
       
   651 
       
   652   // Chedule next positions
       
   653   Simulator::Schedule (Seconds (at), &ConstantVelocityMobilityModel::SetPosition, model,position);
       
   654 
       
   655   return position;
       
   656 }
       
   657 
       
   658 void
   142 Ns2MobilityHelper::Install (void) const
   659 Ns2MobilityHelper::Install (void) const
   143 {
   660 {
   144   Install (NodeList::Begin (), NodeList::End ());
   661   Install (NodeList::Begin (), NodeList::End ());
   145 }
   662 }
   146 
   663 
       
   664 // -----------------------------------------------------------------------------
       
   665 // Testing
       
   666 // -----------------------------------------------------------------------------
       
   667 bool operator== (Vector const & a, Vector const & b)
       
   668 {
       
   669   return (a.x == b.x && a.y == b.y && a.z == b.z);
       
   670 }
       
   671 /**
       
   672  * Every test case is supposed to:
       
   673  *  1. Generate short mobility trace file
       
   674  *  2. Read it back using Ns2MobilityHelper
       
   675  *  3. Check initial node positions and speeds.
       
   676  *  4. Run simulation listening for all CourseChange events and compare actual mobility with the reference
       
   677  */
       
   678 class Ns2MobilityHelperTest : public TestCase
       
   679 {
       
   680 public:
       
   681   /// Single record in mobility reference
       
   682   struct ReferencePoint
       
   683   {
       
   684     std::string node;       ///< node ID as string, e.g. "1"
       
   685     Time time;              ///< timestamp
       
   686     Vector pos;             ///< reference position
       
   687     Vector vel;             ///< reference velocity
       
   688 
       
   689     ReferencePoint (std::string const & id, Time t, Vector const & p, Vector const & v)
       
   690       : node (id),
       
   691         time (t),
       
   692         pos (p),
       
   693         vel (v)
       
   694     {
       
   695     }
       
   696     /// Sort by timestamp
       
   697     bool operator< (ReferencePoint const & o) const
       
   698     {
       
   699       return (time < o.time);
       
   700     }
       
   701   };
       
   702   /**
       
   703    * Create new test case. To make it useful SetTrace () and AddReferencePoint () must be called
       
   704    *
       
   705    * \param name        Short description
       
   706    * \param nodes       Number of nodes used in the test trace, 1 by default
       
   707    */
       
   708   Ns2MobilityHelperTest (std::string const & name, Time timeLimit, uint32_t nodes = 1)
       
   709     : TestCase (name),
       
   710       m_timeLimit (timeLimit),
       
   711       m_nodeCount (nodes),
       
   712       m_nextRefPoint (0)
       
   713   {
       
   714   }
       
   715   /// Empty
       
   716   virtual ~Ns2MobilityHelperTest ()
       
   717   {
       
   718   }
       
   719   /// Set NS-2 trace to read as single large string (don't forget to add \n and quote ")
       
   720   void SetTrace (std::string const & trace)
       
   721   {
       
   722     m_trace = trace;
       
   723   }
       
   724   /// Add next reference point
       
   725   void AddReferencePoint (ReferencePoint const & r)
       
   726   {
       
   727     m_reference.push_back (r);
       
   728   }
       
   729   /// Sugar
       
   730   void AddReferencePoint (const char * id, double sec, Vector const & p, Vector const & v)
       
   731   {
       
   732     AddReferencePoint (ReferencePoint (id, Seconds (sec), p, v));
       
   733   }
       
   734 
       
   735 private:
       
   736   /// Test time limit
       
   737   Time m_timeLimit;
       
   738   /// Number of nodes used in the test
       
   739   uint32_t m_nodeCount;
       
   740   /// Trace as string
       
   741   std::string m_trace;
       
   742   /// Reference mobility
       
   743   std::vector<ReferencePoint> m_reference;
       
   744   /// Next reference point to be checked
       
   745   size_t m_nextRefPoint;
       
   746   /// TMP trace file name
       
   747   std::string m_traceFile;
       
   748 
       
   749 private:
       
   750   /// Dump NS-2 trace to tmp file
       
   751   bool WriteTrace ()
       
   752   {
       
   753     m_traceFile = GetTempDir () + "Ns2MobilityHelperTest.tcl";
       
   754     std::ofstream of (m_traceFile.c_str ());
       
   755     NS_TEST_ASSERT_MSG_EQ (of.is_open (), true, "Need to write tmp. file");
       
   756     of << m_trace;
       
   757     of.close ();
       
   758     return false; // no errors
       
   759   }
       
   760   /// Create and name nodes
       
   761   void CreateNodes ()
       
   762   {
       
   763     NodeContainer nodes;
       
   764     nodes.Create (m_nodeCount);
       
   765     for (uint32_t i = 0; i < m_nodeCount; ++i)
       
   766       {
       
   767         std::ostringstream os;
       
   768         os << i;
       
   769         Names::Add (os.str (), nodes.Get (i));
       
   770       }
       
   771   }
       
   772   /// Check that all initial positions are correct
       
   773   bool CheckInitialPositions ()
       
   774   {
       
   775     std::stable_sort (m_reference.begin (), m_reference.end ());
       
   776     while (m_nextRefPoint < m_reference.size () && m_reference[m_nextRefPoint].time == Seconds (0))
       
   777       {
       
   778         ReferencePoint const & rp = m_reference[m_nextRefPoint];
       
   779         Ptr<Node> node = Names::Find<Node> (rp.node);
       
   780         NS_TEST_ASSERT_MSG_NE (node, 0, "Can't find node with id " << rp.node);
       
   781         Ptr<MobilityModel> mob = node->GetObject<MobilityModel> ();
       
   782         NS_TEST_ASSERT_MSG_NE (mob, 0, "Can't find mobility for node " << rp.node);
       
   783 
       
   784         NS_TEST_EXPECT_MSG_EQ (rp.pos, mob->GetPosition (), "Initial position mismatch for node " << rp.node);
       
   785         NS_TEST_EXPECT_MSG_EQ (rp.vel, mob->GetVelocity (), "Initial velocity mismatch for node " << rp.node);
       
   786 
       
   787         m_nextRefPoint++;
       
   788       }
       
   789     return GetErrorStatus ();
       
   790   }
       
   791   /// Listen for course change events
       
   792   void CourseChange (std::string context, Ptr<const MobilityModel> mobility)
       
   793   {
       
   794     Time time = Simulator::Now ();
       
   795     Ptr<Node> node = mobility->GetObject<Node> ();
       
   796     NS_ASSERT (node);
       
   797     std::string id = Names::FindName (node);
       
   798     NS_ASSERT (!id.empty ());
       
   799     Vector pos = mobility->GetPosition ();
       
   800     Vector vel = mobility->GetVelocity ();
       
   801 
       
   802     NS_TEST_EXPECT_MSG_LT (m_nextRefPoint, m_reference.size (), "Not enough reference points");
       
   803     if (m_nextRefPoint >= m_reference.size ())
       
   804       {
       
   805         return;
       
   806       }
       
   807 
       
   808     ReferencePoint const & ref = m_reference [m_nextRefPoint++];
       
   809     NS_TEST_EXPECT_MSG_EQ (time, ref.time, "Time mismatch");
       
   810     NS_TEST_EXPECT_MSG_EQ (id, ref.node, "Node ID mismatch at time " << time.GetSeconds () << " s");
       
   811     NS_TEST_EXPECT_MSG_EQ (pos, ref.pos, "Position mismatch at time " << time.GetSeconds () << " s for node " << id);
       
   812     NS_TEST_EXPECT_MSG_EQ (vel, ref.vel, "Velocity mismatch at time " << time.GetSeconds () << " s for node " << id);
       
   813   }
       
   814   /// Go
       
   815   bool DoRun ()
       
   816   {
       
   817     NS_TEST_ASSERT_MSG_EQ (m_trace.empty (), false, "Need trace");
       
   818     NS_TEST_ASSERT_MSG_EQ (m_reference.empty (), false, "Need reference");
       
   819 
       
   820     if (WriteTrace ())
       
   821       {
       
   822         return GetErrorStatus ();
       
   823       }
       
   824     CreateNodes ();
       
   825     Ns2MobilityHelper mobility (m_traceFile);
       
   826     mobility.Install ();
       
   827     if (CheckInitialPositions ())
       
   828       {
       
   829         return GetErrorStatus ();
       
   830       }
       
   831     Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
       
   832                      MakeCallback (&Ns2MobilityHelperTest::CourseChange, this));
       
   833     Simulator::Stop (m_timeLimit);
       
   834     Simulator::Run ();
       
   835     Names::Clear ();
       
   836     std::remove (m_traceFile.c_str ());
       
   837     Simulator::Destroy ();
       
   838     return GetErrorStatus ();
       
   839   }
       
   840 };
       
   841 
       
   842 /// The test suite
       
   843 class Ns2MobilityHelperTestSuite : public TestSuite
       
   844 {
       
   845 public:
       
   846   Ns2MobilityHelperTestSuite () : TestSuite ("mobility-ns2-trace-helper", UNIT)
       
   847   {
       
   848     // to be used as temporary variable for test cases.
       
   849     // Note that test suite takes care of deleting all test cases.
       
   850     Ns2MobilityHelperTest * t (0);
       
   851 
       
   852     // Initial position
       
   853     t = new Ns2MobilityHelperTest ("initial position", Seconds (1));
       
   854     t->SetTrace ("$node_(0) set X_ 1.0\n"
       
   855                  "$node_(0) set Y_ 2.0\n"
       
   856                  "$node_(0) set Z_ 3.0\n"
       
   857                  );
       
   858     t->AddReferencePoint ("0", 0, Vector (1, 2, 3), Vector (0, 0, 0));
       
   859     AddTestCase (t);
       
   860 
       
   861     // Check parsing comments, empty lines and no EOF at the end of file
       
   862     t = new Ns2MobilityHelperTest ("comments", Seconds (1));
       
   863     t->SetTrace ("# comment\n"
       
   864                  "\n\n" // empty lines
       
   865                  "$node_(0) set X_ 1.0 # comment \n"
       
   866                  "$node_(0) set Y_ 2.0 ### \n"
       
   867                  "$node_(0) set Z_ 3.0 # $node_(0) set Z_ 3.0\n"
       
   868                  "#$node_(0) set Z_ 100 #"
       
   869                  );
       
   870     t->AddReferencePoint ("0", 0, Vector (1, 2, 3), Vector (0, 0, 0));
       
   871     AddTestCase (t);
       
   872 
       
   873     // Simple setdest. Arguments are interpreted as x, y, speed by default
       
   874     t = new Ns2MobilityHelperTest ("simple setdest", Seconds (10));
       
   875     t->SetTrace ("$ns_ at 1.0 \"$node_(0) setdest 25 0 5\"");
       
   876     //                     id  t  position         velocity
       
   877     t->AddReferencePoint ("0", 0, Vector (0, 0, 0), Vector (0, 0, 0));
       
   878     t->AddReferencePoint ("0", 1, Vector (0, 0, 0), Vector (5, 0, 0));
       
   879     t->AddReferencePoint ("0", 6, Vector (25, 0, 0), Vector (0, 0, 0));
       
   880     AddTestCase (t);
       
   881 
       
   882     // Several set and setdest. Arguments are interpreted as x, y, speed by default
       
   883     t = new Ns2MobilityHelperTest ("square setdest", Seconds (6));
       
   884     t->SetTrace ("$node_(0) set X_ 0.0\n"
       
   885                  "$node_(0) set Y_ 0.0\n"
       
   886                  "$ns_ at 1.0 \"$node_(0) setdest 5  0  5\"\n"
       
   887                  "$ns_ at 2.0 \"$node_(0) setdest 5  5  5\"\n"
       
   888                  "$ns_ at 3.0 \"$node_(0) setdest 0  5  5\"\n"
       
   889                  "$ns_ at 4.0 \"$node_(0) setdest 0  0  5\"\n"
       
   890                  );
       
   891     //                     id  t  position         velocity
       
   892     t->AddReferencePoint ("0", 0, Vector (0, 0, 0), Vector (0,  0, 0));
       
   893     t->AddReferencePoint ("0", 1, Vector (0, 0, 0), Vector (5,  0, 0));
       
   894     t->AddReferencePoint ("0", 2, Vector (5, 0, 0), Vector (0,  0, 0));
       
   895     t->AddReferencePoint ("0", 2, Vector (5, 0, 0), Vector (0,  5, 0));
       
   896     t->AddReferencePoint ("0", 3, Vector (5, 5, 0), Vector (0,  0, 0));
       
   897     t->AddReferencePoint ("0", 3, Vector (5, 5, 0), Vector (-5, 0, 0));
       
   898     t->AddReferencePoint ("0", 4, Vector (0, 5, 0), Vector (0, 0, 0));
       
   899     t->AddReferencePoint ("0", 4, Vector (0, 5, 0), Vector (0, -5, 0));
       
   900     t->AddReferencePoint ("0", 5, Vector (0, 0, 0), Vector (0,  0, 0));
       
   901     AddTestCase (t);
       
   902 
       
   903     // Scheduled set position
       
   904     t = new Ns2MobilityHelperTest ("scheduled set position", Seconds (2));
       
   905     t->SetTrace ("$ns_ at 1.0 \"$node_(0) set X_ 10\"\n"
       
   906                  "$ns_ at 1.0 \"$node_(0) set Z_ 10\"\n"
       
   907                  "$ns_ at 1.0 \"$node_(0) set Y_ 10\"");
       
   908     //                     id  t  position         velocity
       
   909     t->AddReferencePoint ("0", 1, Vector (10, 0, 0), Vector (0, 0, 0));
       
   910     t->AddReferencePoint ("0", 1, Vector (10, 0, 10), Vector (0, 0, 0));
       
   911     t->AddReferencePoint ("0", 1, Vector (10, 10, 10), Vector (0, 0, 0));
       
   912     AddTestCase (t);
       
   913 
       
   914     // Malformed lines
       
   915     t = new Ns2MobilityHelperTest ("malformed lines", Seconds (2));
       
   916     t->SetTrace ("$node() set X_ 1 # node id is not present\n"
       
   917                  "$node # incoplete line\"\n"
       
   918                  "$node this line is not correct\n"
       
   919                  "$node_(0) set X_ 1 # line OK \n"
       
   920                  "$node_(0) set Y_ 2 # line OK \n"
       
   921                  "$node_(0) set Z_ 3 # line OK \n"
       
   922                  "$ns_ at  \"$node_(0) setdest 4 4 4\" # time not present\n"
       
   923                  "$ns_ at 1 \"$node_(0) setdest 2 2 1   \" # line OK \n");
       
   924     //                     id  t  position         velocity
       
   925     t->AddReferencePoint ("0", 0, Vector (1, 2, 3), Vector (0, 0, 0));
       
   926     t->AddReferencePoint ("0", 1, Vector (1, 2, 3), Vector (1, 0, 0));
       
   927     t->AddReferencePoint ("0", 2, Vector (2, 2, 3), Vector (0, 0, 0));
       
   928     AddTestCase (t);
       
   929 
       
   930     // Non possible values
       
   931     t = new Ns2MobilityHelperTest ("non possible values", Seconds (2));
       
   932     t->SetTrace ("$node_(0) set X_ 1 # line OK \n"
       
   933                  "$node_(0) set Y_ 2 # line OK \n"
       
   934                  "$node_(0) set Z_ 3 # line OK \n"
       
   935                  "$node_(-22) set Y_ 3 # node id not correct\n"
       
   936                  "$node_(3.3) set Y_ 1111 # node id not correct\n"
       
   937                  "$ns_ at sss \"$node_(0) setdest 5 5 5\" # time is not a number\n"
       
   938                  "$ns_ at 1 \"$node_(0) setdest 2 2 1\" # line OK \n"
       
   939                  "$ns_ at 1 \"$node_(0) setdest 2 2 -1\" # negative speed is not correct\n"
       
   940                  "$ns_ at 1 \"$node_(0) setdest 2 2 sdfs\"    # speed is not a number\n"
       
   941                  "$ns_ at 1 \"$node_(0) setdest 2 2 s232dfs\" # speed is not a number\n"
       
   942                  "$ns_ at 1 \"$node_(0) setdest 233 2.. s232dfs\"   # more than one non numbers\n"
       
   943                  "$ns_ at -12 \"$node_(0) setdest 11 22 33\" # time should not be negative\n");
       
   944     //                     id  t  position         velocity
       
   945     t->AddReferencePoint ("0", 0, Vector (1, 2, 3), Vector (0, 0, 0));
       
   946     t->AddReferencePoint ("0", 1, Vector (1, 2, 3), Vector (1, 0, 0));
       
   947     t->AddReferencePoint ("0", 2, Vector (2, 2, 3), Vector (0, 0, 0));
       
   948     AddTestCase (t);
       
   949 
       
   950     // More than one node
       
   951     t = new Ns2MobilityHelperTest ("few nodes, combinations of set and setdest", Seconds (10), 3);
       
   952     t->SetTrace ("$node_(0) set X_ 1.0\n"
       
   953                  "$node_(0) set Y_ 2.0\n"
       
   954                  "$node_(0) set Z_ 3.0\n"
       
   955                  "$ns_ at 1.0 \"$node_(1) setdest 25 0 5\"\n"
       
   956                  "$node_(2) set X_ 0.0\n"
       
   957                  "$node_(2) set Y_ 0.0\n"
       
   958                  "$ns_ at 1.0 \"$node_(2) setdest 5  0  5\"\n"
       
   959                  "$ns_ at 2.0 \"$node_(2) setdest 5  5  5\"\n"
       
   960                  "$ns_ at 3.0 \"$node_(2) setdest 0  5  5\"\n"
       
   961                  "$ns_ at 4.0 \"$node_(2) setdest 0  0  5\"\n");
       
   962     //                     id  t  position         velocity
       
   963     t->AddReferencePoint ("0", 0, Vector (1, 2, 3), Vector (0, 0, 0));
       
   964     t->AddReferencePoint ("1", 0, Vector (0, 0, 0), Vector (0, 0, 0));
       
   965     t->AddReferencePoint ("1", 1, Vector (0, 0, 0), Vector (5, 0, 0));
       
   966     t->AddReferencePoint ("1", 6, Vector (25, 0, 0), Vector (0, 0, 0));
       
   967     t->AddReferencePoint ("2", 0, Vector (0, 0, 0), Vector (0,  0, 0));
       
   968     t->AddReferencePoint ("2", 1, Vector (0, 0, 0), Vector (5,  0, 0));
       
   969     t->AddReferencePoint ("2", 2, Vector (5, 0, 0), Vector (0,  0, 0));
       
   970     t->AddReferencePoint ("2", 2, Vector (5, 0, 0), Vector (0,  5, 0));
       
   971     t->AddReferencePoint ("2", 3, Vector (5, 5, 0), Vector (0,  0, 0));
       
   972     t->AddReferencePoint ("2", 3, Vector (5, 5, 0), Vector (-5, 0, 0));
       
   973     t->AddReferencePoint ("2", 4, Vector (0, 5, 0), Vector (0, 0, 0));
       
   974     t->AddReferencePoint ("2", 4, Vector (0, 5, 0), Vector (0, -5, 0));
       
   975     t->AddReferencePoint ("2", 5, Vector (0, 0, 0), Vector (0,  0, 0));
       
   976     AddTestCase (t);
       
   977 
       
   978     // Test for Speed == 0, that acts as stop the node.
       
   979     t = new Ns2MobilityHelperTest ("setdest with speed cero", Seconds (10));
       
   980     t->SetTrace ("$ns_ at 1.0 \"$node_(0) setdest 25 0 5\"\n"
       
   981                  "$ns_ at 7.0 \"$node_(0) setdest 11  22  0\"\n");
       
   982     //                     id  t  position         velocity
       
   983     t->AddReferencePoint ("0", 0, Vector (0, 0, 0), Vector (0, 0, 0));
       
   984     t->AddReferencePoint ("0", 1, Vector (0, 0, 0), Vector (5, 0, 0));
       
   985     t->AddReferencePoint ("0", 6, Vector (25, 0, 0), Vector (0, 0, 0));
       
   986     t->AddReferencePoint ("0", 7, Vector (25, 0, 0), Vector (0, 0, 0));
       
   987     AddTestCase (t);
       
   988 
       
   989 
       
   990     // Test negative positions
       
   991     t = new Ns2MobilityHelperTest ("test negative positions", Seconds (10));
       
   992     t->SetTrace ("$node_(0) set X_ -1.0\n"
       
   993                  "$node_(0) set Y_ 0\n"
       
   994                  "$ns_ at 1.0 \"$node_(0) setdest 0 0 1\"\n"
       
   995                  "$ns_ at 2.0 \"$node_(0) setdest 0  -1  1\"\n");
       
   996     //                     id  t  position         velocity
       
   997     t->AddReferencePoint ("0", 0, Vector (-1, 0, 0), Vector (0, 0, 0));
       
   998     t->AddReferencePoint ("0", 1, Vector (-1, 0, 0), Vector (1, 0, 0));
       
   999     t->AddReferencePoint ("0", 2, Vector (0, 0, 0), Vector (0, 0, 0));
       
  1000     t->AddReferencePoint ("0", 2, Vector (0, 0, 0), Vector (0, -1, 0));
       
  1001     t->AddReferencePoint ("0", 3, Vector (0, -1, 0), Vector (0, 0, 0));
       
  1002     AddTestCase (t);
       
  1003 
       
  1004     // Sqare setdest with values in the form 1.0e+2
       
  1005     t = new Ns2MobilityHelperTest ("Foalt numbers in 1.0e+2 format", Seconds (6));
       
  1006     t->SetTrace ("$node_(0) set X_ 0.0\n"
       
  1007                  "$node_(0) set Y_ 0.0\n"
       
  1008                  "$ns_ at 1.0 \"$node_(0) setdest 1.0e+2  0       1.0e+2\"\n"
       
  1009                  "$ns_ at 2.0 \"$node_(0) setdest 1.0e+2  1.0e+2  1.0e+2\"\n"
       
  1010                  "$ns_ at 3.0 \"$node_(0) setdest 0       1.0e+2  1.0e+2\"\n"
       
  1011                  "$ns_ at 4.0 \"$node_(0) setdest 0       0       1.0e+2\"\n");
       
  1012     //                     id  t  position         velocity
       
  1013     t->AddReferencePoint ("0", 0, Vector (0, 0, 0), Vector (0,  0, 0));
       
  1014     t->AddReferencePoint ("0", 1, Vector (0, 0, 0), Vector (100,  0, 0));
       
  1015     t->AddReferencePoint ("0", 2, Vector (100, 0, 0), Vector (0,  0, 0));
       
  1016     t->AddReferencePoint ("0", 2, Vector (100, 0, 0), Vector (0,  100, 0));
       
  1017     t->AddReferencePoint ("0", 3, Vector (100, 100, 0), Vector (0,  0, 0));
       
  1018     t->AddReferencePoint ("0", 3, Vector (100, 100, 0), Vector (-100, 0, 0));
       
  1019     t->AddReferencePoint ("0", 4, Vector (0, 100, 0), Vector (0, 0, 0));
       
  1020     t->AddReferencePoint ("0", 4, Vector (0, 100, 0), Vector (0, -100, 0));
       
  1021     t->AddReferencePoint ("0", 5, Vector (0, 0, 0), Vector (0,  0, 0));
       
  1022     AddTestCase (t);
       
  1023 
       
  1024   }
       
  1025 } g_ns2TransmobilityHelperTestSuite;
       
  1026 
       
  1027 
   147 } // namespace ns3
  1028 } // namespace ns3