buildings: (merge !125) Add random walk mobility model that avoids buildings
* Adds example, unit test, and bash script to plot results
This commit is contained in:
committed by
Tom Henderson
parent
059640f466
commit
9f805877ea
@@ -74,9 +74,10 @@ allows to choose between Block Ack policy and Implicit Block Ack Request policy
|
||||
allows to request an acknowledgment after a configurable number of MPDUs have been
|
||||
transmitted.</li>
|
||||
<li>The MaxSize attribute is removed from the QueueBase base class and moved to subclasses. A new MaxSize attribute is therefore added to the DropTailQueue class, while the MaxQueueSize attribute of the WifiMacQueue class is renamed as MaxSize for API consistency.</li>
|
||||
<li> A new sequence and timestamp header variant for applications has been added. The SeqTsEchoHeader contains an additional timestamp field for use in echoing a timestamp back to a sender.</li>
|
||||
<li> TCP-based applications (OnOffApplication, BulkSendApplication, and PacketSink) support a new header to convey sequence number, timestamp, and size data. Use is controlled by the "EnableSeqTsSizeHeader" attribute.</li>
|
||||
<li>Added a new trace source <b>PhyRxPayloadBegin</b> in WifiPhy for tracing begin of PSDU reception.</li>
|
||||
<li> A new sequence and timestamp header variant for applications has been added. The SeqTsEchoHeader contains an additional timestamp field for use in echoing a timestamp back to a sender.</li>
|
||||
<li>Added the class <b>RandomWalk2dOutdoorMobilityModel</b> that models a random walk which does not enter any building.</li>
|
||||
</ul>
|
||||
<h2>Changes to existing API:</h2>
|
||||
<ul>
|
||||
|
||||
@@ -28,6 +28,7 @@ New user-visible features
|
||||
- (propagation) 3GPP TR 38.901 pathloss and channel condition models added
|
||||
- (spectrum) Addition three-gpp-channel-model (part of Integration of the 3GPP TR 38.901 fast fading model)
|
||||
- (antenna) Addition of three-gpp-antenna-array-model (part of Integration of the 3GPP TR 38.901 fast fading model)
|
||||
- (buildings) added a random walk mobility model which does not enter in any building
|
||||
- (core) CommandLine can now add the Usage message to the Doxygen for the program; see CommandLine for details.
|
||||
|
||||
Bugs fixed
|
||||
|
||||
130
src/buildings/examples/outdoor-random-walk-example.cc
Normal file
130
src/buildings/examples/outdoor-random-walk-example.cc
Normal file
@@ -0,0 +1,130 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
* Copyright (c) 2019, University of Padova, Dep. of Information Engineering, SIGNET lab
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es> for the code adapted from the lena-dual-stripe.cc example
|
||||
* Author: Michele Polese <michele.polese@gmail.com> for this version
|
||||
*/
|
||||
|
||||
#include "ns3/buildings-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("OutdoorRandomWalkExample");
|
||||
|
||||
void
|
||||
PrintGnuplottableBuildingListToFile (std::string filename)
|
||||
{
|
||||
std::ofstream outFile;
|
||||
outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
|
||||
if (!outFile.is_open ())
|
||||
{
|
||||
NS_LOG_ERROR ("Can't open file " << filename);
|
||||
return;
|
||||
}
|
||||
uint32_t index = 0;
|
||||
for (BuildingList::Iterator it = BuildingList::Begin (); it != BuildingList::End (); ++it)
|
||||
{
|
||||
++index;
|
||||
Box box = (*it)->GetBoundaries ();
|
||||
outFile << "set object " << index
|
||||
<< " rect from " << box.xMin << "," << box.yMin
|
||||
<< " to " << box.xMax << "," << box.yMax
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is an example on how to use the RandomWalk2dOutdoorMobilityModel class.
|
||||
* The script outdoor-random-walk-example.sh can be used to visualize the
|
||||
* positions visited by the random walk.
|
||||
*/
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
LogComponentEnable ("RandomWalk2dOutdoor", LOG_LEVEL_LOGIC);
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// create a grid of buildings
|
||||
double buildingSizeX = 100; // m
|
||||
double buildingSizeY = 50; // m
|
||||
double streetWidth = 25; // m
|
||||
double buildingHeight = 10; // m
|
||||
uint32_t numBuildingsX = 10;
|
||||
uint32_t numBuildingsY = 10;
|
||||
double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
|
||||
double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
|
||||
|
||||
std::vector<Ptr<Building> > buildingVector;
|
||||
for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
|
||||
{
|
||||
for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
|
||||
{
|
||||
Ptr < Building > building;
|
||||
building = CreateObject<Building> ();
|
||||
|
||||
building->SetBoundaries (Box (buildingIdX * (buildingSizeX + streetWidth),
|
||||
buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
|
||||
buildingIdY * (buildingSizeY + streetWidth),
|
||||
buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
|
||||
0.0, buildingHeight));
|
||||
building->SetNRoomsX (1);
|
||||
building->SetNRoomsY (1);
|
||||
building->SetNFloors (1);
|
||||
buildingVector.push_back (building);
|
||||
}
|
||||
}
|
||||
|
||||
// print the list of buildings to file
|
||||
PrintGnuplottableBuildingListToFile ("buildings.txt");
|
||||
|
||||
// create one node
|
||||
NodeContainer nodes;
|
||||
nodes.Create (1);
|
||||
|
||||
// set the RandomWalk2dOutdoorMobilityModel mobility model
|
||||
MobilityHelper mobility;
|
||||
mobility.SetMobilityModel ("ns3::RandomWalk2dOutdoorMobilityModel",
|
||||
"Bounds", RectangleValue (
|
||||
Rectangle (-streetWidth, maxAxisX, -streetWidth, maxAxisY)));
|
||||
// create an OutdoorPositionAllocator and set its boundaries to match those of the mobility model
|
||||
Ptr<OutdoorPositionAllocator> position = CreateObject<OutdoorPositionAllocator> ();
|
||||
Ptr<UniformRandomVariable> xPos = CreateObject<UniformRandomVariable>();
|
||||
xPos->SetAttribute ("Min", DoubleValue (-streetWidth));
|
||||
xPos->SetAttribute ("Max", DoubleValue (maxAxisX));
|
||||
Ptr<UniformRandomVariable> yPos = CreateObject<UniformRandomVariable>();
|
||||
yPos->SetAttribute ("Min", DoubleValue (-streetWidth));
|
||||
yPos->SetAttribute ("Max", DoubleValue (maxAxisY));
|
||||
position->SetAttribute ("X", PointerValue (xPos));
|
||||
position->SetAttribute ("Y", PointerValue (yPos));
|
||||
mobility.SetPositionAllocator (position);
|
||||
// install the mobility model
|
||||
mobility.Install (nodes.Get (0));
|
||||
|
||||
// enable the traces for the mobility model
|
||||
AsciiTraceHelper ascii;
|
||||
MobilityHelper::EnableAsciiAll (ascii.CreateFileStream ("mobility-trace-example.mob"));
|
||||
|
||||
Simulator::Stop (Seconds (1e4));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
41
src/buildings/examples/outdoor-random-walk-example.sh
Executable file
41
src/buildings/examples/outdoor-random-walk-example.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2019, University of Padova, Dep. of Information Engineering, SIGNET lab
|
||||
#
|
||||
# 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: Michele Polese <michele.polese@gmail.com>
|
||||
|
||||
#
|
||||
# Plot the traces generated by outdoor-random-walk-example.cc
|
||||
#
|
||||
|
||||
cat mobility-trace-example.mob | awk -F " " '{ print $3 }' | awk -F "=" '{ print $2 }' | awk -F ":" '{ print $1" "$2 }' > pos.txt
|
||||
cat >aa <<EOL
|
||||
set terminal postscript eps noenhanced color
|
||||
set output 'map.eps'
|
||||
set view map
|
||||
set xlabel 'X [m]'
|
||||
set ylabel 'Y [m]'
|
||||
set xrange [-25:1300]
|
||||
set yrange [-25:800]
|
||||
set style fill transparent solid 0.5
|
||||
unset key
|
||||
set style fill transparent solid 0.35 noborder
|
||||
set style circle radius 5
|
||||
plot "pos.txt" with circles lc rgb "blue"
|
||||
EOL
|
||||
gnuplot buildings.txt aa
|
||||
rm aa
|
||||
rm pos.txt
|
||||
@@ -4,3 +4,6 @@ def build(bld):
|
||||
obj = bld.create_ns3_program('buildings-pathloss-profiler',
|
||||
['buildings'])
|
||||
obj.source = 'buildings-pathloss-profiler.cc'
|
||||
obj = bld.create_ns3_program('outdoor-random-walk-example',
|
||||
['buildings'])
|
||||
obj.source = 'outdoor-random-walk-example.cc'
|
||||
|
||||
438
src/buildings/model/random-walk-2d-outdoor-mobility-model.cc
Normal file
438
src/buildings/model/random-walk-2d-outdoor-mobility-model.cc
Normal file
@@ -0,0 +1,438 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2006,2007 INRIA
|
||||
* Copyright (c) 2019 University of Padova
|
||||
*
|
||||
* 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>
|
||||
* Author: Michele Polese <michele.polese@gmail.com>
|
||||
*/
|
||||
#include "random-walk-2d-outdoor-mobility-model.h"
|
||||
#include "ns3/enum.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/building.h"
|
||||
#include "ns3/building-list.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("RandomWalk2dOutdoor");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (RandomWalk2dOutdoorMobilityModel);
|
||||
|
||||
TypeId
|
||||
RandomWalk2dOutdoorMobilityModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::RandomWalk2dOutdoorMobilityModel")
|
||||
.SetParent<MobilityModel> ()
|
||||
.SetGroupName ("Mobility")
|
||||
.AddConstructor<RandomWalk2dOutdoorMobilityModel> ()
|
||||
.AddAttribute ("Bounds",
|
||||
"Bounds of the area to cruise.",
|
||||
RectangleValue (Rectangle (0.0, 100.0, 0.0, 100.0)),
|
||||
MakeRectangleAccessor (&RandomWalk2dOutdoorMobilityModel::m_bounds),
|
||||
MakeRectangleChecker ())
|
||||
.AddAttribute ("Time",
|
||||
"Change current direction and speed after moving for this delay.",
|
||||
TimeValue (Seconds (20.0)),
|
||||
MakeTimeAccessor (&RandomWalk2dOutdoorMobilityModel::m_modeTime),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("Distance",
|
||||
"Change current direction and speed after moving for this distance.",
|
||||
DoubleValue (30.0),
|
||||
MakeDoubleAccessor (&RandomWalk2dOutdoorMobilityModel::m_modeDistance),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("Mode",
|
||||
"The mode indicates the condition used to "
|
||||
"change the current speed and direction",
|
||||
EnumValue (RandomWalk2dOutdoorMobilityModel::MODE_DISTANCE),
|
||||
MakeEnumAccessor (&RandomWalk2dOutdoorMobilityModel::m_mode),
|
||||
MakeEnumChecker (RandomWalk2dOutdoorMobilityModel::MODE_DISTANCE, "Distance",
|
||||
RandomWalk2dOutdoorMobilityModel::MODE_TIME, "Time"))
|
||||
.AddAttribute ("Direction",
|
||||
"A random variable used to pick the direction (radians).",
|
||||
StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=6.283184]"),
|
||||
MakePointerAccessor (&RandomWalk2dOutdoorMobilityModel::m_direction),
|
||||
MakePointerChecker<RandomVariableStream> ())
|
||||
.AddAttribute ("Speed",
|
||||
"A random variable used to pick the speed (m/s)."
|
||||
"The default value is taken from Figure 1 of the paper"
|
||||
"Henderson, L.F., 1971. The statistics of crowd fluids. nature, 229(5284), p.381.",
|
||||
StringValue ("ns3::NormalRandomVariable[Mean=1.53|Variance=0.040401]"),
|
||||
MakePointerAccessor (&RandomWalk2dOutdoorMobilityModel::m_speed),
|
||||
MakePointerChecker<RandomVariableStream> ())
|
||||
.AddAttribute ("Tolerance",
|
||||
"Tolerance for the intersection point with buildings (m)."
|
||||
"It represents a small distance from where the building limit"
|
||||
"is actually placed, for example to represent a sidewalk.",
|
||||
DoubleValue (1e-6),
|
||||
MakeDoubleAccessor (&RandomWalk2dOutdoorMobilityModel::m_epsilon),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("MaxIterations",
|
||||
"Maximum number of attempts to find an alternative next position"
|
||||
"if the original one is inside a building.",
|
||||
UintegerValue (100),
|
||||
MakeUintegerAccessor (&RandomWalk2dOutdoorMobilityModel::m_maxIter),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::DoInitialize (void)
|
||||
{
|
||||
DoInitializePrivate ();
|
||||
MobilityModel::DoInitialize ();
|
||||
}
|
||||
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::DoInitializePrivate (void)
|
||||
{
|
||||
m_helper.Update ();
|
||||
double speed = m_speed->GetValue ();
|
||||
double direction = m_direction->GetValue ();
|
||||
Vector vector (std::cos (direction) * speed,
|
||||
std::sin (direction) * speed,
|
||||
0.0);
|
||||
m_helper.SetVelocity (vector);
|
||||
m_helper.Unpause ();
|
||||
|
||||
Time delayLeft;
|
||||
if (m_mode == RandomWalk2dOutdoorMobilityModel::MODE_TIME)
|
||||
{
|
||||
delayLeft = m_modeTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
delayLeft = Seconds (m_modeDistance / speed);
|
||||
}
|
||||
DoWalk (delayLeft);
|
||||
}
|
||||
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::DoWalk (Time delayLeft)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << delayLeft.GetSeconds ());
|
||||
|
||||
Vector position = m_helper.GetCurrentPosition ();
|
||||
Vector speed = m_helper.GetVelocity ();
|
||||
Vector nextPosition = position;
|
||||
nextPosition.x += speed.x * delayLeft.GetSeconds ();
|
||||
nextPosition.y += speed.y * delayLeft.GetSeconds ();
|
||||
m_event.Cancel ();
|
||||
|
||||
// check if the nextPosition is inside a building, or if the line
|
||||
// from position to the next position intersects a building
|
||||
auto outdoorBuilding = IsLineClearOfBuildings (position, nextPosition);
|
||||
bool outdoor = std::get<0> (outdoorBuilding);
|
||||
Ptr<Building> building = std::get<1> (outdoorBuilding);
|
||||
|
||||
if (m_bounds.IsInside (nextPosition))
|
||||
{
|
||||
if (outdoor)
|
||||
{
|
||||
m_event = Simulator::Schedule (delayLeft, &RandomWalk2dOutdoorMobilityModel::DoInitializePrivate, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("NextPosition would lead into a building");
|
||||
nextPosition = CalculateIntersectionFromOutside (position, nextPosition, building->GetBoundaries ());
|
||||
Time delay = Seconds ((nextPosition.x - position.x) / speed.x);
|
||||
m_event = Simulator::Schedule (delay, &RandomWalk2dOutdoorMobilityModel::AvoidBuilding, this,
|
||||
delayLeft - delay,
|
||||
nextPosition
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("Out of bounding box");
|
||||
nextPosition = m_bounds.CalculateIntersection (position, speed);
|
||||
// check that this nextPosition is outdoor
|
||||
auto outdoorBuilding = IsLineClearOfBuildings (position, nextPosition);
|
||||
bool outdoor = std::get<0> (outdoorBuilding);
|
||||
Ptr<Building> building = std::get<1> (outdoorBuilding);
|
||||
|
||||
if (outdoor)
|
||||
{
|
||||
Time delay = Seconds ((nextPosition.x - position.x) / speed.x);
|
||||
m_event = Simulator::Schedule (delay, &RandomWalk2dOutdoorMobilityModel::Rebound, this,
|
||||
delayLeft - delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("NextPosition would lead into a building");
|
||||
nextPosition = CalculateIntersectionFromOutside (position, nextPosition, building->GetBoundaries ());
|
||||
Time delay = Seconds ((nextPosition.x - position.x) / speed.x);
|
||||
m_event = Simulator::Schedule (delay, &RandomWalk2dOutdoorMobilityModel::AvoidBuilding, this,
|
||||
delayLeft - delay,
|
||||
nextPosition
|
||||
);
|
||||
}
|
||||
}
|
||||
NS_LOG_LOGIC ("Position " << position << " NextPosition " << nextPosition);
|
||||
|
||||
// store the previous position
|
||||
m_prevPosition = position;
|
||||
NotifyCourseChange ();
|
||||
}
|
||||
|
||||
std::pair<bool, Ptr<Building> >
|
||||
RandomWalk2dOutdoorMobilityModel::IsLineClearOfBuildings ( Vector currentPosition, Vector nextPosition ) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << currentPosition << nextPosition);
|
||||
|
||||
bool intersectBuilding = false;
|
||||
double minIntersectionDistance = std::numeric_limits<double>::max ();
|
||||
Ptr<Building> minIntersectionDistanceBuilding;
|
||||
|
||||
for (BuildingList::Iterator bit = BuildingList::Begin (); bit != BuildingList::End (); ++bit)
|
||||
{
|
||||
// check if this building intersects the line between the current and next positions
|
||||
// this checks also if the next position is inside the building
|
||||
if ((*bit)->IsIntersect (currentPosition, nextPosition))
|
||||
{
|
||||
NS_LOG_LOGIC ("Building " << (*bit)->GetBoundaries ()
|
||||
<< " intersects the line between " << currentPosition
|
||||
<< " and " << nextPosition);
|
||||
auto intersection = CalculateIntersectionFromOutside (
|
||||
currentPosition, nextPosition, (*bit)->GetBoundaries ());
|
||||
double distance = CalculateDistance (intersection, currentPosition);
|
||||
intersectBuilding = true;
|
||||
if (distance < minIntersectionDistance)
|
||||
{
|
||||
minIntersectionDistance = distance;
|
||||
minIntersectionDistanceBuilding = (*bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair (!intersectBuilding, minIntersectionDistanceBuilding);
|
||||
}
|
||||
|
||||
Vector
|
||||
RandomWalk2dOutdoorMobilityModel::CalculateIntersectionFromOutside (const Vector ¤t, const Vector &next, Box boundaries) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << " current " << current << " next " << next);
|
||||
bool inside = boundaries.IsInside (current);
|
||||
NS_ASSERT (!inside);
|
||||
|
||||
// get the closest side
|
||||
Rectangle rect = Rectangle (boundaries.xMin, boundaries.xMax, boundaries.yMin, boundaries.yMax);
|
||||
NS_LOG_INFO ("rect " << rect);
|
||||
Rectangle::Side closestSide = rect.GetClosestSide (current);
|
||||
|
||||
double xIntersect = 0;
|
||||
double yIntersect = 0;
|
||||
|
||||
switch (closestSide)
|
||||
{
|
||||
case Rectangle::RIGHT:
|
||||
NS_LOG_INFO ("The closest side is RIGHT");
|
||||
NS_ABORT_MSG_IF (next.x - current.x == 0, "x position not updated");
|
||||
xIntersect = boundaries.xMax + m_epsilon;
|
||||
yIntersect =
|
||||
(next.y - current.y) / (next.x - current.x) * (xIntersect - current.x) + current.y;
|
||||
break;
|
||||
case Rectangle::LEFT:
|
||||
NS_LOG_INFO ("The closest side is LEFT");
|
||||
xIntersect = boundaries.xMin - m_epsilon;
|
||||
NS_ABORT_MSG_IF (next.x - current.x == 0, "x position not updated");
|
||||
yIntersect =
|
||||
(next.y - current.y) / (next.x - current.x) * (xIntersect - current.x) + current.y;
|
||||
break;
|
||||
case Rectangle::TOP:
|
||||
NS_LOG_INFO ("The closest side is TOP");
|
||||
yIntersect = boundaries.yMax + m_epsilon;
|
||||
NS_ABORT_MSG_IF (next.y - current.y == 0, "y position not updated");
|
||||
xIntersect =
|
||||
(next.x - current.x) / (next.y - current.y) * (yIntersect - current.y) + current.x;
|
||||
break;
|
||||
case Rectangle::BOTTOM:
|
||||
NS_LOG_INFO ("The closest side is BOTTOM");
|
||||
yIntersect = boundaries.yMin - m_epsilon;
|
||||
NS_ABORT_MSG_IF (next.y - current.y == 0, "y position not updated");
|
||||
xIntersect =
|
||||
(next.x - current.x) / (next.y - current.y) * (yIntersect - current.y) + current.x;
|
||||
break;
|
||||
}
|
||||
NS_LOG_INFO ("xIntersect " << xIntersect << " yIntersect " << yIntersect);
|
||||
return Vector (xIntersect, yIntersect, 0);
|
||||
}
|
||||
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::Rebound (Time delayLeft)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << delayLeft.GetSeconds ());
|
||||
m_helper.UpdateWithBounds (m_bounds);
|
||||
Vector position = m_helper.GetCurrentPosition ();
|
||||
Vector speed = m_helper.GetVelocity ();
|
||||
switch (m_bounds.GetClosestSide (position))
|
||||
{
|
||||
case Rectangle::RIGHT:
|
||||
NS_LOG_INFO ("The closest side is RIGHT");
|
||||
case Rectangle::LEFT:
|
||||
NS_LOG_INFO ("The closest side is LEFT");
|
||||
speed.x = -speed.x;
|
||||
break;
|
||||
case Rectangle::TOP:
|
||||
NS_LOG_INFO ("The closest side is TOP");
|
||||
case Rectangle::BOTTOM:
|
||||
NS_LOG_INFO ("The closest side is BOTTOM");
|
||||
speed.y = -speed.y;
|
||||
break;
|
||||
}
|
||||
m_helper.SetVelocity (speed);
|
||||
m_helper.Unpause ();
|
||||
DoWalk (delayLeft);
|
||||
}
|
||||
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::AvoidBuilding (Time delayLeft, Vector intersectPosition)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << delayLeft.GetSeconds ());
|
||||
m_helper.Update ();
|
||||
|
||||
bool nextWouldBeInside = true;
|
||||
uint32_t iter = 0;
|
||||
|
||||
while (nextWouldBeInside && iter < m_maxIter)
|
||||
{
|
||||
NS_LOG_INFO ("The next position would be inside a building, compute an alternative");
|
||||
iter++;
|
||||
double speed = m_speed->GetValue ();
|
||||
double direction = m_direction->GetValue ();
|
||||
Vector velocityVector (std::cos (direction) * speed,
|
||||
std::sin (direction) * speed,
|
||||
0.0);
|
||||
m_helper.SetVelocity (velocityVector);
|
||||
|
||||
Vector nextPosition = intersectPosition;
|
||||
nextPosition.x += velocityVector.x * delayLeft.GetSeconds ();
|
||||
nextPosition.y += velocityVector.y * delayLeft.GetSeconds ();
|
||||
|
||||
// check if this is inside the current buildingBox
|
||||
auto outdoorBuilding = IsLineClearOfBuildings (intersectPosition, nextPosition);
|
||||
bool outdoor = std::get<0> (outdoorBuilding);
|
||||
|
||||
if (!outdoor)
|
||||
{
|
||||
NS_LOG_LOGIC ("inside loop intersect " << intersectPosition << " nextPosition "
|
||||
<< nextPosition << " " << outdoor << " building " << std::get<1> (outdoorBuilding)->GetBoundaries ());
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("inside loop intersect " << intersectPosition << " nextPosition "
|
||||
<< nextPosition << " " << outdoor);
|
||||
}
|
||||
|
||||
if (outdoor && m_bounds.IsInside (nextPosition))
|
||||
{
|
||||
nextWouldBeInside = false;
|
||||
}
|
||||
}
|
||||
|
||||
// after m_maxIter iterations, the positions tested are all inside
|
||||
// to avoid increasing m_maxIter too much, it is possible to perform a step back
|
||||
// to the previous position and continue from there
|
||||
if (iter >= m_maxIter)
|
||||
{
|
||||
NS_LOG_INFO ("Move back to the previous position");
|
||||
|
||||
// compute the difference between the previous position and the intersection
|
||||
Vector posDiff = m_prevPosition - intersectPosition;
|
||||
// compute the distance
|
||||
double distance = CalculateDistance (m_prevPosition, intersectPosition);
|
||||
double speed = distance / delayLeft.GetSeconds (); // compute the speed
|
||||
|
||||
NS_LOG_LOGIC ("prev " << m_prevPosition
|
||||
<< " intersectPosition " << intersectPosition
|
||||
<< " diff " << posDiff << " dist " << distance
|
||||
);
|
||||
|
||||
Vector velocityVector (posDiff.x / distance * speed,
|
||||
posDiff.y / distance * speed,
|
||||
0.0);
|
||||
m_helper.SetVelocity (velocityVector);
|
||||
|
||||
Vector nextPosition = intersectPosition;
|
||||
nextPosition.x += velocityVector.x * delayLeft.GetSeconds ();
|
||||
nextPosition.y += velocityVector.y * delayLeft.GetSeconds ();
|
||||
|
||||
// check if the path is clear
|
||||
auto outdoorBuilding = IsLineClearOfBuildings (intersectPosition, nextPosition);
|
||||
bool outdoor = std::get<0> (outdoorBuilding);
|
||||
if (!outdoor)
|
||||
{
|
||||
NS_LOG_LOGIC ("The position is still inside after "
|
||||
<< m_maxIter + 1 << " iterations, loop intersect "
|
||||
<< intersectPosition << " nextPosition "
|
||||
<< nextPosition << " " << outdoor
|
||||
<< " building " << std::get<1> (outdoorBuilding)->GetBoundaries ());
|
||||
// This error may be due to buildings being attached to one another, or to the boundary of the scenario.
|
||||
NS_FATAL_ERROR ("Not able to find an outdoor position. Try to increase the attribute MaxIterations and check the position of the buildings in the scenario.");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("inside loop intersect " << intersectPosition << " nextPosition "
|
||||
<< nextPosition << " " << outdoor);
|
||||
}
|
||||
}
|
||||
|
||||
m_helper.Unpause ();
|
||||
|
||||
DoWalk (delayLeft);
|
||||
}
|
||||
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::DoDispose (void)
|
||||
{
|
||||
// chain up
|
||||
MobilityModel::DoDispose ();
|
||||
}
|
||||
Vector
|
||||
RandomWalk2dOutdoorMobilityModel::DoGetPosition (void) const
|
||||
{
|
||||
m_helper.UpdateWithBounds (m_bounds);
|
||||
return m_helper.GetCurrentPosition ();
|
||||
}
|
||||
void
|
||||
RandomWalk2dOutdoorMobilityModel::DoSetPosition (const Vector &position)
|
||||
{
|
||||
NS_ASSERT (m_bounds.IsInside (position));
|
||||
m_helper.SetPosition (position);
|
||||
Simulator::Remove (m_event);
|
||||
m_event = Simulator::ScheduleNow (&RandomWalk2dOutdoorMobilityModel::DoInitializePrivate, this);
|
||||
}
|
||||
Vector
|
||||
RandomWalk2dOutdoorMobilityModel::DoGetVelocity (void) const
|
||||
{
|
||||
return m_helper.GetVelocity ();
|
||||
}
|
||||
int64_t
|
||||
RandomWalk2dOutdoorMobilityModel::DoAssignStreams (int64_t stream)
|
||||
{
|
||||
m_speed->SetStream (stream);
|
||||
m_direction->SetStream (stream + 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
135
src/buildings/model/random-walk-2d-outdoor-mobility-model.h
Normal file
135
src/buildings/model/random-walk-2d-outdoor-mobility-model.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2006,2007 INRIA
|
||||
* Copyright (c) 2019 University of Padova
|
||||
*
|
||||
* 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>
|
||||
* Author: Michele Polese <michele.polese@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef RANDOM_WALK_2D_OUTDOOR_MOBILITY_MODEL_H
|
||||
#define RANDOM_WALK_2D_OUTDOOR_MOBILITY_MODEL_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/rectangle.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/constant-velocity-helper.h"
|
||||
#include "ns3/building.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup mobility
|
||||
* \brief 2D random walk mobility model which avoids buildings.
|
||||
*
|
||||
* This class reuses most of the code of RandomWalk2dMobilityModel,
|
||||
* but adds the awareness of buildings objects which are avoided
|
||||
* by moving users.
|
||||
* Each instance moves with a speed and direction chosen at random
|
||||
* with the user-provided random variables until
|
||||
* either a fixed distance has been walked or until a fixed amount
|
||||
* of time. If we hit one of the boundaries (specified by a rectangle)
|
||||
* of the model, we rebound on the boundary with a reflexive angle
|
||||
* and speed. If we hit one of the buildings, we rebound with a random
|
||||
* direction which makes sure that the next step does not enter the building.
|
||||
*
|
||||
* The default values for the random variable that describes the speed is
|
||||
* taken from Figure 1 in the paper:
|
||||
* Henderson, L.F., 1971. The statistics of crowd fluids. nature, 229(5284), p.381.
|
||||
*/
|
||||
class RandomWalk2dOutdoorMobilityModel : public MobilityModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Register this type with the TypeId system.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
/** An enum representing the different working modes of this module. */
|
||||
enum Mode
|
||||
{
|
||||
MODE_DISTANCE,
|
||||
MODE_TIME
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Performs the rebound of the node if it reaches a boundary
|
||||
* \param timeLeft The remaining time of the walk
|
||||
*/
|
||||
void Rebound (Time timeLeft);
|
||||
/**
|
||||
* \brief Avoid a building
|
||||
* \param timeLeft The remaining time of the walk
|
||||
* \param intersectPosition The position at which the building is intersected
|
||||
*/
|
||||
void AvoidBuilding (Time delayLeft, Vector intersectPosition);
|
||||
/**
|
||||
* Walk according to position and velocity, until distance is reached,
|
||||
* time is reached, or intersection with the bounding box, or building
|
||||
*/
|
||||
void DoWalk (Time timeLeft);
|
||||
/**
|
||||
* Perform initialization of the object before MobilityModel::DoInitialize ()
|
||||
*/
|
||||
void DoInitializePrivate (void);
|
||||
/**
|
||||
* Check if there is a building between two positions (or if the nextPosition is inside a building).
|
||||
* The code is taken from MmWave3gppBuildingsPropagationLossModel from the NYU/UNIPD ns-3 mmWave module
|
||||
* \param currentPosition The current position of the node
|
||||
* \param nextPosition The position to check
|
||||
* \return a pair with a boolean (true if the line between the two position does not intersect building),
|
||||
* and a pointer which is 0 if the boolean is true, or it points to the building which is intersected
|
||||
*/
|
||||
std::pair<bool, Ptr<Building> > IsLineClearOfBuildings (Vector currentPosition, Vector nextPosition ) const;
|
||||
/**
|
||||
* Compute the intersecting point of the box represented by boundaries and the line between current and next
|
||||
* Notice that we only consider a 2d plane
|
||||
* \param current The current position
|
||||
* \param next The next position
|
||||
* \param boundaries The boundaries of the building we will intersect
|
||||
* \return a vector with the position of the intersection
|
||||
*/
|
||||
Vector CalculateIntersectionFromOutside (const Vector ¤t, const Vector &next, const Box boundaries) const;
|
||||
|
||||
virtual void DoDispose (void);
|
||||
virtual void DoInitialize (void);
|
||||
virtual Vector DoGetPosition (void) const;
|
||||
virtual void DoSetPosition (const Vector &position);
|
||||
virtual Vector DoGetVelocity (void) const;
|
||||
virtual int64_t DoAssignStreams (int64_t);
|
||||
|
||||
ConstantVelocityHelper m_helper; //!< helper for this object
|
||||
EventId m_event; //!< stored event ID
|
||||
enum Mode m_mode; //!< whether in time or distance mode
|
||||
double m_modeDistance; //!< Change direction and speed after this distance
|
||||
Time m_modeTime; //!< Change current direction and speed after this delay
|
||||
Ptr<RandomVariableStream> m_speed; //!< rv for picking speed
|
||||
Ptr<RandomVariableStream> m_direction; //!< rv for picking direction
|
||||
Rectangle m_bounds; //!< Bounds of the area to cruise
|
||||
double m_epsilon; //!< Tolerance for the intersection point with buildings
|
||||
uint32_t m_maxIter; //!< Maximum number of tries to find the next position
|
||||
Vector m_prevPosition; //!< Store the previous position in case a step back is needed
|
||||
};
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* RANDOM_WALK_2D_OUTDOOR_MOBILITY_MODEL_H */
|
||||
167
src/buildings/test/outdoor-random-walk-test.cc
Normal file
167
src/buildings/test/outdoor-random-walk-test.cc
Normal file
@@ -0,0 +1,167 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/building.h"
|
||||
#include "ns3/building-position-allocator.h"
|
||||
#include "ns3/random-walk-2d-outdoor-mobility-model.h"
|
||||
#include "ns3/mobility-helper.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/pointer.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("OutdoorRandomWalkTest");
|
||||
|
||||
/**
|
||||
* Test case for the class OutdoorRandomWalkTestCase. It checks if the
|
||||
* positions visited by the user are outside buildings
|
||||
*/
|
||||
class OutdoorRandomWalkTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
OutdoorRandomWalkTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~OutdoorRandomWalkTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Builds the simulation scenario and perform the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
void CheckPositionOutdoor (Ptr<RandomWalk2dOutdoorMobilityModel> model);
|
||||
|
||||
std::vector<Ptr<Building> > m_buildings;
|
||||
};
|
||||
|
||||
OutdoorRandomWalkTestCase::OutdoorRandomWalkTestCase ()
|
||||
: TestCase ("Test case for the BuildingsChannelConditionModel"), m_buildings ()
|
||||
{}
|
||||
|
||||
OutdoorRandomWalkTestCase::~OutdoorRandomWalkTestCase ()
|
||||
{}
|
||||
|
||||
void
|
||||
OutdoorRandomWalkTestCase::CheckPositionOutdoor (Ptr<RandomWalk2dOutdoorMobilityModel> model)
|
||||
{
|
||||
auto position = model->GetPosition ();
|
||||
for (auto building : m_buildings)
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ (building->IsInside (position), false, "Position " << position << " is inside");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutdoorRandomWalkTestCase::DoRun (void)
|
||||
{
|
||||
// create a grid of buildings
|
||||
double buildingSizeX = 100; // m
|
||||
double buildingSizeY = 50; // m
|
||||
double streetWidth = 25; // m
|
||||
double buildingHeight = 10; // m
|
||||
uint32_t numBuildingsX = 20;
|
||||
uint32_t numBuildingsY = 20;
|
||||
double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
|
||||
double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
|
||||
|
||||
for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
|
||||
{
|
||||
for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
|
||||
{
|
||||
Ptr < Building > building;
|
||||
building = CreateObject<Building> ();
|
||||
|
||||
building->SetBoundaries (Box (buildingIdX * (buildingSizeX + streetWidth),
|
||||
buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
|
||||
buildingIdY * (buildingSizeY + streetWidth),
|
||||
buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
|
||||
0.0, buildingHeight));
|
||||
building->SetNRoomsX (1);
|
||||
building->SetNRoomsY (1);
|
||||
building->SetNFloors (1);
|
||||
m_buildings.push_back (building);
|
||||
}
|
||||
}
|
||||
|
||||
// create one node
|
||||
NodeContainer nodes;
|
||||
nodes.Create (1);
|
||||
|
||||
// set the RandomWalk2dOutdoorMobilityModel mobility model
|
||||
MobilityHelper mobility;
|
||||
mobility.SetMobilityModel ("ns3::RandomWalk2dOutdoorMobilityModel",
|
||||
"Bounds", RectangleValue (
|
||||
Rectangle (-streetWidth, maxAxisX, -streetWidth, maxAxisY)));
|
||||
// create an OutdoorPositionAllocator and set its boundaries to match those of the mobility model
|
||||
Ptr<OutdoorPositionAllocator> position = CreateObject<OutdoorPositionAllocator> ();
|
||||
Ptr<UniformRandomVariable> xPos = CreateObject<UniformRandomVariable>();
|
||||
xPos->SetAttribute ("Min", DoubleValue (-streetWidth));
|
||||
xPos->SetAttribute ("Max", DoubleValue (maxAxisX));
|
||||
Ptr<UniformRandomVariable> yPos = CreateObject<UniformRandomVariable>();
|
||||
yPos->SetAttribute ("Min", DoubleValue (-streetWidth));
|
||||
yPos->SetAttribute ("Max", DoubleValue (maxAxisY));
|
||||
position->SetAttribute ("X", PointerValue (xPos));
|
||||
position->SetAttribute ("Y", PointerValue (yPos));
|
||||
mobility.SetPositionAllocator (position);
|
||||
// install the mobility model
|
||||
mobility.Install (nodes.Get (0));
|
||||
|
||||
auto mobilityModel = nodes.Get (0)->GetObject<RandomWalk2dOutdoorMobilityModel>();
|
||||
|
||||
// get maxChecks positions, check if they are outdoors
|
||||
double testStep = 10; // s
|
||||
int maxChecks = 1000;
|
||||
for (int i = 0; i < maxChecks; ++i)
|
||||
{
|
||||
Simulator::Schedule (Seconds (i * testStep),
|
||||
&OutdoorRandomWalkTestCase::CheckPositionOutdoor, this, mobilityModel);
|
||||
}
|
||||
|
||||
Simulator::Stop (Seconds (maxChecks * testStep + 1));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suite for the buildings channel condition model
|
||||
*/
|
||||
class OutdoorRandomWalkTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
OutdoorRandomWalkTestSuite ();
|
||||
};
|
||||
|
||||
OutdoorRandomWalkTestSuite::OutdoorRandomWalkTestSuite ()
|
||||
: TestSuite ("outdoor-random-walk-model", UNIT)
|
||||
{
|
||||
AddTestCase (new OutdoorRandomWalkTestCase, TestCase::QUICK);
|
||||
}
|
||||
|
||||
static OutdoorRandomWalkTestSuite OutdoorRandomWalkTestSuite;
|
||||
@@ -16,6 +16,7 @@ def build(bld):
|
||||
'helper/building-position-allocator.cc',
|
||||
'helper/building-allocator.cc',
|
||||
'helper/buildings-helper.cc',
|
||||
'model/random-walk-2d-outdoor-mobility-model.cc',
|
||||
]
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('buildings')
|
||||
@@ -25,6 +26,7 @@ def build(bld):
|
||||
'test/buildings-pathloss-test.cc',
|
||||
'test/buildings-shadowing-test.cc',
|
||||
'test/buildings-channel-condition-model-test.cc',
|
||||
'test/outdoor-random-walk-test.cc',
|
||||
]
|
||||
|
||||
# Tests encapsulating example programs should be listed here
|
||||
@@ -48,6 +50,7 @@ def build(bld):
|
||||
'helper/building-allocator.h',
|
||||
'helper/building-position-allocator.h',
|
||||
'helper/buildings-helper.h',
|
||||
'model/random-walk-2d-outdoor-mobility-model.h',
|
||||
]
|
||||
|
||||
if (bld.env['ENABLE_EXAMPLES']):
|
||||
|
||||
Reference in New Issue
Block a user