Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(488)

Unified Diff: src/mobility/steady-state-random-waypoint-mobility-model.cc

Issue 193105: Steady State Random Waypoint Mobility Model
Patch Set: Test for steady-state RWP mobility model Created 14 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mobility/steady-state-random-waypoint-mobility-model.h ('k') | src/mobility/wscript » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mobility/steady-state-random-waypoint-mobility-model.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/mobility/steady-state-random-waypoint-mobility-model.cc
@@ -0,0 +1,371 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Denis Fakhriev <fakhriev@iitp.ru>
+ */
+#include <cmath>
+#include "ns3/simulator.h"
+#include "ns3/double.h"
+#include "steady-state-random-waypoint-mobility-model.h"
+#include "ns3/test.h"
+#include "ns3/node-container.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (SteadyStateRandomWaypointMobilityModel);
+
+TypeId
+SteadyStateRandomWaypointMobilityModel::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SteadyStateRandomWaypointMobilityModel")
+ .SetParent<MobilityModel> ()
+ .SetGroupName ("Mobility")
+ .AddConstructor<SteadyStateRandomWaypointMobilityModel> ()
+ .AddAttribute ("MinSpeed",
+ "Minimum speed value, [m/s]",
+ DoubleValue (0.3),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_minSpeed),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MaxSpeed",
+ "Maximum speed value, [m/s]",
+ DoubleValue (0.7),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_maxSpeed),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MinPause",
+ "Minimum pause value, [s]",
+ DoubleValue (0.0),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_minPause),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MaxPause",
+ "Maximum pause value, [s]",
+ DoubleValue (0.0),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_maxPause),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MinX",
+ "Minimum X value of traveling region, [m]",
+ DoubleValue (1),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_minX),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MaxX",
+ "Maximum X value of traveling region, [m]",
+ DoubleValue (1),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_maxX),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MinY",
+ "Minimum Y value of traveling region, [m]",
+ DoubleValue (1),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_minY),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("MaxY",
+ "Maximum Y value of traveling region, [m]",
+ DoubleValue (1),
+ MakeDoubleAccessor (&SteadyStateRandomWaypointMobilityModel::m_maxY),
+ MakeDoubleChecker<double> ());
+
+ return tid;
+}
+
+SteadyStateRandomWaypointMobilityModel::SteadyStateRandomWaypointMobilityModel ():
+ alreadyStarted (false)
+{
+}
+
+void
+SteadyStateRandomWaypointMobilityModel::DoStart (void)
+{
+ SteadyStateStart ();
+ MobilityModel::DoStart ();
+}
+
+void
+SteadyStateRandomWaypointMobilityModel::SteadyStateStart (void)
+{
+ alreadyStarted = true;
+ NS_ASSERT (m_minSpeed >= 1e-6);
+ NS_ASSERT (m_minSpeed <= m_maxSpeed);
+ m_speed = UniformVariable (m_minSpeed, m_maxSpeed);
+ NS_ASSERT (m_minX < m_maxX);
+ NS_ASSERT (m_minY < m_maxY);
+ m_position = CreateObject<RandomRectanglePositionAllocator> ();
+ m_position->SetX (UniformVariable (m_minX, m_maxX));
+ m_position->SetY (UniformVariable (m_minY, m_maxY));
+ NS_ASSERT (m_minPause <= m_maxPause);
+ m_pause = UniformVariable (m_minPause, m_maxPause);
+
+ m_helper.Update ();
+ m_helper.Pause ();
+
+ // calculate the steady-state probability that a node is initially paused
+ double expectedPauseTime = (m_minPause + m_maxPause)/2;
+ double a = m_maxX - m_minX;
+ double b = m_maxY - m_minY;
+ double v0 = m_minSpeed;
+ double v1 = m_maxSpeed;
+ double log1 = b*b / a*std::log (std::sqrt ((a*a)/(b*b) + 1) + a/b);
+ double log2 = a*a / b*std::log (std::sqrt ((b*b)/(a*a) + 1) + b/a);
+ double expectedTravelTime = 1.0/6.0*(log1 + log2);
+ expectedTravelTime += 1.0/15.0*((a*a*a)/(b*b) + (b*b*b)/(a*a)) -
+ 1.0/15.0*std::sqrt(a*a + b*b)*((a*a)/(b*b) + (b*b)/(a*a) - 3);
+ if (v0 == v1)
+ {
+ expectedTravelTime /= v0;
+ }
+ else
+ {
+ expectedTravelTime *= std::log(v1/v0)/(v1 - v0);
+ }
+ double probabilityPaused = expectedPauseTime/(expectedPauseTime + expectedTravelTime);
+ NS_ASSERT (probabilityPaused >= 0 && probabilityPaused <= 1);
+
+ UniformVariable u_r;
+ double u = u_r.GetValue(0, 1);
+ if (u < probabilityPaused) // node initially paused
+ {
+ m_helper.SetPosition (m_position->GetNext ());
+ u = u_r.GetValue(0, 1);
+ Time pause;
+ if (m_minPause != m_maxPause)
+ {
+ if (u < (2*m_minPause/(m_minPause + m_maxPause)))
+ {
+ pause = Seconds (u*(m_minPause + m_maxPause)/2);
+ }
+ else
+ {
+ // there is an error in equation 20 in the Tech. Report MCS-03-04
+ // this error is corrected in the TMC 2004 paper and below
+ pause = Seconds (m_maxPause - sqrt ((1 - u)*(m_maxPause*m_maxPause - m_minPause*m_minPause)));
+ }
+ }
+ else // if pause is constant
+ {
+ pause = Seconds (u*expectedPauseTime);
+ }
+ NS_ASSERT (!m_event.IsRunning());
+ m_event = Simulator::Schedule (pause, &SteadyStateRandomWaypointMobilityModel::BeginWalk, this);
+ }
+ else // node initially moving
+ {
+ UniformVariable x1_r, y1_r, x2_r, y2_r;
+ double x1, x2, y1, y2;
+ double r = 0;
+ double u1 = 1;
+ while (u1 >= r)
+ {
+ x1 = x1_r.GetValue (0, a);
+ y1 = y1_r.GetValue (0, b);
+ x2 = x2_r.GetValue (0, a);
+ y2 = y2_r.GetValue (0, b);
+ u1 = u_r.GetValue (0, 1);
+ r = std::sqrt (((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))/(a*a + b*b));
+ NS_ASSERT (r <= 1);
+ }
+ double u2 = u_r.GetValue (0, 1);
+ m_helper.SetPosition (Vector (m_minX + u2*x1 + (1 - u2)*x2, m_minY + u2*y1 + (1 - u2)*y2, 0));
+ NS_ASSERT (!m_event.IsRunning());
+ m_event = Simulator::ScheduleNow (&SteadyStateRandomWaypointMobilityModel::SteadyStateBeginWalk, this,
+ Vector (m_minX + x2, m_minY + y2, 0));
+ }
+ NotifyCourseChange ();
+}
+
+void
+SteadyStateRandomWaypointMobilityModel::SteadyStateBeginWalk (const Vector &destination)
+{
+ m_helper.Update ();
+ Vector m_current = m_helper.GetCurrentPosition ();
+ NS_ASSERT (m_minX <= m_current.x && m_current.x <= m_maxX);
+ NS_ASSERT (m_minY <= m_current.y && m_current.y <= m_maxY);
+ NS_ASSERT (m_minX <= destination.x && destination.x <= m_maxX);
+ NS_ASSERT (m_minY <= destination.y && destination.y <= m_maxY);
+ UniformVariable u_r;
+ double u = u_r.GetValue (0, 1);
+ double speed = std::pow (m_maxSpeed, u)/std::pow (m_minSpeed, u - 1);
+ double dx = (destination.x - m_current.x);
+ double dy = (destination.y - m_current.y);
+ double dz = (destination.z - m_current.z);
+ double k = speed / std::sqrt (dx*dx + dy*dy + dz*dz);
+
+ m_helper.SetVelocity (Vector (k*dx, k*dy, k*dz));
+ m_helper.Unpause ();
+ Time travelDelay = Seconds (CalculateDistance (destination, m_current) / speed);
+ m_event = Simulator::Schedule (travelDelay,
+ &SteadyStateRandomWaypointMobilityModel::Start, this);
+ NotifyCourseChange ();
+}
+
+void
+SteadyStateRandomWaypointMobilityModel::BeginWalk (void)
+{
+ m_helper.Update ();
+ Vector m_current = m_helper.GetCurrentPosition ();
+ NS_ASSERT (m_minX <= m_current.x && m_current.x <= m_maxX);
+ NS_ASSERT (m_minY <= m_current.y && m_current.y <= m_maxY);
+ Vector destination = m_position->GetNext ();
+ double speed = m_speed.GetValue ();
+ double dx = (destination.x - m_current.x);
+ double dy = (destination.y - m_current.y);
+ double dz = (destination.z - m_current.z);
+ double k = speed / std::sqrt (dx*dx + dy*dy + dz*dz);
+
+ m_helper.SetVelocity (Vector (k*dx, k*dy, k*dz));
+ m_helper.Unpause ();
+ Time travelDelay = Seconds (CalculateDistance (destination, m_current) / speed);
+ m_event = Simulator::Schedule (travelDelay,
+ &SteadyStateRandomWaypointMobilityModel::Start, this);
+ NotifyCourseChange ();
+}
+
+void
+SteadyStateRandomWaypointMobilityModel::Start (void)
+{
+ m_helper.Update ();
+ m_helper.Pause ();
+ Time pause = Seconds (m_pause.GetValue ());
+ m_event = Simulator::Schedule (pause, &SteadyStateRandomWaypointMobilityModel::BeginWalk, this);
+ NotifyCourseChange ();
+}
+
+Vector
+SteadyStateRandomWaypointMobilityModel::DoGetPosition (void) const
+{
+ m_helper.Update ();
+ return m_helper.GetCurrentPosition ();
+}
+void
+SteadyStateRandomWaypointMobilityModel::DoSetPosition (const Vector &position)
+{
+ if (alreadyStarted)
+ {
+ m_helper.SetPosition (position);
+ Simulator::Remove (m_event);
+ m_event = Simulator::ScheduleNow (&SteadyStateRandomWaypointMobilityModel::Start, this);
+ }
+}
+Vector
+SteadyStateRandomWaypointMobilityModel::DoGetVelocity (void) const
+{
+ return m_helper.GetVelocity ();
+}
+
+class SteadyStateRandomWaypointTest : public TestCase
+{
+public:
+ SteadyStateRandomWaypointTest ()
+ : TestCase ("Check steady-state rwp mobility model velocity and position distributions") {}
+ virtual ~SteadyStateRandomWaypointTest () {}
+
+private:
+ NodeContainer nodes;
+ double NodeCount;
+private:
+ virtual bool DoRun (void);
+ void DistribCompare ();
+};
+
+bool
+SteadyStateRandomWaypointTest::DoRun (void)
+{
+ SeedManager::SetSeed(123);
+
+ // Total simulation time, seconds
+ double totalTime = 1000;
+ // Create nodes
+ NodeCount = 10000;
+ nodes.Create (NodeCount);
+ // Installmobility
+ MobilityHelper mobility;
+ mobility.SetMobilityModel ("ns3::SteadyStateRandomWaypointMobilityModel",
+ "MinSpeed", DoubleValue (0.01),
+ "MaxSpeed", DoubleValue (20.0),
+ "MinPause", DoubleValue (0.0),
+ "MaxPause", DoubleValue (0.0),
+ "MinX", DoubleValue (0),
+ "MaxX", DoubleValue (1000),
+ "MinY", DoubleValue (0),
+ "MaxY", DoubleValue (600));
+ mobility.Install (nodes);
+
+ Simulator::Schedule (Seconds (0.001), & SteadyStateRandomWaypointTest::DistribCompare, this);
+ Simulator::Schedule (Seconds (totalTime), & SteadyStateRandomWaypointTest::DistribCompare, this);
+ Simulator::Stop (Seconds (totalTime));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return GetErrorStatus ();
+}
+
+void
+SteadyStateRandomWaypointTest::DistribCompare ()
+{
+ Ptr<MobilityModel> model;
+ double velocity;
+ double sum_x = 0;
+ double sum_y = 0;
+ double sum_v = 0;
+ NodeContainer::Iterator i;
+ for (i = nodes.Begin (); i != nodes.End (); ++i)
+ {
+ model = (*i)->GetObject<MobilityModel> ();
+ velocity = sqrt (pow (model->GetVelocity().x, 2) + pow (model->GetVelocity().y, 2));
+ sum_x += model->GetPosition().x;
+ sum_y += model->GetPosition().y;
+ sum_v += velocity;
+ }
+ double mean_x = sum_x / NodeCount;
+ double mean_y = sum_y / NodeCount;
+ double mean_v = sum_v / NodeCount;
+
+ NS_TEST_EXPECT_MSG_EQ_TOL (500, mean_x, 25.0, "Got unexpected x-position mean value");
+ NS_TEST_EXPECT_MSG_EQ_TOL (300, mean_y, 15.0, "Got unexpected y-position mean value");
+ NS_TEST_EXPECT_MSG_EQ_TOL (2.6, mean_v, 0.13, "Got unexpected velocity mean value");
+
+ sum_x = 0;
+ sum_y = 0;
+ sum_v = 0;
+ double tmp;
+ for (i = nodes.Begin (); i != nodes.End (); ++i)
+ {
+ model = (*i)->GetObject<MobilityModel> ();
+ velocity = sqrt (pow (model->GetVelocity().x, 2) + pow (model->GetVelocity().y, 2));
+ tmp = model->GetPosition().x - mean_x;
+ sum_x += tmp * tmp;
+ tmp = model->GetPosition().y - mean_y;
+ sum_y += tmp * tmp;
+ tmp = velocity - mean_v;
+ sum_v += tmp * tmp;
+ }
+ double dev_x = std::sqrt (sum_x / (NodeCount - 1));
+ double dev_y = std::sqrt (sum_y / (NodeCount - 1));
+ double dev_v = std::sqrt (sum_v / (NodeCount - 1));
+
+ NS_TEST_EXPECT_MSG_EQ_TOL (230, dev_x, 10.0, "Got unexpected x-position standard deviation");
+ NS_TEST_EXPECT_MSG_EQ_TOL (140, dev_y, 7.0, "Got unexpected y-position standard deviation");
+ NS_TEST_EXPECT_MSG_EQ_TOL (4.4, dev_v, 0.22, "Got unexpected velocity standard deviation");
+}
+
+struct SteadyStateRandomWaypointTestSuite : public TestSuite
+{
+ SteadyStateRandomWaypointTestSuite () : TestSuite ("steady-state-rwp-mobility-model", UNIT)
+ {
+ AddTestCase (new SteadyStateRandomWaypointTest);
+ }
+} g_steadyStateRandomWaypointTestSuite;
+
+} // namespace ns3
« no previous file with comments | « src/mobility/steady-state-random-waypoint-mobility-model.h ('k') | src/mobility/wscript » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b