A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
gauss-markov-mobility-model.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 Dan Broyles
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Dan Broyles <dbroyl01@ku.edu>
19  */
20 #include <cmath>
21 #include "ns3/simulator.h"
22 #include "ns3/double.h"
23 #include "ns3/pointer.h"
24 #include "ns3/string.h"
25 #include "gauss-markov-mobility-model.h"
26 #include "position-allocator.h"
27 
28 namespace ns3 {
29 
30 NS_OBJECT_ENSURE_REGISTERED (GaussMarkovMobilityModel);
31 
32 TypeId
33 GaussMarkovMobilityModel::GetTypeId (void)
34 {
35  static TypeId tid = TypeId ("ns3::GaussMarkovMobilityModel")
36  .SetParent<MobilityModel> ()
37  .SetGroupName ("Mobility")
38  .AddConstructor<GaussMarkovMobilityModel> ()
39  .AddAttribute ("Bounds",
40  "Bounds of the area to cruise.",
41  BoxValue (Box (-100.0, 100.0, -100.0, 100.0, 0.0, 100.0)),
42  MakeBoxAccessor (&GaussMarkovMobilityModel::m_bounds),
43  MakeBoxChecker ())
44  .AddAttribute ("TimeStep",
45  "Change current direction and speed after moving for this time.",
46  TimeValue (Seconds (1.0)),
47  MakeTimeAccessor (&GaussMarkovMobilityModel::m_timeStep),
48  MakeTimeChecker ())
49  .AddAttribute ("Alpha",
50  "A constant representing the tunable parameter in the Gauss-Markov model.",
51  DoubleValue (1.0),
52  MakeDoubleAccessor (&GaussMarkovMobilityModel::m_alpha),
53  MakeDoubleChecker<double> ())
54  .AddAttribute ("MeanVelocity",
55  "A random variable used to assign the average velocity.",
56  StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1.0]"),
57  MakePointerAccessor (&GaussMarkovMobilityModel::m_rndMeanVelocity),
58  MakePointerChecker<RandomVariableStream> ())
59  .AddAttribute ("MeanDirection",
60  "A random variable used to assign the average direction.",
61  StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=6.283185307]"),
62  MakePointerAccessor (&GaussMarkovMobilityModel::m_rndMeanDirection),
63  MakePointerChecker<RandomVariableStream> ())
64  .AddAttribute ("MeanPitch",
65  "A random variable used to assign the average pitch.",
66  StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"),
67  MakePointerAccessor (&GaussMarkovMobilityModel::m_rndMeanPitch),
68  MakePointerChecker<RandomVariableStream> ())
69  .AddAttribute ("NormalVelocity",
70  "A gaussian random variable used to calculate the next velocity value.",
71  StringValue ("ns3::NormalRandomVariable[Mean=0.0|Variance=1.0|Bound=10.0]"), // Defaults to zero mean, and std dev = 1, and bound to +-10 of the mean
72  MakePointerAccessor (&GaussMarkovMobilityModel::m_normalVelocity),
73  MakePointerChecker<NormalRandomVariable> ())
74  .AddAttribute ("NormalDirection",
75  "A gaussian random variable used to calculate the next direction value.",
76  StringValue ("ns3::NormalRandomVariable[Mean=0.0|Variance=1.0|Bound=10.0]"),
77  MakePointerAccessor (&GaussMarkovMobilityModel::m_normalDirection),
78  MakePointerChecker<NormalRandomVariable> ())
79  .AddAttribute ("NormalPitch",
80  "A gaussian random variable used to calculate the next pitch value.",
81  StringValue ("ns3::NormalRandomVariable[Mean=0.0|Variance=1.0|Bound=10.0]"),
82  MakePointerAccessor (&GaussMarkovMobilityModel::m_normalPitch),
83  MakePointerChecker<NormalRandomVariable> ());
84 
85  return tid;
86 }
87 
88 GaussMarkovMobilityModel::GaussMarkovMobilityModel ()
89 {
90  m_meanVelocity = 0.0;
91  m_meanDirection = 0.0;
92  m_meanPitch = 0.0;
93  m_event = Simulator::ScheduleNow (&GaussMarkovMobilityModel::Start, this);
94  m_helper.Unpause ();
95 }
96 
97 void
98 GaussMarkovMobilityModel::Start (void)
99 {
100  if (m_meanVelocity == 0.0)
101  {
102  //Initialize the mean velocity, direction, and pitch variables
103  m_meanVelocity = m_rndMeanVelocity->GetValue ();
104  m_meanDirection = m_rndMeanDirection->GetValue ();
105  m_meanPitch = m_rndMeanPitch->GetValue ();
106  double cosD = std::cos (m_meanDirection);
107  double cosP = std::cos (m_meanPitch);
108  double sinD = std::sin (m_meanDirection);
109  double sinP = std::sin (m_meanPitch);
110  //Initialize the starting velocity, direction, and pitch to be identical to the mean ones
111  m_Velocity = m_meanVelocity;
112  m_Direction = m_meanDirection;
113  m_Pitch = m_meanPitch;
114  //Set the velocity vector to give to the constant velocity helper
115  m_helper.SetVelocity (Vector (m_Velocity*cosD*cosP, m_Velocity*sinD*cosP, m_Velocity*sinP));
116  }
117  m_helper.Update ();
118 
119  //Get the next values from the gaussian distributions for velocity, direction, and pitch
120  double rv = m_normalVelocity->GetValue ();
121  double rd = m_normalDirection->GetValue ();
122  double rp = m_normalPitch->GetValue ();
123 
124  //Calculate the NEW velocity, direction, and pitch values using the Gauss-Markov formula:
125  //newVal = alpha*oldVal + (1-alpha)*meanVal + sqrt(1-alpha^2)*rv
126  //where rv is a random number from a normal (gaussian) distribution
127  double one_minus_alpha = 1 - m_alpha;
128  double sqrt_alpha = std::sqrt (1 - m_alpha*m_alpha);
129  m_Velocity = m_alpha * m_Velocity + one_minus_alpha * m_meanVelocity + sqrt_alpha * rv;
130  m_Direction = m_alpha * m_Direction + one_minus_alpha * m_meanDirection + sqrt_alpha * rd;
131  m_Pitch = m_alpha * m_Pitch + one_minus_alpha * m_meanPitch + sqrt_alpha * rp;
132 
133  //Calculate the linear velocity vector to give to the constant velocity helper
134  double cosDir = std::cos (m_Direction);
135  double cosPit = std::cos (m_Pitch);
136  double sinDir = std::sin (m_Direction);
137  double sinPit = std::sin (m_Pitch);
138  double vx = m_Velocity * cosDir * cosPit;
139  double vy = m_Velocity * sinDir * cosPit;
140  double vz = m_Velocity * sinPit;
141  m_helper.SetVelocity (Vector (vx, vy, vz));
142 
143  m_helper.Unpause ();
144 
145  DoWalk (m_timeStep);
146 }
147 
148 void
149 GaussMarkovMobilityModel::DoWalk (Time delayLeft)
150 {
151  m_helper.UpdateWithBounds (m_bounds);
152  Vector position = m_helper.GetCurrentPosition ();
153  Vector speed = m_helper.GetVelocity ();
154  Vector nextPosition = position;
155  nextPosition.x += speed.x * delayLeft.GetSeconds ();
156  nextPosition.y += speed.y * delayLeft.GetSeconds ();
157  nextPosition.z += speed.z * delayLeft.GetSeconds ();
158  if (delayLeft.GetSeconds () < 0.0) delayLeft = Seconds (1.0);
159 
160  // Make sure that the position by the next time step is still within the boundary.
161  // If out of bounds, then alter the velocity vector and average direction to keep the position in bounds
162  if (m_bounds.IsInside (nextPosition))
163  {
164  m_event = Simulator::Schedule (delayLeft, &GaussMarkovMobilityModel::Start, this);
165  }
166  else
167  {
168  if (nextPosition.x > m_bounds.xMax || nextPosition.x < m_bounds.xMin)
169  {
170  speed.x = -speed.x;
171  m_meanDirection = 3.14159265 - m_meanDirection;
172  }
173 
174  if (nextPosition.y > m_bounds.yMax || nextPosition.y < m_bounds.yMin)
175  {
176  speed.y = -speed.y;
177  m_meanDirection = -m_meanDirection;
178  }
179 
180  if (nextPosition.z > m_bounds.zMax || nextPosition.z < m_bounds.zMin)
181  {
182  speed.z = -speed.z;
183  m_meanPitch = -m_meanPitch;
184  }
185 
186  m_Direction = m_meanDirection;
187  m_Pitch = m_meanPitch;
188  m_helper.SetVelocity (speed);
189  m_helper.Unpause ();
190  m_event = Simulator::Schedule (delayLeft, &GaussMarkovMobilityModel::Start, this);
191  }
193 }
194 
195 void
197 {
198  // chain up
200 }
201 
202 Vector
204 {
205  m_helper.Update ();
206  return m_helper.GetCurrentPosition ();
207 }
208 void
210 {
211  m_helper.SetPosition (position);
212  Simulator::Remove (m_event);
213  m_event = Simulator::ScheduleNow (&GaussMarkovMobilityModel::Start, this);
214 }
215 Vector
217 {
218  return m_helper.GetVelocity ();
219 }
220 
221 int64_t
223 {
224  m_rndMeanVelocity->SetStream (stream);
225  m_normalVelocity->SetStream (stream + 1);
226  m_rndMeanDirection->SetStream (stream + 2);
227  m_normalDirection->SetStream (stream + 3);
228  m_rndMeanPitch->SetStream (stream + 4);
229  m_normalPitch->SetStream (stream + 5);
230  return 6;
231 }
232 
233 } // namespace ns3
double x
Definition: vector.h:49
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
virtual void DoDispose(void)
Definition: object.cc:335
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
a 3d vector
Definition: vector.h:31
virtual double GetValue(void)=0
Returns a random double from the underlying distribution.
virtual void DoSetPosition(const Vector &position)
virtual Vector DoGetVelocity(void) const
void NotifyCourseChange(void) const
static void Remove(const EventId &id)
Definition: simulator.cc:257
virtual Vector DoGetPosition(void) const
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Definition: simulator.h:981
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
bool IsInside(const Vector &position) const
Definition: box.cc:54