A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Author: Michele Polese <michele.polese@gmail.com>
8 * Heavily edited by Tom Henderson to use HierarchicalMobilityModel
9 */
10
11/**
12 * This example shows how to use the ns3::HierarchicalMobilityModel
13 * to construct a Reference Point Group Mobility model (RPGM) model
14 * as described in "A survey of mobility models for ad hoc network
15 * research" by Tracy Camp, Jeff Boleng, and Vanessa Davies, Wireless
16 * Communications and Mobile Computing, 2002: vol. 2, pp. 2483-502.
17 * This example is closely related to the group mobility example
18 * `src/mobility/group/reference-point-group-mobility-example.cc`
19 * except that this version is buildings-aware.
20 *
21 * The HierarchicalMobilityModel is composed of two mobility models;
22 * a parent and a child. The position of the child is expressed
23 * in reference to the position of the parent. For group mobility,
24 * each node in the group can install the same parent mobility model
25 * and different child mobility models. The parent mobility model
26 * in this case, the "RandomWalk2dOutdoorMobilityModel", is
27 * buildings-aware. The child mobility models are not, but the
28 * "Tolerance" attribute is defined on the parent model such that the
29 * child mobility models do not result in movement through a building
30 * wall.
31 *
32 * Standard ns-3 mobility model course change output is traced in
33 * outdoor-group-mobility-course-change.mob. Time series data of position
34 * is traced in outdoor-group-mobility-time-series.mob. This time series
35 * data can be animated with a corresponding Bash script. Another program
36 * output is the list of buildings ("outdoor-group-mobility-buildings.txt").
37 *
38 * There is one program option: 'useHelper'. This is simply for code
39 * demonstration purposes; it selects the branch of code that is used
40 * to either configure the mobility using a helper object, or
41 * to directly configure using CreateObject<> () and handling of pointers.
42 * The traces generated should be the same.
43 *
44 * Randomness in this program is due to the parent mobility model which
45 * executes a random walk, while the child mobility models are set as
46 * constant position offsets from the parent. Slightly different motion
47 * can be obtained by changing the ns-3 'RunNumber' value (see the
48 * documentation on ns-3 random variables).
49 */
50
51#include "ns3/buildings-module.h"
52#include "ns3/core-module.h"
53#include "ns3/network-module.h"
54#include <ns3/mobility-module.h>
55
56#include <iostream>
57
58using namespace ns3;
59
60NS_LOG_COMPONENT_DEFINE("OutdoorGroupMobilityExample");
61
62/// The time series file.
63std::ofstream g_timeSeries;
64
65/**
66 * Print the node position to the time series file.
67 *
68 * \param node The node.
69 */
70void
72{
73 if (!node)
74 {
75 return;
76 }
77 Ptr<MobilityModel> model = node->GetObject<MobilityModel>();
78 if (!model)
79 {
80 return;
81 }
82 NS_LOG_LOGIC("Node: " << node->GetId() << " Position: " << model->GetPosition());
83 g_timeSeries << Simulator::Now().GetSeconds() << " " << node->GetId() << " "
84 << model->GetPosition() << std::endl;
85}
86
87/**
88 * Print the buildings list in a format that can be used by Gnuplot to draw them.
89 *
90 * \param filename The output filename.
91 */
92void
94{
95 std::ofstream outFile;
96 outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
97 if (!outFile.is_open())
98 {
99 NS_LOG_ERROR("Can't open file " << filename);
100 return;
101 }
102 uint32_t index = 1;
103 for (auto it = BuildingList::Begin(); it != BuildingList::End(); ++it)
104 {
105 ++index;
106 Box box = (*it)->GetBoundaries();
107 outFile << "set object " << index << " rect from " << box.xMin << "," << box.yMin << " to "
108 << box.xMax << "," << box.yMax << std::endl;
109 }
110}
111
112int
113main(int argc, char* argv[])
114{
115 Time simTime = Seconds(800);
116 uint32_t numPrints = 800;
117 bool useHelper = false;
118
119 CommandLine cmd(__FILE__);
120 cmd.AddValue("useHelper", "Whether to use helper code", useHelper);
121 cmd.Parse(argc, argv);
122
123 g_timeSeries.open("outdoor-group-mobility-time-series.mob");
124
126 n.Create(3);
127
128 // The primary mobility model is the RandomWalk2dOutdoorMobilityModel
129 // defined within this bounding box (along with four buildings, not shown):
130 //
131 // (0,50) (100,50)
132 // +-------------------------+
133 // | |
134 // | |
135 // | |
136 // | |
137 // | |
138 // +-------------------------+
139 // (0,0) (100,0)
140 //
141 //
142 // There are two buildings centered at (50,10) and (50,40), and two
143 // additional small buildings centered at (20,25) and (80,25) that
144 // create obstacles for the nodes to avoid.
145
146 std::vector<Ptr<Building>> buildingVector;
148 building->SetBoundaries(Box(45, 55, 5, 15, 0, 10));
149 buildingVector.push_back(building);
150 building = CreateObject<Building>();
151 building->SetBoundaries(Box(45, 55, 35, 45, 0, 10));
152 buildingVector.push_back(building);
153 building = CreateObject<Building>();
154 building->SetBoundaries(Box(17.5, 22.5, 22.5, 27.5, 0, 10));
155 buildingVector.push_back(building);
156 building = CreateObject<Building>();
157 building->SetBoundaries(Box(77.5, 82.5, 22.5, 27.5, 0, 10));
158 buildingVector.push_back(building);
159
160 // print the list of buildings to file
161 PrintGnuplottableBuildingListToFile("outdoor-group-mobility-buildings.txt");
162
163 // The program now branches into two: one using the low-level API, and
164 // one using the GroupMobilityHelper. Both branches result in equivalent
165 // configuration.
166
167 int64_t streamIndex = 1;
168 if (!useHelper)
169 {
170 // The reference (parent) mobility model starts at coordinate (10, 10, 0)
171 // and performs a buildings-aware random walk.
172 //
175 outdoorMm->SetAttribute("Bounds", RectangleValue(Rectangle(0, 100, 0, 50)));
176 // The tolerance value is used to prevent the child mobility models from
177 // crossing building walls. The child mobility models are defined as
178 // offsets from the parent but are not buildings-aware, so it could be
179 // the case that the parent mobility model was just outside of a wall
180 // but the child mobility model was inside of a wall. The tolerance
181 // value (in meters) prevents the composite position from passing
182 // through a building wall.
183 outdoorMm->SetAttribute("Tolerance", DoubleValue(2));
184 // The initial position can be directly set
185 outdoorMm->SetPosition(Vector(10, 10, 0));
186 streamIndex += outdoorMm->AssignStreams(streamIndex);
187
188 // Each HierarchicalMobilityModel contains the above model as the Parent,
189 // and a user defined model as the Child. Two MobilityModel objects are
190 // instantiated per node, and each node also shares the same parent model.
191
192 // Mobility model for the first node (node 0)
194 hierarchical0->SetParent(outdoorMm);
195
196 // Child model for the first node (node 0)
198 child0->SetPosition(Vector(1, 0, 0)); // 1 m offset from parent position
199 // There is no need to AssignStreams() to child0 because the position
200 // is constant and deterministic
201 hierarchical0->SetChild(child0);
202 n.Get(0)->AggregateObject(hierarchical0);
203
204 // Repeat for other two nodes
206 hierarchical1->SetParent(outdoorMm); // Same parent as before
208 child1->SetPosition(Vector(-1, 0, 0));
209 hierarchical1->SetChild(child1);
210 n.Get(1)->AggregateObject(hierarchical1);
212 hierarchical2->SetParent(outdoorMm); // Same parent as before
214 child2->SetPosition(Vector(0, 1, 0));
215 hierarchical2->SetChild(child2);
216 n.Get(2)->AggregateObject(hierarchical2);
217 }
218 else
219 {
220 // This branch demonstrates an equivalent set of commands but using
221 // the GroupMobilityHelper
223
224 // The helper provides a method to set the reference mobility model
225 // for construction by an object factory, but in this case, since we
226 // are using the WaypointMobilityModel, which requires us to add
227 // waypoints directly on the object, we will just pass in the pointer.
228 group.SetReferenceMobilityModel("ns3::RandomWalk2dOutdoorMobilityModel",
229 "Bounds",
230 RectangleValue(Rectangle(0, 100, 0, 50)),
231 "Tolerance",
232 DoubleValue(2));
234 listPosition->Add(Vector(10, 10, 0));
235 group.SetReferencePositionAllocator(listPosition);
236
237 group.SetMemberMobilityModel("ns3::ConstantPositionMobilityModel");
239 listPosition->Add(Vector(1, 0, 0)); // first child
240 listPosition->Add(Vector(-1, 0, 0)); // second child
241 listPosition->Add(Vector(0, 1, 0)); // second child
242 group.SetMemberPositionAllocator(listPosition);
243
244 // Install to all three nodes
245 group.Install(n);
246
247 // After installation, use the helper to make the equivalent
248 // stream assignments as above
249 group.AssignStreams(n, streamIndex);
250 }
251
252 AsciiTraceHelper ascii;
254 ascii.CreateFileStream("outdoor-group-mobility-course-change.mob"));
255
256 // Use a logging PrintPosition() to record time-series position
257 for (unsigned int i = 0; i < numPrints; i++)
258 {
259 for (auto nodeIt = n.Begin(); nodeIt != n.End(); ++nodeIt)
260 {
261 Simulator::Schedule(NanoSeconds(i * simTime.GetNanoSeconds() / numPrints),
263 (*nodeIt));
264 }
265 }
266
267 Simulator::Stop(simTime);
269 g_timeSeries.close();
271
272 return 0;
273}
Manage ASCII trace files for device models.
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:24
double yMax
The y coordinate of the top bound of the box.
Definition box.h:105
double xMin
The x coordinate of the left bound of the box.
Definition box.h:99
double yMin
The y coordinate of the bottom bound of the box.
Definition box.h:103
double xMax
The x coordinate of the right bound of the box.
Definition box.h:101
static Iterator End()
static Iterator Begin()
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
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.
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.
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition object.cc:298
Smart pointer class similar to boost::intrusive_ptr.
a 2d rectangle
Definition rectangle.h:24
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:407
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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.