This commit is contained in:
Gustavo J. A. M. Carneiro
2007-10-08 11:24:16 +01:00
31 changed files with 3737 additions and 63 deletions

View File

@@ -0,0 +1,61 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include <vector>
#include "ns3/ptr.h"
#include "ns3/mobility-model.h"
#include "ns3/mobility-model-notifier.h"
#include "ns3/random-topology.h"
#include "ns3/default-value.h"
#include "ns3/command-line.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/node.h"
#include "ns3/node-list.h"
using namespace ns3;
static void
CourseChange (ns3::TraceContext const&, Ptr<const MobilityModel> mobility)
{
Position pos = mobility->Get ();
Speed vel = mobility->GetSpeed ();
std::cout << Simulator::Now () << ", model=" << mobility << ", POS: x=" << pos.x << ", y=" << pos.y
<< ", z=" << pos.z << "; VEL:" << vel.dx << ", y=" << vel.dy
<< ", z=" << vel.dz << std::endl;
}
int main (int argc, char *argv[])
{
DefaultValue::Bind ("RandomWalk2dMode", "Time");
DefaultValue::Bind ("RandomWalk2dTime", "2s");
DefaultValue::Bind ("RandomWalk2dSpeed", "Constant:1.0");
DefaultValue::Bind ("RandomWalk2dBounds", "0:200:0:100");
DefaultValue::Bind ("RandomDiscPositionX", "100");
DefaultValue::Bind ("RandomDiscPositionY", "50");
DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
DefaultValue::Bind ("RandomTopologyPositionType", "RandomDiscPosition");
DefaultValue::Bind ("RandomTopologyMobilityType", "RandomWalk2dMobilityModel");
CommandLine::Parse (argc, argv);
RandomTopology topology;
for (uint32_t i = 0; i < 100; i++)
{
Ptr<Node> node = Create<Node> ();
node->AddInterface (Create<MobilityModelNotifier> ());
}
topology.Layout (NodeList::Begin (), NodeList::End ());
NodeList::Connect ("/nodes/*/$MobilityModelNotifier/course-change",
MakeCallback (&CourseChange));
Simulator::StopAt (Seconds (100.0));
Simulator::Run ();
return 0;
}

View File

@@ -41,3 +41,6 @@ def build(bld):
['core', 'simulator', 'mobility'])
obj.source = 'main-random-topology.cc'
obj = bld.create_ns3_program('main-random-walk',
['core', 'simulator', 'mobility'])
obj.source = 'main-random-walk.cc'

19
src/core/int-to-type.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef INT_TO_TYPE_H
#define INT_TO_TYPE_H
namespace ns3 {
/**
* This trivial template is extremely useful, as explained in
* "Modern C++ Design", p29, section 2.4,
* "Mapping Integral Constants to Types"
*/
template <int v>
struct IntToType
{
enum {value = v};
};
} // namespace ns3
#endif /* INT_TO_TYPE_H */

View File

@@ -0,0 +1,40 @@
#include "type-traits.h"
#include "test.h"
#ifdef RUN_SELF_TESTS
namespace ns3 {
class TypeTraitsTest : public Test
{
public:
TypeTraitsTest ();
virtual bool RunTests (void);
};
TypeTraitsTest::TypeTraitsTest ()
: Test ("TypeTraits")
{}
bool
TypeTraitsTest::RunTests (void)
{
bool result = true;
//TypeTraits<int &>::ReferencedType ir;
//TypeTraits<const int>::NonConstType uci;
NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (void)>::IsPointerToMember, 1);
NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (void) const>::IsPointerToMember, 1);
NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (int)>::IsPointerToMember, 1);
NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (int) const>::IsPointerToMember, 1);
NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (void) const>::PointerToMemberTraits::nArgs, 0);
NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (int) const>::PointerToMemberTraits::nArgs, 1);
return result;
}
static TypeTraitsTest g_typeTraitsTest;
} // namespace ns3
#endif /* RUN_SELF_TESTS */

View File

@@ -1,25 +1,294 @@
#ifndef TYPE_TRAITS_H
#define TYPE_TRAITS_H
template <typename T>
struct TypeTraits;
template <typename T>
struct TypeTraits
{
typedef T ReferencedType;
};
private:
struct NullType {};
template <typename U> struct UnConst
{
typedef U Result;
};
template <typename U> struct UnConst<const U>
{
typedef U Result;
};
template <typename U> struct ReferenceTraits
{
enum {IsReference = 0};
typedef U ReferencedType;
};
template <typename U> struct ReferenceTraits<U&>
{
enum {IsReference = 1};
typedef U ReferencedType;
};
template <typename U> struct PointerTraits
{
enum {IsPointer = 0};
typedef U PointeeType;
};
template <typename U> struct PointerTraits<U *>
{
enum {IsPointer = 1};
typedef U PointeeType;
};
template <typename U> struct FunctionPtrTraits
{
enum {IsFunctionPointer = 0};
};
template <typename U>
struct FunctionPtrTraits <U (*) (void)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 0};
typedef U ReturnType;
};
template <typename U, typename V1>
struct FunctionPtrTraits <U (*) (V1)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 1};
typedef U ReturnType;
typedef V1 Arg1Type;
};
template <typename U, typename V1, typename V2>
struct FunctionPtrTraits <U (*) (V1,V2)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 2};
typedef U ReturnType;
typedef V1 Arg1Type;
typedef V2 Arg2Type;
};
template <typename U, typename V1, typename V2,
typename V3>
struct FunctionPtrTraits <U (*) (V1,V2,V3)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 3};
typedef U ReturnType;
typedef V1 Arg1Type;
typedef V2 Arg2Type;
typedef V3 Arg3Type;
};
template <typename U, typename V1, typename V2,
typename V3, typename V4>
struct FunctionPtrTraits <U (*) (V1,V2,V3,V4)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 4};
typedef U ReturnType;
typedef V1 Arg1Type;
typedef V2 Arg2Type;
typedef V3 Arg3Type;
typedef V4 Arg4Type;
};
template <typename U, typename V1, typename V2,
typename V3, typename V4,
typename V5>
struct FunctionPtrTraits <U (*) (V1,V2,V3,V4,V5)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 5};
typedef U ReturnType;
typedef V1 Arg1Type;
typedef V2 Arg2Type;
typedef V3 Arg3Type;
typedef V4 Arg4Type;
typedef V5 Arg5Type;
};
template <typename U, typename V1, typename V2,
typename V3, typename V4,
typename V5, typename V6>
struct FunctionPtrTraits <U (*) (V1,V2,V3,V4,V5,V6)>
{
enum {IsFunctionPointer = 1};
enum {nArgs = 6};
typedef U ReturnType;
typedef V1 Arg1Type;
typedef V2 Arg2Type;
typedef V3 Arg3Type;
typedef V4 Arg4Type;
typedef V5 Arg5Type;
typedef V6 Arg6Type;
};
template <typename U> struct PtrToMemberTraits
{
enum {IsPointerToMember = 0};
};
template <typename U, typename V>
struct PtrToMemberTraits <U (V::*) (void)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 0};
typedef U ReturnType;
};
template <typename U, typename V>
struct PtrToMemberTraits <U (V::*) (void) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 0};
typedef U ReturnType;
};
template <typename U, typename V,typename W1>
struct PtrToMemberTraits <U (V::*) (W1)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 1};
typedef U ReturnType;
typedef W1 Arg1Type;
};
template <typename U, typename V,typename W1>
struct PtrToMemberTraits <U (V::*) (W1) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 1};
typedef U ReturnType;
typedef W1 Arg1Type;
};
template <typename U, typename V,typename W1, typename W2>
struct PtrToMemberTraits <U (V::*) (W1,W2)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 2};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
};
template <typename U, typename V,typename W1, typename W2>
struct PtrToMemberTraits <U (V::*) (W1,W2) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 2};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 3};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 3};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3, typename W4>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 4};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
typedef W4 Arg4Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3, typename W4>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 4};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
typedef W4 Arg4Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3, typename W4,
typename W5>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 5};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
typedef W4 Arg4Type;
typedef W5 Arg5Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3, typename W4,
typename W5>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 5};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
typedef W4 Arg4Type;
typedef W5 Arg5Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3, typename W4,
typename W5, typename W6>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5,W6)>
{
enum {IsPointerToMember = 1};
enum {nArgs = 6};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
typedef W4 Arg4Type;
typedef W5 Arg5Type;
typedef W6 Arg6Type;
};
template <typename U, typename V,
typename W1, typename W2,
typename W3, typename W4,
typename W5, typename W6>
struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5,W6) const>
{
enum {IsPointerToMember = 1};
enum {nArgs = 6};
typedef U ReturnType;
typedef W1 Arg1Type;
typedef W2 Arg2Type;
typedef W3 Arg3Type;
typedef W4 Arg4Type;
typedef W5 Arg5Type;
typedef W6 Arg6Type;
};
template <typename T>
struct TypeTraits<const T &>
{
typedef T ReferencedType;
};
template <typename T>
struct TypeTraits<T &>
{
typedef T ReferencedType;
public:
typedef typename UnConst<T>::Result NonConstType;
typedef typename ReferenceTraits<T>::ReferencedType ReferencedType;
typedef typename PointerTraits<T>::PointeeType PointeeType;
enum {IsPointerToMember = PtrToMemberTraits<T>::IsPointerToMember};
enum {IsPointer = PointerTraits<T>::IsPointer};
enum {IsReference = ReferenceTraits<T>::IsReference};
enum {IsFunctionPointer = FunctionPtrTraits<T>::IsFunctionPointer};
typedef PtrToMemberTraits<T> PointerToMemberTraits;
typedef FunctionPtrTraits<T> FunctionPointerTraits;
};

View File

@@ -51,6 +51,7 @@ def build(bld):
'composite-trace-resolver.cc',
'trace-doc.cc',
'trace-source.cc',
'type-traits-test.cc',
]
if sys.platform == 'win32':
@@ -94,5 +95,6 @@ def build(bld):
'composite-trace-resolver.h',
'array-trace-resolver.h',
'trace-doc.h',
'int-to-type.h',
]

View File

@@ -0,0 +1,145 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 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 <mathieu.lacage@sophia.inria.fr>
*/
#include <fstream>
#include <sstream>
#include "ns3/debug.h"
#include "ns3/simulator.h"
#include "ns3/node-list.h"
#include "ns3/node.h"
#include "ns2-mobility-file-topology.h"
#include "static-speed-mobility-model.h"
NS_DEBUG_COMPONENT_DEFINE ("Ns2MobilityFileTopology");
namespace ns3 {
Ns2MobilityFileTopology::Ns2MobilityFileTopology (std::string filename)
: m_filename (filename)
{}
Ptr<StaticSpeedMobilityModel>
Ns2MobilityFileTopology::GetMobilityModel (std::string idString, const ObjectStore &store) const
{
std::istringstream iss;
iss.str (idString);
uint32_t id;
iss >> id;
Ptr<Object> object = store.Get (id);
if (object == 0)
{
return 0;
}
Ptr<StaticSpeedMobilityModel> model =
object->QueryInterface<StaticSpeedMobilityModel> (StaticSpeedMobilityModel::iid);
if (model == 0)
{
model = Create<StaticSpeedMobilityModel> ();
object->AddInterface (model);
}
return model;
}
double
Ns2MobilityFileTopology::ReadDouble (std::string valueString) const
{
std::istringstream iss;
iss.str (valueString);
double value;
iss >> value;
return value;
}
void
Ns2MobilityFileTopology::LayoutObjectStore (const ObjectStore &store) const
{
std::ifstream file (m_filename.c_str (), std::ios::in);
if (file.is_open())
{
while (!file.eof() )
{
std::string line;
getline (file, line);
std::string::size_type startNodeId = line.find_first_of ("(");
std::string::size_type endNodeId = line.find_first_of (")");
if (startNodeId == std::string::npos ||
endNodeId == std::string::npos)
{
continue;
}
Ptr<StaticSpeedMobilityModel> model = GetMobilityModel (line.substr (startNodeId + 1,
endNodeId - startNodeId),
store);
if (model == 0)
{
continue;
}
if (startNodeId == 6)
{
double value = ReadDouble (line.substr (endNodeId + 9, std::string::npos));
std::string coordinate = line.substr (endNodeId + 6, 1);
Position position = model->Get ();
if (coordinate == "X")
{
position.x = value;
NS_DEBUG ("X=" << value);
}
else if (coordinate == "Y")
{
position.y = value;
NS_DEBUG ("Y=" << value);
}
else if (coordinate == "Z")
{
position.z = value;
NS_DEBUG ("Z=" << value);
}
else
{
continue;
}
model->Set (position);
}
else
{
double at = ReadDouble (line.substr (8, startNodeId - 17));
std::string::size_type xSpeedEnd = line.find_first_of (" ", endNodeId + 10);
std::string::size_type ySpeedEnd = line.find_first_of (" ", xSpeedEnd + 1);
double xSpeed = ReadDouble (line.substr (endNodeId + 10, xSpeedEnd - endNodeId - 10));
double ySpeed = ReadDouble (line.substr (xSpeedEnd + 1, ySpeedEnd - xSpeedEnd - 1));
double zSpeed = ReadDouble (line.substr (ySpeedEnd + 1, std::string::npos));
NS_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
Simulator::Schedule (Seconds (at), &StaticSpeedMobilityModel::SetSpeed, model,
Speed (xSpeed, ySpeed, zSpeed));
}
}
file.close();
}
}
void
Ns2MobilityFileTopology::Layout (void) const
{
Layout (NodeList::Begin (), NodeList::End ());
}
} // namespace ns3

View File

@@ -0,0 +1,113 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 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 <mathieu.lacage@sophia.inria.fr>
*/
#ifndef NS2_MOBILITY_FILE_TOPOLOGY_H
#define NS2_MOBILITY_FILE_TOPOLOGY_H
#include <string>
#include <stdint.h>
#include "ns3/ptr.h"
#include "ns3/object.h"
#include "static-speed-mobility-model.h"
namespace ns3 {
/**
* \brief a topology object which can read ns2's movement files
* generated by the CMU setdest tool.
*/
class Ns2MobilityFileTopology
{
public:
/**
* \param filename filename of file which contains the
* ns2 movement trace.
*/
Ns2MobilityFileTopology (std::string filename);
/**
* Read the ns2 trace file and configure the movement
* patterns of all nodes contained in the global ns3::NodeList
* whose nodeId is matches the nodeId of the nodes in the trace
* file.
*/
void Layout (void) const;
/**
* \param begin an iterator which points to the start of the input
* object array.
* \param end an iterator which points to the end of the input
* object array.
*
* Read the ns2 trace file and configure the movement
* patterns of all input objects. Each input object
* is identified by a unique node id which reflects
* the index of the object in the input array.
*/
template <typename T>
void Layout (T begin, T end) const;
private:
class ObjectStore
{
public:
virtual ~ObjectStore () {}
virtual Ptr<Object> Get (uint32_t i) const = 0;
};
void LayoutObjectStore (const ObjectStore &store) const;
Ptr<StaticSpeedMobilityModel> GetMobilityModel (std::string idString, const ObjectStore &store) const;
double ReadDouble (std::string valueString) const;
std::string m_filename;
};
} // namespace ns3
namespace ns3 {
template <typename T>
void
Ns2MobilityFileTopology::Layout (T begin, T end) const
{
class MyObjectStore : public ObjectStore
{
public:
MyObjectStore (T begin, T end)
: m_begin (begin),
m_end (end)
{}
virtual Ptr<Object> Get (uint32_t i) const {
T iterator = m_begin;
iterator += i;
if (iterator >= m_end)
{
return 0;
}
return *iterator;
}
private:
T m_begin;
T m_end;
};
LayoutObjectStore (MyObjectStore (begin, end));
}
} // namespace ns3
#endif /* NS2_MOBILITY_FILE_TOPOLOGY_H */

View File

@@ -0,0 +1,210 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 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 <mathieu.lacage@sophia.inria.fr>
*/
#include "ns3/random-variable-default-value.h"
#include "ns3/rectangle-default-value.h"
#include "ns3/simulator.h"
#include <algorithm>
#include <cmath>
#include "random-direction-2d-mobility-model.h"
#include "ns3/log.h"
NS_LOG_COMPONENT_DEFINE ("RandomDirection2dMobilityModel");
namespace ns3 {
const double RandomDirection2dMobilityModel::PI = 3.14159265358979323846;
const ClassId RandomDirection2dMobilityModel::cid =
MakeClassId<RandomDirection2dMobilityModel> ("RandomDirection2dMobilityModel",
MobilityModel::iid);
static RandomVariableDefaultValue
g_speedVariable ("RandomDirection2dSpeed",
"A random variable to control the speed of a RandomDirection2d mobility model.",
"Uniform:1:2");
static RandomVariableDefaultValue
g_pauseVariable ("RandomDirection2dPause",
"A random variable to control the duration "
"of the pause of a RandomDiretion mobility model.",
"Constant:2");
static RectangleDefaultValue
g_bounds ("RandomDirection2dArea",
"The bounding area for the RandomDirection2d model.",
-100, 100, -100, 100);
RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters ()
: m_bounds (g_bounds.GetValue ()),
m_speedVariable (g_speedVariable.GetCopy ()),
m_pauseVariable (g_pauseVariable.GetCopy ())
{}
RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters
(const Rectangle &bounds,
const RandomVariable &speedVariable,
const RandomVariable &pauseVariable)
: m_bounds (bounds),
m_speedVariable (speedVariable.Copy ()),
m_pauseVariable (pauseVariable.Copy ())
{}
RandomDirection2dMobilityModelParameters::~RandomDirection2dMobilityModelParameters ()
{
delete m_speedVariable;
delete m_pauseVariable;
m_speedVariable = 0;
m_pauseVariable = 0;
}
void
RandomDirection2dMobilityModelParameters::SetSpeed (const RandomVariable &speedVariable)
{
delete m_speedVariable;
m_speedVariable = speedVariable.Copy ();
}
void
RandomDirection2dMobilityModelParameters::SetPause (const RandomVariable &pauseVariable)
{
delete m_pauseVariable;
m_pauseVariable = pauseVariable.Copy ();
}
void
RandomDirection2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
{
m_bounds = bounds;
}
Ptr<RandomDirection2dMobilityModelParameters>
RandomDirection2dMobilityModelParameters::GetCurrent (void)
{
static Ptr<RandomDirection2dMobilityModelParameters> parameters = 0;
if (parameters == 0 ||
g_bounds.IsDirty () ||
g_speedVariable.IsDirty () ||
g_pauseVariable.IsDirty ())
{
parameters = Create<RandomDirection2dMobilityModelParameters> ();
g_bounds.ClearDirtyFlag ();
g_speedVariable.ClearDirtyFlag ();
g_pauseVariable.ClearDirtyFlag ();
}
return parameters;
}
RandomDirection2dMobilityModel::RandomDirection2dMobilityModel ()
: m_parameters (RandomDirection2dMobilityModelParameters::GetCurrent ())
{
SetInterfaceId (RandomDirection2dMobilityModel::iid);
m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
}
RandomDirection2dMobilityModel::RandomDirection2dMobilityModel
(Ptr<RandomDirection2dMobilityModelParameters> parameters)
: m_parameters (parameters)
{
SetInterfaceId (RandomDirection2dMobilityModel::iid);
m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
}
void
RandomDirection2dMobilityModel::DoDispose (void)
{
m_parameters = 0;
// chain up.
MobilityModel::DoDispose ();
}
void
RandomDirection2dMobilityModel::Start (void)
{
double direction = UniformVariable::GetSingleValue (0, 2 * PI);
SetDirectionAndSpeed (direction);
}
void
RandomDirection2dMobilityModel::BeginPause (void)
{
Time pause = Seconds (m_parameters->m_pauseVariable->GetValue ());
m_helper.Pause ();
m_event = Simulator::Schedule (pause, &RandomDirection2dMobilityModel::ResetDirectionAndSpeed, this);
NotifyCourseChange ();
}
void
RandomDirection2dMobilityModel::SetDirectionAndSpeed (double direction)
{
NS_LOG_FUNCTION;
double speed = m_parameters->m_speedVariable->GetValue ();
const Speed vector (std::cos (direction) * speed,
std::sin (direction) * speed,
0.0);
Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
m_helper.Reset (vector);
Position next = m_parameters->m_bounds.CalculateIntersection (position, vector);
Time delay = Seconds (CalculateDistance (position, next) / speed);
m_event = Simulator::Schedule (delay,
&RandomDirection2dMobilityModel::BeginPause, this);
NotifyCourseChange ();
}
void
RandomDirection2dMobilityModel::ResetDirectionAndSpeed (void)
{
double direction = UniformVariable::GetSingleValue (0, PI);
Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
switch (m_parameters->m_bounds.GetClosestSide (position))
{
case Rectangle::RIGHT:
direction += PI / 2;
break;
case Rectangle::LEFT:
direction += - PI / 2;
break;
case Rectangle::TOP:
direction += PI;
break;
case Rectangle::BOTTOM:
direction += 0.0;
break;
}
SetDirectionAndSpeed (direction);
}
Position
RandomDirection2dMobilityModel::DoGet (void) const
{
return m_helper.GetCurrentPosition (m_parameters->m_bounds);
}
void
RandomDirection2dMobilityModel::DoSet (const Position &position)
{
m_helper.InitializePosition (position);
Simulator::Remove (m_event);
m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
}
Speed
RandomDirection2dMobilityModel::DoGetSpeed (void) const
{
return m_helper.GetSpeed ();
}
} // namespace ns3

View File

@@ -0,0 +1,121 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 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 <mathieu.lacage@sophia.inria.fr>
*/
#ifndef RANDOM_DIRECTION_MOBILITY_MODEL_H
#define RANDOM_DIRECTION_MOBILITY_MODEL_H
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "ns3/nstime.h"
#include "ns3/event-id.h"
#include "ns3/component-manager.h"
#include "ns3/rectangle.h"
#include "mobility-model.h"
#include "static-speed-helper.h"
namespace ns3 {
class RandomVariable;
/**
* \brief the parameters to control a RandomDirection mobility model.
*/
class RandomDirection2dMobilityModelParameters : public Object
{
public:
/**
* Create a default parameter object from Bind default values.
*/
RandomDirection2dMobilityModelParameters ();
/**
* \param bounds the 2d bounds of the mobility model
* \param speedVariable the random variable used to pick a random speed
* \param pauseVariable the random variable used to pick a random pause delay
*/
RandomDirection2dMobilityModelParameters (const Rectangle &bounds,
const RandomVariable &speedVariable,
const RandomVariable &pauseVariable);
virtual ~RandomDirection2dMobilityModelParameters ();
/**
* \param speedVariable the random variable used to pick a random speed.
*/
void SetSpeed (const RandomVariable &speedVariable);
/**
* \param pauseVariable the random variable used to pick a random pause delay.
*/
void SetPause (const RandomVariable &pauseVariable);
/**
* \param bounds the 2d bounds of the mobility model.
*/
void SetBounds (const Rectangle &bounds);
private:
friend class RandomDirection2dMobilityModel;
static Ptr<RandomDirection2dMobilityModelParameters> GetCurrent (void);
Rectangle m_bounds;
RandomVariable *m_speedVariable;
RandomVariable *m_pauseVariable;
};
/**
* \brief a RandomDirection mobility model
*
* The movement of objects is based on random directions: each object
* pauses for a specific delay, chooses a random direction and speed and
* then travels in the specific direction until it reaches one of
* the boundaries of the model. When it reaches the boundary, it pauses,
* selects a new direction and speed, aso.
*/
class RandomDirection2dMobilityModel : public MobilityModel
{
public:
static const ClassId cid;
/**
* Create a RandomDirection model from the default Bind values.
*/
RandomDirection2dMobilityModel ();
/**
* \param parameters the parameters which control the behavior of the model.
* Create a RandomDirection model using the parameters specified.
*/
RandomDirection2dMobilityModel (Ptr<RandomDirection2dMobilityModelParameters> parameters);
private:
void Start (void);
void ResetDirectionAndSpeed (void);
void BeginPause (void);
void SetDirectionAndSpeed (double direction);
void InitializeDirectionAndSpeed (void);
virtual void DoDispose (void);
virtual Position DoGet (void) const;
virtual void DoSet (const Position &position);
virtual Speed DoGetSpeed (void) const;
static const double PI;
Ptr<RandomDirection2dMobilityModelParameters> m_parameters;
EventId m_event;
StaticSpeedHelper m_helper;
};
} // namespace ns3
#endif /* RANDOM_DIRECTION_MOBILITY_MODEL_H */

View File

@@ -0,0 +1,233 @@
/* -*- 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 <mathieu.lacage@sophia.inria.fr>
*/
#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 <cmath>
NS_DEBUG_COMPONENT_DEFINE ("RandomWalk2d");
namespace ns3 {
const ClassId RandomWalk2dMobilityModel::cid =
MakeClassId<RandomWalk2dMobilityModel> ("RandomWalk2dMobilityModel", RandomWalk2dMobilityModel::iid);
static EnumDefaultValue<RandomWalk2dMobilityModelParameters::Mode>
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, (void*)0);
static NumericDefaultValue<double>
g_modeDistance ("RandomWalk2dDistance",
"Change current direction and speed after moving this distance.",
2.0);
static TimeDefaultValue
g_modeTime ("RandomWalk2dTime",
"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;
}
void
RandomWalk2dMobilityModelParameters::SetSpeed (const RandomVariable &speed)
{
delete m_speed;
m_speed = speed.Copy ();
}
void
RandomWalk2dMobilityModelParameters::SetDirection (const RandomVariable &direction)
{
delete m_direction;
m_direction = direction.Copy ();
}
void
RandomWalk2dMobilityModelParameters::SetModeDistance (double distance)
{
m_mode = RandomWalk2dMobilityModelParameters::MODE_DISTANCE;
m_modeDistance = distance;
}
void
RandomWalk2dMobilityModelParameters::SetModeTime (Time time)
{
m_mode = RandomWalk2dMobilityModelParameters::MODE_TIME;
m_modeTime = time;
}
void
RandomWalk2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
{
m_bounds = bounds;
}
Ptr<RandomWalk2dMobilityModelParameters>
RandomWalk2dMobilityModelParameters::GetCurrent (void)
{
static Ptr<RandomWalk2dMobilityModelParameters> 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<RandomWalk2dMobilityModelParameters> ();
}
return parameters;
}
RandomWalk2dMobilityModel::RandomWalk2dMobilityModel ()
: m_parameters (RandomWalk2dMobilityModelParameters::GetCurrent ())
{
SetInterfaceId (RandomWalk2dMobilityModel::iid);
m_event = 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)
{
Position position = m_helper.GetCurrentPosition ();
Speed speed = m_helper.GetSpeed ();
Position nextPosition = position;
nextPosition.x += speed.dx * delayLeft.GetSeconds ();
nextPosition.y += speed.dy * delayLeft.GetSeconds ();
if (m_parameters->m_bounds.IsInside (nextPosition))
{
m_event = Simulator::Schedule (delayLeft, &RandomWalk2dMobilityModel::Start, this);
}
else
{
nextPosition = m_parameters->m_bounds.CalculateIntersection (position, speed);
Time delay = Seconds ((nextPosition.x - position.x) / speed.dx);
m_event = Simulator::Schedule (delay, &RandomWalk2dMobilityModel::Rebound, this,
delayLeft - delay);
}
NotifyCourseChange ();
}
void
RandomWalk2dMobilityModel::Rebound (Time delayLeft)
{
Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
Speed speed = m_helper.GetSpeed ();
switch (m_parameters->m_bounds.GetClosestSide (position))
{
case Rectangle::RIGHT:
case Rectangle::LEFT:
speed.dx = - speed.dx;
break;
case Rectangle::TOP:
case Rectangle::BOTTOM:
speed.dy = - speed.dy;
break;
}
m_helper.Reset (speed);
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 (m_parameters->m_bounds.IsInside (position));
m_helper.InitializePosition (position);
Simulator::Remove (m_event);
m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
}
Speed
RandomWalk2dMobilityModel::DoGetSpeed (void) const
{
return m_helper.GetSpeed ();
}
} // namespace ns3

View File

@@ -0,0 +1,147 @@
/* -*- 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 <mathieu.lacage@sophia.inria.fr>
*/
#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 2d model
*
* A single parameter object can be shared by multiple random
* walk models.
*/
class RandomWalk2dMobilityModelParameters : public Object
{
public:
/**
* Instantiate a set of RandomWalk parameters initialized
* with the Bind default values.
*/
RandomWalk2dMobilityModelParameters ();
virtual ~RandomWalk2dMobilityModelParameters ();
/**
* \param speed the random variable used to pick a new
* speed when the direction is changed.
*
*/
void SetSpeed (const RandomVariable &speed);
/**
* \param direction the random variable used to pick a new
* direction.
*/
void SetDirection (const RandomVariable &direction);
/**
* \param distance the distance before a direction change
*
* Unit is meters.
* "time" mode is incompatible with "distance" mode.
*/
void SetModeDistance (double distance);
/**
* \param time the delay before a direction change.
*
* "time" mode is incompatible with "distance" mode.
*/
void SetModeTime (Time time);
/**
* \param bounds the bounds of the random walk
*/
void SetBounds (const Rectangle &bounds);
// needed public for internal default value code.
enum Mode {
MODE_DISTANCE,
MODE_TIME
};
private:
friend class RandomWalk2dMobilityModel;
static Ptr<RandomWalk2dMobilityModelParameters> 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
* with the user-provided random variables 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 "RandomWalk2dSpeed", "RandomWalk2dMode",
* "RandomWalk2dDistance", "RandomWalk2dTime", and, "RandomWalk2dBounds" 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 ();
/**
* \param parameters the parameters to use to control
* the movement of this mobile object.
*
* Create a new position object located at position (0,0,0) with
* the specified parameters.
*/
RandomWalk2dMobilityModel (Ptr<RandomWalk2dMobilityModelParameters> 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);
virtual Speed DoGetSpeed (void) const;
StaticSpeedHelper m_helper;
EventId m_event;
Ptr<RandomWalk2dMobilityModelParameters> m_parameters;
};
} // namespace ns3
#endif /* RANDOM_WALK_2D_MOBILITY_MODEL_H */

View File

@@ -0,0 +1,163 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INRIA
*
* 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 <mathieu.lacage@sophia.inria.fr>
*/
#include <cmath>
#include "ns3/simulator.h"
#include "ns3/random-variable.h"
#include "ns3/random-variable-default-value.h"
#include "ns3/component-manager.h"
#include "random-waypoint-mobility-model.h"
#include "random-position.h"
namespace ns3 {
static RandomVariableDefaultValue
g_speed ("RandomWaypointSpeed",
"A random variable used to pick the speed of a random waypoint model.",
"Uniform:0.3:0.7");
static RandomVariableDefaultValue
g_pause ("RandomWaypointPause",
"A random variable used to pick the pause of a random waypoint model.",
"Constant:2");
static ClassIdDefaultValue
g_position ("RandomWaypointPosition",
"A random position model used to pick the next waypoint position.",
RandomPosition::iid,
"RandomRectanglePosition");
const ClassId RandomWaypointMobilityModel::cid =
MakeClassId<RandomWaypointMobilityModel> ("RandomWaypointMobilityModel", MobilityModel::iid);
RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters ()
: m_speed (g_speed.GetCopy ()),
m_pause (g_pause.GetCopy ())
{
m_position = ComponentManager::Create<RandomPosition> (g_position.GetValue (),
RandomPosition::iid);
}
RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
const RandomVariable &speed,
const RandomVariable &pause)
: m_speed (speed.Copy ()),
m_pause (pause.Copy ()),
m_position (randomPosition)
{}
void
RandomWaypointMobilityModelParameters::SetWaypointPositionModel (Ptr<RandomPosition> randomPosition)
{
m_position = randomPosition;
}
void
RandomWaypointMobilityModelParameters::SetSpeed (const RandomVariable &speed)
{
delete m_speed;
m_speed = speed.Copy ();
}
void
RandomWaypointMobilityModelParameters::SetPause (const RandomVariable &pause)
{
delete m_pause;
m_pause = pause.Copy ();
}
void
RandomWaypointMobilityModelParameters::DoDispose (void)
{
m_position = 0;
delete m_pause;
delete m_speed;
m_pause = 0;
m_speed = 0;
}
Ptr<RandomWaypointMobilityModelParameters>
RandomWaypointMobilityModelParameters::GetCurrent (void)
{
static Ptr<RandomWaypointMobilityModelParameters> parameters = 0;
if (parameters == 0 ||
g_position.IsDirty () ||
g_pause.IsDirty () ||
g_speed.IsDirty ())
{
parameters = Create<RandomWaypointMobilityModelParameters> ();
}
return parameters;
}
RandomWaypointMobilityModel::RandomWaypointMobilityModel ()
: m_parameters (RandomWaypointMobilityModelParameters::GetCurrent ())
{
Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
}
RandomWaypointMobilityModel::RandomWaypointMobilityModel (Ptr<RandomWaypointMobilityModelParameters> parameters)
: m_parameters (parameters)
{
Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
NotifyCourseChange ();
}
void
RandomWaypointMobilityModel::BeginWalk (void)
{
Position m_current = m_helper.GetCurrentPosition ();
Position destination = m_parameters->m_position->Get ();
double speed = m_parameters->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.Reset (Speed (k*dx, k*dy, k*dz));
Time travelDelay = Seconds (CalculateDistance (destination, m_current) / speed);
m_event = Simulator::Schedule (travelDelay,
&RandomWaypointMobilityModel::Start, this);
NotifyCourseChange ();
}
void
RandomWaypointMobilityModel::Start (void)
{
Time pause = Seconds (m_parameters->m_pause->GetValue ());
m_helper.Pause ();
NotifyCourseChange ();
m_event = Simulator::Schedule (pause, &RandomWaypointMobilityModel::BeginWalk, this);
}
Position
RandomWaypointMobilityModel::DoGet (void) const
{
return m_helper.GetCurrentPosition ();
}
void
RandomWaypointMobilityModel::DoSet (const Position &position)
{
m_helper.InitializePosition (position);
Simulator::Remove (m_event);
Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
}
Speed
RandomWaypointMobilityModel::DoGetSpeed (void) const
{
return m_helper.GetSpeed ();
}
} // namespace ns3

View File

@@ -0,0 +1,112 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 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 <mathieu.lacage@sophia.inria.fr>
*/
#ifndef RANDOM_WAYPOINT_MOBILITY_MODEL_H
#define RANDOM_WAYPOINT_MOBILITY_MODEL_H
#include "static-speed-helper.h"
#include "mobility-model.h"
#include "random-position.h"
#include "ns3/ptr.h"
namespace ns3 {
class RandomVariable;
/**
* \brief the parameters which control the behavior of a random waypoint
* mobility model.
*/
class RandomWaypointMobilityModelParameters : public Object
{
public:
/**
* Defaults parameters based on the Bind values.
*/
RandomWaypointMobilityModelParameters ();
/**
* \param randomPosition a random position model to choose the position of waypoints.
* \param speed a random variable to choose the speed
* \param pause a random variable to choose the pause delay
*/
RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
const RandomVariable &speed,
const RandomVariable &pause);
/**
* \param randomPosition a random position model to choose the position of waypoints.
*/
void SetWaypointPositionModel (Ptr<RandomPosition> randomPosition);
/**
* \param speed a random variable to choose the speed
*/
void SetSpeed (const RandomVariable &speed);
/**
* \param pause a random variable to choose the pause delay
*/
void SetPause (const RandomVariable &pause);
private:
friend class RandomWaypointMobilityModel;
static Ptr<RandomWaypointMobilityModelParameters> GetCurrent (void);
virtual void DoDispose (void);
RandomVariable *m_speed;
RandomVariable *m_pause;
Ptr<RandomPosition> m_position;
};
/**
* \brief a random waypoint mobility model
*
* Each object chooses a random destination "waypoint", a random speed,
* and a random pause time: it then pauses for the specified pause time,
* and starts moving towards the specified destination with the specified
* speed. Once the destination is reached the process starts again.
*
* The implementation of this model is not 2d-specific. i.e. if you provide
* a 3d random waypoint position model to this mobility model, the model
* will still work.
*/
class RandomWaypointMobilityModel : public MobilityModel
{
public:
static const ClassId cid;
/**
* Create a waypoint mobility model from the Bind default values.
*/
RandomWaypointMobilityModel ();
/**
* \param parameters the parameters which control the behavior of this model.
*/
RandomWaypointMobilityModel (Ptr<RandomWaypointMobilityModelParameters> parameters);
private:
void Start (void);
void BeginWalk (void);
virtual Position DoGet (void) const;
virtual void DoSet (const Position &position);
virtual Speed DoGetSpeed (void) const;
StaticSpeedHelper m_helper;
Ptr<RandomWaypointMobilityModelParameters> m_parameters;
EventId m_event;
};
} // namespace ns3
#endif /* RANDOM_WAYPOINT_MOBILITY_MODEL_H */

View File

@@ -45,17 +45,17 @@ bool
Rectangle::IsInside (const Position &position) const
{
return
position.x <= xMax && position.x >= xMin &&
position.y <= yMax && position.y >= yMin;
position.x <= this->xMax && position.x >= this->xMin &&
position.y <= this->yMax && position.y >= this->yMin;
}
Rectangle::Side
Rectangle::GetClosestSide (const Position &position) const
{
double xMinDist = std::abs (position.x - xMin);
double xMaxDist = std::abs (xMax - position.x);
double yMinDist = std::abs (position.y - yMin);
double yMaxDist = std::abs (yMax - position.y);
double xMinDist = std::abs (position.x - this->xMin);
double xMaxDist = std::abs (this->xMax - position.x);
double yMinDist = std::abs (position.y - this->yMin);
double yMaxDist = std::abs (this->yMax - position.y);
double minX = std::min (xMinDist, xMaxDist);
double minY = std::min (yMinDist, yMaxDist);
if (minX < minY)
@@ -85,29 +85,29 @@ Rectangle::GetClosestSide (const Position &position) const
Position
Rectangle::CalculateIntersection (const Position &current, const Speed &speed) const
{
double xMaxY = current.y + (xMax - current.x) / speed.dx * speed.dy;
double xMinY = current.y + (xMin - current.x) / speed.dx * speed.dy;
double yMaxX = current.x + (yMax - current.y) / speed.dy * speed.dx;
double yMinX = current.x + (yMin - current.y) / speed.dy * speed.dx;
bool xMaxOk = xMaxY <= yMax && xMaxY >= yMin;
bool xMinOk = xMinY <= yMax && xMinY >= yMin;
bool yMaxOk = yMaxX <= xMax && yMaxX >= xMin;
bool yMinOk = yMinX <= xMax && yMinX >= xMin;
if (xMaxOk && speed.dx >= 0)
double xMaxY = current.y + (this->xMax - current.x) / speed.dx * speed.dy;
double xMinY = current.y + (this->xMin - current.x) / speed.dx * speed.dy;
double yMaxX = current.x + (this->yMax - current.y) / speed.dy * speed.dx;
double yMinX = current.x + (this->yMin - current.y) / speed.dy * speed.dx;
bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
if (xMaxYOk && speed.dx >= 0)
{
return Position (xMax, xMaxY, 0.0);
return Position (this->xMax, xMaxY, 0.0);
}
else if (xMinOk && speed.dx <= 0)
else if (xMinYOk && speed.dx <= 0)
{
return Position (xMin, xMinY, 0.0);
return Position (this->xMin, xMinY, 0.0);
}
else if (yMaxOk && speed.dy >= 0)
else if (yMaxXOk && speed.dy >= 0)
{
return Position (yMaxX, yMax, 0.0);
return Position (yMaxX, this->yMax, 0.0);
}
else if (yMinOk && speed.dy <= 0)
else if (yMinXOk && speed.dy <= 0)
{
return Position (yMinX, yMin, 0.0);
return Position (yMinX, this->yMin, 0.0);
}
else
{

View File

@@ -31,7 +31,8 @@ StaticSpeedHelper::StaticSpeedHelper (const Position &position)
StaticSpeedHelper::StaticSpeedHelper (const Position &position,
const Speed &speed)
: m_position (position),
m_speed (speed)
m_speed (speed),
m_paused (true)
{}
void
StaticSpeedHelper::InitializePosition (const Position &position)
@@ -41,14 +42,7 @@ StaticSpeedHelper::InitializePosition (const Position &position)
m_speed.dy = 0.0;
m_speed.dz = 0.0;
m_lastUpdate = Simulator::Now ();
m_pauseEnd = Simulator::Now ();
}
void
StaticSpeedHelper::Reset (const Speed &speed, const Time &pauseDelay)
{
Reset (speed);
m_pauseEnd = Simulator::Now () + pauseDelay;
m_paused = true;
}
Position
@@ -61,7 +55,7 @@ StaticSpeedHelper::GetCurrentPosition (void) const
Speed
StaticSpeedHelper::GetSpeed (void) const
{
return m_speed;
return m_paused? Speed (0, 0, 0) : m_speed;
}
void
StaticSpeedHelper::SetSpeed (const Speed &speed)
@@ -73,17 +67,13 @@ StaticSpeedHelper::SetSpeed (const Speed &speed)
void
StaticSpeedHelper::Update (void) const
{
if (m_paused)
{
return;
}
Time now = Simulator::Now ();
if (m_pauseEnd > now)
{
return;
}
Time last = std::max (now, m_pauseEnd);
if (m_lastUpdate >= last)
{
return;
}
Time deltaTime = now - last;
NS_ASSERT (m_lastUpdate <= now);
Time deltaTime = now - m_lastUpdate;
m_lastUpdate = now;
double deltaS = deltaTime.GetSeconds ();
m_position.x += m_speed.dx * deltaS;
@@ -96,7 +86,7 @@ StaticSpeedHelper::Reset (const Speed &speed)
{
Update ();
m_speed = speed;
m_pauseEnd = Simulator::Now ();
Unpause ();
}
void
StaticSpeedHelper::UpdateFull (const Rectangle &bounds) const
@@ -115,5 +105,21 @@ StaticSpeedHelper::GetCurrentPosition (const Rectangle &bounds) const
return m_position;
}
void
StaticSpeedHelper::Pause (void)
{
Update ();
m_paused = true;
}
void
StaticSpeedHelper::Unpause (void)
{
if (m_paused)
{
m_lastUpdate = Simulator::Now ();
m_paused = false;
}
}
} // namespace ns3

View File

@@ -37,12 +37,13 @@ class StaticSpeedHelper
const Speed &speed);
void InitializePosition (const Position &position);
void Reset (const Speed &speed, const Time &pauseDelay);
void Reset (const Speed &speed);
Position GetCurrentPosition (const Rectangle &bounds) const;
Position GetCurrentPosition (void) const;
Speed GetSpeed (void) const;
void SetSpeed (const Speed &speed);
void Pause (void);
void Unpause (void);
private:
void Update (void) const;
@@ -50,7 +51,7 @@ class StaticSpeedHelper
mutable Time m_lastUpdate;
mutable Position m_position;
Speed m_speed;
Time m_pauseEnd;
bool m_paused;
};
} // namespace ns3

View File

@@ -16,6 +16,10 @@ def build(bld):
'static-mobility-model.cc',
'static-speed-helper.cc',
'static-speed-mobility-model.cc',
'random-waypoint-mobility-model.cc',
'random-walk-2d-mobility-model.cc',
'random-direction-2d-mobility-model.cc',
'ns2-mobility-file-topology.cc',
]
headers = bld.create_obj('ns3header')
@@ -33,4 +37,8 @@ def build(bld):
'static-mobility-model.h',
'static-speed-helper.h',
'static-speed-mobility-model.h',
'random-waypoint-mobility-model.h',
'random-walk-2d-mobility-model.h',
'random-direction-2d-mobility-model.h',
'ns2-mobility-file-topology.h',
]

View File

@@ -0,0 +1,152 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
* 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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#include "event-garbage-collector.h"
#define CLEANUP_CHUNK_MIN_SIZE 8
#define CLEANUP_CHUNK_MAX_SIZE 128
namespace ns3 {
EventGarbageCollector::EventGarbageCollector () :
m_nextCleanupSize (CLEANUP_CHUNK_MIN_SIZE)
{}
void
EventGarbageCollector::Track (EventId event)
{
m_events.push_back (event);
if (m_events.size () >= m_nextCleanupSize)
Cleanup ();
}
inline bool
EventExpiredPredicate (const EventId &event)
{
return event.IsExpired ();
}
void
EventGarbageCollector::Grow ()
{
m_nextCleanupSize += (m_nextCleanupSize < CLEANUP_CHUNK_MAX_SIZE?
m_nextCleanupSize : CLEANUP_CHUNK_MAX_SIZE);
}
void
EventGarbageCollector::Shrink ()
{
while (m_nextCleanupSize > m_events.size ())
m_nextCleanupSize >>= 1;
Grow ();
}
// Called when a new event was added and the cleanup limit was exceeded in consequence.
void
EventGarbageCollector::Cleanup ()
{
m_events.remove_if (EventExpiredPredicate);
// If after cleanup we are still over the limit, increase the limit.
if (m_events.size () >= m_nextCleanupSize)
Grow ();
else
Shrink ();
}
EventGarbageCollector::~EventGarbageCollector ()
{
for (std::list<EventId>::iterator event = m_events.begin ();
event != m_events.end (); event++)
{
Simulator::Cancel (*event);
}
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
namespace ns3 {
class EventGarbageCollectorTests : public Test
{
int m_counter;
EventGarbageCollector *m_events;
void EventGarbageCollectorCallback ();
public:
EventGarbageCollectorTests ();
virtual ~EventGarbageCollectorTests ();
virtual bool RunTests (void);
};
EventGarbageCollectorTests::EventGarbageCollectorTests ()
: Test ("EventGarbageCollector"), m_counter (0), m_events (0)
{}
EventGarbageCollectorTests::~EventGarbageCollectorTests ()
{}
void
EventGarbageCollectorTests::EventGarbageCollectorCallback ()
{
m_counter++;
if (m_counter == 50)
{
// this should cause the remaining (50) events to be cancelled
delete m_events;
m_events = 0;
}
}
bool EventGarbageCollectorTests::RunTests (void)
{
bool result = true;
m_events = new EventGarbageCollector ();
for (int n = 0; n < 100; n++)
{
m_events->Track (Simulator::Schedule
(Simulator::Now (),
&EventGarbageCollectorTests::EventGarbageCollectorCallback,
this));
}
Simulator::Run ();
NS_TEST_ASSERT_EQUAL (m_events, 0);
NS_TEST_ASSERT_EQUAL (m_counter, 50);
return result;
}
static EventGarbageCollectorTests g_eventCollectorTests;
};
#endif /* RUN_SELF_TESTS */

View File

@@ -0,0 +1,62 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 INESC Porto
* 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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
*/
#ifndef EVENT_GARBAGE_COLLECTOR_H
#define EVENT_GARBAGE_COLLECTOR_H
#include <list>
#include "event-id.h"
#include "simulator.h"
namespace ns3 {
/**
* \brief An object that tracks scheduled events and automatically
* cancels them when it is destroyed. It is useful in situations
* where multiple instances of the same type of event can
* simultaneously be scheduled, and when the events should be limited
* to the lifetime of a container object.
*/
class EventGarbageCollector
{
public:
EventGarbageCollector ();
/**
* \brief Tracks a new event
*/
void Track (EventId event);
~EventGarbageCollector ();
private:
std::list<EventId>::size_type m_nextCleanupSize;
std::list<EventId> m_events;
void Cleanup ();
void Grow ();
void Shrink ();
};
}; // namespace ns3
#endif /* EVENT_GARBAGE_COLLECTOR_H */

View File

@@ -67,9 +67,10 @@ public:
EventId ScheduleDestroy (const Ptr<EventImpl> &event);
void Remove (const EventId &ev);
void Cancel (const EventId &ev);
bool IsExpired (const EventId &ev);
bool IsExpired (const EventId &ev) const;
void Run (void);
Time Now (void) const;
Time GetDelayLeft (const EventId &id) const;
private:
void ProcessOneEvent (void);
@@ -251,6 +252,18 @@ SimulatorPrivate::Now (void) const
{
return TimeStep (m_currentTs);
}
Time
SimulatorPrivate::GetDelayLeft (const EventId &id) const
{
if (IsExpired (id))
{
return TimeStep (0);
}
else
{
return TimeStep (id.GetTs () - m_currentTs);
}
}
void
SimulatorPrivate::Remove (const EventId &ev)
@@ -293,12 +306,12 @@ SimulatorPrivate::Cancel (const EventId &id)
}
bool
SimulatorPrivate::IsExpired (const EventId &ev)
SimulatorPrivate::IsExpired (const EventId &ev) const
{
if (ev.GetUid () == 2)
{
// destroy events.
for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
{
if (*i == ev)
{
@@ -411,6 +424,11 @@ Simulator::Now (void)
{
return GetPriv ()->Now ();
}
Time
Simulator::GetDelayLeft (const EventId &id)
{
return GetPriv ()->GetDelayLeft (id);
}
Ptr<EventImpl>
Simulator::MakeEvent (void (*f) (void))

View File

@@ -552,6 +552,13 @@ public:
* Return the "current simulation time".
*/
static Time Now (void);
/**
* \param id the event id to analyse
* \returns the delay left until the input event id expires.
* if the event is not running, this method returns
* zero.
*/
static Time GetDelayLeft (const EventId &id);
private:
Simulator ();
~Simulator ();

325
src/simulator/timer.cc Normal file
View File

@@ -0,0 +1,325 @@
#include "timer.h"
#include "simulator.h"
#include "simulation-singleton.h"
#include "event-garbage-collector.h"
namespace ns3 {
Timer::Timer ()
: m_flags (0),
m_delay (FemtoSeconds (0)),
m_event (),
m_impl (0)
{}
Timer::Timer (enum SchedulePolicy schedulePolicy,
enum DestroyPolicy destroyPolicy)
: m_flags (schedulePolicy | destroyPolicy),
m_delay (FemtoSeconds (0)),
m_event (),
m_impl (0)
{}
Timer::Timer (enum GarbageCollectPolicy policy)
: m_flags (GARBAGE_COLLECT),
m_delay (FemtoSeconds (0)),
m_event (),
m_impl (0)
{}
Timer::~Timer ()
{
if (m_flags & CHECK_ON_DESTROY)
{
if (m_event.IsRunning ())
{
NS_FATAL_ERROR ("Event is still running while destroying.");
}
}
else if (m_flags & CANCEL_ON_DESTROY)
{
m_event.Cancel ();
}
else if (m_flags & REMOVE_ON_DESTROY)
{
Simulator::Remove (m_event);
}
delete m_impl;
}
void
Timer::SetDelay (const Time &time)
{
m_delay = time;
}
Time
Timer::GetDelay (void) const
{
return m_delay;
}
Time
Timer::GetDelayLeft (void) const
{
switch (GetState ()) {
case Timer::RUNNING:
return Simulator::GetDelayLeft (m_event);
break;
case Timer::EXPIRED:
return TimeStep (0);
break;
case Timer::SUSPENDED:
return m_delayLeft;
break;
default:
NS_ASSERT (false);
return TimeStep (0);
break;
}
}
void
Timer::Cancel (void)
{
Simulator::Cancel (m_event);
}
void
Timer::Remove (void)
{
Simulator::Remove (m_event);
}
bool
Timer::IsExpired (void) const
{
return !IsSuspended () && m_event.IsExpired ();
}
bool
Timer::IsRunning (void) const
{
return !IsSuspended () && m_event.IsRunning ();
}
bool
Timer::IsSuspended (void) const
{
return (m_flags & TIMER_SUSPENDED) == TIMER_SUSPENDED;
}
enum Timer::State
Timer::GetState (void) const
{
if (IsRunning ())
{
return Timer::RUNNING;
}
else if (IsExpired ())
{
return Timer::EXPIRED;
}
else
{
NS_ASSERT (IsSuspended ());
return Timer::SUSPENDED;
}
}
void
Timer::Schedule (void)
{
Schedule (m_delay);
}
void
Timer::Schedule (Time delay)
{
NS_ASSERT (m_impl != 0);
if (m_flags & CHECK_ON_SCHEDULE)
{
if (m_event.IsRunning ())
{
NS_FATAL_ERROR ("Event is still running while re-scheduling.");
}
}
else if (m_flags & CANCEL_ON_SCHEDULE)
{
m_event.Cancel ();
}
else if (m_flags & REMOVE_ON_SCHEDULE)
{
Simulator::Remove (m_event);
}
m_event = m_impl->Schedule (delay);
if (m_flags & GARBAGE_COLLECT)
{
SimulationSingleton<EventGarbageCollector>::Get ()->Track (m_event);
}
}
void
Timer::Suspend (void)
{
NS_ASSERT (IsRunning ());
m_delayLeft = Simulator::GetDelayLeft (m_event);
Simulator::Remove (m_event);
m_flags |= TIMER_SUSPENDED;
}
void
Timer::Resume (void)
{
NS_ASSERT (m_flags & TIMER_SUSPENDED);
m_event = m_impl->Schedule (m_delayLeft);
m_flags &= ~TIMER_SUSPENDED;
}
} // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
namespace {
void bari (int)
{}
void bar2i (int, int)
{}
void bar3i (int, int, int)
{}
void bar4i (int, int, int, int)
{}
void bar5i (int, int, int, int, int)
{}
void bar6i (int, int, int, int, int, int)
{}
void barcir (const int &)
{}
void barir (int &)
{}
void barip (int *)
{}
void barcip (const int *)
{}
}
namespace ns3 {
class TimerTests : public Test
{
public:
TimerTests ();
virtual bool RunTests (void);
void bazi (int) {}
void baz2i (int, int) {}
void baz3i (int, int, int) {}
void baz4i (int, int, int, int) {}
void baz5i (int, int, int, int, int) {}
void baz6i (int, int, int, int, int, int) {}
void bazcir (const int&) {}
void bazir (int&) {}
void bazip (int *) {}
void bazcip (const int *) {}
};
TimerTests::TimerTests ()
: Test ("Timer")
{}
bool
TimerTests::RunTests (void)
{
bool result = true;
Timer timer;
timer.SetFunction (&bari);
timer.SetArguments (1);
timer.SetDelay (Seconds (10.0));
NS_TEST_ASSERT (!timer.IsRunning ());
NS_TEST_ASSERT (timer.IsExpired ());
NS_TEST_ASSERT (!timer.IsSuspended ());
NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::EXPIRED);
timer.Schedule ();
NS_TEST_ASSERT (timer.IsRunning ());
NS_TEST_ASSERT (!timer.IsExpired ());
NS_TEST_ASSERT (!timer.IsSuspended ());
NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::RUNNING);
timer.Suspend ();
NS_TEST_ASSERT (!timer.IsRunning ());
NS_TEST_ASSERT (!timer.IsExpired ());
NS_TEST_ASSERT (timer.IsSuspended ());
NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::SUSPENDED);
timer.Resume ();
NS_TEST_ASSERT (timer.IsRunning ());
NS_TEST_ASSERT (!timer.IsExpired ());
NS_TEST_ASSERT (!timer.IsSuspended ());
NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::RUNNING);
timer.Cancel ();
NS_TEST_ASSERT (!timer.IsRunning ());
NS_TEST_ASSERT (timer.IsExpired ());
NS_TEST_ASSERT (!timer.IsSuspended ());
NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::EXPIRED);
int a = 0;
int &b = a;
const int &c = a;
timer.SetFunction (&bari);
timer.SetArguments (2);
timer.SetArguments (a);
timer.SetArguments (b);
timer.SetArguments (c);
timer.SetFunction (&barir);
timer.SetArguments (2);
timer.SetArguments (a);
timer.SetArguments (b);
timer.SetArguments (c);
timer.SetFunction (&barcir);
timer.SetArguments (2);
timer.SetArguments (a);
timer.SetArguments (b);
timer.SetArguments (c);
// the following call cannot possibly work and is flagged by
// a runtime error.
//timer.SetArguments (0.0);
timer.SetDelay (Seconds (1.0));
timer.Schedule ();
timer.SetFunction (&TimerTests::bazi, this);
timer.SetArguments (3);
timer.SetFunction (&TimerTests::bazir, this);
timer.SetArguments (3);
timer.SetFunction (&TimerTests::bazcir, this);
timer.SetArguments (3);
timer.SetFunction (&bar2i);
timer.SetArguments (1, 1);
timer.SetFunction (&bar3i);
timer.SetArguments (1, 1, 1);
timer.SetFunction (&bar4i);
timer.SetArguments (1, 1, 1, 1);
timer.SetFunction (&bar5i);
timer.SetArguments (1, 1, 1, 1, 1);
//timer.SetFunction (&bar6i);
//timer.SetArguments (1, 1, 1, 1, 1, 1);
timer.SetFunction (&TimerTests::baz2i, this);
timer.SetArguments (1, 1);
timer.SetFunction (&TimerTests::baz3i, this);
timer.SetArguments (1, 1, 1);
timer.SetFunction (&TimerTests::baz4i, this);
timer.SetArguments (1, 1, 1, 1);
timer.SetFunction (&TimerTests::baz5i, this);
timer.SetArguments (1, 1, 1, 1, 1);
//timer.SetFunction (&TimerTests::baz6i, this);
//timer.SetArguments (1, 1, 1, 1, 1, 1);
Simulator::Run ();
Simulator::Destroy ();
return result;
}
TimerTests g_tests;
} // namespace ns3
#endif /* RUN_SELF_TESTS */

991
src/simulator/timer.h Normal file
View File

@@ -0,0 +1,991 @@
#ifndef TIMER_H
#define TIMER_H
#include "ns3/fatal-error.h"
#include "nstime.h"
#include "event-id.h"
#include "ns3/int-to-type.h"
namespace ns3 {
class TimerImpl;
/**
* \brief a simple Timer class
*
* A timer is used to hold together a delay, a function to invoke
* when the delay expires, and a set of arguments to pass to the function
* when the delay expires.
*
* A timer can also be used to enforce a set of predefined event lifetime
* management policies. These policies are specified at construction time
* and cannot be changed after.
*/
class Timer
{
public:
enum SchedulePolicy {
/**
* This policy cancels the event before scheduling a new event
* for each call to Timer::Schedule.
*/
CANCEL_ON_SCHEDULE = (1<<0),
/**
* This policy removes the event from the simulation event list
* before scheduling a new event for each call to Timer::Schedule.
*/
REMOVE_ON_SCHEDULE = (1<<1),
/**
* This policy enforces a check before each call to Timer::Schedule
* to verify that the timer has already expired.
*/
CHECK_ON_SCHEDULE = (1<<2),
};
enum DestroyPolicy {
/**
* This policy cancels the event from the destructor of the Timer
* to verify that the event has already expired.
*/
CANCEL_ON_DESTROY = (1<<3),
/**
* This policy removes the event from the simulation event list
* when the destructor of the Timer is invoked.
*/
REMOVE_ON_DESTROY = (1<<4),
/**
* This policy enforces a check from the destructor of the Timer
* to verify that the timer has already expired.
*/
CHECK_ON_DESTROY = (1<<5)
};
enum GarbageCollectPolicy {
/**
* Every event scheduled with this policy is kept track of by an
* event garbage collector which makes sure that all events
* of timers with a GARBAGE_COLLECT policy are cancelled at the
* end of the simulation.
*/
GARBAGE_COLLECT = (1<<6)
};
enum State {
RUNNING,
EXPIRED,
SUSPENDED,
};
/**
* create a timer with a default event lifetime management policy:
* - CHECK_ON_SCHEDULE
* - CHECK_ON_DESTROY
*/
Timer ();
/**
* \param scheduleFlags the event lifetime management policies to use for schedule events
* \param destroyFlags the event lifetime management policies to use for destroy events
*/
Timer (enum SchedulePolicy schedulePolicy,
enum DestroyPolicy destroyPolicy);
/**
* \param policy the garbage collect policy. Only one
* value is possible.
*/
Timer (enum GarbageCollectPolicy policy);
~Timer ();
/**
* \param fn the function
*
* Store this function in this Timer for later use by Timer::Schedule.
*/
template <typename FN>
void SetFunction (FN fn);
/**
* \param memPtr the member function pointer
* \param objPtr the pointer to object
*
* Store this function and object in this Timer for later use by Timer::Schedule.
*/
template <typename MEM_PTR, typename OBJ_PTR>
void SetFunction (MEM_PTR memPtr, OBJ_PTR objPtr);
/**
* \param a1 the first argument
*
* Store this argument in this Timer for later use by Timer::Schedule.
*/
template <typename T1>
void SetArguments (T1 a1);
/**
* \param a1 the first argument
* \param a2 the second argument
*
* Store these arguments in this Timer for later use by Timer::Schedule.
*/
template <typename T1, typename T2>
void SetArguments (T1 a1, T2 a2);
/**
* \param a1 the first argument
* \param a2 the second argument
* \param a3 the third argument
*
* Store these arguments in this Timer for later use by Timer::Schedule.
*/
template <typename T1, typename T2, typename T3>
void SetArguments (T1 a1, T2 a2, T3 a3);
/**
* \param a1 the first argument
* \param a2 the second argument
* \param a3 the third argument
* \param a4 the fourth argument
*
* Store these arguments in this Timer for later use by Timer::Schedule.
*/
template <typename T1, typename T2, typename T3, typename T4>
void SetArguments (T1 a1, T2 a2, T3 a3, T4 a4);
/**
* \param a1 the first argument
* \param a2 the second argument
* \param a3 the third argument
* \param a4 the fourth argument
* \param a5 the fifth argument
*
* Store these arguments in this Timer for later use by Timer::Schedule.
*/
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
/**
* \param a1 the first argument
* \param a2 the second argument
* \param a3 the third argument
* \param a4 the fourth argument
* \param a5 the fifth argument
* \param a6 the sixth argument
*
* Store these arguments in this Timer for later use by Timer::Schedule.
*/
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
/**
* \param delay the delay
*
* The next call to Schedule will schedule the timer with this delay.
*/
void SetDelay (const Time &delay);
/**
* \returns the currently-configured delay for the next Schedule.
*/
Time GetDelay (void) const;
/**
* \returns the amount of time left until this timer expires.
*
* This method returns zero if the timer is in EXPIRED state.
*/
Time GetDelayLeft (void) const;
/**
* Cancel the currently-running event if there is one. Do nothing
* otherwise.
*/
void Cancel (void);
/**
* Remove from the simulation event-list the currently-running event
* if there is one. Do nothing otherwise.
*/
void Remove (void);
/**
* \return true if there is no currently-running event, false otherwise.
*/
bool IsExpired (void) const;
/**
* \return true if there is a currently-running event, false otherwise.
*/
bool IsRunning (void) const;
/**
* \returns true if this timer was suspended and not yet resumed, false
* otherwise.
*/
bool IsSuspended (void) const;
/**
* \returns the current state of the timer.
*/
enum Timer::State GetState (void) const;
/**
* Schedule a new event using the currently-configured delay, function,
* and arguments.
*/
void Schedule (void);
/**
* \param delay the delay to use
*
* Schedule a new event using the specified delay (ignore the delay set by
* Timer::SetDelay), function, and arguments.
*/
void Schedule (Time delay);
/**
* Cancel the timer and save the amount of time left until it was
* set to expire.
* Calling Suspend on a non-running timer is an error.
*/
void Suspend (void);
/**
* Restart the timer to expire within the amount of time left saved
* during Suspend.
* Calling Resume without a prior call to Suspend is an error.
*/
void Resume (void);
private:
template <typename FN>
void DoSetFunction (IntToType<0>, FN fn);
template <typename FN>
void DoSetFunction (IntToType<1>, FN fn);
template <typename FN>
void DoSetFunction (IntToType<2>, FN fn);
template <typename FN>
void DoSetFunction (IntToType<3>, FN fn);
template <typename FN>
void DoSetFunction (IntToType<4>, FN fn);
template <typename FN>
void DoSetFunction (IntToType<5>, FN fn);
template <typename FN>
void DoSetFunction (IntToType<6>, FN fn);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<0>, MEM_PTR memPtr, OBJ_PTR objPtr);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<1>, MEM_PTR memPtr, OBJ_PTR objPtr);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<2>, MEM_PTR memPtr, OBJ_PTR objPtr);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<3>, MEM_PTR memPtr, OBJ_PTR objPtr);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<4>, MEM_PTR memPtr, OBJ_PTR objPtr);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<5>, MEM_PTR memPtr, OBJ_PTR objPtr);
template <typename MEM_PTR, typename OBJ_PTR>
void DoSetFunction (IntToType<6>, MEM_PTR memPtr, OBJ_PTR objPtr);
enum {
TIMER_SUSPENDED = (1<<7)
};
int m_flags;
Time m_delay;
EventId m_event;
TimerImpl *m_impl;
Time m_delayLeft;
};
} // namespace ns3
// The actual implementation.
#include "simulator.h"
#include "ns3/type-traits.h"
namespace ns3 {
template <typename T>
struct TimerTraits
{
typedef typename TypeTraits<typename TypeTraits<T>::ReferencedType>::NonConstType StoredType;
typedef const StoredType &ParameterType;
};
class TimerImpl
{
public:
virtual ~TimerImpl () {}
virtual EventId Schedule (const Time &delay) = 0;
};
template <typename T1>
struct TimerImplOne : public TimerImpl
{
virtual void SetArguments (T1 a1) = 0;
};
template <typename T1, typename T2>
struct TimerImplTwo : public TimerImpl
{
virtual void SetArguments (T1 a1,T2 a2) = 0;
};
template <typename T1, typename T2, typename T3>
struct TimerImplThree : public TimerImpl
{
virtual void SetArguments (T1 a1,T2 a2,T3 a3) = 0;
};
template <typename T1, typename T2, typename T3, typename T4>
struct TimerImplFour : public TimerImpl
{
virtual void SetArguments (T1 a1,T2 a2,T3 a3, T4 a4) = 0;
};
template <typename T1, typename T2, typename T3, typename T4, typename T5>
struct TimerImplFive : public TimerImpl
{
virtual void SetArguments (T1 a1,T2 a2,T3 a3, T4 a4, T5 a5) = 0;
};
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct TimerImplSix : public TimerImpl
{
virtual void SetArguments (T1 a1,T2 a2,T3 a3, T4 a4, T5 a5, T6 a6) = 0;
};
template <typename FN>
void
Timer::SetFunction (FN fn)
{
NS_ASSERT (TypeTraits<FN>::IsFunctionPointer);
DoSetFunction (IntToType<TypeTraits<FN>::FunctionPointerTraits::nArgs> (), fn);
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<0>, FN fn)
{
struct FnTimerImplZero : public TimerImpl
{
FnTimerImplZero (FN fn)
: m_fn (fn) {}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn);
}
FN m_fn;
} *function = new FnTimerImplZero (fn);
delete m_impl;
m_impl = function;
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<1>, FN fn)
{
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
struct FnTimerImplOne : public TimerImplOne<T1Parameter>
{
FnTimerImplOne (FN fn)
: m_fn (fn) {}
virtual void SetArguments (T1Parameter a1) {
m_a1 = a1;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn, m_a1);
}
FN m_fn;
T1Stored m_a1;
} *function = new FnTimerImplOne (fn);
delete m_impl;
m_impl = function;
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<2>, FN fn)
{
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
struct FnTimerImplTwo : public TimerImplTwo<T1Parameter,T2Parameter>
{
FnTimerImplTwo (FN fn)
: m_fn (fn) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2) {
m_a1 = a1;
m_a2 = a2;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn, m_a1, m_a2);
}
FN m_fn;
T1Stored m_a1;
T2Stored m_a2;
} *function = new FnTimerImplTwo (fn);
delete m_impl;
m_impl = function;
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<3>, FN fn)
{
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
struct FnTimerImplThree : public TimerImplThree<T1Parameter,T2Parameter,T3Parameter>
{
FnTimerImplThree (FN fn)
: m_fn (fn) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3);
}
FN m_fn;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
} *function = new FnTimerImplThree (fn);
delete m_impl;
m_impl = function;
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<4>, FN fn)
{
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg4Type T4;
typedef typename TimerTraits<T4>::ParameterType T4Parameter;
typedef typename TimerTraits<T4>::StoredType T4Stored;
struct FnTimerImplFour : public TimerImplFour<T1Parameter,T2Parameter,T3Parameter,T4Parameter>
{
FnTimerImplFour (FN fn)
: m_fn (fn) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
m_a4 = a4;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3, m_a4);
}
FN m_fn;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
T4Stored m_a4;
} *function = new FnTimerImplFour (fn);
delete m_impl;
m_impl = function;
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<5>, FN fn)
{
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg4Type T4;
typedef typename TimerTraits<T4>::ParameterType T4Parameter;
typedef typename TimerTraits<T4>::StoredType T4Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg5Type T5;
typedef typename TimerTraits<T5>::ParameterType T5Parameter;
typedef typename TimerTraits<T5>::StoredType T5Stored;
struct FnTimerImplFive : public TimerImplFive<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter>
{
FnTimerImplFive (FN fn)
: m_fn (fn) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4, T5Parameter a5) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
m_a4 = a4;
m_a5 = a5;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3, m_a4, m_a5);
}
FN m_fn;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
T4Stored m_a4;
T5Stored m_a5;
} *function = new FnTimerImplFive (fn);
delete m_impl;
m_impl = function;
}
template <typename FN>
void
Timer::DoSetFunction (IntToType<6>, FN fn)
{
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg4Type T4;
typedef typename TimerTraits<T4>::ParameterType T4Parameter;
typedef typename TimerTraits<T4>::StoredType T4Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg5Type T5;
typedef typename TimerTraits<T5>::ParameterType T5Parameter;
typedef typename TimerTraits<T5>::StoredType T5Stored;
typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg6Type T6;
typedef typename TimerTraits<T6>::ParameterType T6Parameter;
typedef typename TimerTraits<T6>::StoredType T6Stored;
struct FnTimerImplSix : public TimerImplSix<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter,T6Parameter>
{
FnTimerImplSix (FN fn)
: m_fn (fn) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4, T5Parameter a5, T6Parameter a6) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
m_a4 = a4;
m_a5 = a5;
m_a6 = a6;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3, m_a4, m_a5, m_a6);
}
FN m_fn;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
T4Stored m_a4;
T5Stored m_a5;
T6Stored m_a6;
} *function = new FnTimerImplSix (fn);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::SetFunction (MEM_PTR memPtr, OBJ_PTR objPtr)
{
NS_ASSERT (TypeTraits<MEM_PTR>::IsPointerToMember);
DoSetFunction (IntToType<TypeTraits<MEM_PTR>::PointerToMemberTraits::nArgs> () , memPtr, objPtr);
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<0>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
struct MemFnTimerImplZero : public TimerImpl
{
MemFnTimerImplZero (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
} *function = new MemFnTimerImplZero (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<1>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
struct MemFnTimerImplOne : public TimerImplOne<T1Parameter>
{
MemFnTimerImplOne (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual void SetArguments (T1Parameter a1) {
m_a1 = a1;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
T1Stored m_a1;
} *function = new MemFnTimerImplOne (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<2>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
struct MemFnTimerImplTwo : public TimerImplTwo<T1Parameter,T2Parameter>
{
MemFnTimerImplTwo (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2) {
m_a1 = a1;
m_a2 = a2;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
T1Stored m_a1;
T2Stored m_a2;
} *function = new MemFnTimerImplTwo (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<3>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
struct MemFnTimerImplThree : public TimerImplThree<T1Parameter,T2Parameter,T3Parameter>
{
MemFnTimerImplThree (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
} *function = new MemFnTimerImplThree (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<4>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg4Type T4;
typedef typename TimerTraits<T4>::ParameterType T4Parameter;
typedef typename TimerTraits<T4>::StoredType T4Stored;
struct MemFnTimerImplFour : public TimerImplFour<T1Parameter,T2Parameter,T3Parameter,T4Parameter>
{
MemFnTimerImplFour (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
m_a4 = a4;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
T4Stored m_a4;
} *function = new MemFnTimerImplFour (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<5>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg4Type T4;
typedef typename TimerTraits<T4>::ParameterType T4Parameter;
typedef typename TimerTraits<T4>::StoredType T4Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg5Type T5;
typedef typename TimerTraits<T5>::ParameterType T5Parameter;
typedef typename TimerTraits<T5>::StoredType T5Stored;
struct MemFnTimerImplFive : public TimerImplFive<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter>
{
MemFnTimerImplFive (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4,T5Parameter a5) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
m_a4 = a4;
m_a5 = a5;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4, m_a5);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
T4Stored m_a4;
T5Stored m_a5;
} *function = new MemFnTimerImplFive (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename MEM_PTR, typename OBJ_PTR>
void
Timer::DoSetFunction (IntToType<6>, MEM_PTR memPtr, OBJ_PTR objPtr)
{
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
typedef typename TimerTraits<T1>::ParameterType T1Parameter;
typedef typename TimerTraits<T1>::StoredType T1Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
typedef typename TimerTraits<T2>::ParameterType T2Parameter;
typedef typename TimerTraits<T2>::StoredType T2Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
typedef typename TimerTraits<T3>::ParameterType T3Parameter;
typedef typename TimerTraits<T3>::StoredType T3Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg4Type T4;
typedef typename TimerTraits<T4>::ParameterType T4Parameter;
typedef typename TimerTraits<T4>::StoredType T4Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg5Type T5;
typedef typename TimerTraits<T5>::ParameterType T5Parameter;
typedef typename TimerTraits<T5>::StoredType T5Stored;
typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg6Type T6;
typedef typename TimerTraits<T6>::ParameterType T6Parameter;
typedef typename TimerTraits<T6>::StoredType T6Stored;
struct MemFnTimerImplSix : public TimerImplSix<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter,T6Parameter>
{
MemFnTimerImplSix (MEM_PTR memPtr, OBJ_PTR objPtr)
: m_memPtr (memPtr), m_objPtr (objPtr) {}
virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4,T5Parameter a5,T6Parameter a6) {
m_a1 = a1;
m_a2 = a2;
m_a3 = a3;
m_a4 = a4;
m_a5 = a5;
m_a6 = a6;
}
virtual EventId Schedule (const Time &delay) {
return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4, m_a5, m_a6);
}
MEM_PTR m_memPtr;
OBJ_PTR m_objPtr;
T1Stored m_a1;
T2Stored m_a2;
T3Stored m_a3;
T4Stored m_a4;
T5Stored m_a5;
T6Stored m_a6;
} *function = new MemFnTimerImplSix (memPtr, objPtr);
delete m_impl;
m_impl = function;
}
template <typename T1>
void
Timer::SetArguments (T1 a1)
{
if (m_impl == 0)
{
NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
return;
}
typedef struct TimerImplOne<
typename TimerTraits<T1>::ParameterType
> TimerImplBase;
TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
if (impl == 0)
{
NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
return;
}
impl->SetArguments (a1);
}
template <typename T1, typename T2>
void
Timer::SetArguments (T1 a1, T2 a2)
{
if (m_impl == 0)
{
NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
return;
}
typedef struct TimerImplTwo<
typename TimerTraits<T1>::ParameterType,
typename TimerTraits<T2>::ParameterType
> TimerImplBase;
TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
if (impl == 0)
{
NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
return;
}
impl->SetArguments (a1, a2);
}
template <typename T1, typename T2, typename T3>
void
Timer::SetArguments (T1 a1, T2 a2, T3 a3)
{
if (m_impl == 0)
{
NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
return;
}
typedef struct TimerImplThree<
typename TimerTraits<T1>::ParameterType,
typename TimerTraits<T2>::ParameterType,
typename TimerTraits<T3>::ParameterType
> TimerImplBase;
TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
if (impl == 0)
{
NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
return;
}
impl->SetArguments (a1, a2, a3);
}
template <typename T1, typename T2, typename T3, typename T4>
void
Timer::SetArguments (T1 a1, T2 a2, T3 a3, T4 a4)
{
if (m_impl == 0)
{
NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
return;
}
typedef struct TimerImplFour<
typename TimerTraits<T1>::ParameterType,
typename TimerTraits<T2>::ParameterType,
typename TimerTraits<T3>::ParameterType,
typename TimerTraits<T4>::ParameterType
> TimerImplBase;
TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
if (impl == 0)
{
NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
return;
}
impl->SetArguments (a1, a2, a3, a4);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void
Timer::SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
if (m_impl == 0)
{
NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
return;
}
typedef struct TimerImplFive<
typename TimerTraits<T1>::ParameterType,
typename TimerTraits<T2>::ParameterType,
typename TimerTraits<T3>::ParameterType,
typename TimerTraits<T4>::ParameterType,
typename TimerTraits<T5>::ParameterType
> TimerImplBase;
TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
if (impl == 0)
{
NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
return;
}
impl->SetArguments (a1, a2, a3, a4, a5);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void
Timer::SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
{
if (m_impl == 0)
{
NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
return;
}
typedef struct TimerImplSix<
typename TimerTraits<T1>::ParameterType,
typename TimerTraits<T2>::ParameterType,
typename TimerTraits<T3>::ParameterType,
typename TimerTraits<T4>::ParameterType,
typename TimerTraits<T5>::ParameterType,
typename TimerTraits<T6>::ParameterType
> TimerImplBase;
TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
if (impl == 0)
{
NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
return;
}
impl->SetArguments (a1, a2, a3, a4, a5, a6);
}
} // namespace ns3
#endif /* TIMER_H */

View File

@@ -60,6 +60,8 @@ def build(bld):
'event-impl.cc',
'simulator.cc',
'time-default-value.cc',
'timer.cc',
'event-garbage-collector.cc',
]
headers = bld.create_obj('ns3header')
@@ -73,6 +75,7 @@ def build(bld):
'scheduler-factory.h',
'simulation-singleton.h',
'time-default-value.h',
'timer.h'
]
env = bld.env_of_name('default')

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 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 <mathieu.lacage@sophia.inria.fr>
*/
#include "ns3/ns2-mobility-file-topology.h"
#include "ns3/object.h"
#include "ns3/simulator.h"
#include "ns3/mobility-model-notifier.h"
#include <iostream>
using namespace ns3;
static void
CourseChange (Ptr<const MobilityModel> position)
{
Position pos = position->Get ();
std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
<< ", z=" << pos.z << std::endl;
}
int main (int argc, char *argv[])
{
std::vector<Ptr<Object> > objects;
while (argc > 0)
{
if (strncmp (*argv, "--n=", strlen ("--n=")) == 0)
{
uint32_t n = atoi (*argv + strlen ("--n="));
for (uint32_t i = 0; i < n; i++)
{
Ptr<MobilityModelNotifier> notifier = Create<MobilityModelNotifier> ();
notifier->RegisterListener (MakeCallback (&CourseChange));
objects.push_back (notifier);
}
}
else if (strncmp (*argv, "--ns2-topology=",
strlen ("--ns2-topology=")) == 0)
{
const char *filename = *argv + strlen ("--ns2-topology=");
Ns2MobilityFileTopology topology (filename);
topology.Layout (objects.begin (), objects.end ());
}
argc--;
argv++;
}
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

View File

@@ -0,0 +1,137 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include <vector>
#include "ns3/ptr.h"
#include "ns3/mobility-model.h"
#include "ns3/mobility-model-notifier.h"
#include "ns3/random-topology.h"
#include "ns3/default-value.h"
#include "ns3/command-line.h"
#include "ns3/command-line.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/node.h"
#include "ns3/node-list.h"
#include "ns3/rectangle-default-value.h"
#include "mobility-visualizer.h"
using namespace ns3;
static Time g_sampleInterval = Seconds (SAMPLE_INTERVAL);
static uint32_t g_numNodes = 10;
template <typename T>
static const T* DefaultValueListGet (const std::string &name)
{
for (DefaultValueList::Iterator iter = DefaultValueList::Begin ();
iter != DefaultValueList::End (); iter++)
{
const DefaultValueBase *value = *iter;
if (value->GetName () == name)
{
return dynamic_cast<const T*> (value);
}
}
return NULL;
}
static void
Sample ()
{
ViewUpdateData *data = new ViewUpdateData;
for (NodeList::Iterator nodeIter = NodeList::Begin (); nodeIter != NodeList::End (); nodeIter++)
{
Ptr<Node> node = *nodeIter;
Ptr<MobilityModel> mobility = node->QueryInterface<MobilityModel> (MobilityModel::iid);
Position pos = mobility->Get ();
Speed vel = mobility->GetSpeed ();
NodeUpdate update;
update.node = PeekPointer<Node> (node);
update.x = pos.x;
update.y = pos.y;
update.vx = vel.dx;
update.vy = vel.dy;
data->updateList.push_back (update);
}
data->time = Simulator::Now ().GetSeconds ();
view_update (data);
Simulator::Schedule (g_sampleInterval, Sample);
}
int model_init (int argc, char *argv[], double *x1, double *y1, double *x2, double *y2)
{
DefaultValue::Bind ("RandomWalk2dMode", "Time");
DefaultValue::Bind ("RandomWalk2dTime", "5s");
DefaultValue::Bind ("RandomWalk2dSpeed", "Constant:20.0");
DefaultValue::Bind ("RandomDirection2dSpeed", "Uniform:10.0:20.0");
DefaultValue::Bind ("RandomWalk2dBounds", "0:400:0:300");
DefaultValue::Bind ("RandomDirection2dArea", "0:400:0:300");
DefaultValue::Bind ("RandomWaypointSpeed", "Uniform:10:30");
// DefaultValue::Bind ("RandomDiscPositionX", "100");
// DefaultValue::Bind ("RandomDiscPositionY", "50");
// DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
DefaultValue::Bind ("RandomTopologyPositionType", "RandomRectanglePosition");
DefaultValue::Bind ("RandomTopologyMobilityType", "RandomWalk2dMobilityModel");
// CommandLine::AddArgValue ("sample-interval","sample interval", g_sampleInterval);
// CommandLine::AddArgValue ("num-nodes","number of nodes", g_numNodes);
CommandLine::Parse (argc, argv);
RandomTopology topology;
for (uint32_t i = 0; i < g_numNodes; i++)
{
Ptr<Node> node = Create<Node> ();
node->AddInterface (Create<MobilityModelNotifier> ());
}
topology.Layout (NodeList::Begin (), NodeList::End ());
Simulator::Schedule (g_sampleInterval, Sample);
ClassId mobType = DefaultValueListGet<ClassIdDefaultValue> ("RandomTopologyMobilityType")->GetValue ();
if (mobType.GetName () == "RandomWalk2dMobilityModel")
{
Rectangle bounds = DefaultValueListGet<RectangleDefaultValue> ("RandomWalk2dBounds")->GetValue ();
*x1 = bounds.xMin;
*y1 = bounds.yMin;
*x2 = bounds.xMax;
*y2 = bounds.yMax;
std::cout << "RECT " << bounds.xMin << " " << bounds.xMax << " "
<< bounds.yMin << " " << bounds.yMax << std::endl;
}
else if (mobType.GetName () == "RandomDirection2dMobilityModel")
{
Rectangle bounds = DefaultValueListGet<RectangleDefaultValue> ("RandomDirection2dArea")->GetValue ();
*x1 = bounds.xMin;
*y1 = bounds.yMin;
*x2 = bounds.xMax;
*y2 = bounds.yMax;
std::cout << "RECT " << bounds.xMin << " " << bounds.xMax << " "
<< bounds.yMin << " " << bounds.yMax << std::endl;
}
else if (mobType.GetName () == "RandomWaypointMobilityModel")
{
std::cerr << "bounds for RandomWaypointMobilityModel not implemented" << std::endl;
//ClassId posType = DefaultValueList::Get<ClassIdDefaultValue> ("RandomWaypointPosition")->GetValue ();
std::cout << "?" << std::endl; // too hard to represent an abstract/probabilistic model graphically
}
else
{
NS_FATAL_ERROR ("mobility type " << mobType.GetName () << " not supported");
}
std::cerr << g_sampleInterval << std::endl;
return 0;
}

View File

@@ -0,0 +1,218 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include <map>
#include <goocanvas.h>
#include <glib/gthread.h>
#include "mobility-visualizer.h"
#include <map>
#include "ns3/simulator.h"
#define MAX_QUEUE_LENGTH 100
#define MAX_EVENTS 20
#define LOOKAHEAD_SECONDS 10
GtkWidget *g_canvas;
int model_init (int argc, char *argv[]);
struct Node
{
GooCanvasItem *m_item;
GooCanvasItem *m_vector;
void create ()
{
GooCanvasItem *root = goo_canvas_get_root_item (GOO_CANVAS (g_canvas));
m_item = goo_canvas_ellipse_new (root, 0, 0, 2.0, 2.0,
"line_width", 0.5,
"stroke_color", "black",
"fill_color", "red",
NULL);
m_vector = goo_canvas_polyline_new (root, FALSE, 0,
"line_width", 0.3,
"stroke_color", "black",
"end-arrow", TRUE,
"arrow-length", 10.0,
"arrow-width", 10.0,
NULL);
}
void update (double x, double y, double vx, double vy)
{
g_object_set (m_item, "center_x", x, "center_y", y, NULL);
if (vx == 0 && vy == 0)
{
GooCanvasPoints *points = goo_canvas_points_new (0);
g_object_set (m_vector, "points", points, NULL);
goo_canvas_points_unref (points);
}
else
{
GooCanvasPoints *points = goo_canvas_points_new (2);
points->coords[0] = x;
points->coords[1] = y;
points->coords[2] = x + vx;
points->coords[3] = y + vy;
g_object_set (m_vector, "points", points, NULL);
goo_canvas_points_unref (points);
}
}
};
std::map<void*, Node> g_nodes;
GTimeVal initialTime = {-1, -1};
gboolean firstTime = TRUE;
double g_lookaheadTime = 0;
GStaticMutex g_lookaheadTimeMux = G_STATIC_MUTEX_INIT;
ViewUpdateData *g_nextData = NULL;
GAsyncQueue *queue;
#define TIME_SCALE 1
double get_current_time ()
{
GTimeVal currTime;
g_get_current_time (&currTime);
GTimeVal relativeTime;
relativeTime.tv_sec = currTime.tv_sec - initialTime.tv_sec + LOOKAHEAD_SECONDS;
relativeTime.tv_usec = currTime.tv_usec;
g_time_val_add (&relativeTime, -initialTime.tv_usec);
return (relativeTime.tv_sec + 1.0e-6*relativeTime.tv_usec)*TIME_SCALE;
}
// called from the simulation thread
void view_update (ViewUpdateData *updateData)
{
while ((g_static_mutex_lock (&g_lookaheadTimeMux), g_lookaheadTime) != 0 and updateData->time >= g_lookaheadTime)
{
g_static_mutex_unlock (&g_lookaheadTimeMux);
g_usleep ((gulong) 10e3);
}
g_static_mutex_unlock (&g_lookaheadTimeMux);
g_async_queue_push (queue, updateData);
}
void view_update_process (ViewUpdateData *updateData)
{
for (std::vector<NodeUpdate>::const_iterator update
= updateData->updateList.begin ();
update != updateData->updateList.end ();
update++)
{
if (g_nodes.find (update->node) == g_nodes.end ())
{
g_nodes[update->node].create ();
}
g_nodes[update->node].update (update->x, update->y, update->vx, update->vy);
}
delete updateData;
}
gboolean view_update_consumer ()
{
if (firstTime)
{
firstTime = FALSE;
g_get_current_time (&initialTime);
}
double now = get_current_time ();
g_static_mutex_lock (&g_lookaheadTimeMux);
g_lookaheadTime = now + LOOKAHEAD_SECONDS;
g_static_mutex_unlock (&g_lookaheadTimeMux);
if (!g_nextData)
g_nextData = (ViewUpdateData *) g_async_queue_try_pop (queue);
if (!g_nextData)
return TRUE;
if (g_nextData->time > now)
return TRUE;
do
{
view_update_process (g_nextData);
g_nextData = (ViewUpdateData *) g_async_queue_try_pop (queue);
}
while (g_nextData && g_nextData->time <= now);
return TRUE;
}
void zoom_changed (GtkAdjustment *adj)
{
goo_canvas_set_scale (GOO_CANVAS (g_canvas), gtk_adjustment_get_value (adj));
}
int main (int argc, char *argv[])
{
g_thread_init (NULL);
gtk_init (&argc, &argv);
double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
model_init (argc, argv, &x1, &y1, &x2, &y2);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
gtk_widget_show (window);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
gtk_widget_show (scrolled_win);
GtkWidget *vbox = gtk_vbox_new (FALSE, 4);
gtk_widget_show (vbox);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, 1, 1, 4);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *hbox = gtk_hbox_new (FALSE, 4);
gtk_widget_show (hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox, false, false, 4);
GtkObject *zoom = gtk_adjustment_new (3.0, 0.1, 10.0, 0.2, 1.0, 1.0);
gtk_box_pack_start(GTK_BOX (hbox),
GTK_WIDGET (g_object_new (GTK_TYPE_SPIN_BUTTON, "adjustment", zoom,
"visible", true, "digits", 2, NULL)),
false, false, 4);
g_canvas = goo_canvas_new ();
gtk_widget_set_size_request (GTK_WIDGET (g_canvas), 600, 450);
goo_canvas_set_bounds (GOO_CANVAS (g_canvas), -500, -500, 500, 500);
g_signal_connect (zoom, "value-changed", G_CALLBACK (zoom_changed), NULL);
gtk_adjustment_value_changed (GTK_ADJUSTMENT (zoom));
gtk_widget_show (g_canvas);
gtk_container_add (GTK_CONTAINER (scrolled_win), g_canvas);
goo_canvas_scroll_to (GOO_CANVAS (g_canvas), 0, 0);
// create the bounds rectangle
if (x1 != x2)
{
GooCanvasItem *item =
goo_canvas_rect_new (goo_canvas_get_root_item (GOO_CANVAS (g_canvas)),
x1, y1, x2-x1, y2-y1, NULL);
g_object_set (item, "line-width", 1.0, "stroke-color", "grey", NULL);
}
queue = g_async_queue_new ();
g_timeout_add ((guint) (SAMPLE_INTERVAL*1000), (GSourceFunc) view_update_consumer, NULL);
g_thread_create (GThreadFunc (ns3::Simulator::Run), NULL, FALSE, NULL);
gtk_main ();
return 0;
}

View File

@@ -0,0 +1,23 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include <vector>
int model_init (int argc, char *argv[], double *x1, double *y1, double *x2, double *y2);
struct NodeUpdate
{
void *node;
double x;
double y;
double vx;
double vy;
};
struct ViewUpdateData
{
std::vector<NodeUpdate> updateList;
double time;
};
void view_update (ViewUpdateData *updateData);
#define SAMPLE_INTERVAL (1.0/30)

View File

@@ -1,5 +1,13 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import os.path
def configure(conf):
check = conf.create_pkgconfig_configurator()
check.name = 'goocanvas gthread-2.0'
check.uselib = 'MOBILITY_VISUALIZER'
check.mandatory = False
conf.env['ENABLE_MOBILITY_VISUALIZER'] = check.run()
def build(bld):
env = bld.env_of_name('default')
@@ -23,3 +31,12 @@ def build(bld):
obj = bld.create_ns3_program('print-trace-sources',
['internet-node', 'csma-cd', 'point-to-point'])
obj.source = 'print-trace-sources.cc'
if env['ENABLE_MOBILITY_VISUALIZER']:
obj = bld.create_ns3_program('mobility-visualizer',
['internet-node', 'mobility'])
obj.source = ['mobility-visualizer-model.cc', 'mobility-visualizer-view.cc']
obj.uselib = 'MOBILITY_VISUALIZER'
if os.path.basename(obj.env['CXX']).startswith("g++"):
obj.env.append_value('CXXFLAGS', '-fno-strict-aliasing')

View File

@@ -143,6 +143,7 @@ def configure(conf):
variant_env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
conf.sub_config('src')
conf.sub_config('utils')
def create_ns3_program(bld, name, dependencies=('simulator',)):