A Discrete-Event Network Simulator
API
random-walk-2d-outdoor-mobility-model.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006,2007 INRIA
3  * Copyright (c) 2019 University of Padova
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  * Author: Michele Polese <michele.polese@gmail.com>
20  */
22 
23 #include "building-list.h"
24 #include "building.h"
25 
26 #include "ns3/double.h"
27 #include "ns3/enum.h"
28 #include "ns3/log.h"
29 #include "ns3/pointer.h"
30 #include "ns3/simulator.h"
31 #include "ns3/string.h"
32 #include "ns3/uinteger.h"
33 
34 #include <cmath>
35 #include <limits>
36 
37 namespace ns3
38 {
39 
40 NS_LOG_COMPONENT_DEFINE("RandomWalk2dOutdoor");
41 
42 NS_OBJECT_ENSURE_REGISTERED(RandomWalk2dOutdoorMobilityModel);
43 
44 TypeId
46 {
47  static TypeId tid =
48  TypeId("ns3::RandomWalk2dOutdoorMobilityModel")
50  .SetGroupName("Mobility")
51  .AddConstructor<RandomWalk2dOutdoorMobilityModel>()
52  .AddAttribute("Bounds",
53  "Bounds of the area to cruise.",
54  RectangleValue(Rectangle(0.0, 100.0, 0.0, 100.0)),
55  MakeRectangleAccessor(&RandomWalk2dOutdoorMobilityModel::m_bounds),
56  MakeRectangleChecker())
57  .AddAttribute("Time",
58  "Change current direction and speed after moving for this delay.",
59  TimeValue(Seconds(20.0)),
62  .AddAttribute("Distance",
63  "Change current direction and speed after moving for this distance.",
64  DoubleValue(30.0),
66  MakeDoubleChecker<double>())
67  .AddAttribute("Mode",
68  "The mode indicates the condition used to "
69  "change the current speed and direction",
71  MakeEnumAccessor<Mode>(&RandomWalk2dOutdoorMobilityModel::m_mode),
73  "Distance",
75  "Time"))
76  .AddAttribute("Direction",
77  "A random variable used to pick the direction (radians).",
78  StringValue("ns3::UniformRandomVariable[Min=0.0|Max=6.283184]"),
80  MakePointerChecker<RandomVariableStream>())
81  .AddAttribute(
82  "Speed",
83  "A random variable used to pick the speed (m/s)."
84  "The default value is taken from Figure 1 of the paper"
85  "Henderson, L.F., 1971. The statistics of crowd fluids. nature, 229(5284), p.381.",
86  StringValue("ns3::NormalRandomVariable[Mean=1.53|Variance=0.040401]"),
88  MakePointerChecker<RandomVariableStream>())
89  .AddAttribute("Tolerance",
90  "Tolerance for the intersection point with buildings (m)."
91  "It represents a small distance from where the building limit"
92  "is actually placed, for example to represent a sidewalk.",
93  DoubleValue(1e-6),
95  MakeDoubleChecker<double>())
96  .AddAttribute("MaxIterations",
97  "Maximum number of attempts to find an alternative next position"
98  "if the original one is inside a building.",
99  UintegerValue(100),
101  MakeUintegerChecker<uint32_t>());
102  return tid;
103 }
104 
105 void
107 {
110 }
111 
112 void
114 {
115  m_helper.Update();
116  double speed = m_speed->GetValue();
117  double direction = m_direction->GetValue();
118  Vector vector(std::cos(direction) * speed, std::sin(direction) * speed, 0.0);
119  m_helper.SetVelocity(vector);
120  m_helper.Unpause();
121 
122  Time delayLeft;
124  {
125  delayLeft = m_modeTime;
126  }
127  else
128  {
129  delayLeft = Seconds(m_modeDistance / speed);
130  }
131  DoWalk(delayLeft);
132 }
133 
134 void
136 {
137  if (delayLeft.IsNegative())
138  {
139  NS_LOG_INFO(this << " Ran out of time");
140  return;
141  }
142  NS_LOG_FUNCTION(this << delayLeft.GetSeconds());
143 
144  Vector position = m_helper.GetCurrentPosition();
145  Vector speed = m_helper.GetVelocity();
146  Vector nextPosition = position;
147  nextPosition.x += speed.x * delayLeft.GetSeconds();
148  nextPosition.y += speed.y * delayLeft.GetSeconds();
149  m_event.Cancel();
150 
151  // check if the nextPosition is inside a building, or if the line
152  // from position to the next position intersects a building
153  auto outdoorBuilding = IsLineClearOfBuildings(position, nextPosition);
154  bool outdoor = std::get<0>(outdoorBuilding);
155  Ptr<Building> building = std::get<1>(outdoorBuilding);
156 
157  if (m_bounds.IsInside(nextPosition))
158  {
159  if (outdoor)
160  {
161  m_event = Simulator::Schedule(delayLeft,
163  this);
164  }
165  else
166  {
167  NS_LOG_LOGIC("NextPosition would lead into a building");
168  nextPosition =
169  CalculateIntersectionFromOutside(position, nextPosition, building->GetBoundaries());
170 
171  double delaySecondsX = std::numeric_limits<double>::max();
172  double delaySecondsY = std::numeric_limits<double>::max();
173  if (speed.x != 0)
174  {
175  delaySecondsX = std::abs((nextPosition.x - position.x) / speed.x);
176  }
177  if (speed.y != 0)
178  {
179  delaySecondsY = std::abs((nextPosition.y - position.y) / speed.y);
180  }
181  Time delay = Seconds(std::min(delaySecondsX, delaySecondsY));
184  this,
185  delayLeft - delay,
186  nextPosition);
187  }
188  }
189  else
190  {
191  NS_LOG_LOGIC("Out of bounding box");
192  nextPosition = m_bounds.CalculateIntersection(position, speed);
193  // check that this nextPosition is outdoor
194  auto outdoorBuilding = IsLineClearOfBuildings(position, nextPosition);
195  bool outdoor = std::get<0>(outdoorBuilding);
196  Ptr<Building> building = std::get<1>(outdoorBuilding);
197 
198  if (outdoor)
199  {
200  double delaySeconds = std::numeric_limits<double>::max();
201  if (speed.x != 0)
202  {
203  delaySeconds =
204  std::min(delaySeconds, std::abs((nextPosition.x - position.x) / speed.x));
205  }
206  else if (speed.y != 0)
207  {
208  delaySeconds =
209  std::min(delaySeconds, std::abs((nextPosition.y - position.y) / speed.y));
210  }
211  else
212  {
213  NS_ABORT_MSG("RandomWalk2dOutdoorMobilityModel::DoWalk: unable to calculate the "
214  "rebound time "
215  "(the node is stationary).");
216  }
217  Time delay = Seconds(delaySeconds);
220  this,
221  delayLeft - delay);
222  }
223  else
224  {
225  NS_LOG_LOGIC("NextPosition would lead into a building");
226  nextPosition =
227  CalculateIntersectionFromOutside(position, nextPosition, building->GetBoundaries());
228 
229  double delaySecondsX = std::numeric_limits<double>::max();
230  double delaySecondsY = std::numeric_limits<double>::max();
231  if (speed.x != 0)
232  {
233  delaySecondsX =
234  std::min(delaySecondsX, std::abs((nextPosition.x - position.x) / speed.x));
235  }
236  if (speed.y != 0)
237  {
238  delaySecondsY =
239  std::min(delaySecondsY, std::abs((nextPosition.y - position.y) / speed.y));
240  }
241  if (delaySecondsX == std::numeric_limits<double>::max() &&
242  delaySecondsY == std::numeric_limits<double>::max())
243  {
244  NS_ABORT_MSG("RandomWalk2dOutdoorMobilityModel::DoWalk: unable to calculate the "
245  "rebound time "
246  "(the node is stationary).");
247  }
248 
249  Time delay = Seconds(std::min(delaySecondsX, delaySecondsY));
252  this,
253  delayLeft - delay,
254  nextPosition);
255  }
256  }
257  NS_LOG_LOGIC("Position " << position << " NextPosition " << nextPosition);
258 
259  // store the previous position
260  m_prevPosition = position;
262 }
263 
264 std::pair<bool, Ptr<Building>>
266  Vector nextPosition) const
267 {
268  NS_LOG_FUNCTION(this << currentPosition << nextPosition);
269 
270  bool intersectBuilding = false;
271  double minIntersectionDistance = std::numeric_limits<double>::max();
272  Ptr<Building> minIntersectionDistanceBuilding;
273 
274  for (auto bit = BuildingList::Begin(); bit != BuildingList::End(); ++bit)
275  {
276  // check if this building intersects the line between the current and next positions
277  // this checks also if the next position is inside the building
278  if ((*bit)->IsIntersect(currentPosition, nextPosition))
279  {
280  NS_LOG_LOGIC("Building " << (*bit)->GetBoundaries() << " intersects the line between "
281  << currentPosition << " and " << nextPosition);
282  auto intersection = CalculateIntersectionFromOutside(currentPosition,
283  nextPosition,
284  (*bit)->GetBoundaries());
285  double distance = CalculateDistance(intersection, currentPosition);
286  intersectBuilding = true;
287  if (distance < minIntersectionDistance)
288  {
289  minIntersectionDistance = distance;
290  minIntersectionDistanceBuilding = (*bit);
291  }
292  }
293  }
294 
295  return std::make_pair(!intersectBuilding, minIntersectionDistanceBuilding);
296 }
297 
298 Vector
300  const Vector& next,
301  Box boundaries) const
302 {
303  NS_LOG_FUNCTION(this << " current " << current << " next " << next);
304  bool inside = boundaries.IsInside(current);
305  NS_ASSERT(!inside);
306 
307  // get the closest side
308  Rectangle rect = Rectangle(boundaries.xMin, boundaries.xMax, boundaries.yMin, boundaries.yMax);
309  NS_LOG_DEBUG("rect " << rect);
310  Rectangle::Side closestSide = rect.GetClosestSideOrCorner(current);
311 
312  double xIntersect = 0;
313  double yIntersect = 0;
314 
315  switch (closestSide)
316  {
318  NS_LOG_DEBUG("The closest side is RIGHT");
319  xIntersect = boundaries.xMax + m_epsilon;
320  NS_ABORT_MSG_IF(next.x - current.x == 0, "x position not updated");
321  yIntersect =
322  (next.y - current.y) / (next.x - current.x) * (xIntersect - current.x) + current.y;
323  break;
324  case Rectangle::LEFTSIDE:
325  NS_LOG_DEBUG("The closest side is LEFT");
326  xIntersect = boundaries.xMin - m_epsilon;
327  NS_ABORT_MSG_IF(next.x - current.x == 0, "x position not updated");
328  yIntersect =
329  (next.y - current.y) / (next.x - current.x) * (xIntersect - current.x) + current.y;
330  break;
331  case Rectangle::TOPSIDE:
332  NS_LOG_DEBUG("The closest side is TOP");
333  yIntersect = boundaries.yMax + m_epsilon;
334  NS_ABORT_MSG_IF(next.y - current.y == 0, "y position not updated");
335  xIntersect =
336  (next.x - current.x) / (next.y - current.y) * (yIntersect - current.y) + current.x;
337  break;
339  NS_LOG_DEBUG("The closest side is BOTTOM");
340  yIntersect = boundaries.yMin - m_epsilon;
341  NS_ABORT_MSG_IF(next.y - current.y == 0, "y position not updated");
342  xIntersect =
343  (next.x - current.x) / (next.y - current.y) * (yIntersect - current.y) + current.x;
344  break;
346  NS_LOG_DEBUG("The closest side is TOPRIGHT");
347  xIntersect = boundaries.xMax + m_epsilon;
348  NS_ABORT_MSG_IF(next.x - current.x == 0, "x position not updated");
349  yIntersect = boundaries.yMax + m_epsilon;
350  NS_ABORT_MSG_IF(next.y - current.y == 0, "y position not updated");
351  break;
353  NS_LOG_DEBUG("The closest side is TOPLEFT");
354  xIntersect = boundaries.xMin - m_epsilon;
355  NS_ABORT_MSG_IF(next.x - current.x == 0, "x position not updated");
356  yIntersect = boundaries.yMax + m_epsilon;
357  NS_ABORT_MSG_IF(next.y - current.y == 0, "y position not updated");
358  break;
360  NS_LOG_DEBUG("The closest side is BOTTOMRIGHT");
361  xIntersect = boundaries.xMax + m_epsilon;
362  NS_ABORT_MSG_IF(next.x - current.x == 0, "x position not updated");
363  yIntersect = boundaries.yMin - m_epsilon;
364  NS_ABORT_MSG_IF(next.y - current.y == 0, "y position not updated");
365  break;
367  NS_LOG_DEBUG("The closest side is BOTTOMLEFT");
368  xIntersect = boundaries.xMin - m_epsilon;
369  NS_ABORT_MSG_IF(next.x - current.x == 0, "x position not updated");
370  yIntersect = boundaries.yMin - m_epsilon;
371  NS_ABORT_MSG_IF(next.y - current.y == 0, "y position not updated");
372  break;
373  }
374  NS_LOG_DEBUG("xIntersect " << xIntersect << " yIntersect " << yIntersect);
375  return Vector(xIntersect, yIntersect, 0);
376 }
377 
378 void
380 {
381  NS_LOG_FUNCTION(this << delayLeft.GetSeconds());
383  Vector position = m_helper.GetCurrentPosition();
384  Vector speed = m_helper.GetVelocity();
385  switch (m_bounds.GetClosestSideOrCorner(position))
386  {
388  case Rectangle::LEFTSIDE:
389  NS_LOG_DEBUG("The closest side is RIGHT or LEFT");
390  speed.x = -speed.x;
391  break;
392  case Rectangle::TOPSIDE:
394  NS_LOG_DEBUG("The closest side is TOP or BOTTOM");
395  speed.y = -speed.y;
396  break;
401  NS_LOG_DEBUG("The closest side is a corner");
402  auto temp = speed.x;
403  speed.x = -speed.y;
404  speed.y = -temp;
405  break;
406  }
407  m_helper.SetVelocity(speed);
408  m_helper.Unpause();
409  DoWalk(delayLeft);
410 }
411 
412 void
413 RandomWalk2dOutdoorMobilityModel::AvoidBuilding(Time delayLeft, Vector intersectPosition)
414 {
415  NS_LOG_FUNCTION(this << delayLeft.GetSeconds());
416  m_helper.Update();
417 
418  bool nextWouldBeInside = true;
419  uint32_t iter = 0;
420 
421  while (nextWouldBeInside && iter < m_maxIter)
422  {
423  NS_LOG_INFO("The next position would be inside a building, compute an alternative");
424  iter++;
425  double speed = m_speed->GetValue();
426  double direction = m_direction->GetValue();
427  Vector velocityVector(std::cos(direction) * speed, std::sin(direction) * speed, 0.0);
428  m_helper.SetVelocity(velocityVector);
429 
430  Vector nextPosition = intersectPosition;
431  nextPosition.x += velocityVector.x * delayLeft.GetSeconds();
432  nextPosition.y += velocityVector.y * delayLeft.GetSeconds();
433 
434  // check if this is inside the current buildingBox
435  auto outdoorBuilding = IsLineClearOfBuildings(intersectPosition, nextPosition);
436  bool outdoor = std::get<0>(outdoorBuilding);
437 
438  if (!outdoor)
439  {
440  NS_LOG_LOGIC("inside loop intersect " << intersectPosition << " nextPosition "
441  << nextPosition << " " << outdoor << " building "
442  << std::get<1>(outdoorBuilding)->GetBoundaries());
443  }
444  else
445  {
446  NS_LOG_LOGIC("inside loop intersect " << intersectPosition << " nextPosition "
447  << nextPosition << " " << outdoor);
448  }
449 
450  if (outdoor && m_bounds.IsInside(nextPosition))
451  {
452  nextWouldBeInside = false;
453  }
454  }
455 
456  // after m_maxIter iterations, the positions tested are all inside
457  // to avoid increasing m_maxIter too much, it is possible to perform a step back
458  // to the previous position and continue from there
459  if (iter >= m_maxIter)
460  {
461  NS_LOG_INFO("Move back to the previous position");
462 
463  // compute the difference between the previous position and the intersection
464  Vector posDiff = m_prevPosition - intersectPosition;
465  // compute the distance
466  double distance = CalculateDistance(m_prevPosition, intersectPosition);
467  double speed = distance / delayLeft.GetSeconds(); // compute the speed
468 
469  NS_LOG_LOGIC("prev " << m_prevPosition << " intersectPosition " << intersectPosition
470  << " diff " << posDiff << " dist " << distance);
471 
472  Vector velocityVector(posDiff.x / distance * speed, posDiff.y / distance * speed, 0.0);
473  m_helper.SetVelocity(velocityVector);
474 
475  Vector nextPosition = intersectPosition;
476  nextPosition.x += velocityVector.x * delayLeft.GetSeconds();
477  nextPosition.y += velocityVector.y * delayLeft.GetSeconds();
478 
479  // check if the path is clear
480  auto outdoorBuilding = IsLineClearOfBuildings(intersectPosition, nextPosition);
481  bool outdoor = std::get<0>(outdoorBuilding);
482  if (!outdoor)
483  {
484  NS_LOG_LOGIC("The position is still inside after "
485  << m_maxIter + 1 << " iterations, loop intersect " << intersectPosition
486  << " nextPosition " << nextPosition << " " << outdoor << " building "
487  << std::get<1>(outdoorBuilding)->GetBoundaries());
488  // This error may be due to buildings being attached to one another, or to the boundary
489  // of the scenario.
491  "Not able to find an outdoor position. Try to increase the attribute MaxIterations "
492  "and check the position of the buildings in the scenario.");
493  }
494  else
495  {
496  NS_LOG_LOGIC("inside loop intersect " << intersectPosition << " nextPosition "
497  << nextPosition << " " << outdoor);
498  }
499  }
500 
501  m_helper.Unpause();
502 
503  DoWalk(delayLeft);
504 }
505 
506 void
508 {
509  // chain up
511 }
512 
513 Vector
515 {
517  return m_helper.GetCurrentPosition();
518 }
519 
520 void
522 {
523  NS_ASSERT(m_bounds.IsInside(position));
524  m_helper.SetPosition(position);
527 }
528 
529 Vector
531 {
532  return m_helper.GetVelocity();
533 }
534 
535 int64_t
537 {
538  m_speed->SetStream(stream);
539  m_direction->SetStream(stream + 1);
540  return 2;
541 }
542 
543 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
#define max(a, b)
Definition: 80211b.c:42
a 3d box
Definition: box.h:35
double yMax
The y coordinate of the top bound of the box.
Definition: box.h:116
bool IsInside(const Vector &position) const
Definition: box.cc:54
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
static Iterator End()
static Iterator Begin()
Vector GetCurrentPosition() const
Get current position vector.
Vector GetVelocity() const
Get velocity; if paused, will return a zero vector.
void Update() const
Update position, if not paused, from last position and time of last update.
void UpdateWithBounds(const Rectangle &rectangle) const
Update position, if not paused, from last position and time of last update.
void Unpause()
Resume mobility from current position at current velocity.
void SetPosition(const Vector &position)
Set position vector.
void SetVelocity(const Vector &vel)
Set new velocity vector.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Hold variables of type enum.
Definition: enum.h:62
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
Keep track of the current position and velocity of an object.
void NotifyCourseChange() const
Must be invoked by subclasses when the course of the position changes to notify course change listene...
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:359
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
2D random walk mobility model which avoids buildings.
void AvoidBuilding(Time delayLeft, Vector intersectPosition)
Avoid a building.
void DoInitializePrivate()
Perform initialization of the object before MobilityModel::DoInitialize ()
int64_t DoAssignStreams(int64_t) override
The default implementation does nothing but return the passed-in parameter.
double m_modeDistance
Change direction and speed after this distance.
ConstantVelocityHelper m_helper
helper for this object
Vector m_prevPosition
Store the previous position in case a step back is needed.
void Rebound(Time timeLeft)
Performs the rebound of the node if it reaches a boundary.
uint32_t m_maxIter
Maximum number of tries to find the next position.
Vector CalculateIntersectionFromOutside(const Vector &current, const Vector &next, const Box boundaries) const
Compute the intersecting point of the box represented by boundaries and the line between current and ...
Ptr< RandomVariableStream > m_direction
rv for picking direction
void DoDispose() override
Destructor implementation.
double m_epsilon
Tolerance for the intersection point with buildings.
void DoWalk(Time delayLeft)
Walk according to position and velocity, until distance is reached, time is reached,...
std::pair< bool, Ptr< Building > > IsLineClearOfBuildings(Vector currentPosition, Vector nextPosition) const
Check if there is a building between two positions (or if the nextPosition is inside a building).
static TypeId GetTypeId()
Register this type with the TypeId system.
void DoInitialize() override
Initialize() implementation.
Time m_modeTime
Change current direction and speed after this delay.
Ptr< RandomVariableStream > m_speed
rv for picking speed
a 2d rectangle
Definition: rectangle.h:35
Side GetClosestSideOrCorner(const Vector &position) const
Definition: rectangle.cc:64
bool IsInside(const Vector &position) const
Definition: rectangle.cc:50
Vector CalculateIntersection(const Vector &current, const Vector &speed) const
Definition: rectangle.cc:152
Side
enum for naming sides
Definition: rectangle.h:41
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
static void Remove(const EventId &id)
Remove an event from the event list.
Definition: simulator.cc:275
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
bool IsNegative() const
Exactly equivalent to t <= 0.
Definition: nstime.h:324
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:194
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition: vector.cc:109