--- a/src/auv/doc/auv.h +++ a/src/auv/doc/auv.h @@ -0,0 +1,27 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * 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 + * + */ + +#ifndef AUV_H +#define AUV_H + +/** + * \defgroup auv Autonomous Underwater Vehicle + * + * This section documents the API of the ns-3 AUV module. For a generic functional description, please refer to the ns-3 manual. + */ + +#endif /* AUV_H */ --- a/src/auv/doc/auv.rst +++ a/src/auv/doc/auv.rst @@ -0,0 +1,10 @@ +An autonomous underwater vehicle (AUV) is a robot which travels underwater +without requiring input from an operator. + +The NS-3 AUV module simulates the below AUVs: + +Seaglider +REMUS 100 +SAUV II + + --- a/src/auv/examples/auv-energy-model.cc +++ a/src/auv/examples/auv-energy-model.cc @@ -0,0 +1,111 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "ns3/glider-energy-model.h" + +using namespace ns3; + +/** + * In this example we show the basic usage of an AUV energy model. + * Specifically, we show how to create a generic node, adding to it a + * basic energy source and consuming energy from the energy source. + * + * The Seaglider AUV power consumption depends on buoyancy and vertical + * speed values, so we simulate a 20 seconds movement at 0.3 m/s of vertical + * speed and 138g of buoyancy. Then a 20 seconds movement at 0.2 m/s + * of vertical speed and 138g of buoyancy and then a stop of 5 seconds. + * + * The required energy will be drained by the model basing on the + * given buoyancy/speed values, from the energy source installed onto + * the node. + * + * We register a callback to the TotalEnergyConsumption traced value. + */ + +void +DoubleTrace (double oldValue, double newValue) +{ + std::cout << "Energy changed from " << oldValue << "J to " << newValue << "J" << std::endl; +} + +int +main (int argc, char **argv) +{ + // uncomment to see energy consumption details + // LogComponentEnable ("GliderEnergyModel", LOG_LEVEL_ALL); + + // create node + Ptr node = CreateObject (); + + // create energy source + ObjectFactory m_energySource; + m_energySource.SetTypeId ("ns3::BasicEnergySource"); + m_energySource.Set ("BasicEnergySourceInitialEnergyJ", + DoubleValue (10000000)); + Ptr source = m_energySource.Create (); + source->SetNode (node); + Ptr sourceCont = CreateObject (); + sourceCont->Add (source); + // aggregate energy source to node + node->AggregateObject (sourceCont); + + // create device energy model + Ptr model = CreateObject (); + // set energy source pointer + model->SetEnergySource (source); + model->SetNode (node); + // add device energy model to model list in energy source + source->AppendDeviceEnergyModel (model); + // register a callback to the total consumption value + model->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeCallback (&DoubleTrace)); + + // retrieve device energy model from energy source + DeviceEnergyModelContainer modelCont = + source->FindDeviceEnergyModels ("ns3::GliderEnergyModel"); + NS_ASSERT (modelCont.GetN () != 0); + // get pointer + Ptr devModel = DynamicCast (modelCont.Get (0)); + + // simulate 20 seconds of movement with 138g buoyancy and 0.3 m/s of W + devModel->ChangeEnergyConsumption (138, 0.3); + + // simulate 20 seconds of movement with 138g buoyancy and 0.2 m/s of W + Simulator::Schedule (Seconds (20), + &GliderEnergyModel::ChangeEnergyConsumption, + devModel, + 138, + 0.2); + + // simulate a stop of the vehicle for the remaining 5 seconds + Simulator::Schedule (Seconds (40), + &GliderEnergyModel::ChangeEnergyConsumption, + devModel, + 0, + 0); + + // run simulation + Simulator::Stop (Seconds (45)); + Simulator::Run (); + Simulator::Destroy (); + + std::cout << "Remaining energy: " << source->GetRemainingEnergy () << std::endl; + + return 0; +} --- a/src/auv/examples/auv-mobility.cc +++ a/src/auv/examples/auv-mobility.cc @@ -0,0 +1,172 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "ns3/glider-mobility-model.h" +#include "ns3/gnuplot.h" +#include "ns3/auv-mobility-helper.h" + +#include + +using namespace ns3; + +/** + * We show how to use the AuvMobilityHelper to install an auv mobility model + * into a (set of) node. + * + * Then we make the AUV to submerge to a depth of 1000 meters. + * We also set a callback function called on reaching of the target depth. + * + * The callback then makes the AUV to emerge to water surface (0 meters). + * We set a callback function called on reaching of the target depth. + * The emerge callback then, stops the AUV. + * + * During the whole navigation process, the AUV's position is tracked by the + * TracePos function and plotted into a Gnuplot graph. + */ + +void Emerge (Ptr mob); + +static void +SubmergeCb (Ptr mob) +{ + // reached the target, makes the vehicle emerge + Emerge (mob->GetObject ()); +} + +static void +EmergeCb (Ptr mob) +{ + // stop the vehicle + mob->GetObject ()->Stop (); +} + +void +Submerge (Ptr mob) +{ + // set the submerge callback + mob->SetSubmergeCallback (MakeCallback (&SubmergeCb)); + + // makes the vehicle submerge to 1000m + mob->Submerge (-1000); +} + +void +Emerge (Ptr mob) +{ + // set the emerge callback + mob->SetEmergeCallback (MakeCallback (&EmergeCb)); + + // makes the vehicle emerge to water surface + mob->Emerge (0); +} + +static void +TracePos (Gnuplot3dDataset* ds, Ptr mob) +{ + Vector curPos = mob->GetPosition (); + ds->Add (curPos.x, curPos.y, curPos.z); + + Simulator::Schedule (Seconds (10), + &TracePos, + ds, + mob); +} + +void +GeneratePlot (const GnuplotDataset& ds) +{ + Gnuplot gp; + gp.SetTitle ("3D view"); + gp.SetExtra ("set multiplot"); + gp.AppendExtra ("set size 0.5,0.5"); + gp.AppendExtra ("set origin 0.0,0.0"); + gp.AppendExtra ("set view 60,30"); + gp.AddDataset (ds); + + Gnuplot gp1; + gp1.SetTitle ("X-Y view"); + gp1.SetExtra ("set view 0,0"); + gp1.AppendExtra ("set origin 0.0,0.5"); + gp1.AddDataset (ds); + + Gnuplot gp2; + gp2.SetTitle ("X-Z view"); + gp2.SetExtra ("set view 90,0"); + gp2.AppendExtra ("set origin 0.5,0.0"); + gp2.AddDataset (ds); + + Gnuplot gp3; + gp3.SetTitle ("Y-Z view"); + gp3.SetExtra ("set view 0,90"); + gp3.AppendExtra ("set origin 0.5,0.5"); + gp3.AddDataset (ds); + + GnuplotCollection gpc ("seaglider-navigation-trace.eps"); + gpc.AddPlot (gp); + gpc.AddPlot (gp1); + gpc.AddPlot (gp2); + gpc.AddPlot (gp3); + gpc.SetTerminal ("postscript eps enhanced color \"Helvetica\" 10"); + + std::ofstream of ("seaglider-navigation-trace.gpl"); + if (!of.is_open ()) + { + NS_FATAL_ERROR ("Can not open GNU Plot outfile: seaglider-navigation-trace.gpl"); + } + gpc.GenerateOutput (of); + of.close (); + + std::cout << "Seaglider navigation trace successfully created!" << std::endl; +} + +int +main (int argc, char **argv) +{ + NodeContainer node; + node.Create (1); + + // install the glider mobility model + AuvMobilityHelper rmh; + rmh.SetType ("ns3::GliderMobilityModel"); + rmh.Install (node); + + Ptr glider = DynamicCast (node.Get (0)->GetObject ()); + NS_ASSERT (glider != NULL); + + // set the initial position of the AUV + glider->SetPosition (Vector (0.,0.,0.)); + + // trace the position + Gnuplot3dDataset ds ("Navigation Trace"); + TracePos (&ds, glider); + + // submerge + Submerge (glider); + + // run simulation + Simulator::Stop (Seconds (4001)); + Simulator::Run (); + Simulator::Destroy (); + + // generate the navigation trace + GeneratePlot (ds); + + return 0; +} --- a/src/auv/examples/auv-waypoint-mobility.cc +++ a/src/auv/examples/auv-waypoint-mobility.cc @@ -0,0 +1,106 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "ns3/remus-mobility-model.h" +#include "ns3/auv-waypoint-mobility-model.h" +#include "ns3/glider-mobility-model.h" + +using namespace ns3; + +/** + * We show how to use the AuvWaypointMobilityModel with a non-standard + * ConstantVelocityMobilityModel. + * + * We first create a waypoint model with an underlying RemusMobilityModel + * setting the mobility trace with two waypoints. + * + * We then create a waypoint model with an underlying GliderMobilityModel + * setting the waypoints separately with the AddWaypoint method. + * + * We start the simulation. + * + * The AUV's position is printed out every seconds. + */ + +static void +TracePos (Ptr mob) +{ + Vector curPos = mob->GetPosition (); + + std::cout << "At " << Simulator::Now ().GetSeconds () << ": " << + curPos.x << " " << curPos.y << " " << curPos.z << std::endl; + + Simulator::Schedule (Seconds (1), + &TracePos, + mob); +} + + +int +main (int argc, char **argv) +{ + Ptr node1 = CreateObject (); + + // create the waypoint model + Ptr mm = CreateObject (); + Ptr remus = CreateObject (); + remus->SetNode (node1); + // set the RemusMobilityModel as the underlying model + mm->SetValidatorMobilityModel (remus); + node1->AggregateObject (mm); + + // set some waypoints + mm->AddWaypoint (Waypoint (Seconds (0), Vector (0, 0, 0))); + mm->AddWaypoint (Waypoint (Seconds (10), Vector (20, 0, 0))); + + std::cout << "Remus simulation" << std::endl; + + // trace the position + TracePos (mm); + + // run the simulation + Simulator::Stop (Seconds (15)); + Simulator::Run (); + Simulator::Destroy (); + + // create another waypoint model with an underlying GliderMobilityModel + Ptr node2 = CreateObject (); + Ptr gmm = CreateObject (); + gmm->SetNode (node2); + Ptr wpmm = CreateObject (); + wpmm->SetValidatorMobilityModel (gmm); + node2->AggregateObject (wpmm); + + // set some waypoints + wpmm->AddWaypoint (Waypoint (Seconds (0), Vector (0,0,0))); + wpmm->AddWaypoint (Waypoint (Seconds (60), Vector (10,0,-20))); + + std::cout << std::endl << "Seaglider simulation" << std::endl; + + // trace the position + TracePos (wpmm); + + // run the simulation + Simulator::Stop (Seconds (62)); + Simulator::Run (); + Simulator::Destroy (); + + return 0; +} --- a/src/auv/examples/uan-energy-auv.cc +++ a/src/auv/examples/uan-energy-auv.cc @@ -0,0 +1,185 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "ns3/core-module.h" +#include "uan-energy-auv.h" +#include "ns3/auv-glider-helper.h" +#include "ns3/auv-waypoint-mobility-model.h" +#include "ns3/basic-energy-source-helper.h" +#include "ns3/constant-position-mobility-model.h" +#include "ns3/uan-channel.h" +#include "ns3/uan-noise-model-default.h" +#include "ns3/uan-prop-model-ideal.h" +#include "ns3/acoustic-modem-energy-model-helper.h" +#include "ns3/energy-model-helper.h" + +using namespace ns3; + +UanEnergyAuv::UanEnergyAuv () + : m_bytesRx (0), + m_sentPackets (0) +{ +} + +UanEnergyAuv::~UanEnergyAuv () +{ + m_auv = NULL; + m_gateway = NULL; +} + +void +UanEnergyAuv::SendOnePacket (Ptr node) +{ + // create an empty 17 bytes packet + Ptr pkt = Create (17); + // send the packet in broadcast + Ptr dev = node->GetDevice (0)->GetObject (); + dev->Send (pkt, dev->GetBroadcast (), 0); + // increase the sent packets number + ++m_sentPackets; + + Simulator::Schedule (Seconds (10), + &UanEnergyAuv::SendOnePacket, + this, + node); +} + +bool +UanEnergyAuv::RxPacket (Ptr dev, Ptr pkt, uint16_t mode, const Address &sender) +{ + // increase the total bytes received + m_bytesRx += pkt->GetSize (); + + return true; +} + +void +UanEnergyAuv::PrintStats () +{ + Ptr source; + + std::cout << "AUV: sent " << m_sentPackets << " packets" << std::endl; + std::cout << "Gateway: received " << m_bytesRx << " bytes" << std::endl; + + source = m_gateway->GetObject ()->Get (0); + std::cout << "Gateway energy consumption: " << 100 - (source->GetEnergyFraction () * 100) << " %" << std::endl; + + source = m_auv->GetObject ()->Get (0); + std::cout << "AUV energy consumption (nav): " << 100 - (source->GetEnergyFraction () * 100) << " %" << std::endl; + + source = m_auv->GetObject ()->Get (1); + std::cout << "AUV energy consumption (comms): " << 100 - (source->GetEnergyFraction () * 100) << " %" << std::endl; +} + +bool +UanEnergyAuv::Run () +{ + UanHelper uan; + AcousticModemEnergyModelHelper umem; + + // create a generic node + m_auv = CreateObject (); + + // create a gateway node + m_gateway = CreateObject (); + + // install the glider components + AuvGliderHelper gh; + gh.Install (m_auv); + + // move the vehicle somewhere + Ptr mob = m_auv->GetObject (); + mob->AddWaypoint (Waypoint (Seconds (0), Vector (500,0,0))); + mob->AddWaypoint (Waypoint (Seconds (3000), Vector (0, 500,-1000))); + mob->AddWaypoint (Waypoint (Seconds (6000), Vector (-500, 0, 0))); + mob->AddWaypoint (Waypoint (Seconds (9000), Vector (0, 500,-1000))); + mob->AddWaypoint (Waypoint (Seconds (12000), Vector (500, 0, 0))); + + // set the gateway mobility model + Ptr mobility = CreateObject (); + mobility->SetPosition (Vector (0, 0, 0)); + m_gateway->AggregateObject (mobility); + + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack on AUV and gateway + uan.Install (m_auv, channel); + uan.Install (m_gateway, channel); + + // setup the energy sources for AUV and gateway + BasicEnergySourceHelper eh; + eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (3888000.0)); + eh.Install (m_gateway); + + // Check nodes setup + Ptr gatewayEnergySource = m_gateway->GetObject ()->Get (0); + NS_ASSERT (gatewayEnergySource != NULL); + + Ptr auvEnergySource = m_auv->GetObject ()->Get (1); + NS_ASSERT (auvEnergySource != NULL); + + Ptr gatewayDevice = m_gateway->GetDevice (0); + NS_ASSERT (gatewayDevice != NULL); + + Ptr auvDevice = m_auv->GetDevice (0); + NS_ASSERT (auvDevice != NULL); + + // micro modem energy model + umem.Install (gatewayDevice, gatewayEnergySource); + umem.Install (auvDevice, auvEnergySource); + + // Animate with a packet every 10 seconds + Simulator::ScheduleNow (&UanEnergyAuv::SendOnePacket, + this, + m_auv); + + // set the receive callback + gatewayDevice->SetReceiveCallback (MakeCallback (&UanEnergyAuv::RxPacket, + this)); + // run the simulation + Simulator::Stop (Hours (3)); + Simulator::Run (); + // print the simulation's statistics + PrintStats (); + Simulator::Destroy (); + return false; +} + +int +main (int argc, char **argv) +{ + CommandLine cmd; + UanEnergyAuv uan; + + cmd.Parse (argc, argv); + + // uncomment to see models log + // LogComponentEnable("GliderEnergyModel", LOG_LEVEL_ALL); + // LogComponentEnable("BasicEnergySource", LOG_LEVEL_ALL); + // LogComponentEnable("AcousticModemEnergyModel", LOG_LEVEL_ALL); + + uan.Run (); + + return 0; +} --- a/src/auv/examples/uan-energy-auv.h +++ a/src/auv/examples/uan-energy-auv.h @@ -0,0 +1,70 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef UAN_ENERGY_AUV_H +#define UAN_ENERGY_AUV_H + + + +/** + * This is a comprehensive example where all the project's components are used. + * We setup two nodes, one fixed surface gateway and a moving Seaglider AUV, + * both equipped with an acoustic modem. + * + * Using the waypoint mobility model with an underlying GliderMobilityModel, + * we make the glider descend to -1000 meters and then emerge to the water surface. + * + * The AUV sends a generic 17-bytes packet every 10 seconds during the navigation + * process. + * The gateway receives the packets and stores the total bytes amount. + * + * During the simulation the AUV consumes energy for navigation and packets sending. + * The energy drained is subtracted from the main energy source. + * The surface gateway instead consumes energy only receiving packets. + * + * At the end of the simulation are printed out the energy consumptions of the two + * nodes and the networking stats. + */ + +#include "ns3/packet.h" +#include "ns3/uan-helper.h" + +using namespace ns3; + +class UanEnergyAuv +{ +public: + UanEnergyAuv (); + ~UanEnergyAuv (); + + bool RxPacket (Ptr dev, Ptr pkt, uint16_t mode, const Address &sender); + void SendOnePacket (Ptr node); + + void PrintStats (); + + bool Run (void); + + uint32_t m_bytesRx; + uint32_t m_sentPackets; + Ptr m_auv; + Ptr m_gateway; +}; + +#endif /* UAN_ENERGY_AUV_H */ --- a/src/auv/examples/wscript +++ a/src/auv/examples/wscript @@ -0,0 +1,15 @@ +# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + obj = bld.create_ns3_program('uan-energy-auv', ['internet', 'uan', 'mobility', 'auv', 'energy']) + obj.source = 'uan-energy-auv.cc' + + obj = bld.create_ns3_program('auv-energy-model', ['internet', 'mobility', 'auv', 'energy']) + obj.source = 'auv-energy-model.cc' + + obj = bld.create_ns3_program('auv-waypoint-mobility', ['internet', 'mobility', 'auv']) + obj.source = 'auv-waypoint-mobility.cc' + + obj = bld.create_ns3_program('auv-mobility', ['internet', 'mobility', 'auv']) + obj.source = 'auv-mobility.cc' + --- a/src/auv/helper/auv-glider-helper.cc +++ a/src/auv/helper/auv-glider-helper.cc @@ -0,0 +1,139 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "auv-glider-helper.h" +#include "ns3/net-device-container.h" +#include "ns3/auv-mobility-helper.h" +#include "ns3/li-ion-energy-source.h" +#include "ns3/glider-energy-model.h" +#include "ns3/glider-mobility-model.h" +#include "ns3/auv-waypoint-mobility-model.h" +#include "ns3/energy-source-container.h" +#include "ns3/acoustic-modem-energy-model-helper.h" +#include "ns3/uan-channel.h" +#include "ns3/uan-net-device.h" +#include "ns3/uan-helper.h" + +namespace ns3 { + +AuvGliderHelper::AuvGliderHelper () +{ +} + +void +AuvGliderHelper::Install (NodeContainer c) const +{ + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + Install (*i); + } +} + +void +AuvGliderHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + Install (node); +} + +void +AuvGliderHelper::Install (Ptr node) const +{ + // waypoint mobility model with underlying glider mobility model + Ptr gmm = CreateObject (); + gmm->SetNode (node); + Ptr wpmm = CreateObject (); + wpmm->SetValidatorMobilityModel (gmm); + node->AggregateObject (wpmm); + + // Motor battery pack. 7 in-series string x 6 strings = 42 cells + // Capacity 18.1 MJ @ 24 V + // + // +--C-C-C-C-C-C-C--+ + // +--C-C-C-C-C-C-C--+ + // ---+--C-C-C-C-C-C-C--+--- + // +--C-C-C-C-C-C-C--+ + // +--C-C-C-C-C-C-C--+ + // +--C-C-C-C-C-C-C--+ + // + Ptr esContainer = CreateObject (); + Ptr cont = node->GetObject (); + NS_ASSERT_MSG (cont == 0, "Energy source already installed!"); + ObjectFactory fact; + fact.SetTypeId (LiIonEnergySource::GetTypeId ()); + fact.Set ("LiIonEnergySourceInitialEnergyJ", DoubleValue (13608000.0)); + fact.Set ("InitialCellVoltage", DoubleValue (3.45 * 7)); + fact.Set ("NominalCellVoltage", DoubleValue (3.3 * 7)); + fact.Set ("ExpCellVoltage", DoubleValue (3.55 * 7)); + fact.Set ("RatedCapacity", DoubleValue (30.0 * 6)); + fact.Set ("NomCapacity", DoubleValue (27.0 * 6)); + fact.Set ("ExpCapacity", DoubleValue (15.0 * 6)); + // 0.145 ohm per cell, 7 in series and 6 string in parallel + // Gstring = 1 / (0.145 * 7) + // Rint = 1 / (Gstring * 6) + fact.Set ("InternalResistance", DoubleValue (0.16917)); + fact.Set ("TypCurrent", DoubleValue (1.0 * 6)); + fact.Set ("ThresholdVoltage", DoubleValue (3.0 * 6)); + Ptr devSource = fact.Create ()->GetObject (); + devSource->SetNode (node); + esContainer->Add (devSource); + + // Analogic/digital power battery pack. 3 in-series string x 4 strings = 12 cells + // Capacity 18.1 MJ @ 10 V + // + // +--C-C-C--+ + // +--C-C-C--+ + // ---+--C-C-C--+--- + // +--C-C-C--+ + // + fact.SetTypeId (LiIonEnergySource::GetTypeId ()); + fact.Set ("LiIonEnergySourceInitialEnergyJ", DoubleValue (3888000.0)); + fact.Set ("InitialCellVoltage", DoubleValue (3.45 * 3)); + fact.Set ("NominalCellVoltage", DoubleValue (3.3 * 3)); + fact.Set ("ExpCellVoltage", DoubleValue (3.55 * 3)); + fact.Set ("RatedCapacity", DoubleValue (30.0 * 4)); + fact.Set ("NomCapacity", DoubleValue (27.0 * 4)); + fact.Set ("ExpCapacity", DoubleValue (15.0 * 4)); + // 0.145 ohm per cell, 3 in series and 4 string in parallel + // Gstring = 1 / (0.145 * 3) + // Rint = 1 / (Gstring * 4) + fact.Set ("InternalResistance", DoubleValue (0.10875)); + fact.Set ("TypCurrent", DoubleValue (1.0 * 4)); + fact.Set ("ThresholdVoltage", DoubleValue (3.0 * 4)); + Ptr devSource1 = fact.Create ()->GetObject (); + devSource1->SetNode (node); + esContainer->Add (devSource1); + + node->AggregateObject (esContainer); + + // get the installed energy source container + cont = node->GetObject (); + NS_ASSERT (cont != NULL); + + // glider energy model + Ptr gem = CreateObject (); + gem->SetEnergySource (devSource); + gem->SetNode (node); + devSource->AppendDeviceEnergyModel (gem); + gem->SetEnergyDepletionCallback (MakeCallback (&AuvWaypointMobilityModel::HandleEnergyDepletion, wpmm)); + gem->SetEnergyRechargedCallback (MakeCallback (&AuvWaypointMobilityModel::HandleEnergyRecharged, wpmm)); +} + +} // namespace ns3 --- a/src/auv/helper/auv-glider-helper.h +++ a/src/auv/helper/auv-glider-helper.h @@ -0,0 +1,95 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef AUV_GLIDER_HELPER_H +#define AUV_GLIDER_HELPER_H + +#include "ns3/node-container.h" +#include "ns3/object-factory.h" +#include "ns3/names.h" + +namespace ns3 { + +/** + * \ingroup auv + * Install into a node (or set of nodes) the Seaglider's features: + * - waypoint model with underlying glider mobility model + * - glider energy model + * - glider energy source + * - micro modem energy model + * + * The glider mobility model is the GliderMobilityModel with default parameters. + * + * The glider energy model is the GliderEnergyModel with default parameters. + * + * Regarding the energy source, the Seaglider features two battery packs, one + * for motor power and one for digital-analog power. + * Each pack is composed of 12 (10V) and 42 (24V) lithium chloride DD-cell batteries, + * respectively [1]. The total power capacity is around 17.5 MJ (3.9 MJ + 13.6 MJ). + * In the original version of the Seaglider there was 18 + 63 D-cell with a total + * power capacity of 10MJ. + * + * The packs design is as follows: + * 10V - 3 in-series string x 4 strings = 12 cells - typical capacity ~100 Ah + * 24V - 7 in-series-strings x 6 strings = 42 cells - typical capacity ~150 Ah + * + * Battery cells are Electrochem 3B36, with 3.6 V nominal voltage and 30.0 Ah + * nominal capacity. + * + * The 10V battery pack is associated with the electronic devices, while the 24V one + * is associated with the pump motor. + * + * The micro modem energy model is the AcousticModemEnergyModel with default parameters. + * + * References: + * [1] Eriksen et al, "Seaglider: A Long-Range Autonomous Underwater Vehicle for Oceanographic Research" + * URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=972073&userType=inst + */ +class AuvGliderHelper +{ +public: + AuvGliderHelper (); + + /** + * Install the Glider features into a set of nodes. + * + * \param c NodeContainer where to install the features + */ + void Install (NodeContainer c) const; + + /** + * Install the Glider features into a single node. + * + * \param nodeName Name of the node where to install the features. + */ + void Install (std::string nodeName) const; + + /** + * Install the Glider features into a single node. + * + * \param node Pointer of the node where to install the features. + */ + void Install (Ptr node) const; + +}; + +} // namespace ns3 + +#endif /* AUV_GLIDER_HELPER_H */ --- a/src/auv/helper/auv-mobility-helper.cc +++ a/src/auv/helper/auv-mobility-helper.cc @@ -0,0 +1,112 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "auv-mobility-helper.h" +#include "ns3/remus-mobility-model.h" +#include "ns3/string.h" + +namespace ns3 { + +AuvMobilityHelper::AuvMobilityHelper () +{ + m_factory.SetTypeId ("ns3::RemusMobilityModel"); + + m_allocator = CreateObjectWithAttributes + ("X", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"), + "Y", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"), + "Z", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]")); +} + +void +AuvMobilityHelper::SetType (std::string type) +{ + m_factory.SetTypeId (type); +} + +void AuvMobilityHelper::SetAttribute (std::string name, + const AttributeValue &value) +{ + m_factory.Set (name, + value); +} + +void +AuvMobilityHelper::SetPositionAllocator (Ptr allocator) +{ + m_allocator = allocator; +} + +void +AuvMobilityHelper::SetPositionAllocator (std::string type, + std::string n1, const AttributeValue &v1, + std::string n2, const AttributeValue &v2, + std::string n3, const AttributeValue &v3, + std::string n4, const AttributeValue &v4, + std::string n5, const AttributeValue &v5, + std::string n6, const AttributeValue &v6, + std::string n7, const AttributeValue &v7, + std::string n8, const AttributeValue &v8, + std::string n9, const AttributeValue &v9) +{ + ObjectFactory pos; + pos.SetTypeId (type); + pos.Set (n1, v1); + pos.Set (n2, v2); + pos.Set (n3, v3); + pos.Set (n4, v4); + pos.Set (n5, v5); + pos.Set (n6, v6); + pos.Set (n7, v7); + pos.Set (n8, v8); + pos.Set (n9, v9); + m_allocator = pos.Create ()->GetObject (); +} + +void +AuvMobilityHelper::Install (NodeContainer c) const +{ + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + Install (*i); + } +} + +void +AuvMobilityHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + Install (node); +} + +void +AuvMobilityHelper::Install (Ptr node) const +{ + Ptr model = m_factory.Create ()->GetObject (); + + NS_ASSERT_MSG (model != NULL, + "The requested mobility model is not an auv mobility model: \"" << + m_factory.GetTypeId ().GetName () << "\""); + + Vector pos = m_allocator->GetNext (); + model->SetPosition (pos); + model->SetNode (node); + node->AggregateObject (model); +} + +} // namespace ns3 --- a/src/auv/helper/auv-mobility-helper.h +++ a/src/auv/helper/auv-mobility-helper.h @@ -0,0 +1,138 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef AUV_MOBILITY_HELPER_H +#define AUV_MOBILITY_HELPER_H + + +#include "ns3/node-container.h" +#include "ns3/object-factory.h" +#include "ns3/position-allocator.h" +#include "ns3/names.h" + +namespace ns3 { + +/** + * \ingroup auv + * \brief Install into a set of nodes an AuvMobilityModel + * + * Install into a set of nodes (or single node) the specified AuvMobilityModel. + * The specific AuvMobilityModel can be specified with the SetType method. + * + * The helper also uses a PositionAllocator to set the nodes positions. + * + * By default the mobility model is the RemusMobilityModel and the position + * allocator is a RandomBoxPositionAllocator with X, Y and Z variables set to + * constant zero. + */ +class AuvMobilityHelper +{ +public: + /** + * Set the default mobility model (RemusMobilityModel) and the + * default position allocator (RandomBoxPositionAllocator with + * constant position in 0,0,0) + */ + AuvMobilityHelper (); + + /** + * \param type the AUV mobility model TypeId + */ + void SetType (std::string type); + + /** + * Set an attribute of the specified auv mobility model + * + * \param name name of the parameter + * \param value value of the parameter + */ + void SetAttribute (std::string name, const AttributeValue &value); + /** + * Set the position allocator to be used during the install process + * to give each node an initial position + * + * \param allocator the position allocator to be set + */ + void SetPositionAllocator (Ptr allocator); + /** + * Set the position allocator to be used during the install process + * to give each node an initial position + * + * \param type the position allocator TypeId + * \param n1 the name of the attribute to set + * \param v1 the value of the attribute to set + * \param n2 the name of the attribute to set + * \param v2 the value of the attribute to set + * \param n3 the name of the attribute to set + * \param v3 the value of the attribute to set + * \param n4 the name of the attribute to set + * \param v4 the value of the attribute to set + * \param n5 the name of the attribute to set + * \param v5 the value of the attribute to set + * \param n6 the name of the attribute to set + * \param v6 the value of the attribute to set + * \param n7 the name of the attribute to set + * \param v7 the value of the attribute to set + * \param n8 the name of the attribute to set + * \param v8 the value of the attribute to set + * \param n9 the name of the attribute to set + * \param v9 the value of the attribute to set + */ + void SetPositionAllocator (std::string type, + std::string n1, const AttributeValue &v1, + std::string n2, const AttributeValue &v2, + std::string n3, const AttributeValue &v3, + std::string n4, const AttributeValue &v4, + std::string n5, const AttributeValue &v5, + std::string n6, const AttributeValue &v6, + std::string n7, const AttributeValue &v7, + std::string n8, const AttributeValue &v8, + std::string n9, const AttributeValue &v9); + + /** + * For each of the input nodes a new mobility model of the specified type + * is created and attached to the node. + * + * \param c a set of nodes + */ + void Install (NodeContainer c) const; + + /** + * Install the specified auv mobility model into the node with the specified + * name. + * + * \param nodeName name of the node + */ + void Install (std::string nodeName) const; + + /** + * Install the specified auv mobility model into the specified node + * + * \param node Pointer of the node where to install the mobility model + */ + void Install (Ptr node) const; + + ObjectFactory m_factory; + Ptr m_allocator; +}; + +} // namespace ns3 + +#endif /* AUV_MOBILITY_HELPER_H */ --- a/src/auv/helper/auv-remus-helper.cc +++ a/src/auv/helper/auv-remus-helper.cc @@ -0,0 +1,83 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "auv-remus-helper.h" +#include "ns3/auv-mobility-helper.h" +#include "ns3/basic-energy-source-helper.h" +#include "ns3/remus-energy-model.h" +#include "ns3/remus-mobility-model.h" +#include "ns3/auv-waypoint-mobility-model.h" +#include "ns3/acoustic-modem-energy-model-helper.h" +#include "ns3/uan-channel.h" +#include "ns3/uan-net-device.h" +#include "ns3/uan-helper.h" +#include "ns3/net-device-container.h" +#include "ns3/net-device-container.h" + +namespace ns3 { + +AuvRemusHelper::AuvRemusHelper () +{ +} + +void +AuvRemusHelper::Install (NodeContainer c) const +{ + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + Install (*i); + } +} + +void +AuvRemusHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + Install (node); +} + +void +AuvRemusHelper::Install (Ptr node) const +{ + // waypoint mobility model with underlying remus mobility model + Ptr rmm = CreateObject (); + rmm->SetNode (node); + Ptr wpmm = CreateObject (); + wpmm->SetValidatorMobilityModel (rmm); + node->AggregateObject (wpmm); + + // 1.1 kWh -> 1.1 * 1000 * 3600 = 3960000J + // remus energy source + BasicEnergySourceHelper eh; + eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (3960000.0)); + eh.Install (node); + + // remus energy model + Ptr rem = CreateObject (); + Ptr source = node->GetObject ()->Get (0); + NS_ASSERT (source != NULL); + rem->SetEnergySource (source); + source->AppendDeviceEnergyModel (rem); + source->SetNode (node); + rem->SetNode (node); + rem->SetEnergyDepletionCallback (MakeCallback (&AuvWaypointMobilityModel::HandleEnergyDepletion, wpmm)); + rem->SetEnergyRechargedCallback (MakeCallback (&AuvWaypointMobilityModel::HandleEnergyRecharged, wpmm)); +} + +} // namespace ns3 --- a/src/auv/helper/auv-remus-helper.h +++ a/src/auv/helper/auv-remus-helper.h @@ -0,0 +1,85 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef AUV_REMUS_HELPER_H +#define AUV_REMUS_HELPER_H + +#include "ns3/node.h" +#include "ns3/node-container.h" +#include "ns3/object-factory.h" +#include "ns3/names.h" + +namespace ns3 { + +/** + * \ingroup auv + * Install into a node (or set of nodes) the REMUS features: + * - waypoint model with REMUS mobility model validation + * - REMUS energy model + * - REMUS energy source + * - micro modem energy model + * + * The REMUS mobility model is the RemusMobilityModel with default parameters. + * + * The REMUS energy model is the RemusEnergyModel with default parameters. + * + * Regarding the energy source, the REMUS features a rechargeable lithium ion + * battery pack rated 1.1 kWh @ 27 V (40 Ah) in operating conditions (specifications + * from [1] and Hydroinc European salesman). + * Since more detailed information about battery pack were not publicly available, + * the energy source used is a BasicEnergySource. + * + * The micro modem energy model is the AcousticModemEnergyModel with default parameters. + * + * References: + * + * [1] Hydroinc Products; http://www.hydroidinc.com/products.html + */ +class AuvRemusHelper +{ +public: + AuvRemusHelper (); + + /** + * Install the REMUS features into a set of nodes + * + * \param c NodeContainer where to install the features + */ + void Install (NodeContainer c) const; + + /** + * Install the REMUS features into a single node + * + * \param nodeName Name of the node where to install the features + */ + void Install (std::string nodeName) const; + + /** + * Install the REMUS features into a single node + * + * \param node Pointer of the node where to install the features + */ + void Install (Ptr node) const; + +}; + +} // namespace ns3 + +#endif /* AUV_REMUS_HELPER_H */ --- a/src/auv/model/auv-mobility-model.cc +++ a/src/auv/model/auv-mobility-model.cc @@ -0,0 +1,114 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "auv-mobility-model.h" + +namespace ns3 { + +TypeId +AuvMobilityModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::AuvMobilityModel") + .SetParent (MobilityModel::GetTypeId ()) + ; + return tid; +} + +AuvMobilityModel::AuvMobilityModel () +{ +} + +AuvMobilityModel::~AuvMobilityModel () +{ +} + +void +AuvMobilityModel::Move (void) +{ + return DoMove (); +} + +void +AuvMobilityModel::Stop (void) +{ + return DoStop (); +} + +void +AuvMobilityModel::Emerge (double depth) +{ + return DoEmerge (depth); +} + +void +AuvMobilityModel::Submerge (double depth) +{ + return DoSubmerge (depth); +} + +double +AuvMobilityModel::GetPitch () const +{ + return DoGetPitch (); +} + +void +AuvMobilityModel::SetPitch (double pitch) +{ + return DoSetPitch (pitch); +} + +double +AuvMobilityModel::GetDepth (void) +{ + return DoGetDepth (); +} + +double +AuvMobilityModel::GetDirection (void) const +{ + return DoGetDirection (); +} + +void +AuvMobilityModel::SetDirection (double dir) +{ + return DoSetDirection (dir); +} + +double +AuvMobilityModel::GetSpeed () const +{ + return DoGetSpeed (); +} + +void +AuvMobilityModel::SetSpeed (double speed) +{ + return DoSetSpeed (speed); +} + +void +AuvMobilityModel::SetVelocity (const Vector &velocity) +{ + return DoSetVelocity (velocity); +} + +} // namespace ns3 --- a/src/auv/model/auv-mobility-model.h +++ a/src/auv/model/auv-mobility-model.h @@ -0,0 +1,198 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef AUV_MOBILITY_MODEL_H_ +#define AUV_MOBILITY_MODEL_H_ + +#include "ns3/constant-velocity-mobility-model.h" +#include "ns3/node.h" + +namespace ns3 { + +/** + * \ingroup auv + * \brief keep track of the current position of an Autonomous Underwater Vehicle (AUV) + * + * Define an interface for AUV mobility models. Every AUV mobility model should derive + * from this interface, and implements all the pure virtual methods. + * + * The interface allow the client to move/stop the vehicle's movement, makes it submerge + * or emerge to a target depth, and getting and setting the main navigation's parameter + * like pitch, direction, speed. + * + * The emerge and submerge callback are called when the vehicle reach the target depth. + */ +class AuvMobilityModel : public MobilityModel +{ +public: + static TypeId GetTypeId (void); + AuvMobilityModel (); + virtual ~AuvMobilityModel () = 0; + + /** + * Makes the AUV to move along the given direction + */ + void Move (void); + /** + * Makes the AUV to stop + */ + void Stop (void); + /** + * Makes the AUV to emerge at the maximum velocity + * to the given depth + * \param depth the depth to which emerge to, in m (negative) + */ + void Emerge (double depth); + /** + * Makes the AUV to submerge at the maximum velocity + * to the given depth + * \param depth the depth to which submerge to, in m (negative) + */ + void Submerge (double depth); + /** + * \returns the current pitch in degrees + */ + double GetPitch () const; + + /** + * \param pitch the pitch to set in degrees + */ + void SetPitch (double pitch); + /** + * \returns the current depth + */ + double GetDepth (void); + /** + * \returns the current direction in degrees + */ + double GetDirection (void) const; + /** + * \param dir the heading direction in degrees + */ + void SetDirection (double dir); + /** + * \returns the current speed in m/s + */ + double GetSpeed () const; + /** + * \param speed the speed to set in m/s + */ + void SetSpeed (double speed); + /** + * \param velocity the velocity vector to set + */ + void SetVelocity (const Vector &velocity); + /** + * \param node the node associated with the mobility model + */ + virtual void SetNode (const Ptr node) = 0; + /** + * \returns the associated node + */ + virtual Ptr GetNode (void) const = 0; + /** + * \param cb the callback being called at the end of the emerging process + */ + virtual void SetEmergeCallback (Callback > cb) = 0; + + /** + ** \param cb the callback being called at the end of the submerging process + */ + virtual void SetSubmergeCallback (Callback > cb) = 0; + +private: + /** + * Concrete subclasses of this base class must + * implement this methods. + */ + + /** + * Makes the AUV to move along the given direction + */ + virtual void DoMove (void) = 0; + /** + * Makes the AUV to stop + */ + virtual void DoStop (void) = 0; + /** + * Makes the AUV to emerge at the maximum velocity + * to the given depth. When reaching the target depth, it + * will be called the EmergeCallback, if set. + * \param depth the depth to which emerge to, in m (negative) + */ + virtual void DoEmerge (double depth) = 0; + /** + * Makes the AUV to submerge at the maximum velocity + * to the given depth. When reaching the target depth, it + * will be called the SubmergeCallback, if set. + * \param depth the depth to which submerge to, in m (negative) + */ + virtual void DoSubmerge (double depth) = 0; + /** + * \returns the current pitch in degrees + */ + virtual double DoGetPitch () const = 0; + /** + * \param pitch the pitch to set in degrees + */ + virtual void DoSetPitch (double pitch) = 0; + /** + * \returns the current depth + */ + virtual double DoGetDepth (void) = 0; + /** + * \returns the current direction in degrees + */ + virtual double DoGetDirection (void) const = 0; + /** + * \param direction the heading direction in degrees + */ + virtual void DoSetDirection (double dir) = 0; + /** + * \returns the current speed in m/s + */ + virtual double DoGetSpeed () const = 0; + /** + * \param speed the speed to set in m/s + */ + virtual void DoSetSpeed (double speed) = 0; + /** + * \param velocity the velocity vector to set + */ + virtual void DoSetVelocity (const Vector &velocity) = 0; + + // inherited from MobilityModel + /** + * \returns the current position + */ + virtual Vector DoGetPosition (void) const = 0; + /** + * \param position the position to set + */ + virtual void DoSetPosition (const Vector &position) = 0; + /** + * \returns the current velocity vector + */ + virtual Vector DoGetVelocity (void) const = 0; +}; + +} // namespace ns3 + +#endif /* AUV_MOBILITY_MODEL_H_ */ --- a/src/auv/model/auv-waypoint-mobility-model.cc +++ a/src/auv/model/auv-waypoint-mobility-model.cc @@ -0,0 +1,280 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * 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: Andrea Sacco + */ +#include "auv-waypoint-mobility-model.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("AuvWaypointMobilityModel"); + +NS_OBJECT_ENSURE_REGISTERED (AuvWaypointMobilityModel); + + +TypeId +AuvWaypointMobilityModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::AuvWaypointMobilityModel") + .SetParent () + .SetGroupName ("AUV") + .AddConstructor () + .AddAttribute ("ValidatorMobilityModel", "The MobilityModel going to be used for the position's validation, must be a constant velocity model", + PointerValue (), + MakePointerAccessor (&AuvWaypointMobilityModel::m_auvMobilityModel), + MakePointerChecker ()) + + ; + return tid; +} + + +AuvWaypointMobilityModel::AuvWaypointMobilityModel () + : m_lazyNotify (false), + m_initialPositionIsWaypoint (true), + m_auvMobilityModel (NULL), + m_energyDepleted (false), + m_lastUpdate (Seconds (-1)), + m_callbackDone (false) +{ + m_waypointReachedCallback.Nullify (); +} + + +AuvWaypointMobilityModel::~AuvWaypointMobilityModel () +{ + m_auvMobilityModel = NULL; + m_waypointReachedCallback.Nullify (); +} + +void +AuvWaypointMobilityModel::SetValidatorMobilityModel (Ptr auvMobilityModel) +{ + m_auvMobilityModel = auvMobilityModel; +} + +Ptr +AuvWaypointMobilityModel::GetValidatorMobilityModel (void) const +{ + return m_auvMobilityModel; +} + +void +AuvWaypointMobilityModel::DoDispose (void) +{ + MobilityModel::DoDispose (); +} + +void +AuvWaypointMobilityModel::Update (void) const +{ + const Time now = Simulator::Now (); + bool newWaypoint = false; + + if ( now == m_lastUpdate ) + { + return; + } + + if ( now < m_current.time ) + { + return; + } + + while ( now >= m_next.time ) + { + + if ( m_waypoints.empty () && m_waypointReachedCallback.IsNull () ) + { + if ( m_current.time <= m_next.time ) + { + /* + Set m_next.time = -1 to make sure this doesn't happen more than once. + The comparison here still needs to be '<=' in the case of mobility with one waypoint. + */ + m_next.time = Seconds (-1.0); + m_current.position = m_next.position; + m_current.time = now; + m_velocity = Vector (0,0,0); + m_auvMobilityModel->SetVelocity (m_velocity); + NotifyCourseChange (); + } + else + { + m_current.time = now; + } + return; + } + + if ( m_energyDepleted ) + { + return; + } + + if ( !m_waypoints.empty () ) + { + m_current = m_next; + m_next = m_waypoints.front (); + m_waypoints.pop_front (); + newWaypoint = true; + } + + const double t_span = (m_next.time - m_current.time).GetSeconds (); + + if (t_span > 0) + { + m_velocity.x = (m_next.position.x - m_current.position.x) / t_span; + m_velocity.y = (m_next.position.y - m_current.position.y) / t_span; + m_velocity.z = (m_next.position.z - m_current.position.z) / t_span; + } + else + { + m_velocity = Vector (0,0,0); + } + + m_auvMobilityModel->SetVelocity (m_velocity); + + if ( now > m_lastUpdate ) + { + m_callbackDone = false; + } + m_lastUpdate = now; + if ( !m_waypointReachedCallback.IsNull () && (!m_callbackDone) ) + { + m_callbackDone = true; + // if the callback causes a call to AddWaypoint() + // this will prevent it from overriding m_current and m_next + bool waypointsEmpty = m_waypoints.empty (); + if (waypointsEmpty) + { + m_waypoints.push_back (Waypoint (Seconds (0), Vector (0,0,0))); + } + m_waypointReachedCallback (); + if (waypointsEmpty) + { + m_waypoints.pop_front (); + } + } + if ( m_waypoints.empty () && !m_waypointReachedCallback.IsNull () ) + { + break; + } + } + + if ( now > m_current.time ) // Won't ever be less, but may be equal + { + const double t_diff = (now - m_current.time).GetSeconds (); + m_current.position.x += m_velocity.x * t_diff; + m_current.position.y += m_velocity.y * t_diff; + m_current.position.z += m_velocity.z * t_diff; + m_current.time = now; + } + + if ( newWaypoint ) + { + NotifyCourseChange (); + } + + else if ( !m_waypointReachedCallback.IsNull () && m_current.time == m_next.time ) + { + m_velocity = Vector (0,0,0); + m_auvMobilityModel->SetVelocity (m_velocity); + NotifyCourseChange (); + } +} + +void +AuvWaypointMobilityModel::DoSetPosition (const Vector &position) +{ + const Time now = Simulator::Now (); + + if ( m_initialPositionIsWaypoint ) + { + AddWaypoint (Waypoint (now, position)); + return; + } + + Update (); + m_current.time = std::max (now, m_next.time); + m_current.position = position; + m_velocity = Vector (0,0,0); + m_auvMobilityModel->SetVelocity (m_velocity); + + if ( now >= m_current.time ) + { + // This is only a course change if the node is actually moving + NotifyCourseChange (); + } +} + +Vector +AuvWaypointMobilityModel::DoGetPosition (void) const +{ + AuvWaypointMobilityModel::Update (); + return m_current.position; +} + + +void +AuvWaypointMobilityModel::AddWaypoint (const Waypoint &waypoint) +{ + NS_ABORT_MSG_IF ((Simulator::Now () <= waypoint.time) && waypoint.time < Seconds (0), + "Waypoint time should be in the future"); + NS_ABORT_MSG_IF ( !m_waypoints.empty () && (m_waypoints.back ().time >= waypoint.time), + "Waypoints must be added in ascending time order"); + + if (m_waypoints.empty ()) + { + m_current = m_next = waypoint; + } + m_waypoints.push_back (waypoint); + if ( !m_lazyNotify ) + { + Simulator::Schedule (waypoint.time - Simulator::Now (), &AuvWaypointMobilityModel::Update, this); + } +} + + +void +AuvWaypointMobilityModel::SetWaypointReachedCallback (WaypointReachedCallback callback) +{ + NS_LOG_FUNCTION (this); + if (callback.IsNull ()) + { + NS_LOG_DEBUG ("AuvWaypointMobilityModel:Setting NULL waypoint reached callback!"); + } + m_waypointReachedCallback = callback; +} + +void +AuvWaypointMobilityModel::HandleEnergyDepletion () +{ + m_energyDepleted = true; + m_waypoints.clear (); + m_current.time = Simulator::Now (); + m_next = m_current; + m_velocity = Vector (0,0,0); + m_auvMobilityModel->SetVelocity (m_velocity); + NotifyCourseChange (); +} + +void +AuvWaypointMobilityModel::HandleEnergyRecharged () +{ + m_energyDepleted = false; +} + +} // namespace ns3 + --- a/src/auv/model/auv-waypoint-mobility-model.h +++ a/src/auv/model/auv-waypoint-mobility-model.h @@ -0,0 +1,105 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * 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: Andrea Sacco + */ + +#ifndef AUV_WAYPOINT_MOBILITY_MODEL_H +#define AUV_WAYPOINT_MOBILITY_MODEL_H + +#include "ns3/log.h" +#include "ns3/abort.h" +#include "ns3/simulator.h" +#include "ns3/pointer.h" +#include "ns3/auv-mobility-model.h" +#include "ns3/waypoint-mobility-model.h" + +namespace ns3 { + +/** + * \ingroup auv + * + * + */ + + +class AuvWaypointMobilityModel : public WaypointMobilityModel +{ +public: + typedef Callback WaypointReachedCallback; + + /** + * Register this type with the TypeId system. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + + /** + * Create a path with no waypoints at location (0,0,0). + */ + AuvWaypointMobilityModel (); + virtual ~AuvWaypointMobilityModel (); + + /** + * \param model mobility model to be used as waypoint validator + */ + void SetValidatorMobilityModel (Ptr auvMobilityModel); + + /** + * \return the underlying mobility model + */ + Ptr GetValidatorMobilityModel (void) const; + + /** + * \param waypoint waypoint to append to the object path. + * + * Add a waypoint to the path of the object. The time must + * be greater than the previous waypoint added, otherwise + * a fatal error occurs. The first waypoint is set as the + * current position with a velocity of zero. + * + */ + void AddWaypoint (const Waypoint &waypoint); + + void SetWaypointReachedCallback (WaypointReachedCallback callback); + + void HandleEnergyDepletion (); + void HandleEnergyRecharged (); + +private: + void Update (void) const; + virtual void DoSetPosition (const Vector &position); + virtual Vector DoGetPosition (void) const; + virtual void DoDispose (void); + bool m_lazyNotify; + mutable Waypoint m_current; + mutable Vector m_velocity; + mutable Waypoint m_next; + bool m_initialPositionIsWaypoint; + mutable std::deque m_waypoints; + Ptr m_auvMobilityModel; + WaypointReachedCallback m_waypointReachedCallback; + bool m_energyDepleted; + mutable Time m_lastUpdate; + mutable bool m_callbackDone; + + + +}; + +} // namespace ns3 + +#endif /* AUV_WAYPOINT_MOBILITY_MODEL_H */ + --- a/src/auv/model/glider-energy-model.cc +++ a/src/auv/model/glider-energy-model.cc @@ -0,0 +1,217 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "glider-energy-model.h" + +NS_LOG_COMPONENT_DEFINE ("GliderEnergyModel"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (GliderEnergyModel); + +TypeId +GliderEnergyModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::GliderEnergyModel") + .SetParent () + .AddConstructor () + .AddTraceSource ("TotalEnergyConsumption", + "Total energy consumption of the glider AUV.", + MakeTraceSourceAccessor (&GliderEnergyModel::m_totalEnergyConsumption), + "ns3::TracedValueCallback::Double") + ; + return tid; +} + +GliderEnergyModel::GliderEnergyModel () +{ + NS_LOG_FUNCTION (this); + m_currentBuoyancy = 0.0; + m_currentW = 0.0; + m_actualCurrentDrain = 0.0; + m_lastUpdateTime = Seconds (0.0); + m_energyDepletionCallback.Nullify (); + m_energyRechargedCallback.Nullify (); + m_node = NULL; + m_source = NULL; +} + +GliderEnergyModel::~GliderEnergyModel () +{ + m_energyDepletionCallback.Nullify (); + m_energyRechargedCallback.Nullify (); + m_node = NULL; + m_source = NULL; +} + +void +GliderEnergyModel::SetNode (Ptr node) +{ + NS_LOG_FUNCTION (this << node); + NS_ASSERT (node != NULL); + m_node = node; +} + +Ptr +GliderEnergyModel::GetNode (void) const +{ + return m_node; +} + +void +GliderEnergyModel::SetEnergySource (Ptr source) +{ + NS_LOG_FUNCTION (this << source); + NS_ASSERT (source != NULL); + m_source = source; +} + +double +GliderEnergyModel::GetTotalEnergyConsumption (void) const +{ + NS_LOG_FUNCTION (this); + + Time duration = Simulator::Now () - m_lastUpdateTime; + double power = GetPower (m_currentBuoyancy, m_currentW); + double energyToDecrease = duration.GetSeconds () * power; + + return m_totalEnergyConsumption + energyToDecrease; +} + +void +GliderEnergyModel::ChangeState (int newState) +{ + NS_FATAL_ERROR ("ChangeState not implemented, use ChangeEnergyConsumption instead."); +} + +void +GliderEnergyModel::ChangeEnergyConsumption (const double buoyancy, const double W) +{ + NS_LOG_FUNCTION (this << buoyancy << W); + + Time duration = Simulator::Now () - m_lastUpdateTime; + NS_ASSERT (duration.GetNanoSeconds () >= 0); // check if duration is valid + + // update remaining energy accordingly + double power = GetPower (m_currentBuoyancy, m_currentW); + double energyToDecrease = duration.GetSeconds () * power; + + // update total energy consumption + m_totalEnergyConsumption += energyToDecrease; + + // update current buoyancy + m_currentBuoyancy = buoyancy; + // update current vertical speed + m_currentW = W; + // update current drain + power = GetPower (m_currentBuoyancy, m_currentW); + double supplyVoltage = m_source->GetSupplyVoltage (); + m_actualCurrentDrain = power / supplyVoltage; + + // update last update time stamp + m_lastUpdateTime = Simulator::Now (); + + // notify energy source + m_source->UpdateEnergySource (); + + // some debug message + NS_LOG_DEBUG ("GliderEnergyModel:Total energy consumption at node #" << + m_node->GetId () << " is " << m_totalEnergyConsumption << "J"); +} + +void +GliderEnergyModel::SetEnergyDepletionCallback (GliderEnergyDepletionCallback callback) +{ + NS_LOG_FUNCTION (this); + if (callback.IsNull ()) + { + NS_LOG_DEBUG ("GliderEnergyModel:Setting NULL energy depletion callback!"); + } + m_energyDepletionCallback = callback; +} + +void +GliderEnergyModel::SetEnergyRechargedCallback (GliderEnergyRechargedCallback callback) +{ + NS_LOG_FUNCTION (this); + if (callback.IsNull ()) + { + NS_LOG_DEBUG ("GliderEnergyModel:Setting NULL energy recharged callback!"); + } + m_energyRechargedCallback = callback; +} + +void +GliderEnergyModel::HandleEnergyDepletion (void) +{ + NS_LOG_FUNCTION (this); + NS_LOG_DEBUG ("GliderEnergyModel:Energy is depleted at node #" << + m_node->GetId ()); + + // invoke energy depletion callback, if set. + if (!m_energyDepletionCallback.IsNull ()) + { + m_energyDepletionCallback (); + } +} + +void +GliderEnergyModel::HandleEnergyRecharged (void) +{ + NS_LOG_FUNCTION (this); + NS_LOG_DEBUG ("GliderEnergyModel:Energy is recharged at node #" << + m_node->GetId ()); + + if (!m_energyRechargedCallback.IsNull ()) + { + m_energyRechargedCallback (); + } +} +/* + * Private functions start here. + */ + +void +GliderEnergyModel::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_node = NULL; + m_source = NULL; + m_energyDepletionCallback.Nullify (); +} + +double +GliderEnergyModel::DoGetCurrentA (void) const +{ + NS_LOG_FUNCTION (this); + + return m_actualCurrentDrain; +} + +double +GliderEnergyModel::GetPower (double buoyancy, double W) const +{ + // power needed to get the buoyancy, in watts + double power = buoyancy / 100 * W; + + return power; +} + +} // namespace ns3 + --- a/src/auv/model/glider-energy-model.h +++ a/src/auv/model/glider-energy-model.h @@ -0,0 +1,184 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef GLIDER_ENERGY_MODEL_H +#define GLIDER_ENERGY_MODEL_H + +#include "ns3/device-energy-model.h" +#include "ns3/energy-source.h" +#include "ns3/traced-value.h" +#include "ns3/log.h" +#include "ns3/simulator.h" + + +namespace ns3 { + +/** + * \ingroup auv + * \brief Keeps track of the Seaglider's energy consumption + * + * Implement the DeviceEnergyModel interface for the Seaglider + * AUV. The energy consumption is calculated with the product of + * buoyancy with vertical speed [1]. + * + * This model should be used in conjunction with the GliderMobilityModel. + * The mobility model, in fact, on every course change, updates the + * energy consumption with the new buoyancy/speed values. + * + * References: + * + * [1] Eriksen et al, "Seaglider: A Long-Range Autonomous Underwater Vehicle for Oceanographic Research" + * URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=972073&userType=inst + */ +class GliderEnergyModel : public DeviceEnergyModel +{ +public: + // / Callback type for energy depletion handling. + typedef Callback GliderEnergyDepletionCallback; + typedef Callback GliderEnergyRechargedCallback; + +public: + static TypeId GetTypeId (void); + GliderEnergyModel (); + virtual ~GliderEnergyModel (); + + /** + * \brief Sets pointer to node. + * + * \param node Pointer to node. + * + * Implements DeviceEnergyModel::SetNode. + */ + virtual void SetNode (Ptr node); + + /** + * \brief Gets pointer to node. + * + * \returns Pointer to node. + * + * Implements DeviceEnergyModel::GetNode. + */ + virtual Ptr GetNode (void) const; + + /** + * \brief Sets pointer to EnergySouce installed on node. + * + * \param source Pointer to EnergySource installed on node. + * + * Implements DeviceEnergyModel::SetEnergySource. + */ + virtual void SetEnergySource (Ptr source); + + /** + * \returns Total energy consumption of the vehicle. + * + * Implements DeviceEnergyModel::GetTotalEnergyConsumption. + */ + virtual double GetTotalEnergyConsumption (void) const; + + /** + * \param newState New state the device is in. + * + * DeviceEnergyModel is a state based model. This function is implemented by + * all child of DeviceEnergyModel to change the model's state. States are to + * be defined by each child using an enum (int). + */ + virtual void ChangeState (int newState); + + /** + * \param buoyancy buoyancy value in grams + * \param W vertical speed value in m/s + * + * Update the energy consumption according to the buoyancy value and vertical + * speed value. + */ + void ChangeEnergyConsumption (const double buoyancy, const double W); + + /** + * \param callback Callback function. + * + * Sets callback for energy depletion handling. + */ + void SetEnergyDepletionCallback (GliderEnergyDepletionCallback callback); + + /** + * \param callback Callback function. + * + * Sets callback for energy recharged handling. + */ + void SetEnergyRechargedCallback (GliderEnergyRechargedCallback callback); + + /** + * \brief Handles energy depletion. + * + * Implements DeviceEnergyModel::HandleEnergyDepletion + */ + virtual void HandleEnergyDepletion (void); + + /** + * \brief Handles energy recharge. + * + * Implements DeviceEnergyModel::HandleEnergyRecharged + */ + virtual void HandleEnergyRecharged (void); + +private: + void DoDispose (void); + + /** + * \returns Current draw of device, at current state. + * + * Implements DeviceEnergyModel::GetCurrentA. + */ + virtual double DoGetCurrentA (void) const; + + /** + * \param buoyancy the buoyancy value in grams + * \param W the vertical speed in m/s + * \return the needed power in watts + * + * This get the power needed to maintain a given buoyancy and vertical speed + */ + double GetPower (double buoyancy, double W) const; + +private: + Ptr m_node; + Ptr m_source; + + // This variable keeps track of the total energy consumed by this particular model. + TracedValue m_totalEnergyConsumption; + + // actual current drain + double m_actualCurrentDrain; + // current buoyancy value in grams + double m_currentBuoyancy; + // current vertical speed value in m/s + double m_currentW; + // time stamp of previous energy update + Time m_lastUpdateTime; + + // energy depletion callback + GliderEnergyDepletionCallback m_energyDepletionCallback; + GliderEnergyRechargedCallback m_energyRechargedCallback; +}; + +} // namespace ns3 + +#endif /* GLIDER_ENERGY_MODEL_H */ --- a/src/auv/model/glider-mobility-model.cc +++ a/src/auv/model/glider-mobility-model.cc @@ -0,0 +1,470 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "glider-mobility-model.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("GliderMobilityModel"); + +NS_OBJECT_ENSURE_REGISTERED (GliderMobilityModel); + +TypeId +GliderMobilityModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::GliderMobilityModel") + .SetParent (AuvMobilityModel::GetTypeId ()) + .AddConstructor () + .AddAttribute ("MaxDepth", "The maximum operational depth, in m", + DoubleValue (-1000.0), + MakeDoubleAccessor (&GliderMobilityModel::m_maxDepth), + MakeDoubleChecker ()) + .AddAttribute ("MinGlideAngle", "The minimum glide angle of the glider, in degrees.", + DoubleValue (14.0), // correspond to a 1/4 glide angle + MakeDoubleAccessor (&GliderMobilityModel::m_minGlideAngle), + MakeDoubleChecker ()) + .AddAttribute ("MaxGlideAngle", "The maximum glide angle of the glider, in degrees.", + DoubleValue (68.2), // correspond to a 5/2 glide angle, derived from the paper + MakeDoubleAccessor (&GliderMobilityModel::m_maxGlideAngle), + MakeDoubleChecker ()) +// .AddAttribute ("MaxHSpeed", "The maximum horizontal speed of the glider, in m/s.", +// DoubleValue (0.32), // derived from the paper +// MakeDoubleAccessor (&GliderMobilityModel::m_maxU), +// MakeDoubleChecker ()) + .AddAttribute ("MaxWSpeed", "The maximum vertical speed of the glider, in m/s.", + DoubleValue (0.5), // derived from the paper + MakeDoubleAccessor (&GliderMobilityModel::m_maxW), + MakeDoubleChecker ()) + .AddAttribute ("MaxBuoyancy", "The maximum buoyancy supported by the glider buoyancy control system, in grammes", + DoubleValue (200), // derived from the paper + MakeDoubleAccessor (&GliderMobilityModel::m_maxBuoyancy), + MakeDoubleChecker ()) + ; + return tid; +} + +GliderMobilityModel::GliderMobilityModel () + : m_direction (0), + m_speed (0), + m_pitch (0), + m_depth (0), + m_deployed (false), + m_node (NULL) +{ + m_emergeCb.Nullify (); + m_submergeCb.Nullify (); +} + +GliderMobilityModel::~GliderMobilityModel () +{ + m_emergeCb.Nullify (); + m_submergeCb.Nullify (); + m_node = NULL; +} + +Vector +GliderMobilityModel::RoundPosition (const Vector &pos, uint16_t decimals) const +{ + Vector roundPos; + + double off = std::pow (10, decimals); + roundPos.x = (std::floor ((pos.x * off) + 0.5)) / off; + roundPos.y = (std::floor ((pos.y * off) + 0.5)) / off; + roundPos.z = (std::floor ((pos.z * off) + 0.5)) / off; + + return roundPos; +} + +double +GliderMobilityModel::GetBuoyancy (void) const +{ + return m_buoyancy; +} + +void +GliderMobilityModel::SetNode (const Ptr node) +{ + NS_ASSERT (node != NULL); + m_node = node; +} + +Ptr +GliderMobilityModel::GetNode (void) const +{ + return m_node; +} + +void +GliderMobilityModel::SetEmergeCallback (Callback > cb) +{ + m_emergeCb = cb; +} + +void +GliderMobilityModel::SetSubmergeCallback (Callback > cb) +{ + m_submergeCb = cb; +} + +Vector +GliderMobilityModel::DoGetPosition (void) const +{ + m_helper.Update (); + + // get the current position + Vector pos = m_helper.GetCurrentPosition (); + + // get the rounded precision position + Vector rpos = RoundPosition (pos, 4); + + return rpos; +} + +void +GliderMobilityModel::DoSetPosition (const Vector &position) +{ + NS_ASSERT (!m_deployed); + + m_helper.SetPosition (position); +} + +Vector +GliderMobilityModel::DoGetVelocity (void) const +{ + return m_helper.GetVelocity (); +} + +void +GliderMobilityModel::DoSetVelocity (const Vector &velocity) +{ + // if velocity is 0 + if (CalculateDistance (velocity,Vector (0, 0, 0)) == 0) + { + // stop the vehicle + DoStop (); + + return; + } + + // get the total speed magnitude + double speed = std::sqrt ((velocity.x * velocity.x) + + (velocity.y * velocity.y) + + (velocity.z * velocity.z)); + + // calculate the pitch + double pitch = std::asin ((velocity.z / speed)); + + NS_ASSERT (std::abs (pitch * 180 / M_PI) <= m_maxGlideAngle); + + // get horizontal and vertical speeds + double u = speed * std::cos (pitch); + double w = speed * std::sin (pitch); + // get the required buoyancy for the given speed + double buoyancy = GetBuoyancy (std::abs (u), std::abs (w)); + + NS_ASSERT (buoyancy <= m_maxBuoyancy); + m_buoyancy = buoyancy; + m_speed = speed; + m_pitch = pitch; + + // get the direction + double dir = std::atan2 (velocity.y, velocity.x); + m_direction = dir; + + m_helper.SetVelocity (velocity); + + Move (); +} + +void +GliderMobilityModel::UpdatePowerConsumption (double buoyancy, double W) +{ + Ptr source = m_node->GetObject (); + if (source != NULL) + { + // retrieve device energy model from energy source + DeviceEnergyModelContainer modelCont; + for (EnergySourceContainer::Iterator it = source->Begin (); it != source->End (); it++) + { + Ptr source = *it; + + modelCont = source->FindDeviceEnergyModels ("ns3::GliderEnergyModel"); + if (modelCont.GetN () != 0) + { + break; + } + } + NS_ASSERT (modelCont.GetN () != 0); + + // get pointer + Ptr devModel = DynamicCast (modelCont.Get (0)); + devModel->ChangeEnergyConsumption (buoyancy, std::abs (W)); + } +} + +void +GliderMobilityModel::Update (void) +{ + // get the vector components + double cosD = std::cos (m_direction); + double cosP = std::cos (m_pitch); + double sinD = std::sin (m_direction); + double sinP = std::sin (m_pitch); + + // set the velocity vector + m_helper.SetVelocity (Vector (m_speed * cosD * cosP, + m_speed * sinD * cosP, + m_speed * sinP)); + + // update buoyancy + m_buoyancy = GetBuoyancy (std::abs (m_speed * cosP), + std::abs (m_speed * sinP)); + + // update depth + m_depth = GetDepth (); + + // update the helper + m_helper.Update (); + + // notify the change + NotifyCourseChange (); +} + +void +GliderMobilityModel::DoMove (void) +{ + if (!m_deployed) + { + // the vehicle has just been deployed + m_deployed = true; + } + + // unpause the helper + m_helper.Unpause (); + + // update the helper with the new nav params + Update (); + + // update the energy consumption + UpdatePowerConsumption (m_buoyancy, std::abs (m_speed * std::sin (m_pitch))); + + // compute the necessary time to reach the maximum operative depth + // or water surface and set a stop event + double vertVel = m_helper.GetVelocity ().z; + + if (vertVel != 0) + { + double stopTime = 0; + if (vertVel < 0) + { + stopTime = (m_maxDepth - DoGetDepth ()) / vertVel; + } + else + { + stopTime = (0 - DoGetDepth ()) / vertVel; + } + + Simulator::Cancel (m_stop); + m_stop = Simulator::Schedule (Seconds (stopTime), + &GliderMobilityModel::Stop, + this); + } +} + +void +GliderMobilityModel::DoStop (void) +{ + // Update (); + m_helper.Update (); + + // now the vehicle is stopped + m_speed = 0; + m_buoyancy = 0; + + // update the energy consumption + UpdatePowerConsumption (m_buoyancy, 0); + + Simulator::Cancel (m_stop); + m_helper.Pause (); +} + +void +GliderMobilityModel::DoEmerge (double depth) +{ + NS_ASSERT (depth <= 0 && depth >= m_maxDepth); + + double deltaDepth = depth - GetDepth (); + + // we want to emerge so the delta depth must be positive + NS_ASSERT (deltaDepth > 0); + // set the maximum pitch value + SetPitch (m_maxGlideAngle); + // set the maximum speed value + // from the paper, the vertical speed seems to not go over 0.15 m/s + // even if there are "outlayers" at 0.5 m/s + SetSpeed (m_maxW / std::sin (m_pitch)); + + // compute the time needed to reach to the specified depth + double emergeTime = deltaDepth / m_maxW; + + // set an event to stop the vehicle when it have reached the specified depth + m_stop = Simulator::Schedule (Seconds (emergeTime), + &GliderMobilityModel::DoStop, + this); + + if (!m_emergeCb.IsNull ()) + { + // schedule the call to the emerge callback + Simulator::Schedule (Seconds (emergeTime), + &GliderMobilityModel::m_emergeCb, + this, + this); + } +} + +void +GliderMobilityModel::DoSubmerge (double depth) +{ + NS_ASSERT (depth >= m_maxDepth && depth <= 0); + + double deltaDepth = depth - GetDepth (); + + // we want to submerge so the delta depth must be negative + NS_ASSERT (deltaDepth < 0); + // set the maximum pitch value + SetPitch (-m_maxGlideAngle); + // set the maximum speed value + SetSpeed (-m_maxW / std::sin (m_pitch)); + + // compute the time needed to reach to the specified depth + double submergeTime = deltaDepth / -m_maxW; + // set an event to stop the vehicle when it have reached the specified depth + m_stop = Simulator::Schedule (Seconds (submergeTime), + &GliderMobilityModel::DoStop, + this); + + if (!m_submergeCb.IsNull ()) + { + // schedule the call to the submerge callback + Simulator::Schedule (Seconds (submergeTime), + &GliderMobilityModel::m_submergeCb, + this, + this); + } +} + +double +GliderMobilityModel::DoGetPitch () const +{ + return m_pitch * 180 / M_PI; +} + +void +GliderMobilityModel::DoSetPitch (double pitch) +{ + // actually sets the glide angle + NS_ASSERT_MSG (std::abs (pitch) <= m_maxGlideAngle, + "An excessive glide angle has been set"); + + NS_ASSERT_MSG (std::abs (pitch) >= m_minGlideAngle, + "An insufficient glide angle has been set"); + + // the pitch angle is stored in radians + m_pitch = pitch * M_PI / 180; + + Update (); +} + +double +GliderMobilityModel::DoGetDepth (void) +{ + // update the current depth + Vector pos = GetPosition (); + m_depth = pos.z; + + return m_depth; +} + +double +GliderMobilityModel::DoGetDirection (void) const +{ + return m_direction * 180 / M_PI; +} + +void +GliderMobilityModel::DoSetDirection (double dir) +{ + m_direction = dir * M_PI / 180; + + Update (); +} + +double +GliderMobilityModel::DoGetSpeed () const +{ + return m_speed; +} + +void +GliderMobilityModel::DoSetSpeed (double speed) +{ + NS_ASSERT ((float) speed <= (float) m_maxW / std::sin (m_maxGlideAngle * M_PI / 180)); + + m_speed = speed; + + Update (); + Move (); +} + +double +GliderMobilityModel::GetBuoyancy (double U, double W) const +{ + // here we get the bouyancy needed to mantain + // the given velocity at the given glide anlge + double a = 0.0022436; + double b = 0.01249; + double c = 9.8016e-6; + // v^2=U^2+W^2 + double v = std::sqrt (U * U + W * W); + // water density kg/m^3 + double rho = 1023; + // dynamic pressure + double q = 0.5 * rho * (v * v); + // seaglider hull length, in m + double l = 1.8; + + double tgteta = W / U; + double teta = std::atan (tgteta); + + double lambda = (a * a) / (b * (1 / std::pow (q, 0.25)) * c); + + double temp = (q * (l * l) * (a * a) * std::sin (teta)) / + (2 * c * (std::cos (teta) * std::cos (teta))); + + // positive sqrt solution for Buoyancy + // double Bp = temp*(1 + std::sqrt(1 - 4/(lambda*(tgteta * tgteta)))); + // negative sqrt solution for Buoyancy + double Bn = temp * (1 - std::sqrt (1 - 4 / (lambda * (tgteta * tgteta)))); + + // the negative solution is returned, as the more efficient, as said into the article + // TODO discrepancies with paper values + return Bn * 100; +} + +} // namespace ns3 --- a/src/auv/model/glider-mobility-model.h +++ a/src/auv/model/glider-mobility-model.h @@ -0,0 +1,133 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef GLIDER_MOBILITY_MODEL_H_ +#define GLIDER_MOBILITY_MODEL_H_ + +#include "auv-mobility-model.h" +#include "ns3/event-id.h" +#include "ns3/glider-energy-model.h" + +namespace ns3 { + +/** + * \ingroup auv + * \brief keep track of the position of a Seaglider AUV + * + * The model is based on the constant velocity mobility model but introduces the physical + * constraints characteristics of the Seaglider AUV: + * + * - maximum operational depth, 1000 m + * - minimum glide angle, +/- 14 degrees + * - maximum glide angle, +/- 68,2 degrees + * - maximum horizontal speed, 0.32 m/s + * - maximum vertical speed, 0.5 + * - maximum buoyancy, 200 grams + * + * Unlike motor propelled AUV, Seaglider exploits small changes in its buoyancy that, + * in conjunction with wings, can convert vertical motion to horizontal. + * So, a glider will reach a point into the water by describing a "saw-tooth" movement. + * Thus the model, keeps track also of the buoyancy needed to maintain a given speed value. + * + * All the technical details and model's equations, can be found in [1] + * + * References: + * [1] Eriksen et al, "Seaglider: A Long-Range Autonomous Underwater Vehicle for Oceanographic Research" + * URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=972073&userType=inst + */ +class GliderMobilityModel : public AuvMobilityModel +{ +public: + static TypeId GetTypeId (void); + GliderMobilityModel (); + ~GliderMobilityModel (); + + /** + * \returns the current buoyancy of the glider in grams + */ + double GetBuoyancy (void) const; + /** + * \param node the node associated with the mobility model + */ + void SetNode (const Ptr node); + /** + * \returns the associated node + */ + Ptr GetNode (void) const; + + virtual void SetEmergeCallback (Callback > cb); + virtual void SetSubmergeCallback (Callback > cb); + +private: + /** + * Round a Vector of double, to the given decimal precision + * + * \param pos the position vector to be rounded + * \param decimals the decimal precision + * \returns the rounded position vector + */ + Vector RoundPosition (const Vector &pos, uint16_t decimals) const; + void Update (void); + void UpdatePowerConsumption (double buoyancy, double W); + + virtual Vector DoGetPosition (void) const; + virtual void DoSetPosition (const Vector &position); + virtual Vector DoGetVelocity (void) const; + + virtual void DoMove (void); + virtual void DoStop (void); + virtual void DoEmerge (double depth); + virtual void DoSubmerge (double depth); + virtual double DoGetPitch () const; + virtual void DoSetPitch (double pitch); + virtual double DoGetDepth (void); + virtual double DoGetDirection (void) const; + virtual void DoSetDirection (double dir); + virtual double DoGetSpeed () const; + virtual void DoSetSpeed (double speed); + virtual void DoSetVelocity (const Vector &velocity); + + // get the buoyancy value in grams from vertical and horizontal speed values + double GetBuoyancy (double U, double W) const; + + ConstantVelocityHelper m_helper; + double m_direction; + double m_speed; + double m_pitch; + double m_depth; + double m_buoyancy; + double m_minGlideAngle; + double m_maxGlideAngle; + // double m_maxU; + double m_maxW; + double m_maxBuoyancy; + double m_maxDepth; + bool m_deployed; + + EventId m_stop; + Ptr m_node; + + Callback > m_emergeCb; + Callback > m_submergeCb; +}; + +} // namespace ns3 + +#endif /* GLIDER_MOBILITY_MODEL_H_ */ --- a/src/auv/model/remus-energy-model.cc +++ a/src/auv/model/remus-energy-model.cc @@ -0,0 +1,218 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "remus-energy-model.h" + +NS_LOG_COMPONENT_DEFINE ("RemusEnergyModel"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (RemusEnergyModel); + +TypeId +RemusEnergyModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RemusEnergyModel") + .SetParent () + .AddConstructor () + .AddAttribute ("PowerSpeedRatio", + "Consumed power ratio with respect to motor speed", + DoubleValue (10.0), // in W*s/m + MakeDoubleAccessor (&RemusEnergyModel::m_powerSpeedRatio), + MakeDoubleChecker ()) + .AddTraceSource ("TotalEnergyConsumption", + "Total energy consumption of the radio device.", + MakeTraceSourceAccessor (&RemusEnergyModel::m_totalEnergyConsumption), + "ns3::TracedValueCallback::Double") + ; + return tid; +} + +RemusEnergyModel::RemusEnergyModel () +{ + NS_LOG_FUNCTION (this); + m_currentSpeed = 0.0; + m_lastUpdateTime = Seconds (0.0); + m_energyDepletionCallback.Nullify (); + m_energyRechargedCallback.Nullify (); + m_node = NULL; + m_source = NULL; +} + +RemusEnergyModel::~RemusEnergyModel () +{ + m_energyDepletionCallback.Nullify (); + m_energyRechargedCallback.Nullify (); + m_node = NULL; + m_source = NULL; +} +void +RemusEnergyModel::SetNode (Ptr node) +{ + NS_LOG_FUNCTION (this << node); + NS_ASSERT (node != NULL); + m_node = node; +} + +Ptr +RemusEnergyModel::GetNode (void) const +{ + return m_node; +} + +void +RemusEnergyModel::SetEnergySource (Ptr source) +{ + NS_LOG_FUNCTION (this << source); + NS_ASSERT (source != NULL); + m_source = source; +} + +double +RemusEnergyModel::GetTotalEnergyConsumption (void) const +{ + NS_LOG_FUNCTION (this); + + Time duration = Simulator::Now () - m_lastUpdateTime; + double power = GetPower (m_currentSpeed); + double energyToDecrease = duration.GetSeconds () * power; + + return m_totalEnergyConsumption + energyToDecrease; +} + +void +RemusEnergyModel::ChangeState (int newState) +{ + NS_FATAL_ERROR ("ChangeState not implemented, use ChangeEnergyConsumption instead."); +} + +void +RemusEnergyModel::ChangeEnergyConsumption (const double speed) +{ + NS_LOG_FUNCTION (this << speed); + + Time duration = Simulator::Now () - m_lastUpdateTime; + NS_ASSERT (duration.GetNanoSeconds () >= 0); // check if duration is valid + + // update remaining energy accordingly + double power = GetPower (m_currentSpeed); + double energyToDecrease = duration.GetSeconds () * power; + + // update total energy consumption + m_totalEnergyConsumption += energyToDecrease; + + // update current speed value + m_currentSpeed = speed; + // update current drain + power = GetPower (m_currentSpeed); + double supplyVoltage = m_source->GetSupplyVoltage (); + m_actualCurrentDrain = power / supplyVoltage; + + // update last update time stamp + m_lastUpdateTime = Simulator::Now (); + + // notify energy source + m_source->UpdateEnergySource (); + + // some debug message + NS_LOG_DEBUG ("RemusEnergyModel:Total energy consumption at node #" << + m_node->GetId () << " is " << m_totalEnergyConsumption << "J"); +} + +void +RemusEnergyModel::SetEnergyDepletionCallback (RemusEnergyDepletionCallback callback) +{ + NS_LOG_FUNCTION (this); + if (callback.IsNull ()) + { + NS_LOG_DEBUG ("RemusEnergyModel:Setting NULL energy depletion callback!"); + } + m_energyDepletionCallback = callback; +} + +void +RemusEnergyModel::SetEnergyRechargedCallback (RemusEnergyRechargedCallback callback) +{ + NS_LOG_FUNCTION (this); + if (callback.IsNull ()) + { + NS_LOG_DEBUG ("RemusEnergyModel:Setting NULL energy recharged callback!"); + } + m_energyRechargedCallback = callback; +} + +void +RemusEnergyModel::HandleEnergyDepletion (void) +{ + NS_LOG_FUNCTION (this); + NS_LOG_DEBUG ("RemusEnergyModel:Energy is depleted at node #" << + m_node->GetId ()); + + // invoke energy depletion callback, if set. + if (!m_energyDepletionCallback.IsNull ()) + { + m_energyDepletionCallback (); + } +} + +void +RemusEnergyModel::HandleEnergyRecharged (void) +{ + NS_LOG_FUNCTION (this); + NS_LOG_DEBUG ("RemusEnergyModel:Energy is recharged at node #" << + m_node->GetId ()); + + if (!m_energyRechargedCallback.IsNull ()) + { + m_energyRechargedCallback (); + } +} +/* + * Private functions start here. + */ + +void +RemusEnergyModel::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_node = NULL; + m_source = NULL; + m_energyDepletionCallback.Nullify (); +} + +double +RemusEnergyModel::DoGetCurrentA (void) const +{ + NS_LOG_FUNCTION (this); + + return m_actualCurrentDrain; +} + +double +RemusEnergyModel::GetPower (double speed) const +{ + // power needed, in watts + // it is about 10 times the speed in m/s, thus for 1.5 m/s of navigation speed + // the electric motor will drain 15 W of power + double power = speed * m_powerSpeedRatio; + + return power; +} + +} // namespace ns3 --- a/src/auv/model/remus-energy-model.h +++ a/src/auv/model/remus-energy-model.h @@ -0,0 +1,178 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#ifndef REMUS_ENERGY_MODEL_H +#define REMUS_ENERGY_MODEL_H + +#include "ns3/device-energy-model.h" +#include "ns3/energy-source.h" +#include "ns3/traced-value.h" +#include "ns3/log.h" +#include "ns3/simulator.h" + +namespace ns3 { + +/** + * \ingroup auv + * \brief Keeps track of the REMUS AUV energy consumption + * + * The class model the energy consumed by the AUV for navigation. + * The REMUS is propelled by a brush-less electric motor. + * + * Consumption values have been taken from [1] and Hydroinc European salesman. + * A typical value is 15 W @ 1.5 m/s of navigation speed. + * + * Since there are not detailed datasheet and specifications publicly available, + * a power consumption linear with speed, is considered. + * + * References: + * [1] Hydroinc REMUS 100 specifications; http://www.hydroidinc.com/100spec.html + */ +class RemusEnergyModel : public DeviceEnergyModel +{ +public: + // / Callback type for energy depletion handling. + typedef Callback RemusEnergyDepletionCallback; + typedef Callback RemusEnergyRechargedCallback; + +public: + static TypeId GetTypeId (void); + RemusEnergyModel (); + virtual ~RemusEnergyModel (); + + /** + * \brief Sets pointer to node. + * + * \param node Pointer to node. + * + * Implements DeviceEnergyModel::SetNode. + */ + virtual void SetNode (Ptr node); + + /** + * \brief Gets pointer to node. + * + * \returns Pointer to node. + * + * Implements DeviceEnergyModel::GetNode. + */ + virtual Ptr GetNode (void) const; + + /** + * \brief Sets pointer to EnergySouce installed on node. + * + * \param source Pointer to EnergySource installed on node. + * + * Implements DeviceEnergyModel::SetEnergySource. + */ + virtual void SetEnergySource (Ptr source); + + /** + * \returns Total energy consumption of the vehicle. + * + * Implements DeviceEnergyModel::GetTotalEnergyConsumption. + */ + virtual double GetTotalEnergyConsumption (void) const; + + /** + * \param newState New state the device is in. + * + * DeviceEnergyModel is a state based model. This function is implemented by + * all child of DeviceEnergyModel to change the model's state. States are to + * be defined by each child using an enum (int). + */ + virtual void ChangeState (int newState); + + /** + * \param speed the speed value of the vehicle + * + * Update the energy consumption according to the speed value. + */ + void ChangeEnergyConsumption (const double speed); + + /** + * \param callback Callback function. + * + * Sets callback for energy depletion handling. + */ + void SetEnergyDepletionCallback (RemusEnergyDepletionCallback callback); + + /** + * \param callback Callback function. + * + * Sets callback for energy recharged handling. + */ + void SetEnergyRechargedCallback (RemusEnergyRechargedCallback callback); + + /** + * \brief Handles energy depletion. + * + * Implements DeviceEnergyModel::HandleEnergyDepletion + */ + virtual void HandleEnergyDepletion (void); + + /** + * \brief Handles energy recharge. + * + * Implements DeviceEnergyModel::HandleEnergyRecharged + */ + virtual void HandleEnergyRecharged (void); + +private: + void DoDispose (void); + + /** + * \returns Current draw of device, at current state. + * + * Implements DeviceEnergyModel::GetCurrentA. + */ + virtual double DoGetCurrentA (void) const; + + /** + * \param speed the navigation speed in m/s + * \return the needed power in watts + * + * This get the power needed to maintain a given speed value. + */ + double GetPower (double speed) const; + +private: + Ptr m_node; + Ptr m_source; + + // This variable keeps track of the total energy consumed by this particular model. + TracedValue m_totalEnergyConsumption; + + // actual current drain + double m_actualCurrentDrain; + // current navigation speed in m/s + double m_currentSpeed; + // time stamp of previous energy update + Time m_lastUpdateTime; + // the power consumption per 1 m/s speed + double m_powerSpeedRatio; + + // energy depletion callback + RemusEnergyDepletionCallback m_energyDepletionCallback; + RemusEnergyRechargedCallback m_energyRechargedCallback; +}; + +} // namespace ns3 + +#endif /* REMUS_ENERGY_MODEL_H */ --- a/src/auv/model/remus-mobility-model.cc +++ a/src/auv/model/remus-mobility-model.cc @@ -0,0 +1,398 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ +#include "remus-mobility-model.h" +#include "ns3/remus-energy-model.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("RemusMobilityModel"); + +NS_OBJECT_ENSURE_REGISTERED (RemusMobilityModel); + +TypeId +RemusMobilityModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RemusMobilityModel") + .SetParent (AuvMobilityModel::GetTypeId ()) + .AddConstructor () + .AddAttribute ("MaxDepth", "The maximum operational depth, in m", + DoubleValue (-100.0), + MakeDoubleAccessor (&RemusMobilityModel::m_maxDepth), + MakeDoubleChecker ()) + .AddAttribute ("MinSpeed", "The minimum speed of the vehicle, in m/s.", + DoubleValue (0.25), + MakeDoubleAccessor (&RemusMobilityModel::m_minSpeed), + MakeDoubleChecker ()) + .AddAttribute ("MaxSpeed", "The maximum speed of the vehicle, in m/s.", + DoubleValue (2.8), + MakeDoubleAccessor (&RemusMobilityModel::m_maxSpeed), + MakeDoubleChecker ()) + ; + return tid; +} + +RemusMobilityModel::RemusMobilityModel () + : m_direction (0), + m_speed (0), + m_pitch (0), + m_depth (0), + m_maxPitch (60), + m_deployed (false), + m_node (NULL) +{ + m_emergeCb.Nullify (); + m_submergeCb.Nullify (); +} + +RemusMobilityModel::~RemusMobilityModel () +{ + m_emergeCb.Nullify (); + m_submergeCb.Nullify (); + m_node = NULL; +} + +Vector +RemusMobilityModel::RoundPosition (const Vector &pos, uint16_t decimals) const +{ + Vector roundPos; + + double off = std::pow (10, decimals); + roundPos.x = (std::floor ((pos.x * off) + 0.5)) / off; + roundPos.y = (std::floor ((pos.y * off) + 0.5)) / off; + roundPos.z = (std::floor ((pos.z * off) + 0.5)) / off; + + return roundPos; +} + +void +RemusMobilityModel::SetNode (const Ptr node) +{ + NS_ASSERT (node != NULL); + m_node = node; +} + +Ptr +RemusMobilityModel::GetNode (void) const +{ + return m_node; +} + +void +RemusMobilityModel::SetEmergeCallback (Callback > cb) +{ + m_emergeCb = cb; +} + +void +RemusMobilityModel::SetSubmergeCallback (Callback > cb) +{ + m_submergeCb = cb; +} + +Vector +RemusMobilityModel::DoGetPosition (void) const +{ + // update the helper position + m_helper.Update (); + + // get the current position + Vector pos = m_helper.GetCurrentPosition (); + + // get the rounded precision position + Vector rpos = RoundPosition (pos, 4); + + return rpos; +} + +void +RemusMobilityModel::DoSetPosition (const Vector &position) +{ + NS_ASSERT (!m_deployed); + + m_helper.SetPosition (position); +} + +Vector +RemusMobilityModel::DoGetVelocity (void) const +{ + return m_helper.GetVelocity (); +} + +void +RemusMobilityModel::DoSetVelocity (const Vector &velocity) +{ + // if velocity is 0 + if (CalculateDistance (velocity,Vector (0, 0, 0)) == 0) + { + // stop the vehicle + DoStop (); + + return; + } + + // convert the cartesians coordinates into polar one + + double speed = std::sqrt ((velocity.x * velocity.x) + + (velocity.y * velocity.y) + + (velocity.z * velocity.z)); + + NS_ASSERT (speed <= m_maxSpeed); + m_speed = speed; + + double dir = std::atan2 (velocity.y, velocity.x); + m_direction = dir; + + double pitch = std::asin ((velocity.z / speed)); + NS_ASSERT (std::abs (pitch * 180 / M_PI) <= m_maxPitch); + m_pitch = pitch; + + m_helper.SetVelocity (velocity); + + Move (); +} + +void +RemusMobilityModel::UpdatePowerConsumption (const double speed) +{ + Ptr source = m_node->GetObject (); + if (source != NULL) + { + // retrieve device energy model from energy source + DeviceEnergyModelContainer modelCont = + source->Get (0)->FindDeviceEnergyModels ("ns3::RemusEnergyModel"); + + NS_ASSERT (modelCont.GetN () != 0); + // get pointer + Ptr devModel = DynamicCast (modelCont.Get (0)); + devModel->ChangeEnergyConsumption (speed); + } +} + +void +RemusMobilityModel::Update (void) +{ + // get the vector components + double cosD = std::cos (m_direction); + double cosP = std::cos (m_pitch); + double sinD = std::sin (m_direction); + double sinP = std::sin (m_pitch); + + // set the velocity vector + m_helper.SetVelocity (Vector (m_speed * cosD * cosP, m_speed * sinD * cosP, m_speed * sinP)); + + // update depth + m_depth = GetDepth (); + + // update the helper + m_helper.Update (); + + // notify the change + NotifyCourseChange (); +} + +void +RemusMobilityModel::DoMove (void) +{ + if (!m_deployed) + { + // the vehicle has just been deployed + m_deployed = true; + } + + // unpause the helper + m_helper.Unpause (); + + // update the helper with the new nav params + Update (); + + // update the energy consumption + UpdatePowerConsumption (m_speed); + + // compute the necessary time to reach the maximum operative depth + // or water surface and set a stop event + double vertVel = m_helper.GetVelocity ().z; + + if (vertVel != 0) + { + double stopTime = 0; + if (vertVel < 0) + { + stopTime = (m_maxDepth - DoGetDepth ()) / vertVel; + } + else + { + stopTime = (0 - DoGetDepth ()) / vertVel; + } + + Simulator::Cancel (m_stop); + m_stop = Simulator::Schedule (Seconds (stopTime), + &RemusMobilityModel::Stop, + this); + } +} + +void +RemusMobilityModel::DoStop (void) +{ + // Update (); + m_helper.Update (); + + // now the vehicle is stopped + m_speed = 0; + + // update the energy consumption + UpdatePowerConsumption (m_speed); + + Simulator::Cancel (m_stop); + m_helper.Pause (); +} + +void +RemusMobilityModel::DoEmerge (double depth) +{ + NS_ASSERT (depth <= 0 && depth >= m_maxDepth); + + double deltaDepth = depth - GetDepth (); + + // we want to emerge so the delta depth must be positive + NS_ASSERT (deltaDepth > 0); + // set the maximum pitch value + SetPitch (m_maxPitch); + // set the maximum speed value + SetSpeed (m_maxSpeed); + + // compute the time needed to reach to the specified depth + double emergeTime = deltaDepth / (m_speed * std::sin (m_pitch)); + + // set an event to stop the vehicle when it have reached the specified depth + m_stop = Simulator::Schedule (Seconds (emergeTime), + &RemusMobilityModel::DoStop, + this); + + // schedule the call to the emerge callback + if (!m_emergeCb.IsNull ()) + { + Simulator::Schedule (Seconds (emergeTime), + &RemusMobilityModel::m_emergeCb, + this, + this); + } +} + +void +RemusMobilityModel::DoSubmerge (double depth) +{ + NS_ASSERT (depth >= m_maxDepth && depth <= 0); + + double deltaDepth = depth - GetDepth (); + + // we want to submerge so the delta depth must be negative + NS_ASSERT (deltaDepth < 0); + // set the maximum pitch value, negative because we're going down + SetPitch (-m_maxPitch); + // set the maximum speed value + SetSpeed (m_maxSpeed); + + // compute the time needed to reach to the specified depth + double submergeTime = deltaDepth / (m_speed * std::sin (m_pitch)); + + // set an event to stop the vehicle when it have reached the specified depth + m_stop = Simulator::Schedule (Seconds (submergeTime), + &RemusMobilityModel::DoStop, + this); + + // schedule the call to the submerge callback + if (!m_submergeCb.IsNull ()) + { + Simulator::Schedule (Seconds (submergeTime), + &RemusMobilityModel::m_submergeCb, + this, + this); + } +} + +double +RemusMobilityModel::DoGetPitch () const +{ + // the pitch angle is stored in radians + return m_pitch * 180 / M_PI; +} + +void +RemusMobilityModel::DoSetPitch (double pitch) +{ + NS_ASSERT_MSG (std::abs (pitch) <= m_maxPitch, + "An excessive pitch angle has been set"); + + // the pitch angle is stored in radians + m_pitch = pitch * M_PI / 180; + + Update (); +} + +double +RemusMobilityModel::DoGetDepth (void) +{ + // update the current depth + Vector pos = GetPosition (); + m_depth = pos.z; + + return m_depth; +} + +double +RemusMobilityModel::DoGetDirection (void) const +{ + return m_direction * 180 / M_PI; +} + +void +RemusMobilityModel::DoSetDirection (double dir) +{ + m_direction = dir * M_PI / 180; + + Update (); +} + +double +RemusMobilityModel::DoGetSpeed () const +{ + return m_speed; +} + +void +RemusMobilityModel::DoSetSpeed (double speed) +{ + NS_ASSERT (speed <= m_maxSpeed); + + if (speed < m_minSpeed) + { + m_speed = 0; + } + else + { + m_speed = speed; + } + + Update (); + Move (); +} + +} // namespace ns3 --- a/src/auv/model/remus-mobility-model.h +++ a/src/auv/model/remus-mobility-model.h @@ -0,0 +1,125 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#ifndef REMUS_MOBILITY_MODEL_H_ +#define REMUS_MOBILITY_MODEL_H_ + +#include "auv-mobility-model.h" +#include "ns3/event-id.h" + + +namespace ns3 { + +/** + * \ingroup auv + * \brief keep track of the position of a REMUS AUV + * + * A REMUS class AUV is an submarine-like device, propelled by an electric motor linked with a propeller. + * + * The model is based on the constant velocity mobility model but introduces the physical + * constraints characteristics of the REMUS AUV [1][2]: + * + * - maximum operational depth, 100 m + * - minimum speed, 0.25 m/s + * - maximum speed, 2.8 m/s + * - pitch range, +/- 60 degrees + * + * References: + * [1] Hydroinc Products; http://www.hydroidinc.com/products.html + * [2] WHOI, Autonomous Underwater Vehicle, REMUS; http://www.whoi.edu/page.do?pid=29856 + */ +class RemusMobilityModel : public AuvMobilityModel +{ +public: + static TypeId GetTypeId (void); + RemusMobilityModel (); + ~RemusMobilityModel (); + + /** + * \param node the node associated with the mobility model + */ + void SetNode (const Ptr node); + /** + * \returns the associated node + */ + Ptr GetNode (void) const; + /** + * Set a callback to be called at the end of the emerging process + * + * \param cb the callback to be set + */ + virtual void SetEmergeCallback (Callback > cb); + /** + * Set a callback to be called at the end of the submerging process + * + * \param cb the callback to be set + */ + virtual void SetSubmergeCallback (Callback > cb); + +private: + /** + * Round a Vector of double, to the given decimal precision + * + * \param pos the position vector to be rounded + * \param decimals the decimal precision + * \returns the rounded position vector + */ + Vector RoundPosition (const Vector &pos, uint16_t decimals) const; + void Update (void); + void UpdatePowerConsumption (const double speed); + + virtual Vector DoGetPosition (void) const; + virtual void DoSetPosition (const Vector &position); + virtual Vector DoGetVelocity (void) const; + + virtual void DoMove (void); + virtual void DoStop (void); + virtual void DoEmerge (double depth); + virtual void DoSubmerge (double depth); + virtual double DoGetPitch () const; + virtual void DoSetPitch (double pitch); + virtual double DoGetDepth (void); + virtual double DoGetDirection (void) const; + virtual void DoSetDirection (double dir); + virtual double DoGetSpeed () const; + virtual void DoSetSpeed (double speed); + virtual void DoSetVelocity (const Vector &velocity); + + ConstantVelocityHelper m_helper; + double m_direction; + double m_speed; + double m_pitch; + double m_depth; + double m_minSpeed; + double m_maxSpeed; + double m_maxDepth; + // maximum pitch value, in degrees + double m_maxPitch; + bool m_deployed; + EventId m_stop; + Ptr m_node; + + Callback > m_emergeCb; + Callback > m_submergeCb; +}; + +} // namespace ns3 + +#endif /* REMUS_MOBILITY_MODEL_H_ */ --- a/src/auv/test/auv-energy-model-test.cc +++ a/src/auv/test/auv-energy-model-test.cc @@ -0,0 +1,477 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "ns3/log.h" +#include "ns3/test.h" +#include "ns3/simple-device-energy-model.h" +#include "ns3/uan-net-device.h" +#include "ns3/simulator.h" +#include "ns3/packet.h" +#include "ns3/node.h" +#include "ns3/auv-glider-helper.h" +#include "ns3/auv-remus-helper.h" +#include "ns3/auv-waypoint-mobility-model.h" +#include "ns3/uan-helper.h" +#include "ns3/basic-energy-source-helper.h" +#include "ns3/acoustic-modem-energy-model-helper.h" +#include "ns3/acoustic-modem-energy-model.h" +#include "ns3/constant-position-mobility-model.h" +#include "ns3/uan-channel.h" +#include "ns3/uan-noise-model-default.h" +#include "ns3/uan-prop-model-ideal.h" +#include "ns3/uan-header-common.h" +#include "ns3/uan-phy.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("AuvEnergyModelTestSuite"); + +class AcousticModemEnergyTestCase : public TestCase +{ +public: + AcousticModemEnergyTestCase (); + ~AcousticModemEnergyTestCase (); + + bool RxPacket (Ptr dev, Ptr pkt, uint16_t mode, const Address &sender); + void SendOnePacket (Ptr node); + + void DoRun (void); + + double m_simTime; + uint32_t m_bytesRx; + uint32_t m_sentPackets; + uint32_t m_packetSize; + Ptr m_node; + Ptr m_gateway; +}; + +AcousticModemEnergyTestCase::AcousticModemEnergyTestCase () + : TestCase ("Acoustic Modem energy model test case"), + m_simTime (25), + m_bytesRx (0), + m_sentPackets (0), + m_packetSize (17) +{ +} + +AcousticModemEnergyTestCase::~AcousticModemEnergyTestCase () +{ + m_node = NULL; + m_gateway = NULL; +} + +void +AcousticModemEnergyTestCase::SendOnePacket (Ptr node) +{ + // create an empty 17 bytes packet + Ptr pkt = Create (m_packetSize); + // send the packet in broadcast + Ptr dev = node->GetDevice (0)->GetObject (); + dev->Send (pkt, dev->GetBroadcast (), 0); + // increase the sent packets number + ++m_sentPackets; + + Simulator::Schedule (Seconds (10), + &AcousticModemEnergyTestCase::SendOnePacket, + this, + node); +} + +bool +AcousticModemEnergyTestCase::RxPacket (Ptr dev, Ptr pkt, uint16_t mode, const Address &sender) +{ + // increase the total bytes received + m_bytesRx += pkt->GetSize (); + + return true; +} + +void +AcousticModemEnergyTestCase::DoRun () +{ + // create a generic node + m_node = CreateObject (); + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack + UanHelper uan; + Ptr devNode = uan.Install (m_node, channel); + + // compute a packet (header + payload) duration + uint32_t datarate = devNode->GetPhy ()->GetMode (0).GetDataRateBps (); + UanHeaderCommon hd; + double packetDuration = (m_packetSize + hd.GetSerializedSize ()) * 8.0 / (double) datarate; + + // energy source + BasicEnergySourceHelper eh; + eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (10000000.0)); + eh.Install (m_node); + + // mobility model + Ptr mobility = CreateObject (); + mobility->SetPosition (Vector (0,0,-500)); + m_node->AggregateObject (mobility); + + // micro modem energy model + AcousticModemEnergyModelHelper modemHelper; + Ptr source = m_node->GetObject ()->Get (0); + DeviceEnergyModelContainer cont = modemHelper.Install (devNode,source); + + // Schedule a packet every 10 seconds + Simulator::ScheduleNow (&AcousticModemEnergyTestCase::SendOnePacket, + this, + m_node); + + // create a gateway node + m_gateway = CreateObject (); + + // install the underwater communication stack + Ptr devGateway = uan.Install (m_gateway, channel); + + // energy source + eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (10000000.0)); + eh.Install (m_gateway); + + // mobility model + Ptr mobility2 = CreateObject (); + mobility2->SetPosition (Vector (0,0,0)); + m_gateway->AggregateObject (mobility2); + + // micro modem energy model + Ptr source2 = m_gateway->GetObject ()->Get (0); + DeviceEnergyModelContainer cont2 = modemHelper.Install (devGateway, source2); + + // set the receive callback + Ptr dev = m_gateway->GetDevice (0); + dev->SetReceiveCallback (MakeCallback (&AcousticModemEnergyTestCase::RxPacket, + this)); + + // run the simulation + Simulator::Stop (Seconds (m_simTime)); + Simulator::Run (); + Simulator::Destroy (); + + uint32_t receivedPackets = m_bytesRx / m_packetSize; + Ptr src1 = m_gateway->GetObject ()->Get (0); + double consumed1 = src1->GetInitialEnergy () - src1->GetRemainingEnergy (); + double computed1 = cont2.Get (0)->GetObject ()->GetRxPowerW () * packetDuration * receivedPackets + + cont2.Get (0)->GetObject ()->GetIdlePowerW () * (m_simTime - (double) 2.0 / 3.0 - packetDuration * receivedPackets); + + NS_TEST_ASSERT_MSG_EQ_TOL (consumed1, computed1, 1.0e-5, + "Incorrect gateway consumed energy!"); + + Ptr src2 = m_node->GetObject ()->Get (0); + double consumed2 = src2->GetInitialEnergy () - src2->GetRemainingEnergy (); + double computed2 = cont.Get (0)->GetObject ()->GetTxPowerW () * packetDuration * m_sentPackets + + cont.Get (0)->GetObject ()->GetIdlePowerW () * (m_simTime - 1 - packetDuration * m_sentPackets); + + NS_TEST_ASSERT_MSG_EQ_TOL (consumed2, computed2, 1.0e-5, + "Incorrect node consumed energy!"); + +} + +class AcousticModemEnergyDepletionTestCase : public TestCase +{ +public: + AcousticModemEnergyDepletionTestCase (); + ~AcousticModemEnergyDepletionTestCase (); + + void DepletionHandler (void); + void SendOnePacket (Ptr node); + + void DoRun (void); + + double m_simTime; + uint32_t m_callbackCount; + uint32_t m_packetSize; + Ptr m_node; +}; + +AcousticModemEnergyDepletionTestCase::AcousticModemEnergyDepletionTestCase () + : TestCase ("Acoustic Modem energy depletion test case"), + m_simTime (25), + m_callbackCount (0), + m_packetSize (17) +{ +} + +AcousticModemEnergyDepletionTestCase::~AcousticModemEnergyDepletionTestCase () +{ + m_node = NULL; +} + +void +AcousticModemEnergyDepletionTestCase::DepletionHandler (void) +{ + // increase callback count + m_callbackCount++; +} + +void +AcousticModemEnergyDepletionTestCase::SendOnePacket (Ptr node) +{ + // create an empty packet + Ptr pkt = Create (m_packetSize); + // send the packet in broadcast + Ptr dev = node->GetDevice (0)->GetObject (); + dev->Send (pkt, dev->GetBroadcast (), 0); + + Simulator::Schedule (Seconds (10), + &AcousticModemEnergyDepletionTestCase::SendOnePacket, + this, + node); +} + +void +AcousticModemEnergyDepletionTestCase::DoRun (void) +{ + // create a generic node + m_node = CreateObject (); + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack + UanHelper uan; + Ptr devNode = uan.Install (m_node, channel); + + // set an empty energy source + BasicEnergySourceHelper eh; + eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (0.0)); + eh.Install (m_node); + + // mobility model + Ptr mobility = CreateObject (); + mobility->SetPosition (Vector (0,0,0)); + m_node->AggregateObject (mobility); + + // micro modem energy model + AcousticModemEnergyModelHelper modemHelper; + Ptr source = m_node->GetObject ()->Get (0); + // set the depletion callback + AcousticModemEnergyModel::AcousticModemEnergyDepletionCallback callback = + MakeCallback (&AcousticModemEnergyDepletionTestCase::DepletionHandler, this); + modemHelper.SetDepletionCallback (callback); + DeviceEnergyModelContainer cont = modemHelper.Install (devNode,source); + + // try to send a packet + Simulator::ScheduleNow (&AcousticModemEnergyDepletionTestCase::SendOnePacket, + this, + m_node); + + Simulator::Stop (Seconds (m_simTime)); + Simulator::Run (); + Simulator::Destroy (); + + NS_TEST_ASSERT_MSG_EQ (m_callbackCount, 1, "Callback not invoked"); + +} + +class GliderEnergyTestCase : public TestCase +{ +public: + GliderEnergyTestCase (); + ~GliderEnergyTestCase (); + + void DoRun (void); + void GetPosition (void); + + double m_simTime; + Ptr m_node; +}; + +GliderEnergyTestCase::GliderEnergyTestCase () + : TestCase ("Glider energy model test case"), + m_node (NULL) +{ +} + +GliderEnergyTestCase::~GliderEnergyTestCase () +{ + m_node = NULL; +} + +void +GliderEnergyTestCase::GetPosition () +{ + Ptr model = m_node->GetObject (); + + Simulator::Schedule (Seconds (1), + &GliderEnergyTestCase::GetPosition, + this); +} + +void +GliderEnergyTestCase::DoRun () +{ + m_node = CreateObject (); + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack + UanHelper uan; + Ptr devNode = uan.Install (m_node, channel); + + // install the glider components + AuvGliderHelper gh; + gh.Install (m_node); + + Ptr motorSrc = m_node->GetObject ()->Get (0); + Ptr modemSrc = m_node->GetObject ()->Get (1); + + AcousticModemEnergyModelHelper umem; + umem.Install (devNode, modemSrc); + + // move the vehicle somewhere + Ptr mob = m_node->GetObject (); + mob->AddWaypoint (Waypoint (Seconds (0), Vector (0,0,0))); + mob->AddWaypoint (Waypoint (Seconds (20), Vector (4.5,0,-10))); + GetPosition (); + + // run the simulation + Simulator::Stop (Seconds (25)); + Simulator::Run (); + Simulator::Destroy (); + + double motorConsumption = motorSrc->GetInitialEnergy () - motorSrc->GetRemainingEnergy (); + double motorEstimated = 19 * 0.96999; + NS_TEST_ASSERT_MSG_EQ_TOL (motorConsumption, motorEstimated, 1.0e-4, + "Incorrect motor consumed energy!"); + + double modemConsumption = modemSrc->GetInitialEnergy () - modemSrc->GetRemainingEnergy (); + double modemEstimated = 24 * 0.158; + NS_TEST_ASSERT_MSG_EQ_TOL (modemConsumption, modemEstimated, 1.0e-4, + "Incorrect modem consumed energy!"); +} + +class RemusEnergyTestCase : public TestCase +{ +public: + RemusEnergyTestCase (); + ~RemusEnergyTestCase (); + + void DoRun (void); + void GetPosition (void); + + double m_simTime; + Ptr m_node; +}; + +RemusEnergyTestCase::RemusEnergyTestCase () + : TestCase ("Remus energy model test case"), + m_node (NULL) +{ +} + +RemusEnergyTestCase::~RemusEnergyTestCase () +{ + m_node = NULL; +} + +void +RemusEnergyTestCase::GetPosition () +{ + Ptr model = m_node->GetObject (); + + Simulator::Schedule (Seconds (1), + &RemusEnergyTestCase::GetPosition, + this); +} + +void +RemusEnergyTestCase::DoRun () +{ + m_node = CreateObject (); + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack + UanHelper uan; + Ptr devNode = uan.Install (m_node, channel); + + // install the remus components + AuvRemusHelper rh; + rh.Install (m_node); + + Ptr src = m_node->GetObject ()->Get (0); + + AcousticModemEnergyModelHelper umem; + umem.Install (devNode, src); + + // move the vehicle somewhere + Ptr mob = m_node->GetObject (); + mob->AddWaypoint (Waypoint (Seconds (0), Vector (0,0,0))); + mob->AddWaypoint (Waypoint (Seconds (50), Vector (100,0,0))); + GetPosition (); + + // run the simulation + Simulator::Stop (Seconds (55)); + Simulator::Run (); + Simulator::Destroy (); + + double consumed = src->GetInitialEnergy () - src->GetRemainingEnergy (); + // motor + modem idle energy + double estimated = 20 * 49 + 0.158 * 54; + + NS_TEST_ASSERT_MSG_EQ_TOL (consumed, estimated, 1.0e-5, + "Incorrect consumed energy!"); +} + +// -------------------------------------------------------------------------- // + +/** + * Unit test suite for underwater energy model. Include test on acoustic modem, + * acoustic modem energy depletion, glider energy model, remus energy model. + */ +class AuvEnergyModelTestSuite : public TestSuite +{ +public: + AuvEnergyModelTestSuite (); +}; + +AuvEnergyModelTestSuite::AuvEnergyModelTestSuite () + : TestSuite ("auv-energy-model", UNIT) +{ + AddTestCase (new AcousticModemEnergyTestCase, TestCase::QUICK); + AddTestCase (new AcousticModemEnergyDepletionTestCase, TestCase::QUICK); + AddTestCase (new GliderEnergyTestCase, TestCase::QUICK); + AddTestCase (new RemusEnergyTestCase, TestCase::QUICK); +} + +// create an instance of the test suite +AuvEnergyModelTestSuite g_auvEnergyModelTestSuite; + +} // namespace ns3 --- a/src/auv/test/auv-mobility-test.cc +++ a/src/auv/test/auv-mobility-test.cc @@ -0,0 +1,431 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 Andrea Sacco + * + * 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: Andrea Sacco + */ + +#include "ns3/remus-mobility-model.h" +#include "ns3/glider-mobility-model.h" +#include "ns3/auv-waypoint-mobility-model.h" +#include "ns3/test.h" +#include "ns3/simulator.h" +#include "ns3/node.h" +#include "ns3/nstime.h" +#include "ns3/vector.h" +#include "ns3/log.h" +#include "ns3/gnuplot.h" +#include "ns3/auv-glider-helper.h" +#include "ns3/auv-remus-helper.h" +#include "ns3/uan-channel.h" +#include "ns3/uan-noise-model-default.h" +#include "ns3/uan-prop-model-ideal.h" +#include "ns3/uan-net-device.h" +#include "ns3/uan-helper.h" + +#include +#include + +using namespace ns3; + +class RemusMobilityTestCase : public TestCase +{ +public: + RemusMobilityTestCase (void); + ~RemusMobilityTestCase (void); + + virtual void DoRun (void); + void DoSubmergeTest (void); + void DoEmergeTest (void); + void DoNavigationTest (int16_t dir); + +private: + void SubmergeCb (Ptr mob); + void EmergeCb (Ptr mob); + void SpeedCb (int16_t dir); + + Ptr m_remusMob; +}; + +RemusMobilityTestCase::RemusMobilityTestCase () + : TestCase ("Test the Remus mobility model") +{ +} + +RemusMobilityTestCase::~RemusMobilityTestCase () +{ + m_remusMob = 0; +} + +void +RemusMobilityTestCase::DoSubmergeTest (void) +{ + m_remusMob->SetSubmergeCallback (MakeCallback (&RemusMobilityTestCase::SubmergeCb, + this)); + // makes the vehicle submerge to 100m + m_remusMob->Submerge (-100); +} + +void +RemusMobilityTestCase::DoEmergeTest (void) +{ + m_remusMob->SetEmergeCallback (MakeCallback (&RemusMobilityTestCase::EmergeCb, + this)); + m_remusMob->Emerge (0); +} + +void +RemusMobilityTestCase::DoNavigationTest (int16_t dir) +{ + + if (dir == 1) + { + m_remusMob->SetPitch (0.); + m_remusMob->SetDirection (90); + m_remusMob->SetSpeed (2); + } + if (dir == -1) + { + m_remusMob->SetVelocity (Vector (0,-2,0)); + } + + Simulator::Schedule (Seconds (2), + &RemusMobilityTestCase::SpeedCb, + this, + dir); +} + +void +RemusMobilityTestCase::SubmergeCb (Ptr mob) +{ + double depth = m_remusMob->GetDepth (); + + // depth should be -100 + NS_ASSERT (depth == -100); +} + +void +RemusMobilityTestCase::EmergeCb (Ptr mob) +{ + double depth = m_remusMob->GetDepth (); + + // the depth should be 0m + NS_ASSERT (depth == 0); +} + +void +RemusMobilityTestCase::SpeedCb (int16_t dir) +{ + Vector pos = m_remusMob->GetPosition (); + + if (dir == 1) + { + // after 2 seconds along +y at 2m/s + NS_ASSERT (pos.y == 4); + } + if (dir == -1) + { + // after 2 seconds along -y at 2m/s + NS_ASSERT (pos.y == 0); + } + + m_remusMob->Stop (); +} + +void +RemusMobilityTestCase::DoRun (void) +{ + Ptr auv = CreateObject (); + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack + UanHelper uan; + Ptr devNode = uan.Install (auv, channel); + + AuvRemusHelper helper; + helper.Install (auv); + + m_remusMob = auv->GetObject ()->GetValidatorMobilityModel ()->GetObject (); + NS_ASSERT (m_remusMob != NULL); + + m_remusMob->SetPosition (Vector (0.,0.,0.)); + + Time now = Simulator::Now (); + + // submerge + Simulator::Schedule (now, + &RemusMobilityTestCase::DoSubmergeTest, + this); + + // emerge + now += Seconds (100); + Simulator::Schedule (now, + &RemusMobilityTestCase::DoEmergeTest, + this); + + // direction, pitch, speed + now += Seconds (100); + Simulator::Schedule (now, + &RemusMobilityTestCase::DoNavigationTest, + this, + 1); + + // velocity + now += Seconds (100); + Simulator::Schedule (now, + &RemusMobilityTestCase::DoNavigationTest, + this, + -1); + + Simulator::Run (); + Simulator::Destroy (); +} + +class GliderMobilityTestCase : public TestCase +{ +public: + GliderMobilityTestCase (void); + ~GliderMobilityTestCase (void); + + virtual void DoRun (void); + void DoSubmergeTest (void); + void DoEmergeTest (void); + void DoNavigationTest (int16_t dir); + void DoBuoyancyTest (void); + +private: + void SubmergeCb (Ptr mob); + void EmergeCb (Ptr mob); + void SpeedCb (int16_t dir); + + Ptr m_gliderMob; + EventId m_id; + Vector m_lastEndPos; +}; + +GliderMobilityTestCase::GliderMobilityTestCase () + : TestCase ("Test the Seaglider mobility model") +{ +} + +GliderMobilityTestCase::~GliderMobilityTestCase () +{ + m_gliderMob = 0; +} + +void +GliderMobilityTestCase::DoSubmergeTest (void) +{ + m_gliderMob->SetSubmergeCallback (MakeCallback (&GliderMobilityTestCase::SubmergeCb, + this)); + // submerge to 1000m + m_gliderMob->Submerge (-1000); +} + +void +GliderMobilityTestCase::DoEmergeTest (void) +{ + m_gliderMob->SetEmergeCallback (MakeCallback (&GliderMobilityTestCase::EmergeCb, + this)); + // emerge to water surface + m_gliderMob->Emerge (0); +} + +void +GliderMobilityTestCase::DoNavigationTest (int16_t dir) +{ + + if (dir == 1) + { + m_gliderMob->SetPitch (-60); + m_gliderMob->SetDirection (45); + m_gliderMob->SetSpeed (0.3); + } + else if (dir == -1) + { + m_gliderMob->SetVelocity (Vector (0.2, -0.2, 0.2)); + } + + // proceed along the set direction for 60 seconds + Simulator::Schedule (Seconds (60), + &GliderMobilityTestCase::SpeedCb, + this, + dir); +} + +void +GliderMobilityTestCase::DoBuoyancyTest (void) +{ + double U = 0.25; + double W = 0.3; + + m_gliderMob->SetVelocity (Vector (U, .0, W)); + + double buoyancy = m_gliderMob->GetBuoyancy (); + + // test the buoyancy error against 1e-15 tolerance + NS_ASSERT ((buoyancy - 139.05836821925641) < 1e-15); +} + +void +GliderMobilityTestCase::SubmergeCb (Ptr mob) +{ + double depth = m_gliderMob->GetDepth (); + + // depth should be -1000 + NS_ASSERT (depth == -1000); + + m_lastEndPos = m_gliderMob->GetPosition (); +} + +void +GliderMobilityTestCase::EmergeCb (Ptr mob) +{ + double depth = m_gliderMob->GetDepth (); + + // the depth should be 0m + NS_ASSERT (depth == 0); + + m_lastEndPos = m_gliderMob->GetPosition (); +} + +void +GliderMobilityTestCase::SpeedCb (int16_t dir) +{ + Vector pos = m_gliderMob->GetPosition (); + + if (dir == 1) + { + double x = pos.x - m_lastEndPos.x; + double y = pos.y - m_lastEndPos.y; + double z = pos.z - m_lastEndPos.z; + + double dx = x - (std::cos (45 * M_PI / 180) * std::cos (-60 * M_PI / 180) * 0.3 * 60); + double dy = y - (std::sin (45 * M_PI / 180) * std::cos (-60 * M_PI / 180) * 0.3 * 60); + double dz = z - (std::sin (-60 * M_PI / 180) * 0.3 * 60); + + // test the error against 0.1 mm tolerance + NS_ASSERT (dx < 1e-4); + NS_ASSERT (dy < 1e-4); + NS_ASSERT (dz < 1e-4); + + m_lastEndPos = pos; + } + if (dir == -1) + { + double x = pos.x - m_lastEndPos.x; + double y = pos.y - m_lastEndPos.y; + double z = pos.z - m_lastEndPos.z; + + double dx = x - 0.2 * 60; + double dy = y - (-0.2) * 60; + double dz = z - 0.2 * 60; + + // test the error against 0.1 mm tolerance + NS_ASSERT (dx < 1e-4); + NS_ASSERT (dy < 1e-4); + NS_ASSERT (dz < 1e-4); + + m_lastEndPos = pos; + + Simulator::Cancel (m_id); + } + + m_gliderMob->Stop (); +} + +void +GliderMobilityTestCase::DoRun (void) +{ + Ptr auv = CreateObject (); + + // create a default underwater channel + Ptr channel = CreateObject (); + Ptr noise = CreateObject (); + channel->SetPropagationModel (CreateObject ()); + channel->SetNoiseModel (noise); + + // install the underwater communication stack + UanHelper uan; + Ptr devNode = uan.Install (auv, channel); + + AuvGliderHelper helper; + helper.Install (auv); + + m_gliderMob = auv->GetObject ()->GetValidatorMobilityModel ()->GetObject (); + NS_ASSERT (m_gliderMob != NULL); + + // deploy the AUV + m_gliderMob->SetPosition (Vector (0.,0.,0.)); + + // buoyancy + DoBuoyancyTest (); + + Time now = Simulator::Now (); + + // submerge + Simulator::Schedule (now, + &GliderMobilityTestCase::DoSubmergeTest, + this); + + // emerge + now += Seconds (2010); + Simulator::Schedule (now, + &GliderMobilityTestCase::DoEmergeTest, + this); + + // direction, pitch, speed + now += Seconds (2010); + Simulator::Schedule (now, + &GliderMobilityTestCase::DoNavigationTest, + this, + 1); + + // velocity + now += Seconds (100); + Simulator::Schedule (now, + &GliderMobilityTestCase::DoNavigationTest, + this, + -1); + + now += Seconds (100); + + Simulator::Stop (now); + Simulator::Run (); + Simulator::Destroy (); + +} + +// -------------------------------------------------------------------------- // + +/** + * Unit test suite for AUV mobility model. + * Glider mobility test: a simulation of buoyancy value, submerge, emerge and + * basic navigation. + * REMUS mobility test: a simulation of submerge, emerge and + * basic navigation. + */ +class AuvMobilityTestSuite : public TestSuite +{ +public: + AuvMobilityTestSuite (); +}; + --- a/src/auv/test/examples-to-run.py +++ a/src/auv/test/examples-to-run.py @@ -0,0 +1,18 @@ +#! /usr/bin/env python +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +# A list of C++ examples to run in order to ensure that they remain +# buildable and runnable over time. Each tuple in the list contains +# +# (example_name, do_run, do_valgrind_run). +# +# See test.py for more information. +cpp_examples = [] + +# A list of Python examples to run in order to ensure that they remain +# runnable over time. Each tuple in the list contains +# +# (example_name, do_run). +# +# See test.py for more information. +python_examples = [] --- a/src/auv/wscript +++ a/src/auv/wscript @@ -0,0 +1,41 @@ +# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + module = bld.create_ns3_module('auv', ['uan', 'mobility', 'energy']) + module.source = [ + 'model/auv-mobility-model.cc', + 'model/glider-mobility-model.cc', + 'model/remus-mobility-model.cc', + 'model/glider-energy-model.cc', + 'model/remus-energy-model.cc', + 'model/auv-waypoint-mobility-model.cc', + 'helper/auv-mobility-helper.cc', + 'helper/auv-glider-helper.cc', + 'helper/auv-remus-helper.cc', + ] + + module_test = bld.create_ns3_module_test_library('auv') + module_test.source = [ + 'test/auv-mobility-test.cc', + 'test/auv-energy-model-test.cc', + ] + + + headers = bld(features='ns3header') + headers.module = 'auv' + headers.source = [ + 'model/auv-mobility-model.h', + 'model/glider-mobility-model.h', + 'model/remus-mobility-model.h', + 'model/glider-energy-model.h', + 'model/remus-energy-model.h', + 'model/auv-waypoint-mobility-model.h', + 'helper/auv-mobility-helper.h', + 'helper/auv-glider-helper.h', + 'helper/auv-remus-helper.h', + ] + + if bld.env.ENABLE_EXAMPLES: + bld.recurse('examples') + + bld.ns3_python_bindings()