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