15#include "ns3/double.h"
18#include "ns3/pointer.h"
19#include "ns3/simulator.h"
20#include "ns3/string.h"
21#include "ns3/uinteger.h"
37 TypeId(
"ns3::RandomWalk2dOutdoorMobilityModel")
39 .SetGroupName(
"Mobility")
41 .AddAttribute(
"Bounds",
42 "Bounds of the area to cruise.",
47 "Change current direction and speed after moving for this delay.",
51 .AddAttribute(
"Distance",
52 "Change current direction and speed after moving for this distance.",
57 "The mode indicates the condition used to "
58 "change the current speed and direction",
65 .AddAttribute(
"Direction",
66 "A random variable used to pick the direction (radians).",
67 StringValue(
"ns3::UniformRandomVariable[Min=0.0|Max=6.283184]"),
72 "A random variable used to pick the speed (m/s)."
73 "The default value is taken from Figure 1 of the paper"
74 "Henderson, L.F., 1971. The statistics of crowd fluids. nature, 229(5284), p.381.",
75 StringValue(
"ns3::NormalRandomVariable[Mean=1.53|Variance=0.040401]"),
78 .AddAttribute(
"Tolerance",
79 "Tolerance for the intersection point with buildings (m)."
80 "It represents a small distance from where the building limit"
81 "is actually placed, for example to represent a sidewalk.",
85 .AddAttribute(
"MaxIterations",
86 "Maximum number of attempts to find an alternative next position"
87 "if the original one is inside a building.",
107 Vector velocity(std::cos(direction) * speed, std::sin(direction) * speed, 0.0);
135 Vector nextPosition = position;
136 nextPosition.x += velocity.x * delayLeft.
GetSeconds();
137 nextPosition.y += velocity.y * delayLeft.
GetSeconds();
143 bool outdoor = std::get<0>(outdoorBuilding);
156 NS_LOG_LOGIC(
"NextPosition would lead into a building");
160 double delaySecondsX = std::numeric_limits<double>::max();
161 double delaySecondsY = std::numeric_limits<double>::max();
164 delaySecondsX = std::abs((nextPosition.x - position.x) / velocity.x);
168 delaySecondsY = std::abs((nextPosition.y - position.y) / velocity.y);
170 Time delay =
Seconds(std::min(delaySecondsX, delaySecondsY));
184 bool outdoor = std::get<0>(outdoorBuilding);
189 double delaySeconds = std::numeric_limits<double>::max();
193 std::min(delaySeconds, std::abs((nextPosition.x - position.x) / velocity.x));
195 else if (velocity.y != 0)
198 std::min(delaySeconds, std::abs((nextPosition.y - position.y) / velocity.y));
202 NS_ABORT_MSG(
"RandomWalk2dOutdoorMobilityModel::DoWalk: unable to calculate the "
204 "(the node is stationary).");
214 NS_LOG_LOGIC(
"NextPosition would lead into a building");
218 double delaySecondsX = std::numeric_limits<double>::max();
219 double delaySecondsY = std::numeric_limits<double>::max();
223 std::min(delaySecondsX, std::abs((nextPosition.x - position.x) / velocity.x));
228 std::min(delaySecondsY, std::abs((nextPosition.y - position.y) / velocity.y));
230 if (delaySecondsX == std::numeric_limits<double>::max() &&
231 delaySecondsY == std::numeric_limits<double>::max())
233 NS_ABORT_MSG(
"RandomWalk2dOutdoorMobilityModel::DoWalk: unable to calculate the "
235 "(the node is stationary).");
238 Time delay =
Seconds(std::min(delaySecondsX, delaySecondsY));
246 NS_LOG_LOGIC(
"Position " << position <<
" NextPosition " << nextPosition);
253std::pair<bool, Ptr<Building>>
255 Vector nextPosition)
const
259 bool intersectBuilding =
false;
260 double minIntersectionDistance = std::numeric_limits<double>::max();
267 if ((*bit)->IsIntersect(currentPosition, nextPosition))
269 NS_LOG_LOGIC(
"Building " << (*bit)->GetBoundaries() <<
" intersects the line between "
270 << currentPosition <<
" and " << nextPosition);
273 (*bit)->GetBoundaries());
275 intersectBuilding =
true;
276 if (distance < minIntersectionDistance)
278 minIntersectionDistance = distance;
279 minIntersectionDistanceBuilding = (*bit);
284 return std::make_pair(!intersectBuilding, minIntersectionDistanceBuilding);
290 Box boundaries)
const
293 bool inside = boundaries.
IsInside(current);
301 double xIntersect = 0;
302 double yIntersect = 0;
311 (next.y - current.y) / (next.x - current.x) * (xIntersect - current.x) + current.y;
318 (next.y - current.y) / (next.x - current.x) * (xIntersect - current.x) + current.y;
325 (next.x - current.x) / (next.y - current.y) * (yIntersect - current.y) + current.x;
332 (next.x - current.x) / (next.y - current.y) * (yIntersect - current.y) + current.x;
363 NS_LOG_DEBUG(
"xIntersect " << xIntersect <<
" yIntersect " << yIntersect);
364 return Vector(xIntersect, yIntersect, 0);
379 velocity.x = -velocity.x;
384 velocity.y = -velocity.y;
391 velocity.x = -velocity.x;
392 velocity.y = -velocity.y;
406 bool nextWouldBeInside =
true;
409 while (nextWouldBeInside && iter <
m_maxIter)
411 NS_LOG_INFO(
"The next position would be inside a building, compute an alternative");
415 Vector velocityVector(std::cos(direction) * speed, std::sin(direction) * speed, 0.0);
418 Vector nextPosition = intersectPosition;
419 nextPosition.x += velocityVector.x * delayLeft.
GetSeconds();
420 nextPosition.y += velocityVector.y * delayLeft.
GetSeconds();
424 bool outdoor = std::get<0>(outdoorBuilding);
428 NS_LOG_LOGIC(
"inside loop intersect " << intersectPosition <<
" nextPosition "
429 << nextPosition <<
" " << outdoor <<
" building "
430 << std::get<1>(outdoorBuilding)->GetBoundaries());
434 NS_LOG_LOGIC(
"inside loop intersect " << intersectPosition <<
" nextPosition "
435 << nextPosition <<
" " << outdoor);
440 nextWouldBeInside =
false;
455 double speed = distance / delayLeft.
GetSeconds();
458 <<
" diff " << posDiff <<
" dist " << distance);
460 Vector velocityVector(posDiff.x / distance * speed, posDiff.y / distance * speed, 0.0);
463 Vector nextPosition = intersectPosition;
464 nextPosition.x += velocityVector.x * delayLeft.
GetSeconds();
465 nextPosition.y += velocityVector.y * delayLeft.
GetSeconds();
469 bool outdoor = std::get<0>(outdoorBuilding);
473 <<
m_maxIter + 1 <<
" iterations, loop intersect " << intersectPosition
474 <<
" nextPosition " << nextPosition <<
" " << outdoor <<
" building "
475 << std::get<1>(outdoorBuilding)->GetBoundaries());
479 "Not able to find an outdoor position. Try to increase the attribute MaxIterations "
480 "and check the position of the buildings in the scenario.");
484 NS_LOG_LOGIC(
"inside loop intersect " << intersectPosition <<
" nextPosition "
485 << nextPosition <<
" " << outdoor);
double yMax
The y coordinate of the top bound of the box.
bool IsInside(const Vector &position) const
double xMin
The x coordinate of the left bound of the box.
double yMin
The y coordinate of the bottom bound of the box.
double xMax
The x coordinate of the right bound of the box.
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'.
Hold variables of type enum.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
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.
virtual void DoDispose()
Destructor implementation.
Smart pointer class similar to boost::intrusive_ptr.
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
Rectangle m_bounds
Bounds of the area to cruise.
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 DoGetPosition() const override
Vector CalculateIntersectionFromOutside(const Vector ¤t, const Vector &next, const Box boundaries) const
Compute the intersecting point of the box represented by boundaries and the line between current and ...
EventId m_event
stored event ID
Ptr< RandomVariableStream > m_direction
rv for picking direction
void DoDispose() override
Destructor implementation.
Mode m_mode
whether in time or distance mode
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.
Vector DoGetVelocity() const override
void DoInitialize() override
Initialize() implementation.
Time m_modeTime
Change current direction and speed after this delay.
Ptr< RandomVariableStream > m_speed
rv for picking speed
void DoSetPosition(const Vector &position) override
Side GetClosestSideOrCorner(const Vector &position) const
bool IsInside(const Vector &position) const
Vector CalculateIntersection(const Vector ¤t, const Vector &speed) const
Side
enum for naming sides
AttributeValue implementation for Rectangle.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
static void Remove(const EventId &id)
Remove an event from the event list.
Hold variables of type string.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
bool IsNegative() const
Exactly equivalent to t <= 0.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Ptr< const AttributeChecker > MakeDoubleChecker()
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Ptr< const AttributeChecker > MakeRectangleChecker()
Ptr< const AttributeAccessor > MakeRectangleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Ptr< const AttributeChecker > MakeUintegerChecker()
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Seconds(double value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
double CalculateDistance(const Vector3D &a, const Vector3D &b)