mobility: Add Reference Point Group Mobility (RPGM) example and script

This commit is contained in:
Tom Henderson
2021-03-09 20:23:27 -08:00
parent 2422b35238
commit 4fb672de9f
3 changed files with 262 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
#!/bin/bash
# Copyright (c) 2019, University of Padova, Dep. of Information Engineering, SIGNET lab
# Copyright (c) 2021, University of Washington: animation extensions
#
# 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
#
# Authors: Michele Polese <michele.polese@gmail.com>
# Tom Henderson <tomhend@uw.edu>
#
# Plot the trace generated by reference-point-group-mobility-example.cc
# in a manner that enables animation
#
# This Bash script is a variant of outdoor-random-walk-example.sh that
# generates a large number of PNG image files, one for each node position
# traced in the mobility trace file 'reference-point-time-series.mob'.
#
# This script relies on gnuplot (version 5.0 or greater).
#
# The PNGs are named in increasing numerical order from '0000.png' to
# '0799.png'. The images can be assembled into an animated gif file
# using a tool such as ImageMagick's convert utility, such as:
#
# $ convert -delay 10 -loop 0 *.png rpgm-animation.gif
#
# and the output file 'rpgm-animation.gif' can be viewed by an image viewer.
#
# Because this file generates many PNG files, it is recommended to move
# this script and the generated time-series mobility file
# named 'reference-point-time-series.mob' to a subdirectory, and then
# run:
# $ ./reference-point-group-mobility-animation.sh
# $ convert -delay 10 -loop 0 *.png rpgm-animation.gif
#
# The script first checks and enforces that only three nodes are present
num_nodes=`cat reference-point-time-series.mob | awk '{ print $2 }' | sort -n | uniq | wc -l`
if [ "$num_nodes" -ne "3" ]; then
echo "Exiting: this tracing program designed only for 3 nodes"
exit 1
fi
# Next, reduce the trace
cat reference-point-time-series.mob | awk -F " " '{ print $3 }' | awk -F ":" '{ print $1" "$2 }' > rpgm-time-series.tmp
# read three lines at a time from the reduced trace, convert to
# a plottable temporary file, and invoke gnuplot. Loop until done.
n=0
while read p1 && read p2 && read p3; do
basename=$(printf "%04d" "$n")
cat >plotcmds <<EOL
# If you do not have pngcairo installed, you can 'set terminal png' below,
# but it will render the dashed bounding box as a solid line
set terminal pngcairo dashed
set output '$basename.png'
set view map
set xlabel 'X [m]'
set ylabel 'Y [m]'
set xrange [-10:110]
set yrange [-10:60]
set style fill transparent solid 0.5
unset key
set style fill transparent solid 0.35 noborder
set style circle radius 0.5
# Define dashed lines to mark the outer bounding box
set arrow from 0,0 to 100,0 nohead dt "-" lc rgb "light-grey"
set arrow from 100,0 to 100,50 nohead dt "-" lc rgb "light-grey"
set arrow from 0,50 to 100,50 nohead dt "-" lc rgb "light-grey"
set arrow from 0,0 to 0,50 nohead dt "-" lc rgb "light-grey"
plot "<echo '$p1'" with circles lc rgb "red",\
"<echo '$p2'" with circles lc rgb "blue",\
"<echo '$p3'" with circles lc rgb "black"
EOL
gnuplot plotcmds
rm plotcmds
(( n++ ))
done < rpgm-time-series.tmp
rm rpgm-time-series.tmp

View File

@@ -0,0 +1,169 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2020 Institute for the Wireless Internet of Things, Northeastern University, Boston, MA
*
* 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>
*
* Heavily edited by Tom Henderson (for proof-of-concept purposes)
* - Reduced from src/mobility/examples/group-mobility-example.cc
*/
/**
* This example shows how to use the ns3::HierarchicalMobilityModel
* to construct a Reference Point Group Mobility model (RPGM) model
* as described in "A survey of mobility models for ad hoc network
* research" by Tracy Camp, Jeff Boleng, and Vanessa Davies, Wireless
* Communications and Mobile Computing, 2002: vol. 2, pp. 2483-502.
*
* The HierarchicalMobilityModel is composed of two mobility models;
* a parent and a child. The position of the child is expressed
* in reference to the position of the parent. For group mobility,
* each node in the group can install the same parent mobility model
* and different child mobility models.
*
* Standard ns-3 mobility model course change output is traced in
* 'reference-point-course-change.mob' file. This file only traces
* position when there is a course change. A second trace is produced,
* which is a time-series of node positions sampled every second.
* This file is 'reference-point-time-series.mob' and can be plotted
* with the 'reference-point-group-mobility-animation.sh' program.
*
* There is a bit of randomness in the child mobility models (random
* walk within a 10m x 10m box surrounding the parent mobility position);
* slightly different output can be rendered by changing the ns-3 random
* number 'run number' global value.
*/
#include <iostream>
#include "ns3/core-module.h"
#include <ns3/mobility-module.h>
#include "ns3/network-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("ReferencePointGroupMobilityExample");
std::ofstream g_timeSeries;
void
PrintPosition (Ptr<Node> node)
{
if (node == nullptr) return;
Ptr<MobilityModel> model = node->GetObject<MobilityModel> ();
if (model == nullptr) return;
NS_LOG_LOGIC ("Node: " << node->GetId () << " Position: " << model->GetPosition ());
g_timeSeries << Simulator::Now ().GetSeconds () << " " << node->GetId () << " " << model->GetPosition () << std::endl;
}
int
main (int argc, char *argv[])
{
Time simTime = Seconds (800);
uint32_t numPrints = 800;
CommandLine cmd (__FILE__);
cmd.Parse (argc, argv);
g_timeSeries.open ("reference-point-time-series.mob");
NodeContainer n;
n.Create (3);
// The primary mobility model is the WaypointMobilityModel defined within
// this bounding box:
//
// (0,50) (100,50)
// +-------------------------+
// | .(10,40) (90,40). |
// | |
// | |
// | .(10,10) (90,10). |
// | |
// +-------------------------+
// (0,0) (100,0)
//
// The reference (parent) mobility model starts at coordinate (10,10
// and walks clockwise to each waypoint, making two laps. The time
// to travel between each waypoint is 100s, so the velocity alternates
// between two values due to the rectangular path.
// No actual node is represented by the position of this mobility
// model; it forms the reference point from which the node's child
// mobility model position is offset.
//
Ptr<WaypointMobilityModel> waypointMm = CreateObject<WaypointMobilityModel> ();
waypointMm->AddWaypoint (Waypoint (Seconds (0), Vector (10, 10, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (100), Vector (10, 40, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (200), Vector (90, 40, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (300), Vector (90, 10, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (400), Vector (10, 10, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (500), Vector (10, 40, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (600), Vector (90, 40, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (700), Vector (90, 10, 0)));
waypointMm->AddWaypoint (Waypoint (Seconds (800), Vector (10, 10, 0)));
// Each HierachicalMobilityModel contains the above model as the Parent,
// and a user defined model as the Child. Two MobilityModel objects are
// instantiated per node (one hierarchical, and one child model), and
// a single parent model is reused across all nodes.
// Mobility model for the first node (node 0)
Ptr<HierarchicalMobilityModel> hierarchical0 = CreateObject<HierarchicalMobilityModel> ();
hierarchical0->SetParent (waypointMm);
// Child Mobility model for the first node (node 0). This can be any
// other mobility model type; for this example, we reuse the random walk
// but with a small 10m x 10m bounding box.
Ptr<RandomWalk2dMobilityModel> childRandomWalk0 = CreateObject<RandomWalk2dMobilityModel> ();
// Position in reference to the original random walk
childRandomWalk0->SetAttribute ("Bounds", RectangleValue (Rectangle (-5, 5, -5, 5)));
childRandomWalk0->SetAttribute ("Speed", StringValue ("ns3::ConstantRandomVariable[Constant=0.1]"));
hierarchical0->SetChild (childRandomWalk0);
n.Get (0)->AggregateObject (hierarchical0);
// Repeat for other two nodes
Ptr<HierarchicalMobilityModel> hierarchical1 = CreateObject<HierarchicalMobilityModel> ();
hierarchical1->SetParent (waypointMm); // Same parent as before
Ptr<RandomWalk2dMobilityModel> childRandomWalk1 = CreateObject<RandomWalk2dMobilityModel> ();
childRandomWalk1->SetAttribute ("Bounds", RectangleValue (Rectangle (-5, 5, -5, 5)));
childRandomWalk1->SetAttribute ("Speed", StringValue ("ns3::ConstantRandomVariable[Constant=0.1]"));
hierarchical1->SetChild (childRandomWalk1);
n.Get (1)->AggregateObject (hierarchical1);
Ptr<HierarchicalMobilityModel> hierarchical2 = CreateObject<HierarchicalMobilityModel> ();
hierarchical2->SetParent (waypointMm); // Same parent as before
Ptr<RandomWalk2dMobilityModel> childRandomWalk2 = CreateObject<RandomWalk2dMobilityModel> ();
childRandomWalk2->SetAttribute ("Bounds", RectangleValue (Rectangle (-5, 5, -5, 5)));
childRandomWalk2->SetAttribute ("Speed", StringValue ("ns3::ConstantRandomVariable[Constant=0.1]"));
hierarchical2->SetChild (childRandomWalk2);
n.Get (2)->AggregateObject (hierarchical2);
AsciiTraceHelper ascii;
MobilityHelper::EnableAsciiAll (ascii.CreateFileStream ("reference-point-course-change.mob"));
// Use a logging PrintPosition() to record time-series position
for (unsigned int i = 0; i < numPrints; i++)
{
for (auto nodeIt = n.Begin (); nodeIt != n.End (); ++nodeIt)
{
Simulator::Schedule (NanoSeconds (i * simTime.GetNanoSeconds () / numPrints), &PrintPosition, (*nodeIt));
}
}
Simulator::Stop (simTime);
Simulator::Run ();
g_timeSeries.close ();
Simulator::Destroy ();
}

View File

@@ -27,3 +27,7 @@ def build(bld):
obj = bld.create_ns3_program('bonnmotion-ns2-example',
['core', 'mobility'])
obj.source = 'bonnmotion-ns2-example.cc'
obj = bld.create_ns3_program('reference-point-group-mobility-example',
['core', 'network', 'mobility'])
obj.source = 'reference-point-group-mobility-example.cc'