A Discrete-Event Network Simulator
API
outdoor-group-mobility-example.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Institute for the Wireless Internet of Things, Northeastern University, Boston, MA
4  * Copyright (c) 2021, University of Washington: refactor for hierarchical model
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: Michele Polese <michele.polese@gmail.com>
20  * Heavily edited by Tom Henderson to use HierarchicalMobilityModel
21  */
22 
63 #include <iostream>
64 #include "ns3/core-module.h"
65 #include <ns3/mobility-module.h>
66 #include "ns3/network-module.h"
67 #include "ns3/buildings-module.h"
68 
69 using namespace ns3;
70 
71 NS_LOG_COMPONENT_DEFINE ("OutdoorGroupMobilityExample");
72 
73 std::ofstream g_timeSeries;
74 
75 void
77 {
78  if (node == nullptr) return;
79  Ptr<MobilityModel> model = node->GetObject<MobilityModel> ();
80  if (model == nullptr) return;
81  NS_LOG_LOGIC ("Node: " << node->GetId () << " Position: " << model->GetPosition ());
82  g_timeSeries << Simulator::Now ().GetSeconds () << " " << node->GetId () << " " << model->GetPosition () << std::endl;
83 
84 }
85 
86 void
88 {
89  std::ofstream outFile;
90  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
91  if (!outFile.is_open ())
92  {
93  NS_LOG_ERROR ("Can't open file " << filename);
94  return;
95  }
96  uint32_t index = 1;
98  {
99  ++index;
100  Box box = (*it)->GetBoundaries ();
101  outFile << "set object " << index
102  << " rect from " << box.xMin << "," << box.yMin
103  << " to " << box.xMax << "," << box.yMax
104  << std::endl;
105  }
106 }
107 
108 int
109 main (int argc, char *argv[])
110 {
111  Time simTime = Seconds (800);
112  uint32_t numPrints = 800;
113  bool useHelper = false;
114 
115  CommandLine cmd (__FILE__);
116  cmd.AddValue ("useHelper", "Whether to use helper code", useHelper);
117  cmd.Parse (argc, argv);
118 
119  g_timeSeries.open ("outdoor-group-mobility-time-series.mob");
120 
121  NodeContainer n;
122  n.Create (3);
123 
124  // The primary mobility model is the RandomWalk2dOutdoorMobilityModel
125  // defined within this bounding box (along with four buildings, not shown):
126  //
127  // (0,50) (100,50)
128  // +-------------------------+
129  // | |
130  // | |
131  // | |
132  // | |
133  // | |
134  // +-------------------------+
135  // (0,0) (100,0)
136  //
137  //
138  // There are two buildings centered at (50,10) and (50,40), and two
139  // additional small buildings centered at (20,25) and (80,25) that
140  // create obstacles for the nodes to avoid.
141 
142  std::vector<Ptr<Building> > buildingVector;
143  Ptr<Building> building = CreateObject<Building> ();
144  building->SetBoundaries (Box (45, 55, 5, 15, 0, 10));
145  buildingVector.push_back (building);
146  building = CreateObject<Building> ();
147  building->SetBoundaries (Box (45, 55, 35, 45, 0, 10));
148  buildingVector.push_back (building);
149  building = CreateObject<Building> ();
150  building->SetBoundaries (Box (17.5, 22.5, 22.5, 27.5, 0, 10));
151  buildingVector.push_back (building);
152  building = CreateObject<Building> ();
153  building->SetBoundaries (Box (77.5, 82.5, 22.5, 27.5, 0, 10));
154  buildingVector.push_back (building);
155 
156  // print the list of buildings to file
157  PrintGnuplottableBuildingListToFile ("outdoor-group-mobility-buildings.txt");
158 
159  // The program now branches into two: one using the low-level API, and
160  // one using the GroupMobilityHelper. Both branches result in equivalent
161  // configuration.
162 
163  int64_t streamIndex = 1;
164  if (useHelper == false)
165  {
166  // The reference (parent) mobility model starts at coordinate (10, 10, 0)
167  // and performs a buildings-aware random walk.
168  //
169  Ptr<RandomWalk2dOutdoorMobilityModel> outdoorMm = CreateObject<RandomWalk2dOutdoorMobilityModel> ();
170  outdoorMm->SetAttribute ("Bounds", RectangleValue (Rectangle (0, 100, 0, 50)));
171  // The tolerance value is used to prevent the child mobility models from
172  // crossing building walls. The child mobility models are defined as
173  // offsets from the parent but are not buildings-aware, so it could be
174  // the case that the parent mobility model was just outside of a wall
175  // but the child mobility model was inside of a wall. The tolerance
176  // value (in meters) prevents the composite position from passing
177  // through a building wall.
178  outdoorMm->SetAttribute ("Tolerance", DoubleValue (2));
179  // The initial position can be directly set
180  outdoorMm->SetPosition (Vector (10, 10, 0));
181  streamIndex += outdoorMm->AssignStreams (streamIndex);
182 
183  // Each HierachicalMobilityModel contains the above model as the Parent,
184  // and a user defined model as the Child. Two MobilityModel objects are
185  // instantiated per node, and each node also shares the same parent model.
186 
187  // Mobility model for the first node (node 0)
188  Ptr<HierarchicalMobilityModel> hierarchical0 = CreateObject<HierarchicalMobilityModel> ();
189  hierarchical0->SetParent (outdoorMm);
190 
191  // Child model for the first node (node 0)
192  Ptr<ConstantPositionMobilityModel> child0 = CreateObject<ConstantPositionMobilityModel> ();
193  child0->SetPosition (Vector (1, 0, 0)); // 1 m offset from parent position
194  // There is no need to AssignStreams() to child0 because the position
195  // is constant and deterministic
196  hierarchical0->SetChild (child0);
197  n.Get (0)->AggregateObject (hierarchical0);
198 
199  // Repeat for other two nodes
200  Ptr<HierarchicalMobilityModel> hierarchical1 = CreateObject<HierarchicalMobilityModel> ();
201  hierarchical1->SetParent (outdoorMm); // Same parent as before
202  Ptr<ConstantPositionMobilityModel> child1 = CreateObject<ConstantPositionMobilityModel> ();
203  child1->SetPosition (Vector (-1, 0, 0));
204  hierarchical1->SetChild (child1);
205  n.Get (1)->AggregateObject (hierarchical1);
206  Ptr<HierarchicalMobilityModel> hierarchical2 = CreateObject<HierarchicalMobilityModel> ();
207  hierarchical2->SetParent (outdoorMm); // Same parent as before
208  Ptr<ConstantPositionMobilityModel> child2 = CreateObject<ConstantPositionMobilityModel> ();
209  child2->SetPosition (Vector (0, 1, 0));
210  hierarchical2->SetChild (child2);
211  n.Get (2)->AggregateObject (hierarchical2);
212  }
213  else
214  {
215  // This branch demonstrates an equivalent set of commands but using
216  // the GroupMobilityHelper
217  GroupMobilityHelper group;
218 
219  // The helper provides a method to set the reference mobility model
220  // for construction by an object factory, but in this case, since we
221  // are using the WaypointMobilityModel, which requires us to add
222  // waypoints directly on the object, we will just pass in the pointer.
223  group.SetReferenceMobilityModel ("ns3::RandomWalk2dOutdoorMobilityModel",
224  "Bounds", RectangleValue (Rectangle (0, 100, 0, 50)),
225  "Tolerance", DoubleValue (2));
226  Ptr<ListPositionAllocator> listPosition = CreateObject<ListPositionAllocator> ();
227  listPosition->Add (Vector (10, 10, 0));
228  group.SetReferencePositionAllocator (listPosition);
229 
230  group.SetMemberMobilityModel ("ns3::ConstantPositionMobilityModel");
231  listPosition = CreateObject<ListPositionAllocator> ();
232  listPosition->Add (Vector (1, 0, 0)); // first child
233  listPosition->Add (Vector (-1, 0, 0)); // second child
234  listPosition->Add (Vector (0, 1, 0)); // second child
235  group.SetMemberPositionAllocator (listPosition);
236 
237  // Install to all three nodes
238  group.Install (n);
239 
240  // After installation, use the helper to make the equivalent
241  // stream assignments as above
242  group.AssignStreams (n, streamIndex);
243  }
244 
245  AsciiTraceHelper ascii;
246  MobilityHelper::EnableAsciiAll (ascii.CreateFileStream ("outdoor-group-mobility-course-change.mob"));
247 
248  // Use a logging PrintPosition() to record time-series position
249  for (unsigned int i = 0; i < numPrints; i++)
250  {
251  for (auto nodeIt = n.Begin (); nodeIt != n.End (); ++nodeIt)
252  {
253  Simulator::Schedule (NanoSeconds (i * simTime.GetNanoSeconds () / numPrints), &PrintPosition, (*nodeIt));
254  }
255  }
256 
257  Simulator::Stop (simTime);
258  Simulator::Run ();
259  g_timeSeries.close ();
261 }
Manage ASCII trace files for device models.
Definition: trace-helper.h:163
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
a 3d box
Definition: box.h:35
double yMax
The y coordinate of the top bound of the box.
Definition: box.h:116
double xMin
The x coordinate of the left bound of the box.
Definition: box.h:110
double yMin
The y coordinate of the bottom bound of the box.
Definition: box.h:114
double xMax
The x coordinate of the right bound of the box.
Definition: box.h:112
std::vector< Ptr< Building > >::const_iterator Iterator
Const Iterator.
Definition: building-list.h:40
static Iterator End(void)
static Iterator Begin(void)
Parse command-line arguments.
Definition: command-line.h:229
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
Helper class used to assign positions and mobility models to nodes for a group mobility configuration...
int64_t AssignStreams(NodeContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the mobility models on t...
void SetMemberPositionAllocator(Ptr< PositionAllocator > allocator)
Set the position allocator which will be used to allocate the initial position of the member mobility...
void Install(Ptr< Node > node)
Install and configure a hierarchical mobility model to the given node, based on the configured refere...
void SetReferenceMobilityModel(Ptr< MobilityModel > mobility)
Set the reference mobility model which will be installed as the parent mobility model during GroupMob...
void SetReferencePositionAllocator(Ptr< PositionAllocator > allocator)
Set the position allocator which will be used to allocate the initial position of the reference mobil...
void SetMemberMobilityModel(std::string type, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue(), std::string n5="", const AttributeValue &v5=EmptyAttributeValue(), std::string n6="", const AttributeValue &v6=EmptyAttributeValue(), std::string n7="", const AttributeValue &v7=EmptyAttributeValue(), std::string n8="", const AttributeValue &v8=EmptyAttributeValue(), std::string n9="", const AttributeValue &v9=EmptyAttributeValue())
Configure the mobility model which will be installed as the member (child) mobility model during Grou...
static void EnableAsciiAll(Ptr< OutputStreamWrapper > stream)
Keep track of the current position and velocity of an object.
Vector GetPosition(void) const
keep track of a set of node pointers.
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t GetId(void) const
Definition: node.cc:109
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:252
a 2d rectangle
Definition: rectangle.h:35
AttributeValue implementation for Rectangle.
Definition: rectangle.h:97
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:391
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:35
void PrintGnuplottableBuildingListToFile(std::string filename)
std::ofstream g_timeSeries
void PrintPosition(Ptr< Node > node)