Added UAN AUV module: remus and glider mobility and energy models, helpers and examples
authorsocket
Sat, 16 Apr 2011 00:38:20 +0200
changeset 6961 99743340f944
parent 6960 f44b11251773
child 6962 d1c33ed5ed79
Added UAN AUV module: remus and glider mobility and energy models, helpers and examples
src/uan/auv/examples/auv-energy-model.cc
src/uan/auv/examples/auv-mobility.cc
src/uan/auv/examples/uan-energy-auv.cc
src/uan/auv/examples/uan-energy-auv.h
src/uan/auv/examples/waypoint-mobility.cc
src/uan/auv/examples/wscript
src/uan/auv/helper/auv-glider-helper.cc
src/uan/auv/helper/auv-glider-helper.h
src/uan/auv/helper/auv-mobility-helper.cc
src/uan/auv/helper/auv-mobility-helper.h
src/uan/auv/helper/auv-remus-helper.cc
src/uan/auv/helper/auv-remus-helper.h
src/uan/auv/model/auv-mobility-model.cc
src/uan/auv/model/auv-mobility-model.h
src/uan/auv/model/glider-energy-model.cc
src/uan/auv/model/glider-energy-model.h
src/uan/auv/model/glider-mobility-model.cc
src/uan/auv/model/glider-mobility-model.h
src/uan/auv/model/remus-energy-model.cc
src/uan/auv/model/remus-energy-model.h
src/uan/auv/model/remus-mobility-model.cc
src/uan/auv/model/remus-mobility-model.h
src/uan/auv/test/auv-energy-model-test.cc
src/uan/auv/test/auv-mobility-test.cc
src/uan/auv/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/examples/auv-energy-model.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,115 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/simulator.h"
+#include "ns3/node.h"
+#include "ns3/log.h"
+#include "ns3/glider-energy-model.h"
+#include "ns3/energy-source-container.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> node = CreateObject<Node> ();
+
+  // create energy source
+  ObjectFactory m_energySource;
+  m_energySource.SetTypeId ("ns3::BasicEnergySource");
+  m_energySource.Set ("BasicEnergySourceInitialEnergyJ",
+                      DoubleValue (10000000));
+  Ptr<EnergySource> source = m_energySource.Create<EnergySource> ();
+  source->SetNode (node);
+  Ptr<EnergySourceContainer> sourceCont = CreateObject<EnergySourceContainer> ();
+  sourceCont->Add (source);
+  // aggregate energy source to node
+  node->AggregateObject (sourceCont);
+
+  // create device energy model
+  Ptr<GliderEnergyModel> model = CreateObject<GliderEnergyModel> ();
+  // 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<GliderEnergyModel> devModel = DynamicCast<GliderEnergyModel> (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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/examples/auv-mobility.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,179 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/glider-mobility-model.h"
+#include "ns3/auv-mobility-model.h"
+#include "ns3/simulator.h"
+#include "ns3/node.h"
+#include "ns3/nstime.h"
+#include "ns3/vector.h"
+#include "ns3/gnuplot.h"
+#include "ns3/auv-mobility-helper.h"
+
+#include <fstream>
+
+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<GliderMobilityModel> mob);
+
+static void
+SubmergeCb (Ptr<MobilityModel> mob)
+{
+  // reached the target, makes the vehicle emerge
+  Emerge (mob->GetObject<GliderMobilityModel> ());
+}
+
+static void
+EmergeCb (Ptr<MobilityModel> mob)
+{
+  // stop the vehicle
+  mob->GetObject<GliderMobilityModel> ()->Stop ();
+}
+
+void
+Submerge (Ptr<GliderMobilityModel> mob)
+{
+  // set the submerge callback
+  mob->SetSubmergeCallback (MakeCallback (&SubmergeCb));
+
+  // makes the vehicle submerge to 1000m
+  mob->Submerge (-1000);
+}
+
+void
+Emerge (Ptr<GliderMobilityModel> 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<const GliderMobilityModel> 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<GliderMobilityModel> glider = DynamicCast<GliderMobilityModel> (node.Get (0)->GetObject<AuvMobilityModel> ());
+  NS_ASSERT (glider != 0);
+
+  // 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/examples/uan-energy-auv.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,188 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+#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/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/constant-position-mobility-model.h"
+#include "ns3/log.h"
+#include "ns3/uan-channel.h"
+#include "ns3/uan-noise-model-default.h"
+#include "ns3/uan-prop-model-ideal.h"
+#include "uan-energy-auv.h"
+
+using namespace ns3;
+
+UanEnergyAuv::UanEnergyAuv ()
+  : m_bytesRx (0),
+    m_sentPackets (0)
+{
+}
+
+UanEnergyAuv::~UanEnergyAuv ()
+{
+  m_auv = 0;
+  m_gateway = 0;
+}
+
+void
+UanEnergyAuv::SendOnePacket (Ptr<Node> node)
+{
+  // create an empty 17 bytes packet
+  Ptr<Packet> pkt = Create<Packet> (17);
+  // send the packet in broadcast
+  Ptr<UanNetDevice> dev = node->GetDevice (0)->GetObject<UanNetDevice> ();
+  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<NetDevice> dev, Ptr<const Packet> pkt, uint16_t mode, const Address &sender)
+{
+  // increase the total bytes received
+  m_bytesRx += pkt->GetSize ();
+
+  return true;
+}
+
+void
+UanEnergyAuv::PrintStats ()
+{
+  std::cout << "AUV: sent " << m_sentPackets << " packets" << std::endl;
+
+  std::cout << "Gateway: received " << m_bytesRx << " bytes" << std::endl;
+
+  Ptr<EnergySource> src1 = m_gateway->GetObject<EnergySourceContainer> ()->Get (0);
+  std::cout << "Gateway energy consumption: " << src1->GetInitialEnergy () - src1->GetRemainingEnergy () << " J" << std::endl;
+
+  Ptr<EnergySource> src2 = m_auv->GetObject<EnergySourceContainer> ()->Get (1);
+  double init0 = src2->GetInitialEnergy ();
+  double init1 = src2->GetRemainingEnergy ();
+  std::cout << "AUV energy consumption (comms): " << init0 - init1 << " J" << std::endl;
+
+  Ptr<EnergySource> src3 = m_auv->GetObject<EnergySourceContainer> ()->Get (0);
+  std::cout << "AUV energy consumption (nav): " << src3->GetInitialEnergy () - src3->GetRemainingEnergy () << " J" << std::endl;
+}
+
+bool
+UanEnergyAuv::Run ()
+{
+  // create a generic node
+  NodeContainer nc = NodeContainer ();
+  nc.Create (1);
+  m_auv = nc.Get (0);
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> devNode = uan.Install (m_auv, channel);
+
+  // install the glider components
+  AuvGliderHelper gh;
+  gh.Install (m_auv);
+
+  // move the vehicle somewhere
+  Ptr<WaypointMobilityModel> mob = m_auv->GetObject<WaypointMobilityModel> ();
+  mob->AddWaypoint (Waypoint (Seconds (0), Vector (0,0,0)));
+  mob->AddWaypoint (Waypoint (Seconds (2000), Vector (450,0,-1000)));
+  mob->AddWaypoint (Waypoint (Seconds (4000), Vector (900,0,0)));
+
+  // Schedule a packet every 10 seconds
+  Simulator::ScheduleNow (&UanEnergyAuv::SendOnePacket,
+                          this,
+                          m_auv);
+
+  // create a gateway node
+  NodeContainer nc1 = NodeContainer ();
+  nc1.Create (1);
+  m_gateway = nc1.Get (0);
+
+  // install the underwater communication stack
+  Ptr<UanNetDevice> devNode1 = uan.Install (m_gateway, channel);
+
+  // energy source
+  BasicEnergySourceHelper eh;
+  eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (10000000.0));
+  eh.Install (nc1);
+
+  // mobility model
+  Ptr<ConstantPositionMobilityModel> mobility = CreateObject<ConstantPositionMobilityModel> ();
+  mobility->SetPosition (Vector (1000,0,0));
+  m_gateway->AggregateObject (mobility);
+
+  // micro modem energy model
+  /*
+  Ptr<AcousticModemEnergyModel> umem = CreateObject<AcousticModemEnergyModel> ();
+  Ptr<EnergySource> source = m_gateway->GetObject<EnergySourceContainer> ()->Get (0);
+  NS_ASSERT (source != 0);
+  umem->SetEnergySource (source);
+  source->AppendDeviceEnergyModel (umem);
+  */
+  AcousticModemEnergyModelHelper modemHelper;
+  Ptr<EnergySource> source = m_gateway->GetObject<EnergySourceContainer> ()->Get (0);
+  DeviceEnergyModelContainer cont = modemHelper.Install (devNode1, source);
+
+  // set the receive callback
+  Ptr<NetDevice> dev = m_gateway->GetDevice (0);
+  dev->SetReceiveCallback (MakeCallback (&UanEnergyAuv::RxPacket,
+                                         this));
+
+  // run the simulation
+  Simulator::Stop (Seconds (4005));
+  Simulator::Run ();
+
+  // print the simulation's statistics
+  PrintStats ();
+
+  Simulator::Destroy ();
+
+  return false;
+}
+
+int
+main (int argc, char **argv)
+{
+  // uncomment to see models log
+  // LogComponentEnable("GliderEnergyModel", LOG_LEVEL_ALL);
+  // LogComponentEnable("BasicEnergySource", LOG_LEVEL_ALL);
+  // LogComponentEnable("LiIonEnergySource", LOG_LEVEL_ALL);
+  // LogComponentEnable("AcousticModemEnergyModel", LOG_LEVEL_ALL);
+
+  UanEnergyAuv uan;
+  uan.Run ();
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/examples/uan-energy-auv.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,65 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#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.
+ */
+
+using namespace ns3;
+
+class UanEnergyAuv
+{
+public:
+  UanEnergyAuv ();
+  ~UanEnergyAuv ();
+
+  bool RxPacket (Ptr<NetDevice> dev, Ptr<const Packet> pkt, uint16_t mode, const Address &sender);
+  void SendOnePacket (Ptr<Node> node);
+
+  void PrintStats ();
+
+  bool Run (void);
+
+  uint32_t m_bytesRx;
+  uint32_t m_sentPackets;
+  Ptr<Node> m_auv;
+  Ptr<Node> m_gateway;
+};
+
+#endif /* UAN_ENERGY_AUV_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/examples/waypoint-mobility.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,108 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/waypoint.h"
+#include "ns3/simulator.h"
+#include "ns3/remus-mobility-model.h"
+#include "ns3/waypoint-mobility-model.h"
+#include "ns3/glider-mobility-model.h"
+
+using namespace ns3;
+
+/**
+ * We show how to use the WaypointMobilityModel 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<const WaypointMobilityModel> 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<Node> node1 = CreateObject<Node> ();
+
+  // create the waypoint model
+  Ptr<WaypointMobilityModel> mm = CreateObject<WaypointMobilityModel> ();
+  Ptr<RemusMobilityModel> remus = CreateObject<RemusMobilityModel> ();
+  remus->SetNode (node1);
+  // set the RemusMobilityModel as the underlying model
+  mm->SetMobilityModel (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<Node> node2 = CreateObject<Node> ();
+  Ptr<GliderMobilityModel> gmm = CreateObject<GliderMobilityModel> ();
+  gmm->SetNode (node2);
+  Ptr<WaypointMobilityModel> wpmm = CreateObject<WaypointMobilityModel> ();
+  wpmm->SetMobilityModel (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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/examples/wscript	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,14 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_program('uan-energy-auv', ['core', 'simulator', 'uan', 'mobility', 'energy'])
+    obj.source = 'uan-energy-auv.cc'
+        
+    obj = bld.create_ns3_program('auv-energy-model', ['core', 'simulator', 'mobility'])
+    obj.source = 'auv-energy-model.cc'
+    
+    obj = bld.create_ns3_program('waypoint-mobility', ['core', 'simulator', 'mobility'])
+    obj.source = 'waypoint-mobility.cc'
+
+    obj = bld.create_ns3_program('auv-mobility', ['core', 'simulator', 'mobility'])
+    obj.source = 'auv-mobility.cc'
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/helper/auv-glider-helper.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,149 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/names.h"
+#include "ns3/auv-mobility-helper.h"
+#include "ns3/li-ion-energy-source.h"
+#include "ns3/glider-energy-model.h"
+#include "ns3/acoustic-modem-energy-model-helper.h"
+#include "ns3/uan-helper.h"
+#include "ns3/glider-mobility-model.h"
+#include "ns3/waypoint-mobility-model.h"
+#include "ns3/energy-source-container.h"
+#include "auv-glider-helper.h"
+#include "ns3/li-ion-energy-source-helper.h"
+
+namespace ns3 {
+
+AuvGliderHelper::AuvGliderHelper ()
+{
+  m_navigationEnergyPack.SetTypeId ("ns3::LiIonEnergySource");
+  m_navigationEnergyPack.Set ("LiIonEnergySourceInitialEnergyJ", DoubleValue (13608000.0));
+  m_navigationEnergyPack.Set ("IntialCellVoltage", DoubleValue (3.45 * 7));
+  m_navigationEnergyPack.Set ("NominalCellVoltage", DoubleValue (3.3 * 7));
+  m_navigationEnergyPack.Set ("ExpCellVoltage", DoubleValue (3.55 * 7));
+  m_navigationEnergyPack.Set ("RatedCapacity", DoubleValue (30.0 * 6));
+  m_navigationEnergyPack.Set ("NomCapacity", DoubleValue (27.0 * 6));
+  m_navigationEnergyPack.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)
+  m_navigationEnergyPack.Set ("InternalResistance", DoubleValue (0.16917));
+  m_navigationEnergyPack.Set ("TypCurrent", DoubleValue (1.0 * 6));
+  m_navigationEnergyPack.Set ("ThresholdVoltage", DoubleValue (3.0 * 6));
+
+  m_commsEnergyPack.SetTypeId ("ns3::LiIonEnergySource");
+  m_commsEnergyPack.Set ("LiIonEnergySourceInitialEnergyJ", DoubleValue (3888000.0));
+  m_commsEnergyPack.Set ("IntialCellVoltage", DoubleValue (3.45 * 3));
+  m_commsEnergyPack.Set ("NominalCellVoltage", DoubleValue (3.3 * 3));
+  m_commsEnergyPack.Set ("ExpCellVoltage", DoubleValue (3.55 * 3));
+  m_commsEnergyPack.Set ("RatedCapacity", DoubleValue (30.0 * 4));
+  m_commsEnergyPack.Set ("NomCapacity", DoubleValue (27.0 * 4));
+  m_commsEnergyPack.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)
+  m_commsEnergyPack.Set ("InternalResistance", DoubleValue (0.10875));
+  m_commsEnergyPack.Set ("TypCurrent", DoubleValue (1.0 * 4));
+  m_commsEnergyPack.Set ("ThresholdVoltage", DoubleValue (3.0 * 4));
+}
+
+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> node = Names::Find<Node> (nodeName);
+  Install (node);
+}
+
+void
+AuvGliderHelper::Install (Ptr<Node> node) const
+{
+  // waypoint mobility model with underlying glider mobility model
+  Ptr<GliderMobilityModel> gmm = CreateObject<GliderMobilityModel> ();
+  gmm->SetNode (node);
+  Ptr<WaypointMobilityModel> wpmm = CreateObject<WaypointMobilityModel> ();
+  wpmm->SetMobilityModel (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<EnergySourceContainer> esContainer = CreateObject<EnergySourceContainer> ();
+  Ptr<EnergySourceContainer> cont = node->GetObject<EnergySourceContainer> ();
+  NS_ASSERT_MSG (cont == 0, "Energy source already installed!");
+  //ObjectFactory fact;
+  //fact.SetTypeId (LiIonEnergySource::GetTypeId ());
+  Ptr<EnergySource> navSource = m_navigationEnergyPack.Create<EnergySource> ();
+  esContainer->Add (navSource);
+  navSource->SetNode (node);
+
+  // 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 ());
+  Ptr<EnergySource> commsSource = m_commsEnergyPack.Create<EnergySource> ();
+  esContainer->Add (commsSource);
+  commsSource->SetNode (node);
+
+  node->AggregateObject (esContainer);
+
+  // get the installed energy source container
+  cont = node->GetObject<EnergySourceContainer> ();
+  NS_ASSERT (cont != 0);
+
+  // glider energy model
+  Ptr<GliderEnergyModel> gem = CreateObject<GliderEnergyModel> ();
+  gem->SetEnergySource (navSource);
+  navSource->AppendDeviceEnergyModel (gem);
+  gem->SetNode (node);
+
+  // micro modem energy model
+  AcousticModemEnergyModelHelper modemH;
+  Ptr<UanNetDevice> dev = node->GetDevice (0)->GetObject<UanNetDevice> ();
+  NS_ASSERT_MSG (dev != 0, "Node does not contains an UanNetDevice");
+  DeviceEnergyModelContainer devcont = modemH.Install (dev, commsSource);
+
+  return;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/helper/auv-glider-helper.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,98 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef AUV_GLIDER_HELPER_H_
+#define AUV_GLIDER_HELPER_H_
+
+#include <stdint.h>
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+
+namespace ns3 {
+
+/**
+ * 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 auv glider features into a set of nodes
+   *
+   * \param c a set of nodes
+   */
+  void Install (NodeContainer c) const;
+
+  /**
+   * Install the auv 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 auv glider features into a single node
+   *
+   * \param node Pointer of the node where to install the features
+   */
+  void Install (Ptr<Node> node) const;
+
+private:
+  ObjectFactory m_navigationEnergyPack;
+  ObjectFactory m_commsEnergyPack;
+};
+
+} // namespace ns3
+
+#endif /* AUV_GLIDER_HELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/helper/auv-mobility-helper.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,116 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#include "auv-mobility-helper.h"
+#include "ns3/remus-mobility-model.h"
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/names.h"
+#include "ns3/position-allocator.h"
+
+namespace ns3 {
+
+AuvMobilityHelper::AuvMobilityHelper ()
+{
+  m_factory.SetTypeId ("ns3::RemusMobilityModel");
+
+  m_allocator = CreateObjectWithAttributes<RandomBoxPositionAllocator>
+      ("X", RandomVariableValue (ConstantVariable (0.0)),
+      "Y", RandomVariableValue (ConstantVariable (0.0)),
+      "Z", RandomVariableValue (ConstantVariable (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<PositionAllocator> 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<PositionAllocator> ();
+}
+
+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> node = Names::Find<Node> (nodeName);
+  Install (node);
+}
+
+void
+AuvMobilityHelper::Install (Ptr<Node> node) const
+{
+  Ptr<AuvMobilityModel> model = m_factory.Create<AuvMobilityModel> ();
+
+  NS_ASSERT_MSG (model != 0,
+                 "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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/helper/auv-mobility-helper.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,136 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef AUV_MOBILITY_HELPER_H
+#define AUV_MOBILITY_HELPER_H
+
+#include <stdint.h>
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+#include "ns3/position-allocator.h"
+
+namespace ns3 {
+
+/**
+ * \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<PositionAllocator> 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> node) const;
+
+  ObjectFactory m_factory;
+  Ptr<PositionAllocator> m_allocator;
+};
+
+} // namespace ns3
+
+#endif /* AUV_MOBILITY_HELPER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/helper/auv-remus-helper.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/names.h"
+#include "ns3/auv-mobility-helper.h"
+#include "ns3/basic-energy-source-helper.h"
+#include "ns3/remus-energy-model.h"
+#include "ns3/acoustic-modem-energy-model-helper.h"
+#include "ns3/remus-mobility-model.h"
+#include "ns3/waypoint-mobility-model.h"
+#include "auv-remus-helper.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> node = Names::Find<Node> (nodeName);
+  Install (node);
+}
+
+void
+AuvRemusHelper::Install (Ptr<Node> node) const
+{
+  // waypoint mobility model with underlying remus mobility model
+  Ptr<RemusMobilityModel> rmm = CreateObject<RemusMobilityModel> ();
+  rmm->SetNode (node);
+  Ptr<WaypointMobilityModel> wpmm = CreateObject<WaypointMobilityModel> ();
+  wpmm->SetMobilityModel (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<RemusEnergyModel> rem = CreateObject<RemusEnergyModel> ();
+  Ptr<EnergySource> source = node->GetObject<EnergySourceContainer> ()->Get (0);
+  NS_ASSERT (source != 0);
+  rem->SetEnergySource (source);
+  source->AppendDeviceEnergyModel (rem);
+  source->SetNode (node);
+  rem->SetNode (node);
+
+  // device energy model helper
+  AcousticModemEnergyModelHelper modemH;
+  Ptr<NetDevice> dev = node->GetDevice (0);
+  modemH.Install (dev, source);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/helper/auv-remus-helper.h	Sat Apr 16 00:38:20 2011 +0200
@@ -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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef AUV_REMUS_HELPER_H_
+#define AUV_REMUS_HELPER_H_
+
+#include <stdint.h>
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+
+namespace ns3 {
+
+/**
+ * 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 auv REMUS features into a set of nodes
+   *
+   * \param c NodeContainer where to install the features
+   */
+  void Install (NodeContainer c) const;
+
+  /**
+   * Install the auv 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 auv REMUS features into a single node
+   *
+   * \param node Pointer of the node where to install the features
+   */
+  void Install (Ptr<Node> node) const;
+};
+
+} // namespace ns3
+
+#endif /* AUV_REMUS_HELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/auv-mobility-model.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,115 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#include "auv-mobility-model.h"
+#include "ns3/double.h"
+
+namespace ns3 {
+
+TypeId
+AuvMobilityModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::AuvMobilityModel")
+    .SetParent (ConstantVelocityMobilityModel::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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/auv-mobility-model.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,197 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef AUV_MOBILITY_MODEL_H_
+#define AUV_MOBILITY_MODEL_H_
+
+#include "ns3/constant-velocity-mobility-model.h"
+#include "ns3/node.h"
+
+namespace ns3 {
+
+/**
+ * \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 ConstantVelocityMobilityModel
+{
+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> node) = 0;
+  /**
+   * \returns the associated node
+   */
+  virtual Ptr<Node> GetNode (void) const = 0;
+  /**
+   * \param cb the callback being called at the end of the emerging process
+   */
+  virtual void SetEmergeCallback (Callback<void, Ptr<MobilityModel> > cb) = 0;
+
+  /**
+   ** \param cb the callback being called at the end of the submerging process
+   */
+  virtual void SetSubmergeCallback (Callback<void, Ptr<MobilityModel> > 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_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/glider-energy-model.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,186 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/double.h"
+#include "ns3/simulator.h"
+#include "ns3/trace-source-accessor.h"
+#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<DeviceEnergyModel> ()
+    .AddConstructor<GliderEnergyModel> ()
+    .AddTraceSource ("TotalEnergyConsumption",
+                     "Total energy consumption of the glider AUV.",
+                     MakeTraceSourceAccessor (&GliderEnergyModel::m_totalEnergyConsumption))
+  ;
+  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_node = 0;
+  m_source = 0;
+}
+
+GliderEnergyModel::~GliderEnergyModel ()
+{
+}
+
+void
+GliderEnergyModel::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  NS_ASSERT (node != NULL);
+  m_node = node;
+}
+
+Ptr<Node>
+GliderEnergyModel::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+GliderEnergyModel::SetEnergySource (Ptr<EnergySource> source)
+{
+  NS_LOG_FUNCTION (this << source);
+  NS_ASSERT (source != 0);
+  m_source = source;
+}
+
+double
+GliderEnergyModel::GetTotalEnergyConsumption (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_totalEnergyConsumption;
+}
+
+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
+  double actualPower = GetPower (m_currentBuoyancy, m_currentW);
+  double supplyVoltage = m_source->GetSupplyVoltage ();
+  m_actualCurrentDrain = actualPower / 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::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 ();
+    }
+}
+
+/*
+ * Private functions start here.
+ */
+
+void
+GliderEnergyModel::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  m_source = 0;
+  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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/glider-energy-model.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,166 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef GLIDER_ENERGY_MODEL_H
+#define GLIDER_ENERGY_MODEL_H
+
+#include "ns3/device-energy-model.h"
+#include "ns3/energy-source.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+#include "ns3/traced-value.h"
+
+namespace ns3 {
+
+/**
+ * \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<void> GliderEnergyDepletionCallback;
+
+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> node);
+
+  /**
+   * \brief Gets pointer to node.
+   *
+   * \returns Pointer to node.
+   *
+   * Implements DeviceEnergyModel::GetNode.
+   */
+  virtual Ptr<Node> 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<EnergySource> 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);
+
+  /**
+   * \brief Handles energy depletion.
+   *
+   * Implements DeviceEnergyModel::HandleEnergyDepletion
+   */
+  virtual void HandleEnergyDepletion (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<Node> m_node;
+  Ptr<EnergySource> m_source;
+
+  // This variable keeps track of the total energy consumed by this particular model.
+  TracedValue<double> 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;
+};
+
+} // namespace ns3
+
+#endif /* GLIDER_ENERGY_MODEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/glider-mobility-model.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -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 <andrea.sacco85@gmail.com>
+ */
+
+#include "glider-mobility-model.h"
+#include <cmath>
+#include "ns3/double.h"
+#include "ns3/simulator.h"
+#include "ns3/energy-source.h"
+#include "ns3/energy-source-container.h"
+#include "ns3/device-energy-model-container.h"
+#include "ns3/glider-energy-model.h"
+#include "ns3/log.h"
+#include "ns3/vector.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<GliderMobilityModel> ()
+    .AddAttribute ("MaxDepth", "The maximum operational depth, in m",
+                   DoubleValue (-1000.0),
+                   MakeDoubleAccessor (&GliderMobilityModel::m_maxDepth),
+                   MakeDoubleChecker<double> ())
+    .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<double> ())
+    .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<double> ())
+    .AddAttribute ("MaxHSpeed", "The maximum horizontal speed of the glider, in m/s.",
+                   DoubleValue (0.32), // derived from the paper
+                   MakeDoubleAccessor (&GliderMobilityModel::m_maxU),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxWSpeed", "The maximum vertical speed of the glider, in m/s.",
+                   DoubleValue (0.5), // derived from the paper
+                   MakeDoubleAccessor (&GliderMobilityModel::m_maxW),
+                   MakeDoubleChecker<double> ())
+    .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<double> ())
+  ;
+  return tid;
+}
+
+GliderMobilityModel::GliderMobilityModel ()
+  : m_direction (0),
+    m_speed (0),
+    m_pitch (0),
+    m_depth (0),
+    m_deployed (false)
+{
+}
+
+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> node)
+{
+  NS_ASSERT (node != 0);
+  m_node = node;
+}
+
+Ptr<Node>
+GliderMobilityModel::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+GliderMobilityModel::SetEmergeCallback (Callback<void, Ptr<MobilityModel> > cb)
+{
+  m_emergeCb = cb;
+}
+
+void
+GliderMobilityModel::SetSubmergeCallback (Callback<void, Ptr<MobilityModel> > 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_MSG (buoyancy <= m_maxBuoyancy, "Max Buoyancy value exceeded");
+  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<EnergySourceContainer> source = m_node->GetObject<EnergySourceContainer> ();
+  if (source != 0)
+    {
+      // retrieve device energy model from energy source
+      DeviceEnergyModelContainer modelCont;
+      for (EnergySourceContainer::Iterator it = source->Begin (); it != source->End (); it++)
+        {
+          Ptr<EnergySource> source = *it;
+
+          modelCont = source->FindDeviceEnergyModels ("ns3::GliderEnergyModel");
+          if (modelCont.GetN () != 0)
+            {
+              break;
+            }
+        }
+      NS_ASSERT (modelCont.GetN () != 0);
+
+      // get pointer
+      Ptr<GliderEnergyModel> devModel = DynamicCast<GliderEnergyModel> (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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/glider-mobility-model.h	Sat Apr 16 00:38:20 2011 +0200
@@ -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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef GLIDER_MOBILITY_MODEL_H_
+#define GLIDER_MOBILITY_MODEL_H_
+
+#include "auv-mobility-model.h"
+#include "ns3/constant-velocity-helper.h"
+#include "ns3/box.h"
+#include "ns3/event-id.h"
+#include "ns3/vector.h"
+
+namespace ns3 {
+
+/**
+ * \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 ();
+
+  /**
+   * \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> node);
+  /**
+   * \returns the associated node
+   */
+  Ptr<Node> GetNode (void) const;
+
+  virtual void SetEmergeCallback (Callback<void, Ptr<MobilityModel> > cb);
+  virtual void SetSubmergeCallback (Callback<void, Ptr<MobilityModel> > 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<Node> m_node;
+
+  Callback<void, Ptr<MobilityModel> > m_emergeCb;
+  Callback<void, Ptr<MobilityModel> > m_submergeCb;
+};
+
+}; // namespace ns3
+
+#endif /* GLIDER_MOBILITY_MODEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/remus-energy-model.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,190 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/double.h"
+#include "ns3/simulator.h"
+#include "ns3/trace-source-accessor.h"
+#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<DeviceEnergyModel> ()
+    .AddConstructor<RemusEnergyModel> ()
+    .AddAttribute ("PowerSpeedRatio",
+                   "Consumed power ratio with respect to motor speed",
+                   DoubleValue (10.0), // in W*s/m
+                   MakeDoubleAccessor (&RemusEnergyModel::m_powerSpeedRatio),
+                   MakeDoubleChecker<double> ())
+    .AddTraceSource ("TotalEnergyConsumption",
+                     "Total energy consumption of the radio device.",
+                     MakeTraceSourceAccessor (&RemusEnergyModel::m_totalEnergyConsumption))
+  ;
+  return tid;
+}
+
+RemusEnergyModel::RemusEnergyModel ()
+{
+  NS_LOG_FUNCTION (this);
+  m_currentSpeed = 0.0;
+  m_lastUpdateTime = Seconds (0.0);
+  m_energyDepletionCallback.Nullify ();
+  m_node = 0;
+  m_source = 0;
+}
+
+RemusEnergyModel::~RemusEnergyModel ()
+{
+  m_energyDepletionCallback.Nullify ();
+  m_node = 0;
+  m_source = 0;
+}
+void
+RemusEnergyModel::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  NS_ASSERT (node != NULL);
+  m_node = node;
+}
+
+Ptr<Node>
+RemusEnergyModel::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+RemusEnergyModel::SetEnergySource (Ptr<EnergySource> source)
+{
+  NS_LOG_FUNCTION (this << source);
+  NS_ASSERT (source != 0);
+  m_source = source;
+}
+
+double
+RemusEnergyModel::GetTotalEnergyConsumption (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_totalEnergyConsumption;
+}
+
+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 (speed);
+  double energyToDecrease = duration.GetSeconds () * power;
+
+  // update total energy consumption
+  m_totalEnergyConsumption += energyToDecrease;
+
+  // update current speed value
+  m_currentSpeed = speed;
+  // update current drain
+  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
+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::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 ();
+    }
+}
+
+/*
+ * Private functions start here.
+ */
+
+void
+RemusEnergyModel::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  m_source = 0;
+  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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/remus-energy-model.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,142 @@
+#ifndef GLIDER_ENERGY_MODEL_H
+#define GLIDER_ENERGY_MODEL_H
+
+#include "ns3/device-energy-model.h"
+#include "ns3/energy-source.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+#include "ns3/traced-value.h"
+
+namespace ns3 {
+
+/**
+ * \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<void> RemusEnergyDepletionCallback;
+
+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> node);
+
+  /**
+   * \brief Gets pointer to node.
+   *
+   * \returns Pointer to node.
+   *
+   * Implements DeviceEnergyModel::GetNode.
+   */
+  virtual Ptr<Node> 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<EnergySource> 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);
+
+  /**
+   * \brief Handles energy depletion.
+   *
+   * Implements DeviceEnergyModel::HandleEnergyDepletion
+   */
+  virtual void HandleEnergyDepletion (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<Node> m_node;
+  Ptr<EnergySource> m_source;
+
+  // This variable keeps track of the total energy consumed by this particular model.
+  TracedValue<double> 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;
+
+  double m_powerSpeedRatio;
+
+  // energy depletion callback
+  RemusEnergyDepletionCallback m_energyDepletionCallback;
+};
+
+} // namespace ns3
+
+#endif /* GLIDER_ENERGY_MODEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/remus-mobility-model.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,397 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#include "remus-mobility-model.h"
+#include <cmath>
+#include "ns3/double.h"
+#include "ns3/simulator.h"
+#include "ns3/energy-source.h"
+#include "ns3/energy-source-container.h"
+#include "ns3/device-energy-model-container.h"
+#include "ns3/remus-energy-model.h"
+#include "ns3/vector.h"
+#include "ns3/log.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<RemusMobilityModel> ()
+    .AddAttribute ("MaxDepth", "The maximum operational depth, in m",
+                   DoubleValue (-100.0),
+                   MakeDoubleAccessor (&RemusMobilityModel::m_maxDepth),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MinSpeed", "The minimum speed of the vehicle, in m/s.",
+                   DoubleValue (0.25),
+                   MakeDoubleAccessor (&RemusMobilityModel::m_minSpeed),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxSpeed", "The maximum speed of the vehicle, in m/s.",
+                   DoubleValue (2.8),
+                   MakeDoubleAccessor (&RemusMobilityModel::m_maxSpeed),
+                   MakeDoubleChecker<double> ())
+  ;
+  return tid;
+}
+
+RemusMobilityModel::RemusMobilityModel ()
+  : m_direction (0),
+    m_speed (0),
+    m_pitch (0),
+    m_depth (0),
+    m_maxPitch (60),
+    m_deployed (false)
+{
+}
+
+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> node)
+{
+  NS_ASSERT (node != 0);
+  m_node = node;
+}
+
+Ptr<Node>
+RemusMobilityModel::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+RemusMobilityModel::SetEmergeCallback (Callback<void, Ptr<MobilityModel> > cb)
+{
+  m_emergeCb = cb;
+}
+
+void
+RemusMobilityModel::SetSubmergeCallback (Callback<void, Ptr<MobilityModel> > 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<EnergySourceContainer> source = m_node->GetObject<EnergySourceContainer> ();
+  if (source != 0)
+    {
+      // retrieve device energy model from energy source
+      DeviceEnergyModelContainer modelCont =
+        source->Get (0)->FindDeviceEnergyModels ("ns3::RemusEnergyModel");
+
+      NS_ASSERT (modelCont.GetN () != 0);
+      // get pointer
+      Ptr<RemusEnergyModel> devModel = DynamicCast<RemusEnergyModel> (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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/model/remus-mobility-model.h	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,124 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#ifndef REMUS_MOBILITY_MODEL_H_
+#define REMUS_MOBILITY_MODEL_H_
+
+#include "auv-mobility-model.h"
+#include "ns3/constant-velocity-helper.h"
+#include "ns3/box.h"
+#include "ns3/event-id.h"
+
+namespace ns3 {
+
+/**
+ * \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 ();
+
+  /**
+   * \param node the node associated with the mobility model
+   */
+  void SetNode (const Ptr<Node> node);
+  /**
+   * \returns the associated node
+   */
+  Ptr<Node> 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<void, Ptr<MobilityModel> > 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<void, Ptr<MobilityModel> > 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<Node> m_node;
+
+  Callback<void, Ptr<MobilityModel> > m_emergeCb;
+  Callback<void, Ptr<MobilityModel> > m_submergeCb;
+};
+
+}; // namespace ns3
+
+#endif /* REMUS_MOBILITY_MODEL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/test/auv-energy-model-test.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,493 @@
+/* -*- 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 <andrea.sacco85@gmail.com>
+ */
+
+#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/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<NetDevice> dev, Ptr<const Packet> pkt, uint16_t mode, const Address &sender);
+  void SendOnePacket (Ptr<Node> node);
+
+  void DoRun (void);
+
+  double m_simTime;
+  uint32_t m_bytesRx;
+  uint32_t m_sentPackets;
+  uint32_t m_packetSize;
+  Ptr<Node> m_node;
+  Ptr<Node> 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 = 0;
+  m_gateway = 0;
+}
+
+void
+AcousticModemEnergyTestCase::SendOnePacket (Ptr<Node> node)
+{
+  // create an empty 17 bytes packet
+  Ptr<Packet> pkt = Create<Packet> (m_packetSize);
+  // send the packet in broadcast
+  Ptr<UanNetDevice> dev = node->GetDevice (0)->GetObject<UanNetDevice> ();
+  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<NetDevice> dev, Ptr<const Packet> 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<Node> ();
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> 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<ConstantPositionMobilityModel> mobility = CreateObject<ConstantPositionMobilityModel> ();
+  mobility->SetPosition (Vector (0,0,-500));
+  m_node->AggregateObject (mobility);
+
+  // micro modem energy model
+  AcousticModemEnergyModelHelper modemHelper;
+  Ptr<EnergySource> source = m_node->GetObject<EnergySourceContainer> ()->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<Node> ();
+
+  // install the underwater communication stack
+  Ptr<UanNetDevice> devGateway = uan.Install (m_gateway, channel);
+
+  // energy source
+  eh.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (10000000.0));
+  eh.Install (m_gateway);
+
+  // mobility model
+  Ptr<ConstantPositionMobilityModel> mobility2 = CreateObject<ConstantPositionMobilityModel> ();
+  mobility2->SetPosition (Vector (0,0,0));
+  m_gateway->AggregateObject (mobility2);
+
+  // micro modem energy model
+  Ptr<EnergySource> source2 = m_gateway->GetObject<EnergySourceContainer> ()->Get (0);
+  DeviceEnergyModelContainer cont2 = modemHelper.Install (devGateway, source2);
+
+  // set the receive callback
+  Ptr<NetDevice> 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<EnergySource> src1 = m_gateway->GetObject<EnergySourceContainer> ()->Get (0);
+  double consumed1 = src1->GetInitialEnergy () - src1->GetRemainingEnergy ();
+  double computed1 = cont2.Get (0)->GetObject<AcousticModemEnergyModel> ()->GetRxPowerW () * packetDuration * receivedPackets +
+    cont2.Get (0)->GetObject<AcousticModemEnergyModel> ()->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<EnergySource> src2 = m_node->GetObject<EnergySourceContainer> ()->Get (0);
+  double consumed2 = src2->GetInitialEnergy () - src2->GetRemainingEnergy ();
+  double computed2 = cont.Get (0)->GetObject<AcousticModemEnergyModel> ()->GetTxPowerW () * packetDuration * m_sentPackets +
+    cont.Get (0)->GetObject<AcousticModemEnergyModel> ()->GetIdlePowerW () * (m_simTime - 1 - packetDuration * m_sentPackets);
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (consumed2, computed2, 1.0e-5,
+                             "Incorrect node consumed energy!");
+
+  return;
+}
+
+class AcousticModemEnergyDepletionTestCase : public TestCase
+{
+public:
+  AcousticModemEnergyDepletionTestCase ();
+  ~AcousticModemEnergyDepletionTestCase ();
+
+  void DepletionHandler (void);
+  void SendOnePacket (Ptr<Node> node);
+
+  void DoRun (void);
+
+  double m_simTime;
+  uint32_t m_callbackCount;
+  uint32_t m_packetSize;
+  Ptr<Node> m_node;
+};
+
+AcousticModemEnergyDepletionTestCase::AcousticModemEnergyDepletionTestCase ()
+  : TestCase ("Acoustic Modem energy depletion test case"),
+    m_simTime (25),
+    m_callbackCount (0),
+    m_packetSize (17)
+{
+}
+
+AcousticModemEnergyDepletionTestCase::~AcousticModemEnergyDepletionTestCase ()
+{
+  m_node = 0;
+}
+
+void
+AcousticModemEnergyDepletionTestCase::DepletionHandler (void)
+{
+  // increase callback count
+  m_callbackCount++;
+}
+
+void
+AcousticModemEnergyDepletionTestCase::SendOnePacket (Ptr<Node> node)
+{
+  // create an empty packet
+  Ptr<Packet> pkt = Create<Packet> (m_packetSize);
+  // send the packet in broadcast
+  Ptr<UanNetDevice> dev = node->GetDevice (0)->GetObject<UanNetDevice> ();
+  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<Node> ();
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> 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<ConstantPositionMobilityModel> mobility = CreateObject<ConstantPositionMobilityModel> ();
+  mobility->SetPosition (Vector (0,0,0));
+  m_node->AggregateObject (mobility);
+
+  // micro modem energy model
+  AcousticModemEnergyModelHelper modemHelper;
+  Ptr<EnergySource> source = m_node->GetObject<EnergySourceContainer> ()->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");
+
+  return;
+}
+*/
+
+class GliderEnergyTestCase : public TestCase
+{
+public:
+  GliderEnergyTestCase ();
+  ~GliderEnergyTestCase ();
+
+  void DoRun (void);
+  void GetPosition (void);
+
+  double m_simTime;
+  Ptr<Node> m_node;
+};
+
+GliderEnergyTestCase::GliderEnergyTestCase ()
+  : TestCase ("Glider energy model test case")
+{
+}
+
+GliderEnergyTestCase::~GliderEnergyTestCase ()
+{
+  m_node = 0;
+}
+
+void
+GliderEnergyTestCase::GetPosition ()
+{
+  Ptr<WaypointMobilityModel> model = m_node->GetObject<WaypointMobilityModel> ();
+  Vector pos = model->GetPosition ();
+
+  Simulator::Schedule (Seconds (1),
+                       &GliderEnergyTestCase::GetPosition,
+                       this);
+}
+
+void
+GliderEnergyTestCase::DoRun ()
+{
+  m_node = CreateObject<Node> ();
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> devNode = uan.Install (m_node, channel);
+
+  // install the glider components
+  AuvGliderHelper gh;
+  gh.Install (m_node);
+
+  double navTime = 20;
+  double commTime = 25;
+
+  // move the vehicle somewhere
+  Ptr<WaypointMobilityModel> mob = m_node->GetObject<WaypointMobilityModel> ();
+  mob->AddWaypoint (Waypoint (Seconds (0), Vector (0,0,0)));
+  mob->AddWaypoint (Waypoint (Seconds (navTime), Vector (4.5,0,-10)));
+  // GetPosition ();
+
+  // run the simulation
+  Simulator::Stop (Seconds (commTime + 0.1));
+  Simulator::Run ();
+
+  // get the motor energy source
+  Ptr<EnergySource> motorSrc = m_node->GetObject<EnergySourceContainer> ()->Get (0);
+  double motorConsumption = motorSrc->GetInitialEnergy () - motorSrc->GetRemainingEnergy ();
+  // dovrebbe essere 0.9702456448979383 da debug
+  double motorEstimated = (navTime - 1) * 0.970004254;
+  //double gliderConsumption = motorSrc->FindDeviceEnergyModels("ns3::GliderEnergyModel").Get(0)->GetTotalEnergyConsumption();
+
+  // get the communications energy source
+  Ptr<EnergySource> modemSrc = m_node->GetObject<EnergySourceContainer> ()->Get (1);
+  double modemConsumption = modemSrc->GetInitialEnergy () - modemSrc->GetRemainingEnergy ();
+  double modemEstimated = commTime * 0.158;
+
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (motorConsumption, motorEstimated, 1.0e-3,
+                             "Incorrect motor consumed energy!");
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (modemConsumption, modemEstimated, 1.0e-3,
+                             "Incorrect modem consumed energy!");
+
+  Simulator::Destroy ();
+
+  return;
+}
+
+class RemusEnergyTestCase : public TestCase
+{
+public:
+  RemusEnergyTestCase ();
+  ~RemusEnergyTestCase ();
+
+  void DoRun (void);
+  void GetPosition (void);
+
+  double m_simTime;
+  Ptr<Node> m_node;
+};
+
+RemusEnergyTestCase::RemusEnergyTestCase ()
+  : TestCase ("Remus energy model test case")
+{
+}
+
+RemusEnergyTestCase::~RemusEnergyTestCase ()
+{
+  m_node = 0;
+}
+
+void
+RemusEnergyTestCase::GetPosition ()
+{
+  Ptr<WaypointMobilityModel> model = m_node->GetObject<WaypointMobilityModel> ();
+  Vector pos = model->GetPosition ();
+
+  Simulator::Schedule (Seconds (1),
+                       &RemusEnergyTestCase::GetPosition,
+                       this);
+}
+
+void
+RemusEnergyTestCase::DoRun ()
+{
+  m_node = CreateObject<Node> ();
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> devNode = uan.Install (m_node, channel);
+
+  // install the glider components
+  AuvRemusHelper gh;
+  gh.Install (m_node);
+
+  double navTime = 50.0;
+  double commTime = 55.0;
+
+  // move the vehicle somewhere
+  Ptr<WaypointMobilityModel> mob = m_node->GetObject<WaypointMobilityModel> ();
+  mob->AddWaypoint (Waypoint (Seconds (0), Vector (0,0,0)));
+  mob->AddWaypoint (Waypoint (Seconds (navTime), Vector (100,0,0)));
+  GetPosition ();
+
+  // run the simulation
+  Simulator::Stop (Seconds (commTime + 0.1));
+  Simulator::Run ();
+
+  Ptr<EnergySource> src = m_node->GetObject<EnergySourceContainer> ()->Get (0);
+  double consumed = src->GetInitialEnergy () - src->GetRemainingEnergy ();
+
+  // motor + modem idle energy
+  double estimated = 20 * (navTime -1) + 0.158 * commTime;
+
+  NS_TEST_ASSERT_MSG_EQ_TOL (consumed, estimated, 1.0e-5,
+                             "Incorrect consumed energy!");
+
+  Simulator::Destroy ();
+
+  return;
+}
+
+// -------------------------------------------------------------------------- //
+
+/**
+ * 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);
+  //AddTestCase (new AcousticModemEnergyDepletionTestCase);
+  AddTestCase (new GliderEnergyTestCase);
+  AddTestCase (new RemusEnergyTestCase);
+}
+
+// create an instance of the test suite
+AuvEnergyModelTestSuite g_auvEnergyModelTestSuite;
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/test/auv-mobility-test.cc	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,436 @@
+/* -*-  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 <andrea.sacco85@gmail.com>
+ */
+
+#include "ns3/remus-mobility-model.h"
+#include "ns3/glider-mobility-model.h"
+#include "ns3/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 <cmath>
+#include <iomanip>
+
+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<MobilityModel> mob);
+  void EmergeCb (Ptr<MobilityModel> mob);
+  void SpeedCb (int16_t dir);
+
+  Ptr<RemusMobilityModel> 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)
+{
+  Vector pos = m_remusMob->GetPosition ();
+
+  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<MobilityModel> mob)
+{
+  double depth = m_remusMob->GetDepth ();
+
+  // depth should be -100
+  NS_ASSERT (depth == -100);
+}
+
+void
+RemusMobilityTestCase::EmergeCb (Ptr<MobilityModel> 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<Node> auv = CreateObject<Node> ();
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> devNode = uan.Install (auv, channel);
+
+  AuvRemusHelper helper;
+  helper.Install (auv);
+
+  m_remusMob = auv->GetObject<WaypointMobilityModel> ()->GetMobilityModel ()->GetObject<RemusMobilityModel> ();
+  NS_ASSERT (m_remusMob != 0);
+
+  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 ();
+
+  return;
+}
+
+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<MobilityModel> mob);
+  void EmergeCb (Ptr<MobilityModel> mob);
+  void SpeedCb (int16_t dir);
+
+  Ptr<GliderMobilityModel> 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)
+{
+  Vector pos = m_gliderMob->GetPosition ();
+
+  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<MobilityModel> mob)
+{
+  double depth = m_gliderMob->GetDepth ();
+
+  // depth should be -1000
+  NS_ASSERT (depth == -1000);
+
+  m_lastEndPos = m_gliderMob->GetPosition ();
+}
+
+void
+GliderMobilityTestCase::EmergeCb (Ptr<MobilityModel> 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<Node> auv = CreateObject<Node> ();
+
+  // create a default underwater channel
+  Ptr<UanChannel> channel = CreateObject<UanChannel> ();
+  Ptr<UanNoiseModelDefault> noise = CreateObject<UanNoiseModelDefault> ();
+  channel->SetPropagationModel (CreateObject<UanPropModelIdeal> ());
+  channel->SetNoiseModel (noise);
+
+  // install the underwater communication stack
+  UanHelper uan;
+  Ptr<UanNetDevice> devNode = uan.Install (auv, channel);
+
+  AuvGliderHelper helper;
+  helper.Install (auv);
+
+  m_gliderMob = auv->GetObject<WaypointMobilityModel> ()->GetMobilityModel ()->GetObject<GliderMobilityModel> ();
+  NS_ASSERT (m_gliderMob != 0);
+
+  // 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 ();
+
+  return;
+}
+
+class AuvMobilityTestSuite : public TestSuite
+{
+public:
+  AuvMobilityTestSuite ();
+};
+
+AuvMobilityTestSuite::AuvMobilityTestSuite ()
+  : TestSuite ("auv-mobility", UNIT)
+{
+  AddTestCase (new RemusMobilityTestCase);
+  AddTestCase (new GliderMobilityTestCase);
+}
+
+// create an instance of the test suite
+AuvMobilityTestSuite g_auvMobilityTestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/uan/auv/wscript	Sat Apr 16 00:38:20 2011 +0200
@@ -0,0 +1,31 @@
+## -*- 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-energy-model.cc',
+        'model/glider-mobility-model.cc',
+        'model/remus-energy-model.cc',
+        'model/remus-mobility-model.cc',
+        'helper/auv-glider-helper.cc',
+        'helper/auv-mobility-helper.cc',
+        'helper/auv-remus-helper.cc',
+        'test/auv-energy-model-test.cc',
+        'test/auv-mobility-test.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'auv'
+    headers.source = [
+        'model/auv-mobility-model.h',
+        'model/glider-energy-model.h',
+        'model/glider-mobility-model.h',
+        'model/remus-energy-model.h',
+        'model/remus-mobility-model.h',
+        'helper/auv-glider-helper.h',
+        'helper/auv-mobility-helper.h',
+        'helper/auv-remus-helper.h',
+        ]
+    
+    if (bld.env['ENABLE_EXAMPLES']):
+      bld.add_subdirs('examples')
--- a/src/wscript	Sat Apr 16 00:34:39 2011 +0200
+++ b/src/wscript	Sat Apr 16 00:38:20 2011 +0200
@@ -56,6 +56,7 @@
     'topology-read',
     'contrib/energy',
     'tools/visualizer',
+    'uan/auv',
     )
 
 def set_options(opt):