diff --git a/src/mobility/examples/reference-point-group-mobility-animate.sh b/src/mobility/examples/reference-point-group-mobility-animate.sh new file mode 100755 index 000000000..0fee3a25f --- /dev/null +++ b/src/mobility/examples/reference-point-group-mobility-animate.sh @@ -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 +# Tom Henderson + +# +# 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 < + * + * 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 +#include "ns3/core-module.h" +#include +#include "ns3/network-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("ReferencePointGroupMobilityExample"); + +std::ofstream g_timeSeries; + +void +PrintPosition (Ptr node) +{ + if (node == nullptr) return; + Ptr model = node->GetObject (); + 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 waypointMm = CreateObject (); + 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 hierarchical0 = CreateObject (); + 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 childRandomWalk0 = CreateObject (); + // 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 hierarchical1 = CreateObject (); + hierarchical1->SetParent (waypointMm); // Same parent as before + Ptr childRandomWalk1 = CreateObject (); + 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 hierarchical2 = CreateObject (); + hierarchical2->SetParent (waypointMm); // Same parent as before + Ptr childRandomWalk2 = CreateObject (); + 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 (); +} diff --git a/src/mobility/examples/wscript b/src/mobility/examples/wscript index 9ee60ff9b..284e46e87 100644 --- a/src/mobility/examples/wscript +++ b/src/mobility/examples/wscript @@ -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'