NS-3 based Named Data Networking (NDN) simulator
ndnSIM: NDN, CCN, CCNx, content centric networks
API Documentation
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
spring-mobility-model.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006, 2007 INRIA
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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19  */
20 #include "spring-mobility-model.h"
21 #include "ns3/simulator.h"
22 #include "ns3/double.h"
23 #include "ns3/log.h"
24 #include "ns3/node-list.h"
25 #include "ns3/node.h"
26 
27 #include <boost/foreach.hpp>
28 
29 NS_LOG_COMPONENT_DEFINE ("SpringMobilityModel");
30 
31 namespace ns3 {
32 
33 NS_OBJECT_ENSURE_REGISTERED (SpringMobilityModel);
34 
35 double SpringMobilityModel::m_totalKineticEnergy = 0.0;
36 bool SpringMobilityModel::m_stable = false;
37 EventId SpringMobilityModel::m_updateEvent;
38 double SpringMobilityModel::m_epsilon = 100.0;
39 
40 const double COLOUMB_K = 200;
41 
42 TypeId SpringMobilityModel::GetTypeId (void)
43 {
44  static TypeId tid = TypeId ("ns3::SpringMobilityModel")
45  .SetParent<MobilityModel> ()
46  .AddConstructor<SpringMobilityModel> ()
47  // .AddAttribute ("Epsilon", "Bound for kinetic energy when system is considered stable",
48  // DoubleValue (100.0),
49  // MakeDoubleAccessor (&SpringMobilityModel::m_epsilon),
50  // MakeDoubleChecker<double> ())
51  .AddAttribute ("NodeMass", "Node mass",
52  DoubleValue (10),
53  MakeDoubleAccessor (&SpringMobilityModel::m_nodeMass),
54  MakeDoubleChecker<double> ())
55  .AddAttribute ("NodeCharge", "Node charge",
56  DoubleValue (2),
57  MakeDoubleAccessor (&SpringMobilityModel::m_nodeCharge),
58  MakeDoubleChecker<double> ())
59  .AddAttribute ("SpringNormalLength", "Normal length of spring length",
60  DoubleValue (10),
61  MakeDoubleAccessor (&SpringMobilityModel::m_springNormalLength),
62  MakeDoubleChecker<double> ())
63  .AddAttribute ("SpringConstant", "Spring constant",
64  DoubleValue (0.2),
65  MakeDoubleAccessor (&SpringMobilityModel::m_springConstant),
66  MakeDoubleChecker<double> ())
67  .AddAttribute ("DampingFactor", "Dumping factor",
68  DoubleValue (0.8),
69  MakeDoubleAccessor (&SpringMobilityModel::m_dampingFactor),
70  MakeDoubleChecker<double> ())
71  ;
72 
73  return tid;
74 }
75 
77  : m_position (0,0,0)
78  , m_velocity (0,0,0)
79 {
80 }
81 
82 SpringMobilityModel::~SpringMobilityModel ()
83 {
84 }
85 
86 void
87 SpringMobilityModel::AddSpring (Ptr<MobilityModel> node)
88 {
89  m_springs.push_back (node);
90 }
91 
92 void
93 SpringMobilityModel::DoStart ()
94 {
95  if (!m_updateEvent.IsRunning ())
96  m_updateEvent = Simulator::Schedule (Seconds(0.05), SpringMobilityModel::UpdateAll);
97 }
98 
99 void
100 SpringMobilityModel::UpdateAll ()
101 {
102  for (NodeList::Iterator node = NodeList::Begin ();
103  node != NodeList::End ();
104  node++)
105  {
106  Ptr<SpringMobilityModel> model = (*node)->GetObject<SpringMobilityModel> ();
107  if (model != 0)
108  model->Update ();
109  }
110 
111  if (m_totalKineticEnergy < m_epsilon)
112  {
113  m_stable = true;
114  NS_LOG_INFO ("Stabilized with " << m_totalKineticEnergy);
115  }
116  else
117  m_updateEvent = Simulator::Schedule (Seconds(0.05), SpringMobilityModel::UpdateAll);
118 }
119 
120 void
121 SpringMobilityModel::Update () const
122 {
123  NS_LOG_FUNCTION (this << m_stable << m_position << m_velocity);
124  if (m_stable) return;
125  Time now = Simulator::Now ();
126 
127  if (now <= m_lastTime)
128  {
129  m_lastTime = now;
130  return;
131  }
132 
133  double time_step_s = (now - m_lastTime).ToDouble (Time::S);
134  m_lastTime = now;
135 
136  Vector force (0.0, 0.0, 0.0);
137 
138  for (NodeList::Iterator node = NodeList::Begin ();
139  node != NodeList::End ();
140  node++)
141  {
142  if ((*node)->GetId () == GetObject<Node> ()->GetId ()) continue;
143  Ptr<SpringMobilityModel> model = (*node)->GetObject<SpringMobilityModel> ();
144  if (model == 0) continue;
145  if (model == this) continue;
146 
147  double distance = GetDistanceFrom (model);
148  if (distance < 0.1) continue;
149 
150  Vector direction = (GetPosition () - model->GetPosition ()) / distance; // direction vector of size 1, force trying to take nodes apart
151 
152  force += direction * COLOUMB_K * m_nodeCharge * m_nodeCharge / distance / distance;
153  }
154 
155  BOOST_FOREACH (Ptr<MobilityModel> model, m_springs)
156  {
157  double distance = GetDistanceFrom (model);
158  Vector direction = (model->GetPosition () - GetPosition ()) / distance; // direction vector of size 1, force trying to take nodes closer, if they are more than distance apart
159 
160  force += direction * (- m_springNormalLength + distance) / m_springConstant;
161  }
162 
163  // NS_LOG_DEBUG ("force: " << force);
164 
165  // subtract previous value of kinetic energy for the node
166  double velocityValue = CalculateDistance (m_velocity, Vector(0,0,0));
167  m_totalKineticEnergy -= m_nodeMass * velocityValue * velocityValue;
168 
169  // Correct velocity and position
170  m_velocity = (m_velocity + force * time_step_s) * m_dampingFactor;
171  m_position += m_velocity * time_step_s;
172 
173  // Add new value for the kinetic energy
174  velocityValue = CalculateDistance (m_velocity, Vector(0,0,0));
175  m_totalKineticEnergy += m_nodeMass * velocityValue * velocityValue;
176 
177  NotifyCourseChange ();
178 }
179 
180 Vector
181 SpringMobilityModel::DoGetPosition (void) const
182 {
183  // NS_LOG_FUNCTION (this << m_position);
184  return m_position;
185 }
186 void
187 SpringMobilityModel::DoSetPosition (const Vector &position)
188 {
189  // NS_LOG_FUNCTION (this << position);
190  m_position = position;
191 
192  NotifyCourseChange ();
193  m_stable = false;
194 
195 
196  for (NodeList::Iterator node = NodeList::Begin ();
197  node != NodeList::End ();
198  node++)
199  {
200  Ptr<SpringMobilityModel> model = (*node)->GetObject<SpringMobilityModel> ();
201  if (model != 0)
202  model->m_lastTime = Simulator::Now ();
203  }
204 
205  if (!m_updateEvent.IsRunning ())
206  m_updateEvent = Simulator::Schedule (Seconds(0.05), SpringMobilityModel::UpdateAll);
207 }
208 Vector
209 SpringMobilityModel::DoGetVelocity (void) const
210 {
211  return m_velocity;
212 }
213 
214 } // namespace ns3