blob: 5fb968bbca1c42c09cf33db2a3364babaad87c78 [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;
36
37const double COLOUMB_K = 200;
38
39TypeId SpringMobilityModel::GetTypeId (void)
40{
41 static TypeId tid = TypeId ("ns3::SpringMobilityModel")
42 .SetParent<MobilityModel> ()
43 .AddConstructor<SpringMobilityModel> ()
44 .AddAttribute ("Epsilon", "Bound for kinetic energy when system is considered stable",
45 DoubleValue (1000.0),
46 MakeDoubleAccessor (&SpringMobilityModel::m_epsilon),
47 MakeDoubleChecker<double> ())
48 .AddAttribute ("NodeMass", "Node mass",
49 DoubleValue (10),
50 MakeDoubleAccessor (&SpringMobilityModel::m_nodeMass),
51 MakeDoubleChecker<double> ())
52 .AddAttribute ("NodeCharge", "Node charge",
53 DoubleValue (2),
54 MakeDoubleAccessor (&SpringMobilityModel::m_nodeCharge),
55 MakeDoubleChecker<double> ())
56 .AddAttribute ("SpringNormalLength", "Normal length of spring length",
57 DoubleValue (10),
58 MakeDoubleAccessor (&SpringMobilityModel::m_springNormalLength),
59 MakeDoubleChecker<double> ())
60 .AddAttribute ("SpringConstant", "Spring constant",
61 DoubleValue (0.2),
62 MakeDoubleAccessor (&SpringMobilityModel::m_springConstant),
63 MakeDoubleChecker<double> ())
64 .AddAttribute ("DampingFactor", "Dumping factor",
65 DoubleValue (0.6),
66 MakeDoubleAccessor (&SpringMobilityModel::m_dampingFactor),
67 MakeDoubleChecker<double> ())
68 ;
69
70 return tid;
71}
72
73SpringMobilityModel::SpringMobilityModel ()
74 : m_position (0,0,0)
75 , m_velocity (0,0,0)
76 , m_stable (false)
77{
78}
79
80SpringMobilityModel::~SpringMobilityModel ()
81{
82}
83
84void
85SpringMobilityModel::AddSpring (Ptr<MobilityModel> node)
86{
87 m_springs.push_back (node);
88}
89
90void
91SpringMobilityModel::DoStart ()
92{
93 // m_updateEvent = Simulator::Schedule (Seconds(0.05), &SpringMobilityModel::Update, this);
94
95 // Simulator::Schedule (Seconds(2.0), &SpringMobilityModel::Test, this);
96}
97
98void
99SpringMobilityModel::Update () const
100{
101 // NS_LOG_FUNCTION (this << m_stable << m_position << m_velocity);
102 if (m_stable) return;
103 Time now = Simulator::Now ();
104
105 if (now <= m_lastTime)
106 {
107 m_lastTime = now;
108 return;
109 }
110
111 double time_step_s = (now - m_lastTime).ToDouble (Time::S);
112 m_lastTime = now;
113
114 Vector force (0.0, 0.0, 0.0);
115
116 for (NodeList::Iterator node = NodeList::Begin ();
117 node != NodeList::End ();
118 node++)
119 {
120 if ((*node)->GetId () == GetObject<Node> ()->GetId ()) continue;
121 Ptr<SpringMobilityModel> model = (*node)->GetObject<SpringMobilityModel> ();
122 if (model == 0) continue;
123 if (model == this) continue;
124
125 double distance = GetDistanceFrom (model);
126 if (distance < 0.1) continue;
127
128 Vector direction = (GetPosition () - model->GetPosition ()) / distance; // direction vector of size 1, force trying to take nodes apart
129
130 force += direction * COLOUMB_K * m_nodeCharge * m_nodeCharge / distance / distance;
131 }
132
133 BOOST_FOREACH (Ptr<MobilityModel> model, m_springs)
134 {
135 double distance = GetDistanceFrom (model);
136 Vector direction = (model->GetPosition () - GetPosition ()) / distance; // direction vector of size 1, force trying to take nodes closer, if they are more than distance apart
137
138 force += direction * (- m_springNormalLength + distance) / m_springConstant;
139 }
140
141 // NS_LOG_DEBUG ("force: " << force);
142
143 // subtract previous value of kinetic energy for the node
144 double velocityValue = CalculateDistance (m_velocity, Vector(0,0,0));
145 m_totalKineticEnergy -= m_nodeMass * velocityValue * velocityValue;
146
147 // Correct velocity and position
148 m_velocity = (m_velocity + force * time_step_s) * m_dampingFactor;
149 m_position += m_velocity * time_step_s;
150
151 // Add new value for the kinetic energy
152 velocityValue = CalculateDistance (m_velocity, Vector(0,0,0));
153 m_totalKineticEnergy += m_nodeMass * velocityValue * velocityValue;
154
155 if (m_totalKineticEnergy < m_epsilon)
156 {
157 m_stable = true;
158 NS_LOG_INFO ("Stabilized with " << m_totalKineticEnergy);
159 }
160
161 NotifyCourseChange ();
162 // m_updateEvent = Simulator::Schedule (Seconds(0.05), &SpringMobilityModel::Update, this);
163}
164
165Vector
166SpringMobilityModel::DoGetPosition (void) const
167{
168 // NS_LOG_FUNCTION (this << m_position);
169 Update ();
170
171 return m_position;
172}
173void
174SpringMobilityModel::DoSetPosition (const Vector &position)
175{
176 // NS_LOG_FUNCTION (this << position);
177 m_position = position;
178
179 NotifyCourseChange ();
180 m_stable = false;
181}
182Vector
183SpringMobilityModel::DoGetVelocity (void) const
184{
185 return m_velocity;
186}
187
188} // namespace ns3