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