1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "ns3/mobility-helper.h"
21 #include "ns3/mobility-model.h"
22 #include "ns3/position-allocator.h"
23 #include "ns3/hierarchical-mobility-model.h"
24 #include "ns3/log.h"
25 #include "ns3/pointer.h"
26 #include "ns3/config.h"
27 #include "ns3/simulator.h"
28 #include "ns3/names.h"
29 #include "ns3/string.h"
30 #include <iostream>
31 
32 namespace ns3 {
33 
34 NS_LOG_COMPONENT_DEFINE ("MobilityHelper");
35 
MobilityHelper()36 MobilityHelper::MobilityHelper ()
37 {
38   m_position = CreateObjectWithAttributes<RandomRectanglePositionAllocator>
39       ("X", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"),
40       "Y", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"));
41   m_mobility.SetTypeId ("ns3::ConstantPositionMobilityModel");
42 }
~MobilityHelper()43 MobilityHelper::~MobilityHelper ()
44 {
45 }
46 void
SetPositionAllocator(Ptr<PositionAllocator> allocator)47 MobilityHelper::SetPositionAllocator (Ptr<PositionAllocator> allocator)
48 {
49   m_position = allocator;
50 }
51 
52 void
SetPositionAllocator(std::string type,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7,std::string n8,const AttributeValue & v8,std::string n9,const AttributeValue & v9)53 MobilityHelper::SetPositionAllocator (std::string type,
54                                       std::string n1, const AttributeValue &v1,
55                                       std::string n2, const AttributeValue &v2,
56                                       std::string n3, const AttributeValue &v3,
57                                       std::string n4, const AttributeValue &v4,
58                                       std::string n5, const AttributeValue &v5,
59                                       std::string n6, const AttributeValue &v6,
60                                       std::string n7, const AttributeValue &v7,
61                                       std::string n8, const AttributeValue &v8,
62                                       std::string n9, const AttributeValue &v9)
63 {
64   ObjectFactory pos;
65   pos.SetTypeId (type);
66   pos.Set (n1, v1);
67   pos.Set (n2, v2);
68   pos.Set (n3, v3);
69   pos.Set (n4, v4);
70   pos.Set (n5, v5);
71   pos.Set (n6, v6);
72   pos.Set (n7, v7);
73   pos.Set (n8, v8);
74   pos.Set (n9, v9);
75   m_position = pos.Create ()->GetObject<PositionAllocator> ();
76 }
77 
78 void
SetMobilityModel(std::string type,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7,std::string n8,const AttributeValue & v8,std::string n9,const AttributeValue & v9)79 MobilityHelper::SetMobilityModel (std::string type,
80                                   std::string n1, const AttributeValue &v1,
81                                   std::string n2, const AttributeValue &v2,
82                                   std::string n3, const AttributeValue &v3,
83                                   std::string n4, const AttributeValue &v4,
84                                   std::string n5, const AttributeValue &v5,
85                                   std::string n6, const AttributeValue &v6,
86                                   std::string n7, const AttributeValue &v7,
87                                   std::string n8, const AttributeValue &v8,
88                                   std::string n9, const AttributeValue &v9)
89 {
90   m_mobility.SetTypeId (type);
91   m_mobility.Set (n1, v1);
92   m_mobility.Set (n2, v2);
93   m_mobility.Set (n3, v3);
94   m_mobility.Set (n4, v4);
95   m_mobility.Set (n5, v5);
96   m_mobility.Set (n6, v6);
97   m_mobility.Set (n7, v7);
98   m_mobility.Set (n8, v8);
99   m_mobility.Set (n9, v9);
100 }
101 
102 void
PushReferenceMobilityModel(Ptr<Object> reference)103 MobilityHelper::PushReferenceMobilityModel (Ptr<Object> reference)
104 {
105   Ptr<MobilityModel> mobility = reference->GetObject<MobilityModel> ();
106   m_mobilityStack.push_back (mobility);
107 }
108 
109 void
PushReferenceMobilityModel(std::string referenceName)110 MobilityHelper::PushReferenceMobilityModel (std::string referenceName)
111 {
112   Ptr<MobilityModel> mobility = Names::Find<MobilityModel> (referenceName);
113   m_mobilityStack.push_back (mobility);
114 }
115 
116 void
PopReferenceMobilityModel(void)117 MobilityHelper::PopReferenceMobilityModel (void)
118 {
119   m_mobilityStack.pop_back ();
120 }
121 
122 
123 std::string
GetMobilityModelType(void) const124 MobilityHelper::GetMobilityModelType (void) const
125 {
126   return m_mobility.GetTypeId ().GetName ();
127 }
128 
129 void
Install(Ptr<Node> node) const130 MobilityHelper::Install (Ptr<Node> node) const
131 {
132   Ptr<Object> object = node;
133   Ptr<MobilityModel> model = object->GetObject<MobilityModel> ();
134   if (model == 0)
135     {
136       model = m_mobility.Create ()->GetObject<MobilityModel> ();
137       if (model == 0)
138         {
139           NS_FATAL_ERROR ("The requested mobility model is not a mobility model: \""<<
140                           m_mobility.GetTypeId ().GetName ()<<"\"");
141         }
142       if (m_mobilityStack.empty ())
143         {
144           NS_LOG_DEBUG ("node="<<object<<", mob="<<model);
145           object->AggregateObject (model);
146         }
147       else
148         {
149           // we need to setup a hierarchical mobility model
150           Ptr<MobilityModel> parent = m_mobilityStack.back ();
151           Ptr<MobilityModel> hierarchical =
152             CreateObjectWithAttributes<HierarchicalMobilityModel> ("Child", PointerValue (model),
153                                                                    "Parent", PointerValue (parent));
154           object->AggregateObject (hierarchical);
155           NS_LOG_DEBUG ("node="<<object<<", mob="<<hierarchical);
156         }
157     }
158   Vector position = m_position->GetNext ();
159   model->SetPosition (position);
160 }
161 
162 void
Install(std::string nodeName) const163 MobilityHelper::Install (std::string nodeName) const
164 {
165   Ptr<Node> node = Names::Find<Node> (nodeName);
166   Install (node);
167 }
168 void
Install(NodeContainer c) const169 MobilityHelper::Install (NodeContainer c) const
170 {
171   for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
172     {
173       Install (*i);
174     }
175 }
176 
177 void
InstallAll(void)178 MobilityHelper::InstallAll (void)
179 {
180   Install (NodeContainer::GetGlobal ());
181 }
182 /**
183  * Utility function that rounds |1e-4| < input value < |1e-3| up to +/- 1e-3
184  * and value <= |1e-4| to zero
185  * \param v value to round
186  * \return rounded value
187  */
188 static double
DoRound(double v)189 DoRound (double v)
190 {
191   if (v <= 1e-4 && v >= -1e-4)
192     {
193       return 0.0;
194     }
195   else if (v <= 1e-3 && v >= 0)
196     {
197       return 1e-3;
198     }
199   else if (v >= -1e-3 && v <= 0)
200     {
201       return -1e-3;
202     }
203   else
204     {
205       return v;
206     }
207 }
208 void
CourseChanged(Ptr<OutputStreamWrapper> stream,Ptr<const MobilityModel> mobility)209 MobilityHelper::CourseChanged (Ptr<OutputStreamWrapper> stream, Ptr<const MobilityModel> mobility)
210 {
211   std::ostream* os = stream->GetStream ();
212   Vector pos = mobility->GetPosition ();
213   Vector vel = mobility->GetVelocity ();
214   *os << "now=" << Simulator::Now ()
215       << " node=" << mobility->GetObject<Node> ()->GetId ();
216   pos.x = DoRound (pos.x);
217   pos.y = DoRound (pos.y);
218   pos.z = DoRound (pos.z);
219   vel.x = DoRound (vel.x);
220   vel.y = DoRound (vel.y);
221   vel.z = DoRound (vel.z);
222   std::streamsize saved_precision = os->precision ();
223   std::ios::fmtflags saved_flags = os->flags ();
224   os->precision (3);
225   os->setf (std::ios::fixed,std::ios::floatfield);
226   *os << " pos=" << pos.x << ":" << pos.y << ":" << pos.z
227       << " vel=" << vel.x << ":" << vel.y << ":" << vel.z
228       << std::endl;
229   os->flags (saved_flags);
230   os->precision (saved_precision);
231 }
232 
233 void
EnableAscii(Ptr<OutputStreamWrapper> stream,uint32_t nodeid)234 MobilityHelper::EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid)
235 {
236   std::ostringstream oss;
237   oss << "/NodeList/" << nodeid << "/$ns3::MobilityModel/CourseChange";
238   Config::ConnectWithoutContextFailSafe (oss.str (),
239                                          MakeBoundCallback (&MobilityHelper::CourseChanged, stream));
240 }
241 void
EnableAscii(Ptr<OutputStreamWrapper> stream,NodeContainer n)242 MobilityHelper::EnableAscii (Ptr<OutputStreamWrapper> stream, NodeContainer n)
243 {
244   for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
245     {
246       EnableAscii (stream, (*i)->GetId ());
247     }
248 }
249 void
EnableAsciiAll(Ptr<OutputStreamWrapper> stream)250 MobilityHelper::EnableAsciiAll (Ptr<OutputStreamWrapper> stream)
251 {
252   EnableAscii (stream, NodeContainer::GetGlobal ());
253 }
254 int64_t
AssignStreams(NodeContainer c,int64_t stream)255 MobilityHelper::AssignStreams (NodeContainer c, int64_t stream)
256 {
257   int64_t currentStream = stream;
258   Ptr<Node> node;
259   Ptr<MobilityModel> mobility;
260   for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
261     {
262       node = (*i);
263       mobility = node->GetObject<MobilityModel> ();
264       if (mobility)
265         {
266           currentStream += mobility->AssignStreams (currentStream);
267         }
268     }
269   return (currentStream - stream);
270 }
271 
272 double
GetDistanceSquaredBetween(Ptr<Node> n1,Ptr<Node> n2)273 MobilityHelper::GetDistanceSquaredBetween (Ptr<Node> n1, Ptr<Node> n2)
274 {
275   NS_LOG_FUNCTION_NOARGS ();
276   double distSq = 0.0;
277 
278   Ptr<MobilityModel> rxPosition = n1->GetObject<MobilityModel> ();
279   NS_ASSERT (rxPosition != 0);
280 
281   Ptr<MobilityModel> txPosition = n2->GetObject<MobilityModel> ();
282   NS_ASSERT (txPosition != 0);
283 
284   double dist = rxPosition -> GetDistanceFrom (txPosition);
285   distSq = dist * dist;
286 
287   return distSq;
288 }
289 
290 } // namespace ns3
291