[RoutesMobilityModel] schedule multiple routes

252 views
Skip to first unread message

Michał Król

unread,
Nov 27, 2015, 2:03:08 AM11/27/15
to ns-3-users
Dear All,

I started to use RoutesMobilityModel - works great! However I have some problems realizing my simulation scenario. I want a node to go from a randomly chosen point to another, and after reaching the destination chose another point to go (as in RandomWaypointModel, A->B->C->...).

The problem is,  I don't know how can I tell if my node already reached its destination and how to schedule another route. I tried to invoke ChooseRoute several times:

ChooseRoute(A, B, node);
Schedule -> ChooseRoute(B, C, node);

In such a case the node goes from A to B and then teleports to C.

Is there any way to do it?

Thanks in advance,
Michał Król

Tommaso Pecorella

unread,
Nov 27, 2015, 6:50:16 PM11/27/15
to ns-3-users
Hi,

I can't find RoutesMobilityModel in the ns-3 distribution. Mind to explain what it is and where did you find it ?

Thanks,

T.

Michał Król

unread,
Nov 29, 2015, 10:19:22 AM11/29/15
to ns-3-users
Hi Tommaso,

thanks your answer. This module is not in ns3 by default, but can be installed from here:

https://www.nsnam.org/wiki/RoutesMobilityModel

Tommaso Pecorella

unread,
Nov 29, 2015, 11:41:09 AM11/29/15
to ns-3-users, tiago.m...@gmail.com
I see... I forgot about it.

The best thing is to write directly to Tiago, perhaps you found a bug, or at least something that should be blocked with a warning or an assert.
As a side note, it's best if you provide the offending script to Tiago, it will speedup the debugging.

Cheers,

T.

Tiago Cerqueira

unread,
Nov 29, 2015, 12:03:58 PM11/29/15
to ns-3-users
Hi,
Firstly, thank you Tommaso for forwarding this issue to me! I don't check ns-3-users anymore, so I thank you for letting me know of any issues that might come up.
As for the issue itself, I'll have to take a look at the script code to figure out. As Tommaso said, we might be looking at a bug (I didn't consider your use case scenario). Also, we should consider adding the ability to keep the nodes moving to a random destination (when the automatic mobility generation is chosen by the user) out of the box. The required changes should be fairly straightforward, and I'll try to push them ASAP.
Please post the script code when you can, so I can help you out!

Michał Król

unread,
Nov 30, 2015, 12:43:26 AM11/30/15
to ns-3-users
I attach my script. I try to realize a path A ("35.7879759,139.777894") -> B ("35.8122277,139.7116542") -> C (35.7126605,139.7388475).
So I try invoking:

routes.ChooseRoute(A,B);
routes
.ChooseRoute(B,C);



I used a schedule function for the second call. If not I get an error:

aborted. cond="!m_waypoints.empty () && (m_waypoints.back ().time >= waypoint.time)", msg="Waypoints must be added in ascending time order"


Thanks a lot,
Michał
routes-mobility-example.cc

Tiago Cerqueira

unread,
Nov 30, 2015, 7:25:35 PM11/30/15
to ns-3-users
Hi,
We can go about this in two ways, but I need to know what it is that you're trying to accomplish.
If you only need to specify a path like A passing through B and arriving at C (with the node stopping at C for the rest of the simulation), then it's only a question of making a small change to the Google Maps query. However, I don't think this is it. From what I've gathered, you want the nodes to continue moving, indefinitely, to random destinations.
If it's the latter, I'll send you a patch that will enable you to do so. Basically, the problem is that the SchedulePoints function of the helper class will always give the first waypoint a time of 0 (hence the triggered assert during the second execution of ChooseRoute. The WaypointMobilityModel is attempting to schedule points for time=0 when the previous point was scheduled for a time greater than 0). We can fix this by enabling the user to specify a start time for the nodes (something we're going to implement in a future release), for the ChooseRoute functions. That, coupled with queries to the Gmaps API when a node arrives at the destination, would keep the nodes moving indefinitely. (For example, the module selects, randomly, A and B as start and endpoints for the first trip of the node. When the node arrives at B, the module would select another random destination, C, and get the node moving immediately or after a small stop time).

Tiago Cerqueira

unread,
Nov 30, 2015, 7:29:58 PM11/30/15
to ns-3-users
Just a small addition to the post: I don't know why the assert is not being triggered when you use the scheduler to schedule execution of the ChooseRoute function, or why the node just teleports to the final position. I'll have to debug that as soon as possible

Michał Król

unread,
Nov 30, 2015, 11:10:28 PM11/30/15
to ns-3-users
Thank Tiago!

Indeed I need to schedule more paths, ideally to random points (but I can random them myself, so it's not a problem). I'd be grateful for the patch - it's exactly what I need.

For the assert in the schedule. I think it can be a mismatch between relative and absolute time. If the SchedulePoints function sets time to 0 and the simulation time is already 1000s it actually becomes 1000. If you check the simulation in NetAnim it looks like it's is very long, but after reaching point B it just jumps right to the end (both the node AND simulation time).

Let me know if I can help more in debugging.

Thanks once again,
Michał

Tiago Cerqueira

unread,
Dec 7, 2015, 7:42:30 PM12/7/15
to ns-3-users, Michele Albano
Hi,
I've finished implementing the features you requested. I made small changes to the helper class, which will enable you to keep the nodes moving to other destinations.
In summary, I created a new ChooseRoute function, similar to the one you used, with an extra parameter. This function takes a std::vector, with the locations you want the node to move. For example, say you want the node to go to A, B, C and D, you only need to call the ChooseRoute function with the startPoint=A, endpoint=B and locations C and D go into the std::vector.
int ChooseRoute (std::string startPoint, std::string endPoint, Ptr<Node> node, std::vector<std::string> locArray);

To use this, you need to invoke it, from the simulation environment, like this:
  //Set the mobility helper
  MobilityHelper mobility;
  mobility.SetMobilityModel ("ns3::WaypointMobilityModel");
  //Install mobility helper on the nodes
  mobility.Install (nodes);
  std::vector<std::string> locArray;
  locArray.push_back("C");
  locArray.push_back("D");
  //Instantiate Routes Mobility Helper
  //Pass the constructor the coordinates to center the cartesian plane
  RoutesMobilityHelper routes (centerLat,centerLng,centerAltitude);
  routes.ChooseRoute("A", "B",nodes.Get(0),locArray);

In order to allow the user to generate the points automatically, I modified the ChooseRoute function that takes a user-specified area and generates random start and endpoints. I added the (optional) iterations argument to this function which, in practice, tells the module how many locations should the node move to, within the user specified area.
int ChooseRoute(NodeContainer& nodes, double upperLat, double upperLng, double lowerLat, double lowerLng, int iterations = 0);
To use this, you need to invoke it, from the simulation environment, like this:
  //Set the mobility helper
  MobilityHelper mobility;
  mobility.SetMobilityModel ("ns3::WaypointMobilityModel");
  //Install mobility helper on the nodes
  mobility.Install (nodes);

  //Instantiate Routes Mobility Helper
  //Pass the constructor the coordinates to center the cartesian plane
  RoutesMobilityHelper routes (centerLat,centerLng,centerAltitude);
  //To quickly generate a mobility trace with locations within a specified area the following code can be used.
  //This will pick coordinates, at random, inside the user specified area. Change the coordinates as appropriate.
  routes.ChooseRoute (nodes, 41.161093, -8.633352, 41.146487, -8.606916,3);

I've pushed these changes to the repository, but I added the changed files to this post. Just copy these files into the src/mobility-service-interface/helper folder and run ./waf build, and you should be all set!
Bear in mind that these features were not exhaustibly tested. They worked fine and netanim confirmed the node's movements but, as with all experimental features, your mileage may vary.

Finally, I'd like to appologize for not sending you this feature sooner, but I ran into some hardware troubles on my development machine and I could only get to it today!

Best regards,
Tiago Cerqueira
routes-mobility-helper.cc
routes-mobility-helper.h

Michał Król

unread,
Dec 8, 2015, 12:16:10 AM12/8/15
to ns-3-...@googlegroups.com
Thanks a lot! Looks great, that's exactly what I needed. I'll start
testing tomorrow and let you know my feedback.

Best,
Michał

Tiago Cerqueira

unread,
Dec 8, 2015, 5:12:14 PM12/8/15
to ns-3-...@googlegroups.com
Please do, I appreciate it! I still haven’t gotten around to checking the behaviour you mentioned using the schedule function… I suppose it’s a bug, the module was never intended to be used with it.

Best regards,
Tiago Cerqueira
> --
> You received this message because you are subscribed to a topic in the Google Groups "ns-3-users" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/ns-3-users/Z9y1esigQQg/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to ns-3-users+...@googlegroups.com.
> To post to this group, send email to ns-3-...@googlegroups.com.
> Visit this group at http://groups.google.com/group/ns-3-users.
> For more options, visit https://groups.google.com/d/optout.

Michał Król

unread,
Dec 10, 2015, 4:29:25 AM12/10/15
to ns-3-users
The extension seems to work really well!

However now I wanted to test create a simulation on a slightly bigger network (200 nodes)  and every time I got an error while requesting route 144 from google API:

assert failed. cond="(strcmp (status.c_str (),"INVALID_REQUEST") != 0)", msg="The request was denied by the service!", file=../src/mobility-service-interface/model/sax-handler.cc, line=117
terminate called without an active exception


I'm calling:
routes.ChooseRoute(A, B, node);
in a loop. It doesn't matter what route is it (i tried different topology files and it's always number 144;), so I guess it's just a performance issue, probably caused by google.

I checked the option allowing to read from xml files. I guess It's not possible to download a whole map of a given area and then query it for any route in this area? As far as I see I can schedule only one route for every nodes. So to realize my scenario in offline mode I would have to download every route I can possibly need, then random one and load a corresponding file? Can you think of any simpler way?

I have also one small remark about the interface. It could be nice to be able to use Vector class as the an input for ChooseRoutes(), it's not a big deal, but makes the code much cleaner in some cases ;)

Thanks a lot,
Michał

Michał Król

unread,
Dec 10, 2015, 4:36:16 AM12/10/15
to ns-3-users
Or maybe just a possibility of bulk queries (where I can ask for many routes at once) can be a solution to this?

Tiago Cerqueira

unread,
Dec 14, 2015, 2:47:17 AM12/14/15
to ns-3-users
Hi,
I'll respond inline if that's ok.

quinta-feira, 10 de Dezembro de 2015 às 09:29:25 UTC, Michał Król escreveu:
The extension seems to work really well!

However now I wanted to test create a simulation on a slightly bigger network (200 nodes)  and every time I got an error while requesting route 144 from google API:

assert failed. cond="(strcmp (status.c_str (),"INVALID_REQUEST") != 0)", msg="The request was denied by the service!", file=../src/mobility-service-interface/model/sax-handler.cc, line=117
terminate called without an active exception
 
It could be a problem with your input. Can you please enable the GoogleMapsApiConnect debug module? The GoogleMapsApiConnect prints the exact message that is used to query the API, and you can then paste the query in the browser to see the corresponding XML (which contains a clearer error message). I've been meaning to display the error message from the API to the user, using the assert message, but I haven't gotten around to it yet.
I'm calling:
routes.ChooseRoute(A, B, node);
in a loop. It doesn't matter what route is it (i tried different topology files and it's always number 144;), so I guess it's just a performance issue, probably caused by google.
Why are you calling the ChooseRoute function in a loop, may I ask? Are you using that function to loop through the container and assign routes to every node? If that is the case, look into the routes-automatic-example. In it, you can find a method for automatic, unique routes generation, in a user specified location. I also added the functionality you requested in this automatic method of trip generation. Just take a look at the above post, which details a function that takes a user specified area, and the number of iterations (trips) you want to generate. 

I checked the option allowing to read from xml files. I guess It's not possible to download a whole map of a given area and then query it for any route in this area? As far as I see I can schedule only one route for every nodes. So to realize my scenario in offline mode I would have to download every route I can possibly need, then random one and load a corresponding file? Can you think of any simpler way?
Google doesn't allow, in the Gmaps ToS, that the user keeps cached responses for more than thirty days. So, I would advise against using such method, as it would violate Google's ToS 
 
I have also one small remark about the interface. It could be nice to be able to use Vector class as the an input for ChooseRoutes(), it's not a big deal, but makes the code much cleaner in some cases ;)
Indeed, I was surprised to see that. I thought I had changed it.  Anyway, I'll try to push that on the next commit, thanks!

Michał Król

unread,
Dec 15, 2015, 1:11:33 AM12/15/15
to ns-3-users
In my simulation I have some static nodes and mobile nodes moving between them. However it can't be random. I load the positions from a text file, that's why I use a loop. I used to have my own system to translate GPS coordinates into Cartesian ones, but since I want to use the same system for all nodes I use ChooseRoutes(A,A) for  static ones (probably there's a better way?).

Here's a part of the debug:

---------------------
Waypoint number 1 added to Node 143
---------------------
144:35.7021,139.62
Request performed with the following URL: https://maps.googleapis.com/maps/api/directions/xml?origin=35.7021%2C139.62&destination=35.7021%2C139.62&sensor=false&mode=driving&departure_time=1450158676&key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This is the first point in the list, and its time was set to zero seconds
Leg 0: 0x4215c00
Iterating step Step:
Point 0:
Latitude:35.70213
Longitude: 139.62004
X
: -8922.82215892031
Y
: -9578.85049023516
Z
:-13.4508158954159
Time:0
---------------------

Latitude:35.70213
Longitude: 139.62004
X
: -8922.82215892031
Y
: -9578.85049023516
Z
:-13.4508158954159
Time:0
---------------------
Waypoint number 1 added to Node 144
---------------------
145:35.7451,139.848
Request performed with the following URL: https://maps.googleapis.com/maps/api/directions/xml?origin=35.7451%2C139.848&destination=35.7451%2C139.848&sensor=false&mode=driving&departure_time=1450158676&key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX

assert failed. cond="(strcmp (status.c_str (),"INVALID_REQUEST") != 0)", msg="The request was denied by the service!", file=../src/mobility-service-interface/model/sax-handler.cc, line=117
terminate called without an active exception
Command ['/home/harnen/sensors/ns-allinone-3.24/ns-3.24/build/scratch/evacuation_sites/evacuation_sites', '-topoFile=tokyo_center.txt', '-verbose=1'] terminated with signal SIGIOT. Run it under a debugger to get more information (./waf --run <program> --command-template="gdb --args %s <args>").

It looks that the URL's are the same, but number 144 always fails.

Once again, thanks a lot for your help!

Tiago Cerqueira

unread,
Dec 15, 2015, 1:27:00 AM12/15/15
to ns-3-...@googlegroups.com
As for the error, I’ll have to check that in debug mode. Can you provide me with the script and the text file?
Regarding your main issue, I guess you can load the start and endpoints to an array and then invoke the int ChooseRoute (std::string const *listTokenStartEndPoint, NodeContainer &nodeContainer) function. To use this, you must add the locations to the array in this format:

Node 1 - Going from A to B
Node 2 - Going from C to D
Node 3 - Going from X to Z

The array must have the locations in this order: A,B,C,D,X,Z.
You must ensure that the number of locations in the array is enough for all the nodes in the container!

I hope this post is helpful!

Best regards,
Tiago

Michał Król

unread,
Dec 15, 2015, 2:31:32 AM12/15/15
to ns-3-users
Here's my code. Everything is in SetupMobility function.

To run:
./waf --run "evacuation_sites -topoFile=tokyo_center.txt -verbose=1"
...
evacuation_sites.tar.gz

Tiago Cerqueira

unread,
Dec 17, 2015, 3:24:53 AM12/17/15
to ns-3-users
Hi,
I looked at the code you sent me and I must say that you've encountered the elusive "it's not a bug, it's a feature" problem.
The problem here is that the module feeds a departure time to google, in order to have google maps calculate the best route based on the time of day. This is used mainly for public transportations, but still it is provided to Google. By default, this time is set to the current system time when the RoutesMobilityHelper constructor is invoked.
Now, Google doesn't allow to ask directions in the past (I experimented around and it should have worked in your case, but the fact is that it didn't), and because the variable was set in the beginning of the simulation, it would eventually be considered the past as far as the API was concerned, and it would sent back an INVALID_REQUEST response. In your case, this would happen in execution number 144.

A quick fix for this, without altering the module's code, is to set the departure time to a value in the future (I tried with 8 days from now) and you won't run into this problem. You must set the time to EPOCH, and you can convert easily between the "human" time and EPOCH using the date command.
For example:
date +%s -d "December 24 2015 4:56:00"
You can also use several online converters, such as this.
To set the departure time for the RoutesMobilityModule, you must invoke the SetDepartureTime(std::string) function before the execution of the ChooseRoutes function, like this:
routes.SetDepartureTime("1450932960"); //EPOCH time for December 24 2015 4:56:00

I executed your script with the departure time set as above and everything went fine. I'll try to push a fix for this soon, but I don't know when I'll get around to it. I also didn't notice this bug before because, when dealing with numerous nodes I would use a virtual machine. Nothing like this ever happened, as far as I can recall, and I went back to it to try and confirm it there, but I couldn't reproduce it with 200 nodes. I noticed that the departure time was set only once, for every request.
I tinkered with the departure_time variable to perform some requests manually and I noticed that google allows for the directions to be asked in the past, as long as it wasn't too far back. The time google allows for the directions to be asked (estimated with the manual requests, around an hour) in the past should be more than enough for most simulations, so it could also be a problem with Google.

Also, a side note. You said before that you were setting some nodes to a fixed position, using the module. You should use the ConstantPositionMobilityModel, to set the nodes's positions. You can find the values for X,Y and Z with the debug output from the RoutesMobilityHelper debug module (just run your script once and record the values of X, Y and Z for the nodes you want to keep stationed).
You can use the ConstantPositionMobilityModel as such (I modified this from some code I had, so it should work, but I didn't test it. If it doesn't work, check the documentation for this mobility model ;) ):
void
PositionFixedNodes (NodeContainer& nodeContainer, double x, double y, double z)
  {
  MobilityHelper mobility;
  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
  uint32_t numOfNodes = nodeContainer.GetN();
   for(uint32_t i = 0; i< numOfNodes; i++)
    {   
    positionAlloc->Add(Vector(x,y,z));
    }   
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.SetPositionAllocator(positionAlloc);
  mobility.Install(nodeContainer);
  }

Best regards,
Tiago

Michał Król

unread,
Dec 20, 2015, 10:46:14 PM12/20/15
to ns-3-...@googlegroups.com
It worked! Thanks for your help and the feature ;)

For the static nodes I'll use GeographicLib::LocalCartesian::Forward() function. At the begining, I just wanted to make sure the coordinates are translated in the same way for mobile and static nodes.

I really appreciate your help and quick response.

Regards,
Michał

--
Posting to this group should follow these guidelines https://www.nsnam.org/wiki/Ns-3-users-guidelines-for-posting
---

Tiago Cerqueira

unread,
Dec 21, 2015, 6:53:13 AM12/21/15
to ns-3-...@googlegroups.com
No problem, let me know if you run into any more issues… I’ll try to fix these in the next release!

Best regards,
Tiago
Reply all
Reply to author
Forward
0 new messages