diff --git a/SConstruct b/SConstruct index 82e530348..c854eb3d8 100644 --- a/SConstruct +++ b/SConstruct @@ -64,6 +64,7 @@ core.add_sources([ 'default-value.cc', 'random-variable-default-value.cc', 'rectangle-default-value.cc', + 'rectangle.cc', 'command-line.cc', 'type-name.cc', 'component-manager.cc', @@ -97,6 +98,7 @@ core.add_inst_headers([ 'default-value.h', 'random-variable-default-value.h', 'rectangle-default-value.h', + 'rectangle.h', 'command-line.h', 'type-name.h', 'component-manager.h', @@ -255,8 +257,7 @@ node.add_sources ([ 'grid-topology.cc', 'random-topology.cc', 'random-walk-mobility-model.cc', - 'random-mobility-model.cc', - 'random-direction-mobility-model.cc', + 'random-walk-2d-mobility-model.cc', 'hierarchical-mobility-model.cc', 'ns2-mobility-file-topology.cc', 'mobility-model-helper.cc', @@ -290,8 +291,7 @@ node.add_inst_headers ([ 'grid-topology.h', 'random-topology.h', 'random-walk-mobility-model.h', - 'random-mobility-model.h', - 'random-direction-mobility-model.h', + 'random-walk-2d-mobility-model.h', 'hierarchical-mobility-model.h', 'ns2-mobility-file-topology.h', 'mobility-model-helper.h', diff --git a/src/node/random-walk-2d-mobility-model.cc b/src/node/random-walk-2d-mobility-model.cc new file mode 100644 index 000000000..d2267286e --- /dev/null +++ b/src/node/random-walk-2d-mobility-model.cc @@ -0,0 +1,179 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006,2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include "random-walk-2d-mobility-model.h" +#include "ns3/default-value.h" +#include "ns3/time-default-value.h" +#include "ns3/rectangle-default-value.h" +#include "ns3/random-variable-default-value.h" +#include "ns3/simulator.h" +#include "ns3/debug.h" +#include + +NS_DEBUG_COMPONENT_DEFINE ("RandomWalk2d"); + +namespace ns3 { + +const ClassId RandomWalk2dMobilityModel::cid = + MakeClassId ("RandomWalk2dMobilityModel", RandomWalk2dMobilityModel::iid); + + +static EnumDefaultValue +g_mode ("RandomWalk2dMode", + "The mode indicates the condition used to " + "change the current speed and direction", + RandomWalk2dMobilityModelParameters::MODE_DISTANCE, "Distance", + RandomWalk2dMobilityModelParameters::MODE_TIME, "Time", + 0, 0); + +static IntegerDefaultValue +g_modeDistance ("RandomWalk2dDistance", + "Change current direction and speed after moving this distance.", + 2.0); + +static TimeDefaultValue +g_modeTime ("RandomWalk2dDelay", + "Change current direction and speed after moving for this delay.", + Seconds (1.0)); + +static RandomVariableDefaultValue +g_speed ("RandomWalk2dSpeed", + "A random variable used to pick the speed.", + "Uniform:2:4"); +static RandomVariableDefaultValue +g_direction ("RandomWalk2dDirection", + "A random variable used to pick the direction (gradients).", + "Uniform:0.0:6.283184"); + +static RectangleDefaultValue +g_rectangle ("RandomWalk2dBounds", + "Bounds of the area to cruise.", + 0.0, 0.0, 100.0, 100.0); + +RandomWalk2dMobilityModelParameters::RandomWalk2dMobilityModelParameters () + : m_mode (g_mode.GetValue ()), + m_modeDistance (g_modeDistance.GetValue ()), + m_modeTime (g_modeTime.GetValue ()), + m_speed (g_speed.GetCopy ()), + m_direction (g_direction.GetCopy ()), + m_bounds (g_rectangle.GetValue ()) +{} + +RandomWalk2dMobilityModelParameters::~RandomWalk2dMobilityModelParameters () +{ + delete m_speed; + delete m_direction; + m_speed = 0; + m_direction = 0; +} + +Ptr +RandomWalk2dMobilityModelParameters::GetCurrent (void) +{ + static Ptr parameters = 0; + if (parameters == 0 || + g_speed.IsDirty () || + g_direction.IsDirty () || + g_mode.IsDirty () || + g_modeDistance.IsDirty () || + g_modeTime.IsDirty () || + g_rectangle.IsDirty ()) + { + parameters = Create (); + } + return parameters; +} + +RandomWalk2dMobilityModel::RandomWalk2dMobilityModel () + : m_parameters (RandomWalk2dMobilityModelParameters::GetCurrent ()) +{ + SetInterfaceId (RandomWalk2dMobilityModel::iid); + Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this); +} + +void +RandomWalk2dMobilityModel::Start (void) +{ + double speed = m_parameters->m_speed->GetValue (); + double direction = m_parameters->m_direction->GetValue (); + Speed vector (std::cos (direction) * speed, + std::sin (direction) * speed, + 0.0); + m_helper.Reset (vector); + + Time delayLeft; + if (m_parameters->m_mode == RandomWalk2dMobilityModelParameters::MODE_TIME) + { + delayLeft = m_parameters->m_modeTime; + } + else + { + delayLeft = Seconds (m_parameters->m_modeDistance / speed); + } + DoWalk (delayLeft); +} + +void +RandomWalk2dMobilityModel::DoWalk (Time delayLeft) +{ + Time delay = m_helper.GetDelayToNextPosition (m_parameters->m_bounds, + delayLeft); + if (delay < delayLeft) + { + m_event = Simulator::Schedule (delay, &RandomWalk2dMobilityModel::Rebound, this, + delayLeft - delay); + } + else + { + NS_ASSERT (delay == delayLeft); + m_event = Simulator::Schedule (delay, &RandomWalk2dMobilityModel::Start, this); + } +} + +void +RandomWalk2dMobilityModel::Rebound (Time delayLeft) +{ + m_helper.Rebound (m_parameters->m_bounds); + DoWalk (delayLeft); +} + +void +RandomWalk2dMobilityModel::DoDispose (void) +{ + m_parameters = 0; + // chain up + MobilityModel::DoDispose (); +} +Position +RandomWalk2dMobilityModel::DoGet (void) const +{ + return m_helper.GetCurrentPosition (m_parameters->m_bounds); +} +void +RandomWalk2dMobilityModel::DoSet (const Position &position) +{ + NS_ASSERT (position.IsInside (m_parameters->m_bounds)); + m_helper.InitializePosition (position); + Simulator::Remove (m_event); + Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this); +} + + +} // namespace ns3 diff --git a/src/node/random-walk-2d-mobility-model.h b/src/node/random-walk-2d-mobility-model.h new file mode 100644 index 000000000..d30ebfb87 --- /dev/null +++ b/src/node/random-walk-2d-mobility-model.h @@ -0,0 +1,123 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006,2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef RANDOM_WALK_2D_MOBILITY_MODEL_H +#define RANDOM_WALK_2D_MOBILITY_MODEL_H + +#include "ns3/object.h" +#include "ns3/nstime.h" +#include "ns3/component-manager.h" +#include "ns3/event-id.h" +#include "ns3/rectangle.h" +#include "mobility-model.h" +#include "static-speed-helper.h" + +namespace ns3 { + +class RandomVariable; + +/** + * \brief parameters to control a random walk model + */ +class RandomWalk2dMobilityModelParameters : public Object +{ + public: + /** + * Instantiate a set of RandomWalk parameters initialized + * with the Bind default values. + */ + RandomWalk2dMobilityModelParameters (); + virtual ~RandomWalk2dMobilityModelParameters (); + /** + */ + void SetSpeed (const RandomVariable &speed); + void SetDirection (const RandomVariable &direction); + /** + * \param distance the distance before a direction change + * + * Unit is meters + */ + void SetModeDistance (double distance); + /** + * \param time the delay before a direction change. + */ + void SetModeTime (Time time); + + + enum Mode { + MODE_DISTANCE, + MODE_TIME + }; + private: + friend class RandomWalk2dMobilityModel; + static Ptr GetCurrent (void); + + enum Mode m_mode; + double m_modeDistance; + Time m_modeTime; + RandomVariable *m_speed; + RandomVariable *m_direction; + Rectangle m_bounds; +}; + +/** + * \brief a 2D random walk position model + * + * Each instance moves with a speed and direction choosen at random + * in the intervals [minspeed,maxspeed] and [0,2pi] until + * either a fixed distance has been walked or until a fixed amount + * of time. + * + * The parameters of the model can be specified either with the ns3::Bind + * function and the variables "RandomWalk2dMinSpeed", "RandomWalk2dMaxSpeed", + * "RandomWalk2dMode", "RandomWalk2dModeDistance", and, "RandomWalk2dModeTime" or + * with an instance of the RandomWalk2dMobilityModelParameters class which + * must be fed to the RandomWalk2dMobilityModel constructors. + */ +class RandomWalk2dMobilityModel : public MobilityModel +{ + public: + static const ClassId cid; + /** + * Create a new position object located at position (0,0,0) + */ + RandomWalk2dMobilityModel (); + /** + * Create a new position object located at position (0,0,0) + */ + RandomWalk2dMobilityModel (Ptr parameters); + + private: + void Start (void); + void Rebound (Time timeLeft); + void DoWalk (Time timeLeft); + virtual void DoDispose (void); + virtual Position DoGet (void) const; + virtual void DoSet (const Position &position); + + StaticSpeedHelper m_helper; + EventId m_event; + Ptr m_parameters; +}; + + +} // namespace ns3 + +#endif /* RANDOM_WALK_2D_MOBILITY_MODEL_H */ diff --git a/src/node/static-speed-helper.cc b/src/node/static-speed-helper.cc index ed66d63b1..c56eb5dd9 100644 --- a/src/node/static-speed-helper.cc +++ b/src/node/static-speed-helper.cc @@ -1,4 +1,5 @@ #include "ns3/simulator.h" +#include "ns3/rectangle.h" #include "static-speed-helper.h" namespace ns3 { @@ -18,8 +19,7 @@ StaticSpeedHelper::InitializePosition (const Position &position) void StaticSpeedHelper::Reset (const Speed &speed, const Time &pauseDelay) { - Update (); - m_speed = speed; + Reset (speed); m_pauseEnd = Simulator::Now () + pauseDelay; } @@ -57,4 +57,98 @@ StaticSpeedHelper::Update (void) const m_position.z += m_speed.dz * deltaS; } +void +StaticSpeedHelper::Reset (const Speed &speed) +{ + Update (); + m_speed = speed; + m_pauseEnd = Simulator::Now (); +} +Position +StaticSpeedHelper::IntersectCurrentDirection (const Rectangle &bounds) +{ + double xMaxY = m_position.y + (bounds.xMax - m_position.x) / m_speed.dx * m_speed.dy; + double xMinY = m_position.y + (bounds.xMin - m_position.x) / m_speed.dx * m_speed.dy; + double yMaxX = m_position.x + (bounds.yMax - m_position.y) / m_speed.dy * m_speed.dx; + double yMinX = m_position.x + (bounds.yMin - m_position.y) / m_speed.dy * m_speed.dx; + bool xMaxOk = xMaxY <= bounds.yMax && xMaxY >= bounds.yMin; + bool xMinOk = xMinY <= bounds.yMax && xMinY >= bounds.yMin; + bool yMaxOk = yMaxX <= bounds.xMax && yMaxX >= bounds.xMin; + bool yMinOk = yMinX <= bounds.xMax && yMinX >= bounds.xMin; + if (xMaxOk && m_speed.dx >= 0) + { + return Position (bounds.xMax, xMaxY, 0.0); + } + else if (xMinOk && m_speed.dx <= 0) + { + return Position (bounds.xMin, xMinY, 0.0); + } + else if (yMaxOk && m_speed.dy >= 0) + { + return Position (yMaxX, bounds.yMax, 0.0); + } + else if (yMinOk && m_speed.dy <= 0) + { + return Position (yMinX, bounds.yMin, 0.0); + } + else + { + NS_ASSERT (false); + // quiet compiler + return Position (0.0, 0.0, 0.0); + } +} +Time +StaticSpeedHelper::GetDelayToNextPosition (const Rectangle &bounds, Time delayLeft) +{ + UpdateFull (bounds); + Position nextPosition = m_position; + nextPosition.x += m_speed.dx * delayLeft.GetSeconds (); + nextPosition.y += m_speed.dy * delayLeft.GetSeconds (); + if (nextPosition.IsInside (bounds)) + { + return delayLeft; + } + nextPosition = IntersectCurrentDirection (bounds); + Time delay = Seconds ((nextPosition.x - m_position.x) / m_speed.dx); + return delay; +} +void +StaticSpeedHelper::Rebound (const Rectangle &bounds) +{ + UpdateFull (bounds); + double xMinDist = m_position.x - bounds.xMin; + double xMaxDist = bounds.xMax - m_position.x; + double yMinDist = m_position.y - bounds.yMin; + double yMaxDist = bounds.yMax - m_position.y; + double minX = std::min (xMinDist, xMaxDist); + double minY = std::min (yMinDist, yMaxDist); + if (minY < minX) + { + m_speed.dy = - m_speed.dy; + } + else + { + m_speed.dx = - m_speed.dx; + } +} + +void +StaticSpeedHelper::UpdateFull (const Rectangle &bounds) const +{ + Update (); + m_position.x = std::min (bounds.xMax, m_position.x); + m_position.x = std::max (bounds.xMin, m_position.x); + m_position.y = std::min (bounds.yMax, m_position.y); + m_position.y = std::max (bounds.yMin, m_position.y); +} + +Position +StaticSpeedHelper::GetCurrentPosition (const Rectangle &bounds) const +{ + UpdateFull (bounds); + return m_position; +} + + } // namespace ns3 diff --git a/src/node/static-speed-helper.h b/src/node/static-speed-helper.h index cd651c951..aae5abbc8 100644 --- a/src/node/static-speed-helper.h +++ b/src/node/static-speed-helper.h @@ -7,6 +7,8 @@ namespace ns3 { +class Rectangle; + class StaticSpeedHelper { public: @@ -15,11 +17,18 @@ class StaticSpeedHelper void Reset (const Speed &speed, const Time &pauseDelay); + void Reset (const Speed &speed); + Time GetDelayToNextPosition (const Rectangle &bounds, Time delayLeft); + void Rebound (const Rectangle &bounds); + Position GetCurrentPosition (const Rectangle &bounds) const; + Position GetCurrentPosition (void) const; Speed GetCurrentSpeed (void) const; private: void Update (void) const; + void UpdateFull (const Rectangle &rectangle) const; + Position IntersectCurrentDirection (const Rectangle &bounds); mutable Time m_lastUpdate; mutable Position m_position; Speed m_speed;