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
69using namespace ns3;
70
71NS_LOG_COMPONENT_DEFINE("OutdoorGroupMobilityExample");
72
74std::ofstream g_timeSeries;
75
81void
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
103void
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;
114 for (BuildingList::Iterator it = BuildingList::Begin(); it != BuildingList::End(); ++it)
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
123int
124main(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
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
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;
264 MobilityHelper::EnableAsciiAll(
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),
274 (*nodeIt));
275 }
276 }
277
278 Simulator::Stop(simTime);
279 Simulator::Run();
280 g_timeSeries.close();
281 Simulator::Destroy();
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
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...
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.
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
Vector3D Vector
Vector alias typedef for compatibility with mobility models.
Definition: vector.h:324
#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 Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
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.