blob: 170b428870445b97d5fe7a943069c7ec1d3035b2 [file] [log] [blame]
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -08001/* -*- 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
29NS_LOG_COMPONENT_DEFINE ("SpringMobilityModel");
30
31namespace ns3 {
32
33NS_OBJECT_ENSURE_REGISTERED (SpringMobilityModel);
34
35double SpringMobilityModel::m_totalKineticEnergy = 0.0;
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -080036bool SpringMobilityModel::m_stable = false;
37EventId SpringMobilityModel::m_updateEvent;
38double SpringMobilityModel::m_epsilon = 100.0;
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -080039
40const double COLOUMB_K = 200;
41
42TypeId SpringMobilityModel::GetTypeId (void)
43{
44 static TypeId tid = TypeId ("ns3::SpringMobilityModel")
45 .SetParent<MobilityModel> ()
46 .AddConstructor<SpringMobilityModel> ()
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -080047 // .AddAttribute ("Epsilon", "Bound for kinetic energy when system is considered stable",
48 // DoubleValue (100.0),
49 // MakeDoubleAccessor (&SpringMobilityModel::m_epsilon),
50 // MakeDoubleChecker<double> ())
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -080051 .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",
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -080068 DoubleValue (0.8),
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -080069 MakeDoubleAccessor (&SpringMobilityModel::m_dampingFactor),
70 MakeDoubleChecker<double> ())
71 ;
72
73 return tid;
74}
75
76SpringMobilityModel::SpringMobilityModel ()
77 : m_position (0,0,0)
78 , m_velocity (0,0,0)
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -080079{
80}
81
82SpringMobilityModel::~SpringMobilityModel ()
83{
84}
85
86void
87SpringMobilityModel::AddSpring (Ptr<MobilityModel> node)
88{
89 m_springs.push_back (node);
90}
91
92void
93SpringMobilityModel::DoStart ()
94{
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -080095 if (!m_updateEvent.IsRunning ())
96 m_updateEvent = Simulator::Schedule (Seconds(0.05), SpringMobilityModel::UpdateAll);
97}
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -080098
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -080099void
100SpringMobilityModel::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);
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -0800118}
119
120void
121SpringMobilityModel::Update () const
122{
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -0800123 NS_LOG_FUNCTION (this << m_stable << m_position << m_velocity);
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -0800124 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
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -0800177 NotifyCourseChange ();
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -0800178}
179
180Vector
181SpringMobilityModel::DoGetPosition (void) const
182{
183 // NS_LOG_FUNCTION (this << m_position);
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -0800184 return m_position;
185}
186void
187SpringMobilityModel::DoSetPosition (const Vector &position)
188{
189 // NS_LOG_FUNCTION (this << position);
190 m_position = position;
191
192 NotifyCourseChange ();
193 m_stable = false;
Alexander Afanasyev5beb35a2011-12-21 16:45:13 -0800194
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);
Alexander Afanasyev7dbdcaf2011-12-13 21:40:37 -0800207}
208Vector
209SpringMobilityModel::DoGetVelocity (void) const
210{
211 return m_velocity;
212}
213
214} // namespace ns3