A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
reference-point-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: for HierarchicalMobilityModel
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 reuse HierarchicalMobilityModel)
20 */
21
22/**
23 * This example shows how to use the ns3::HierarchicalMobilityModel
24 * to construct a Reference Point Group Mobility model (RPGM) model
25 * as described in "A survey of mobility models for ad hoc network
26 * research" by Tracy Camp, Jeff Boleng, and Vanessa Davies, Wireless
27 * Communications and Mobile Computing, 2002: vol. 2, pp. 2483-502.
28 *
29 * The HierarchicalMobilityModel is composed of two mobility models;
30 * a parent and a child. The position of the child is expressed
31 * in reference to the position of the parent. For group mobility,
32 * each node in the group installs the same parent mobility model
33 * and different child mobility models.
34 *
35 * There is no node associated with the parent (reference) model.
36 * Instead, all nodes are associated with a hierarchical mobility model
37 * containing both the parent and child models, and the position of
38 * the node is the vector sum of these parent and child positions.
39 *
40 * Standard ns-3 mobility model course change output is traced in
41 * 'reference-point-course-change.mob' file. This file only traces
42 * position when there is a course change. A second trace is produced
43 * by this example: a time-series of node positions sampled every second.
44 * This file is 'reference-point-time-series.mob' and can be plotted
45 * with the 'reference-point-group-mobility-animation.sh' program.
46 *
47 * There is a bit of randomness in the child mobility models (random
48 * walk within a 10m x 10m box surrounding the parent mobility position);
49 * slightly different output can be rendered by changing the ns-3 'RunNumber'
50 * value (see the documentation on ns-3 random variables).
51 *
52 * There is one program option: 'useHelper'. This is simply for code
53 * demonstration purposes; it selects the branch of code that is used
54 * to either configure the mobility using a helper object, or
55 * to directly configure using CreateObject<> () and handling of pointers.
56 * The traces generated should be the same.
57 */
58
59#include "ns3/core-module.h"
60#include "ns3/network-module.h"
61#include <ns3/mobility-module.h>
62
63#include <iostream>
64
65using namespace ns3;
66
67NS_LOG_COMPONENT_DEFINE("ReferencePointGroupMobilityExample");
68
69/// The time series file.
70std::ofstream g_timeSeries;
71
72/**
73 * Print the node position to the time series file.
74 *
75 * \param node The node.
76 */
77void
79{
80 if (!node)
81 {
82 return;
83 }
84 Ptr<MobilityModel> model = node->GetObject<MobilityModel>();
85 if (!model)
86 {
87 return;
88 }
89 NS_LOG_LOGIC("Node: " << node->GetId() << " Position: " << model->GetPosition());
90 g_timeSeries << Simulator::Now().GetSeconds() << " " << node->GetId() << " "
91 << model->GetPosition() << std::endl;
92}
93
94int
95main(int argc, char* argv[])
96{
97 Time simTime = Seconds(800);
98 uint32_t numPrints = 800;
99 bool useHelper = false;
100
101 CommandLine cmd(__FILE__);
102 cmd.AddValue("useHelper", "Whether to use helper code", useHelper);
103 cmd.Parse(argc, argv);
104
105 g_timeSeries.open("reference-point-time-series.mob");
106
108 n.Create(3);
109
110 // The primary mobility model is the WaypointMobilityModel defined within
111 // this bounding box:
112 //
113 // (0,50) (100,50)
114 // +-------------------------+
115 // | .(10,40) (90,40). |
116 // | |
117 // | |
118 // | .(10,10) (90,10). |
119 // | |
120 // +-------------------------+
121 // (0,0) (100,0)
122 //
123
124 // The reference (parent) mobility model starts at coordinate (10,10
125 // and walks clockwise to each waypoint, making two laps. The time
126 // to travel between each waypoint is 100s, so the velocity alternates
127 // between two values due to the rectangular path.
128 // No actual node is represented by the position of this mobility
129 // model; it forms the reference point from which the node's child
130 // mobility model position is offset.
131 //
132 Ptr<WaypointMobilityModel> waypointMm = CreateObject<WaypointMobilityModel>();
133 waypointMm->AddWaypoint(Waypoint(Seconds(0), Vector(10, 10, 0)));
134 waypointMm->AddWaypoint(Waypoint(Seconds(100), Vector(10, 40, 0)));
135 waypointMm->AddWaypoint(Waypoint(Seconds(200), Vector(90, 40, 0)));
136 waypointMm->AddWaypoint(Waypoint(Seconds(300), Vector(90, 10, 0)));
137 waypointMm->AddWaypoint(Waypoint(Seconds(400), Vector(10, 10, 0)));
138 waypointMm->AddWaypoint(Waypoint(Seconds(500), Vector(10, 40, 0)));
139 waypointMm->AddWaypoint(Waypoint(Seconds(600), Vector(90, 40, 0)));
140 waypointMm->AddWaypoint(Waypoint(Seconds(700), Vector(90, 10, 0)));
141 waypointMm->AddWaypoint(Waypoint(Seconds(800), Vector(10, 10, 0)));
142
143 // Each HierarchicalMobilityModel contains the above model as the Parent,
144 // and a user defined model as the Child. Two MobilityModel objects are
145 // instantiated per node (one hierarchical, and one child model), and
146 // a single parent model is reused across all nodes.
147
148 // The program now branches into two: one using the low-level API, and
149 // one using the GroupMobilityHelper. Both branches result in equivalent
150 // configuration.
151
152 int64_t streamIndex = 1;
153 if (!useHelper)
154 {
155 // Assign random variable stream numbers on the parent and each child
156 streamIndex += waypointMm->AssignStreams(streamIndex);
157
158 // Mobility model for the first node (node 0)
159 Ptr<HierarchicalMobilityModel> hierarchical0 = CreateObject<HierarchicalMobilityModel>();
160 hierarchical0->SetParent(waypointMm);
161
162 // Child Mobility model for the first node (node 0). This can be any
163 // other mobility model type; for this example, we reuse the random walk
164 // but with a small 10m x 10m bounding box.
165 Ptr<RandomWalk2dMobilityModel> childRandomWalk0 = CreateObject<RandomWalk2dMobilityModel>();
166 // Position in reference to the original random walk
167 childRandomWalk0->SetAttribute("Bounds", RectangleValue(Rectangle(-5, 5, -5, 5)));
168 childRandomWalk0->SetAttribute("Speed",
169 StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));
170 streamIndex += childRandomWalk0->AssignStreams(streamIndex);
171 hierarchical0->SetChild(childRandomWalk0);
172 n.Get(0)->AggregateObject(hierarchical0);
173 // Repeat for other two nodes
174 Ptr<HierarchicalMobilityModel> hierarchical1 = CreateObject<HierarchicalMobilityModel>();
175 hierarchical1->SetParent(waypointMm); // Same parent as before
176 Ptr<RandomWalk2dMobilityModel> childRandomWalk1 = CreateObject<RandomWalk2dMobilityModel>();
177 childRandomWalk1->SetAttribute("Bounds", RectangleValue(Rectangle(-5, 5, -5, 5)));
178 childRandomWalk1->SetAttribute("Speed",
179 StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));
180 streamIndex += childRandomWalk1->AssignStreams(streamIndex);
181 hierarchical1->SetChild(childRandomWalk1);
182 n.Get(1)->AggregateObject(hierarchical1);
183 Ptr<HierarchicalMobilityModel> hierarchical2 = CreateObject<HierarchicalMobilityModel>();
184 hierarchical2->SetParent(waypointMm); // Same parent as before
185 Ptr<RandomWalk2dMobilityModel> childRandomWalk2 = CreateObject<RandomWalk2dMobilityModel>();
186 childRandomWalk2->SetAttribute("Bounds", RectangleValue(Rectangle(-5, 5, -5, 5)));
187 childRandomWalk2->SetAttribute("Speed",
188 StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));
189 streamIndex += childRandomWalk2->AssignStreams(streamIndex);
190 hierarchical2->SetChild(childRandomWalk2);
191 n.Get(2)->AggregateObject(hierarchical2);
192 }
193 else
194 {
195 // This branch demonstrates an equivalent set of commands but using
196 // the GroupMobilityHelper
198
199 // The helper provides a method to set the reference mobility model
200 // for construction by an object factory, but in this case, since we
201 // are using the WaypointMobilityModel, which requires us to add
202 // waypoints directly on the object, we will just pass in the pointer.
203 group.SetReferenceMobilityModel(waypointMm);
204
205 // The WaypointMobilityModel does not need a position allocator
206 // (it can use its first waypoint as such), but in general, the
207 // GroupMobilityHelper can be configured to accept configuration for
208 // a PositionAllocator for the reference model. We skip that here.
209
210 // Next, configure the member mobility model
211 group.SetMemberMobilityModel("ns3::RandomWalk2dMobilityModel",
212 "Bounds",
213 RectangleValue(Rectangle(-5, 5, -5, 5)),
214 "Speed",
215 StringValue("ns3::ConstantRandomVariable[Constant=0.1]"));
216
217 // Again, we could call 'SetMemberPositionAllocator' and provide a
218 // position allocator here for the member nodes, but none is provided
219 // in this example, so they will start at time zero with the same
220 // position as the reference node.
221
222 // Install to all three nodes
223 group.Install(n);
224
225 // After installation, use the helper to make the equivalent
226 // stream assignments as above
227 group.AssignStreams(n, streamIndex);
228 }
229
230 // Note: The tracing methods are static methods declared on the
231 // MobilityHelper class, not on the GroupMobilityHelper class
232 AsciiTraceHelper ascii;
233 MobilityHelper::EnableAsciiAll(ascii.CreateFileStream("reference-point-course-change.mob"));
234
235 // Use a logging PrintPosition() to record time-series position
236 for (unsigned int i = 0; i < numPrints; i++)
237 {
238 for (auto nodeIt = n.Begin(); nodeIt != n.End(); ++nodeIt)
239 {
240 Simulator::Schedule(NanoSeconds(i * simTime.GetNanoSeconds() / numPrints),
242 (*nodeIt));
243 }
244 }
245
246 Simulator::Stop(simTime);
248 g_timeSeries.close();
250}
Manage ASCII trace files for device models.
Definition: trace-helper.h:174
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.
Parse command-line arguments.
Definition: command-line.h:232
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 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...
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:309
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
a 2d rectangle
Definition: rectangle.h:35
AttributeValue implementation for Rectangle.
Definition: rectangle.h:125
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Hold variables of type string.
Definition: string.h:56
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:418
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
a (time, location) pair.
Definition: waypoint.h:36
#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:1355
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns cmd
Definition: second.py:40
std::ofstream g_timeSeries
The time series file.
void PrintPosition(Ptr< Node > node)
Print the node position to the time series file.