Merge Gauss Markov Mobility Model
authorDan Broyles <muxman@sbcglobal.net>
Wed, 03 Mar 2010 10:58:27 -0500
changeset 6100 38066d5d262b
parent 6099 b37a72870f2d
child 6101 6e16bf523c55
Merge Gauss Markov Mobility Model
AUTHORS
src/mobility/box.cc
src/mobility/box.h
src/mobility/constant-velocity-helper.cc
src/mobility/constant-velocity-helper.h
src/mobility/gauss-markov-mobility-model.cc
src/mobility/gauss-markov-mobility-model.h
src/mobility/position-allocator.cc
src/mobility/position-allocator.h
src/mobility/wscript
--- a/AUTHORS	Tue Mar 02 15:29:53 2010 +0000
+++ b/AUTHORS	Wed Mar 03 10:58:27 2010 -0500
@@ -48,3 +48,4 @@
 Tom Wambold (tom5760@gmail.com)
 Florian Westphal (fw@strlen.de)
 Josh Pelkey (jpelkey@gatech.edu)
+Dan Broyles (muxman@sbcglobal.net)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/box.cc	Wed Mar 03 10:58:27 2010 -0500
@@ -0,0 +1,169 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Dan Broyles
+ *
+ * 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: Dan Broyles <dbroyl01@ku.edu>
+ */
+
+#include "box.h"
+#include "ns3/vector.h"
+#include "ns3/assert.h"
+#include "ns3/fatal-error.h"
+#include <cmath>
+#include <algorithm>
+#include <sstream> 
+
+namespace ns3 {
+
+Box::Box (double _xMin, double _xMax,
+          double _yMin, double _yMax,
+          double _zMin, double _zMax)
+  : xMin (_xMin),
+    xMax (_xMax),
+    yMin (_yMin),
+    yMax (_yMax),
+    zMin (_zMin),
+    zMax (_zMax)
+{}
+
+Box::Box ()
+  : xMin (0.0),
+    xMax (0.0),
+    yMin (0.0),
+    yMax (0.0),
+    zMin (0.0),
+    zMax (0.0)
+{}
+
+bool 
+Box::IsInside (const Vector &position) const
+{
+  return 
+    position.x <= this->xMax && position.x >= this->xMin &&
+    position.y <= this->yMax && position.y >= this->yMin &&
+    position.z <= this->zMax && position.z >= this->zMin;
+}
+
+Box::Side 
+Box::GetClosestSide (const Vector &position) const
+{
+  double xMinDist = std::abs (position.x - this->xMin);
+  double xMaxDist = std::abs (this->xMax - position.x);
+  double yMinDist = std::abs (position.y - this->yMin);
+  double yMaxDist = std::abs (this->yMax - position.y);
+  double zMinDist = std::abs (position.z - this->zMin);
+  double zMaxDist = std::abs (this->zMax - position.z);
+  double minX = std::min (xMinDist, xMaxDist);
+  double minY = std::min (yMinDist, yMaxDist);
+  double minZ = std::min (zMinDist, zMaxDist);
+  if (minX < minY && minX < minZ)
+    {
+      if (xMinDist < xMaxDist)
+        {
+          return LEFT;
+        }
+      else
+        {
+          return RIGHT;
+        }
+    }
+  else if (minY < minZ)
+    {
+      if (yMinDist < yMaxDist)
+        {
+          return BOTTOM;
+        }
+      else
+        {
+          return TOP;
+        }
+    }
+  else
+    {
+      if (zMinDist < zMaxDist)
+        {
+          return DOWN;
+        }
+      else
+        {
+          return UP;
+        }
+    }
+}
+
+Vector
+Box::CalculateIntersection (const Vector &current, const Vector &speed) const
+{
+  NS_ASSERT (IsInside (current));
+  double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
+  double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
+  double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
+  double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
+  bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
+  bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
+  bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
+  bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
+  if (xMaxYOk && speed.x >= 0)
+    {
+      return Vector (this->xMax, xMaxY, 0.0);
+    }
+  else if (xMinYOk && speed.x <= 0)
+    {
+      return Vector (this->xMin, xMinY, 0.0);
+    }
+  else if (yMaxXOk && speed.y >= 0)
+    {
+      return Vector (yMaxX, this->yMax, 0.0);
+    }
+  else if (yMinXOk && speed.y <= 0)
+    {
+      return Vector (yMinX, this->yMin, 0.0);
+    }
+  else
+    {
+      NS_ASSERT (false);
+      // quiet compiler
+      return Vector (0.0, 0.0, 0.0);
+    }
+
+}
+
+ATTRIBUTE_HELPER_CPP (Box);
+
+std::ostream &
+operator << (std::ostream &os, const Box &box)
+{
+  os << box.xMin << "|" << box.xMax << "|" << box.yMin << "|" << box.yMax << "|" << box.zMin << "|" << box.zMax;
+  return os;
+}
+std::istream &
+operator >> (std::istream &is, Box &box)
+ {
+  char c1, c2, c3, c4, c5;
+  is >> box.xMin >> c1 >> box.xMax >> c2 >> box.yMin >> c3 >> box.yMax >> c4 >> box.zMin >> c5 >> box.zMax;
+  if (c1 != '|' ||
+      c2 != '|' ||
+      c3 != '|' ||
+      c4 != '|' ||
+      c5 != '|')
+    {
+      is.setstate (std::ios_base::failbit);
+    }
+  return is;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/box.h	Wed Mar 03 10:58:27 2010 -0500
@@ -0,0 +1,113 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Dan Broyles
+ *
+ * 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: Dan Broyles <dbroyl01@ku.edu>
+ */
+#ifndef BOX_H
+#define BOX_H
+
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
+#include "ns3/vector.h"
+
+namespace ns3 {
+
+/**
+ * \brief a 3d box
+ */
+class Box
+{
+public:
+  enum Side {
+    RIGHT,
+    LEFT,
+    TOP,
+    BOTTOM,
+    UP,
+    DOWN
+  };
+  /**
+   * \param _xMin x coordinates of left boundary.
+   * \param _xMax x coordinates of right boundary.
+   * \param _yMin y coordinates of bottom boundary.
+   * \param _yMax y coordinates of top boundary.
+   * \param _zMin z coordinates of down boundary.
+   * \param _zMax z coordinates of up boundary.
+   *
+   * Create a box.
+   */
+  Box (double _xMin, double _xMax,
+       double _yMin, double _yMax,
+       double _zMin, double _zMax);
+  /**
+   * Create a zero-sized box located at coordinates (0.0,0.0,0.0)
+   */
+  Box ();
+  /**
+   * \param position the position to test.
+   * \returns true if the input position is located within the box, 
+   *          false otherwise.
+   *
+   * This method compares the x, y, and z coordinates of the input position.
+   */
+  bool IsInside (const Vector &position) const;
+  /**
+   * \param position the position to test.
+   * \returns the side of the cube the input position is closest to.
+   *
+   * This method compares the x, y, and z coordinates of the input position.
+   */
+  Side GetClosestSide (const Vector &position) const;
+  /**
+   * \param current the current position
+   * \param speed the current speed
+   * \returns the intersection point between the rectangle and the current+speed vector.
+   *
+   * This method assumes that the current position is located _inside_
+   * the cube and checks for this with an assert.
+   * This method compares only the x and y coordinates of the input position
+   * and speed. It ignores the z coordinate.
+   */
+  Vector CalculateIntersection (const Vector &current, const Vector &speed) const;
+
+  /* The x coordinate of the left bound of the box */
+  double xMin;
+  /* The x coordinate of the right bound of the box */
+  double xMax;
+  /* The y coordinate of the bottom bound of the box */
+  double yMin;
+  /* The y coordinate of the top bound of the box */
+  double yMax;
+  /* The z coordinate of the down bound of the box */
+  double zMin;
+  /* The z coordinate of the up bound of the box */
+  double zMax;
+};
+
+std::ostream &operator << (std::ostream &os, const Box &box);
+std::istream &operator >> (std::istream &is, Box &box);
+
+/**
+ * \class ns3::BoxValue
+ * \brief hold objects of type ns3::Box
+ */
+
+ATTRIBUTE_HELPER_HEADER (Box);
+
+} // namespace ns3
+
+#endif /* BOX_H */
--- a/src/mobility/constant-velocity-helper.cc	Tue Mar 02 15:29:53 2010 +0000
+++ b/src/mobility/constant-velocity-helper.cc	Wed Mar 03 10:58:27 2010 -0500
@@ -19,6 +19,7 @@
  */
 #include "ns3/simulator.h"
 #include "ns3/rectangle.h"
+#include "ns3/box.h"
 #include "constant-velocity-helper.h"
 
 namespace ns3 {
@@ -89,6 +90,18 @@
   m_position.y = std::max (bounds.yMin, m_position.y);
 }
 
+void
+ConstantVelocityHelper::UpdateWithBounds (const Box &bounds) const
+{
+  Update ();
+  m_position.x = std::min (bounds.xMax, m_position.x);
+  m_position.x = std::max (bounds.xMin, m_position.x);
+  m_position.y = std::min (bounds.yMax, m_position.y);
+  m_position.y = std::max (bounds.yMin, m_position.y);
+  m_position.z = std::min (bounds.zMax, m_position.z);
+  m_position.z = std::max (bounds.zMin, m_position.z);
+}
+
 void 
 ConstantVelocityHelper::Pause (void)
 {
--- a/src/mobility/constant-velocity-helper.h	Tue Mar 02 15:29:53 2010 +0000
+++ b/src/mobility/constant-velocity-helper.h	Wed Mar 03 10:58:27 2010 -0500
@@ -22,6 +22,7 @@
 
 #include "ns3/nstime.h"
 #include "ns3/vector.h"
+#include "ns3/box.h"
 
 namespace ns3 {
 
@@ -43,6 +44,7 @@
   void Unpause (void);
 
   void UpdateWithBounds (const Rectangle &rectangle) const;
+  void UpdateWithBounds (const Box &bounds) const;
   void Update (void) const;
  private:
   mutable Time m_lastUpdate;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/gauss-markov-mobility-model.cc	Wed Mar 03 10:58:27 2010 -0500
@@ -0,0 +1,222 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Dan Broyles
+ *
+ * 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: Dan Broyles <dbroyl01@ku.edu>
+ */
+#include <cmath>
+#include "ns3/simulator.h"
+#include "ns3/random-variable.h"
+#include "ns3/double.h"
+#include "ns3/pointer.h"
+#include "gauss-markov-mobility-model.h"
+#include "position-allocator.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (GaussMarkovMobilityModel);
+
+TypeId
+GaussMarkovMobilityModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::GaussMarkovMobilityModel")
+    .SetParent<MobilityModel> ()
+    .SetGroupName ("Mobility")
+    .AddConstructor<GaussMarkovMobilityModel> ()
+    .AddAttribute ("Bounds",
+                   "Bounds of the area to cruise.",
+                   BoxValue (Box (-100.0, 100.0, -100.0, 100.0, 0.0, 100.0)),
+                   MakeBoxAccessor (&GaussMarkovMobilityModel::m_bounds),
+                   MakeBoxChecker ())
+    .AddAttribute ("TimeStep",
+                   "Change current direction and speed after moving for this time.",
+                   TimeValue (Seconds (1.0)),
+                   MakeTimeAccessor (&GaussMarkovMobilityModel::m_timeStep),
+                   MakeTimeChecker ())
+    .AddAttribute ("Alpha",
+                   "A constant representing the tunable parameter in the Gauss-Markov model.",
+                   DoubleValue (1.0),
+                   MakeDoubleAccessor (&GaussMarkovMobilityModel::m_alpha),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MeanVelocity",
+                   "A random variable used to assign the average velocity.",
+                   RandomVariableValue (UniformVariable (0.0, 1.0)),  
+                   MakeRandomVariableAccessor (&GaussMarkovMobilityModel::m_rndMeanVelocity),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("MeanDirection",
+                   "A random variable used to assign the average direction.",
+                   RandomVariableValue (UniformVariable (0.0, 6.283185307)),  
+                   MakeRandomVariableAccessor (&GaussMarkovMobilityModel::m_rndMeanDirection),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("MeanPitch",
+                   "A random variable used to assign the average pitch.",
+                   RandomVariableValue (ConstantVariable (0.0)),  
+                   MakeRandomVariableAccessor (&GaussMarkovMobilityModel::m_rndMeanPitch),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("NormalVelocity",
+                   "A gaussian random variable used to calculate the next velocity value.",
+                   RandomVariableValue (NormalVariable (0.0, 1.0, 10.0)), // Defaults to zero mean, and std dev = 1, and bound to +-10 of the mean
+                   MakeRandomVariableAccessor (&GaussMarkovMobilityModel::m_normalVelocity),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("NormalDirection",
+                   "A gaussian random variable used to calculate the next direction value.",
+                   RandomVariableValue (NormalVariable (0.0, 1.0, 10.0)),
+                   MakeRandomVariableAccessor (&GaussMarkovMobilityModel::m_normalDirection),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("NormalPitch",
+                   "A gaussian random variable used to calculate the next pitch value.",
+                   RandomVariableValue (NormalVariable (0.0, 1.0, 10.0)),
+                   MakeRandomVariableAccessor (&GaussMarkovMobilityModel::m_normalPitch),
+                   MakeRandomVariableChecker ());
+  
+  return tid;
+}
+
+GaussMarkovMobilityModel::GaussMarkovMobilityModel ()
+{
+  m_meanVelocity = 0.0;
+  m_meanDirection = 0.0;
+  m_meanPitch = 0.0;
+  m_event = Simulator::ScheduleNow (&GaussMarkovMobilityModel::Start, this);
+  m_helper.Unpause ();
+}
+
+void
+GaussMarkovMobilityModel::Start (void)
+{
+  if (m_meanVelocity == 0.0)
+    {
+      //Initialize the mean velocity, direction, and pitch variables
+      m_meanVelocity = m_rndMeanVelocity.GetValue ();
+      m_meanDirection = m_rndMeanDirection.GetValue ();
+      m_meanPitch = m_rndMeanPitch.GetValue ();
+      double cosD = std::cos (m_meanDirection);
+      double cosP = std::cos (m_meanPitch);
+      double sinD = std::sin (m_meanDirection);
+      double sinP = std::sin (m_meanPitch);
+      //Initialize the starting velocity, direction, and pitch to be identical to the mean ones
+      m_Velocity = m_meanVelocity;
+      m_Direction = m_meanDirection;
+      m_Pitch = m_meanPitch;
+      //Set the velocity vector to give to the constant velocity helper
+      m_helper.SetVelocity (Vector (m_Velocity*cosD*cosP, m_Velocity*sinD*cosP, m_Velocity*sinP));
+    }
+  m_helper.Update ();
+
+  //Get the next values from the gaussian distributions for velocity, direction, and pitch
+  double rv = m_normalVelocity.GetValue ();
+  double rd = m_normalDirection.GetValue ();
+  double rp = m_normalPitch.GetValue ();
+
+  //Calculate the NEW velocity, direction, and pitch values using the Gauss-Markov formula:
+  //newVal = alpha*oldVal + (1-alpha)*meanVal + sqrt(1-alpha^2)*rv  
+  //where rv is a random number from a normal (gaussian) distribution
+  double one_minus_alpha = 1 - m_alpha;
+  double sqrt_alpha = std::sqrt (1 - m_alpha*m_alpha);
+  m_Velocity  = m_alpha * m_Velocity  + one_minus_alpha * m_meanVelocity  + sqrt_alpha * rv;
+  m_Direction = m_alpha * m_Direction + one_minus_alpha * m_meanDirection + sqrt_alpha * rd;
+  m_Pitch     = m_alpha * m_Pitch     + one_minus_alpha * m_meanPitch     + sqrt_alpha * rp;
+
+  //Calculate the linear velocity vector to give to the constant velocity helper
+  double cosDir = std::cos (m_Direction);
+  double cosPit = std::cos (m_Pitch);
+  double sinDir = std::sin (m_Direction);
+  double sinPit = std::sin (m_Pitch);
+  double vx = m_Velocity * cosDir * cosPit;
+  double vy = m_Velocity * sinDir * cosPit;
+  double vz = m_Velocity * sinPit;
+  m_helper.SetVelocity (Vector (vx, vy, vz));
+
+  m_helper.Unpause ();
+
+  DoWalk (m_timeStep);
+}
+
+void
+GaussMarkovMobilityModel::DoWalk (Time delayLeft)
+{
+  m_helper.UpdateWithBounds (m_bounds);
+  Vector position = m_helper.GetCurrentPosition ();
+  Vector speed = m_helper.GetVelocity ();
+  Vector nextPosition = position;
+  nextPosition.x += speed.x * delayLeft.GetSeconds ();
+  nextPosition.y += speed.y * delayLeft.GetSeconds ();
+  nextPosition.z += speed.z * delayLeft.GetSeconds ();
+  if (delayLeft.GetSeconds () < 0.0) delayLeft = Seconds (1.0);
+
+  // Make sure that the position by the next time step is still within the boundary.
+  // If out of bounds, then alter the velocity vector and average direction to keep the position in bounds
+  if (m_bounds.IsInside (nextPosition))
+    {
+      m_event = Simulator::Schedule (delayLeft, &GaussMarkovMobilityModel::Start, this);
+    }
+  else
+    {
+      if (nextPosition.x > m_bounds.xMax || nextPosition.x < m_bounds.xMin) 
+        {
+          speed.x = - speed.x;
+          m_meanDirection = 3.14159265 - m_meanDirection;
+        }
+
+      if (nextPosition.y > m_bounds.yMax || nextPosition.y < m_bounds.yMin) 
+        {
+          speed.y = - speed.y;
+          m_meanDirection = - m_meanDirection;
+        }
+
+      if (nextPosition.z > m_bounds.zMax || nextPosition.z < m_bounds.zMin) 
+        {
+          speed.z = - speed.z;
+          m_meanPitch = - m_meanPitch;
+        }
+
+      m_Direction = m_meanDirection;
+      m_Pitch = m_meanPitch;
+      m_helper.SetVelocity (speed);
+      m_helper.Unpause ();
+      m_event = Simulator::Schedule (delayLeft, &GaussMarkovMobilityModel::Start, this);
+    }
+  NotifyCourseChange ();
+}
+
+void
+GaussMarkovMobilityModel::DoDispose (void)
+{
+  // chain up
+  MobilityModel::DoDispose ();
+}
+
+Vector
+GaussMarkovMobilityModel::DoGetPosition (void) const
+{
+  m_helper.Update ();
+  return m_helper.GetCurrentPosition ();
+}
+void 
+GaussMarkovMobilityModel::DoSetPosition (const Vector &position)
+{
+  m_helper.SetPosition (position);
+  Simulator::Remove (m_event);
+  m_event = Simulator::ScheduleNow (&GaussMarkovMobilityModel::Start, this);
+}
+Vector
+GaussMarkovMobilityModel::DoGetVelocity (void) const
+{
+  return m_helper.GetVelocity ();
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/gauss-markov-mobility-model.h	Wed Mar 03 10:58:27 2010 -0500
@@ -0,0 +1,113 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Dan Broyles
+ *
+ * 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: Dan Broyles <dbroyl01@ku.edu>
+ * Thanks to the students and faculty in the ResiliNets initiative 
+ * at Kansas University, https://wiki.ittc.ku.edu/resilinets/Main_Page
+ */
+#ifndef GAUSS_MARKOV_MOBILITY_MODEL_H
+#define GAUSS_MARKOV_MOBILITY_MODEL_H
+
+#include "constant-velocity-helper.h"
+#include "mobility-model.h"
+#include "position-allocator.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+#include "ns3/box.h"
+#include "ns3/random-variable.h"
+
+namespace ns3 {
+
+/**
+ * \brief description of gauss markov mobility model
+ *
+ * This is a 3D version of the Gauss-Markov mobility model described in [1]. 
+ * Unlike the other mobility models in ns-3, which are memoryless, the Gauss
+ * Markov model has both memory and variability. The tunable alpha parameter
+ * determines the how much memory and randomness you want to model.
+ * Each object starts with a specific velocity, direction (radians), and pitch 
+ * angle (radians) equivalent to the mean velocity, direction, and pitch. 
+ * At each timestep, a new velocity, direction, and pitch angle are generated 
+ * based upon the previous value, the mean value, and a gaussian random variable. 
+ * This version is suited for simple airplane flight, where direction, velocity,
+ * and pitch are the key variables.
+ * The motion field is limited by a 3D bounding box (called "box") which is a 3D
+ * version of the "rectangle" field that is used in 2-dimensional ns-3 mobility models.
+ * 
+ * Here is an example of how to implement the model and set the initial node positions:
+ * 
+ *   MobilityHelper mobility;
+ * 
+ *   mobility.SetMobilityModel ("ns3::GaussMarkovMobilityModel",
+ *     "Bounds", BoxValue (Box (0, 150000, 0, 150000, 0, 10000)),
+ *     "TimeStep", TimeValue (Seconds (0.5)),
+ *     "Alpha", DoubleValue (0.85),
+ *     "MeanVelocity", RandomVariableValue (UniformVariable (800, 1200)),
+ *     "MeanDirection", RandomVariableValue (UniformVariable (0, 6.283185307)),
+ *     "MeanPitch", RandomVariableValue (UniformVariable (0.05, 0.05)),
+ *     "NormalVelocity", RandomVariableValue (NormalVariable (0.0, 0.0, 0.0)),
+ *     "NormalDirection", RandomVariableValue (NormalVariable (0.0, 0.2, 0.4)),
+ *     "NormalPitch", RandomVariableValue (NormalVariable (0.0, 0.02, 0.04)));
+ * 
+ *   mobility.SetPositionAllocator ("ns3::RandomBoxPositionAllocator",
+ *     "X", RandomVariableValue (UniformVariable (0, 150000)),
+ *     "Y", RandomVariableValue (UniformVariable (0, 150000)),
+ *     "Z", RandomVariableValue (UniformVariable (0, 10000)));
+ *
+ *   mobility.Install (wifiStaNodes);
+ *
+ * [1] Tracy Camp, Jeff Boleng, Vanessa Davies, "A Survey of Mobility Models
+ * for Ad Hoc Network Research", Wireless Communications and Mobile Computing,
+ * Wiley, vol.2 iss.5, September 2002, pp.483-502
+ */
+
+class GaussMarkovMobilityModel : public MobilityModel
+{
+public:
+  static TypeId GetTypeId (void);
+  GaussMarkovMobilityModel ();
+private:
+  void Start (void);
+  void DoWalk (Time timeLeft);
+  virtual void DoDispose (void);
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
+  ConstantVelocityHelper m_helper;
+  Time m_timeStep;
+  double m_alpha;
+  double m_meanVelocity;
+  double m_meanDirection;
+  double m_meanPitch;
+  double m_Velocity;
+  double m_Direction;
+  double m_Pitch;
+  RandomVariable m_rndMeanVelocity;
+  RandomVariable m_normalVelocity;
+  RandomVariable m_rndMeanDirection;
+  RandomVariable m_normalDirection;
+  RandomVariable m_rndMeanPitch;
+  RandomVariable m_normalPitch;
+  EventId m_event;
+  Box m_bounds;
+};
+
+} // namespace ns3
+
+#endif /* GAUSS_MARKOV_MOBILITY_MODEL_H */
--- a/src/mobility/position-allocator.cc	Tue Mar 02 15:29:53 2010 +0000
+++ b/src/mobility/position-allocator.cc	Wed Mar 03 10:58:27 2010 -0500
@@ -245,6 +245,66 @@
   return Vector (x, y, 0.0);
 }
 
+
+NS_OBJECT_ENSURE_REGISTERED (RandomBoxPositionAllocator);
+
+TypeId
+RandomBoxPositionAllocator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::RandomBoxPositionAllocator")
+    .SetParent<PositionAllocator> ()
+    .SetGroupName ("Mobility")
+    .AddConstructor<RandomBoxPositionAllocator> ()
+    .AddAttribute ("X",
+                   "A random variable which represents the x coordinate of a position in a random box.",
+                   RandomVariableValue (UniformVariable (0.0, 1.0)),
+                   MakeRandomVariableAccessor (&RandomBoxPositionAllocator::m_x),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("Y",
+                   "A random variable which represents the y coordinate of a position in a random box.",
+                   RandomVariableValue (UniformVariable (0.0, 1.0)),
+                   MakeRandomVariableAccessor (&RandomBoxPositionAllocator::m_y),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("Z",
+                   "A random variable which represents the z coordinate of a position in a random box.",
+                   RandomVariableValue (UniformVariable (0.0, 1.0)),
+                   MakeRandomVariableAccessor (&RandomBoxPositionAllocator::m_z),
+                   MakeRandomVariableChecker ());
+  return tid;
+}
+
+RandomBoxPositionAllocator::RandomBoxPositionAllocator ()
+{}
+RandomBoxPositionAllocator::~RandomBoxPositionAllocator ()
+{}
+
+void 
+RandomBoxPositionAllocator::SetX (RandomVariable x)
+{
+  m_x = x;
+}
+void 
+RandomBoxPositionAllocator::SetY (RandomVariable y)
+{
+  m_y = y;
+}
+void 
+RandomBoxPositionAllocator::SetZ (RandomVariable z)
+{
+  m_z = z;
+}
+
+Vector
+RandomBoxPositionAllocator::GetNext (void) const
+{
+  double x = m_x.GetValue ();
+  double y = m_y.GetValue ();
+  double z = m_z.GetValue ();
+  return Vector (x, y, z);
+}
+
+
+
 NS_OBJECT_ENSURE_REGISTERED (RandomDiscPositionAllocator);
 
 TypeId
--- a/src/mobility/position-allocator.h	Tue Mar 02 15:29:53 2010 +0000
+++ b/src/mobility/position-allocator.h	Wed Mar 03 10:58:27 2010 -0500
@@ -181,6 +181,28 @@
 };
 
 /**
+ * \brief allocate random positions within a 3D box
+ * according to a set of three random variables.
+ */
+class RandomBoxPositionAllocator : public PositionAllocator
+{
+public:
+  static TypeId GetTypeId (void);
+  RandomBoxPositionAllocator ();
+  virtual ~RandomBoxPositionAllocator ();
+
+  void SetX (RandomVariable x);
+  void SetY (RandomVariable y);
+  void SetZ (RandomVariable z);
+
+  virtual Vector GetNext (void) const;
+private:
+  RandomVariable m_x;
+  RandomVariable m_y;
+  RandomVariable m_z;
+};
+
+/**
  * \brief allocate random positions within a disc
  * according to a given distribution for the polar coordinates of each
  * node with respect to the provided center of the disc 
--- a/src/mobility/wscript	Tue Mar 02 15:29:53 2010 +0000
+++ b/src/mobility/wscript	Wed Mar 03 10:58:27 2010 -0500
@@ -7,9 +7,11 @@
         'mobility-model.cc',
         'position-allocator.cc',
         'rectangle.cc',
+        'box.cc',
         'constant-position-mobility-model.cc',
         'constant-velocity-helper.cc',
         'constant-velocity-mobility-model.cc',
+        'gauss-markov-mobility-model.cc',
         'random-waypoint-mobility-model.cc',
         'steady-state-random-waypoint-mobility-model.cc',
         'random-walk-2d-mobility-model.cc',
@@ -26,9 +28,11 @@
         'mobility-model.h',
         'position-allocator.h',
         'rectangle.h',
+        'box.h',
         'constant-position-mobility-model.h',
         'constant-velocity-helper.h',
         'constant-velocity-mobility-model.h',
+        'gauss-markov-mobility-model.h',
         'random-waypoint-mobility-model.h',
         'steady-state-random-waypoint-mobility-model.h',
         'random-walk-2d-mobility-model.h',