DESERT 3.5.1
Loading...
Searching...
No Matches
uwoptical-mpropagation.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2017 Regents of the SIGNET lab, University of Padova.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution.
13// 3. Neither the name of the University of Padova (SIGNET lab) nor the
14// names of its contributors may be used to endorse or promote products
15// derived from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29
39#include <node-core.h>
41#include <math.h>
42#include <fstream>
43#include <sstream>
44#include <iostream>
45#include <iomanip>
46
50static class UwOpticalMPropagationClass : public TclClass
51{
52public:
57 : TclClass("Module/UW/OPTICAL/Propagation")
58 {
59 }
64 TclObject *
65 create(int, const char *const *)
66 {
67 return (new UwOpticalMPropagation);
68 }
70
72 : Ar_(1)
73 , At_(1)
74 , c_(0)
75 , theta_(0)
76 , omnidirectional_(false)
77 , variable_c_(false)
78 , use_woss_(false)
79 , lut_file_name_("")
80 , lut_token_separator_(',')
81
82{
83 /*bind_error("token_separator_", &token_separator_);*/
84 bind("Ar_", &Ar_);
85 bind("At_", &At_);
86 bind("c_", &c_);
87 bind("theta_", &theta_);
88 bind("debug_", &debug_);
89}
90
91int
92UwOpticalMPropagation::command(int argc, const char *const *argv)
93{
94 if (argc == 2) {
95 if (strcasecmp(argv[1], "setOmnidirectional") == 0) {
96 omnidirectional_ = true;
97 return TCL_OK;
98 } else if (strcasecmp(argv[1], "setDirectional") == 0) {
99 omnidirectional_ = false;
100 return TCL_OK;
101 } else if (strcasecmp(argv[1], "setVariableC") == 0) {
102 variable_c_ = true;
103 return TCL_OK;
104 } else if (strcasecmp(argv[1], "setFixedC") == 0) {
105 variable_c_ = false;
106 return TCL_OK;
107 } else if (strcasecmp(argv[1], "setLUT") == 0) {
109 return TCL_OK;
110 }
111 } else if (argc == 3) {
112 if (strcasecmp(argv[1], "setAr") == 0) {
113 Ar_ = strtod(argv[2], NULL);
114 return TCL_OK;
115 } else if (strcasecmp(argv[1], "setAt") == 0) {
116 At_ = strtod(argv[2], NULL);
117 return TCL_OK;
118 } else if (strcasecmp(argv[1], "setC") == 0) {
119 c_ = strtod(argv[2], NULL);
120 return TCL_OK;
121 } else if (strcasecmp(argv[1], "setTheta") == 0) {
122 theta_ = strtod(argv[2], NULL);
123 return TCL_OK;
124 } else if (strcasecmp(argv[1], "setLUTFileName") == 0) {
125 string tmp_ = ((char *) argv[2]);
126 if (tmp_.size() == 0) {
127 fprintf(stderr, "Empty string for the file name");
128 return TCL_ERROR;
129 }
130 lut_file_name_ = tmp_;
131 return TCL_OK;
132 } else if (strcasecmp(argv[1], "setLUTSeparator") == 0) {
133 string tmp_ = ((char *) argv[2]);
134 if (tmp_.size() == 0) {
135 fprintf(stderr, "Empty char for the file name");
136 return TCL_ERROR;
137 }
138 lut_token_separator_ = tmp_.at(0);
139 return TCL_OK;
140 }
141 }
142
143 return MPropagation::command(argc, argv);
144}
145
146void
148{
149 use_woss_ = flag;
150}
151
152void
154{
155 std::cout << NOW << " UwOpticalMPropagation::updateC depth = " << depth
156 << std::endl;
157
158 LUT_c_iter it = lut_c_.lower_bound(depth);
159 assert(it != lut_c_.end());
160 if (it->first == depth) {
161 c_ = it->second.first;
162 return;
163 }
164 assert(it != lut_c_.begin());
165 it--;
166 double d_low = it->first;
167 double c_low = it->second.first;
168 double d_up = (++it)->first;
169 double c_up = it->second.first;
170 c_ = linearInterpolator(depth, d_low, d_up, c_low, c_up);
171}
172
173double
174UwOpticalMPropagation::getWossOrientation(Position *src, Position *dest)
175{
176 if (src->getDist(dest) == 0)
177 return 0;
178 double src_depth = -src->getAltitude();
179 double dest_depth = -dest->getAltitude();
180 if (debug_)
181 std::cout << NOW << " UwOpticalMPropagation::getWossOrientation() "
182 << "src_depth = " << src_depth
183 << " dest_depth = " << dest_depth
184 << " dist = " << dest->getDist(src) << std::endl;
185 double cosBeta = (dest_depth - src_depth) / src->getDist(dest);
186 cosBeta = cosBeta > 1 ? 1 : cosBeta < -1 ? -1 : cosBeta;
187 return asin(cosBeta);
188}
189
190double
192{
193 hdr_MPhy *ph = HDR_MPHY(p);
194 Position *source = ph->srcPosition;
195 Position *destination = ph->dstPosition;
196 assert(source);
197 assert(destination);
198 double beta_ = use_woss_
199 ? (destination->getAltitude() == source->getAltitude()
200 ? 0
201 : getWossOrientation(source, destination))
202 : (source->getZ() == destination->getZ()
203 ? 0
204 : M_PI / 2 -
205 (source->getRelZenith(destination) > 0
206 ? source->getRelZenith(
207 destination)
208 : -source->getRelZenith(
209 destination)));
210 return beta_;
211}
212
213bool
218
219double
221{
222 if (variable_c_ && p != NULL) {
223 hdr_MPhy *ph = HDR_MPHY(p);
224 Position *source = ph->srcPosition;
225 Position *destination = ph->dstPosition;
226 double destination_depth =
227 use_woss_ ? -destination->getAltitude() : -destination->getZ();
228 double source_depth =
229 use_woss_ ? -source->getAltitude() : -source->getZ();
230 double min_depth_ = min(destination_depth,source_depth);
231 double max_depth_ = max(destination_depth,source_depth);
232 if ((lut_c_.empty() == true) ||
233 (min_depth_ < ((lut_c_.begin())->first) ||
234 (max_depth_ > ((lut_c_.rbegin())->first)))) {
235
236 goto done;
237 //return c_;
238 }
239
240 LUT_c_iter lower = lut_c_.lower_bound(min_depth_);
241 assert(lower != lut_c_.end());
242 if (lower->first > min_depth_) {
243 assert(lower != lut_c_.begin());
244 lower--;
245 }
246 double first_depth = lower->first;
247 double temp_depth = lower->first;
248 double c_temp = lower->second.first;
249 ++lower;
250 if (lower->first >= max_depth_) {
251 return c_temp;
252 }
253
254 double average_c = 0;
255 for (; lower->first < max_depth_; ++lower) {
256 average_c = average_c + (c_temp + lower->second.first) * (lower->first-temp_depth)/2;
257 temp_depth = lower->first;
258 c_temp = lower->second.first;
259 }
260
261 return average_c / (temp_depth - first_depth);
262 }
263
264done:
265 return c_;
266}
267
268double
270{
271 hdr_MPhy *ph = HDR_MPHY(p);
272 Position *source = ph->srcPosition;
273 Position *destination = ph->dstPosition;
274 //assert(source);
275 //assert(destination);
276
277 double beta_ = getBeta(p);
278 double PCgain;
279
280 if (source != 0 || destination != 0) {
281 if (!variable_c_ || beta_ == 0) {
282 if (variable_c_)
283 updateC(use_woss_ ? -destination->getAltitude()
284 : -destination->getZ());
285 double dist = source->getDist(destination);
286 PCgain = getLambertBeerGain(dist, beta_);
287 if (debug_)
288 std::cout << NOW << " UwOpticalMPropagation::getGain()"
289 << " dist=" << dist << " gain=" << PCgain << std::endl;
290 } else {
291 double destination_depth =
292 use_woss_ ? -destination->getAltitude() : -destination->getZ();
293 double source_depth =
294 use_woss_ ? -source->getAltitude() : -source->getZ();
295 if (debug_)
296 std::cout << NOW
297 << " UwOpticalMPropagation::getGain() destination_depth "
298 << destination_depth << " source_depth " << source_depth
299 << std::endl;
300 PCgain = getLambertBeerGain_variableC(beta_,
301 min(destination_depth, source_depth),
302 max(destination_depth, source_depth));
303 if (debug_)
304 std::cout << NOW << " UwOpticalMPropagation::getGain()"
305 << "c_variable"
306 << " gain=" << PCgain << std::endl;
307 }
308 } else {
309 std::cerr << "UwOpticalMPropagation::getGain(), source or destination not found";
310 }
311 return PCgain;
312}
313
314double
316{
317 double cosBeta = omnidirectional_ ? 1 : cos(beta_);
318 double L = d / cosBeta;
319 double PCgain = 2 * Ar_ * cosBeta /
320 (M_PI * pow(L, 2.0) * (1 - cos(theta_)) + 2 * At_) * exp(-c_ * d);
321 return (PCgain == PCgain) ? PCgain : 0;
322}
323
324void
326{
327 ifstream input_file_;
328 string line_;
329 input_file_.open(lut_file_name_.c_str());
330 if (input_file_.is_open()) {
331 lut_c_.clear();
332 while (std::getline(input_file_, line_)) {
333 ::std::stringstream line_stream(line_);
334 double d;
335 double c;
336 double t;
337 line_stream >> d;
338 line_stream.ignore(256, lut_token_separator_);
339 line_stream >> c;
340 line_stream.ignore(256, lut_token_separator_);
341 line_stream >> t;
342 lut_c_[d] = std::make_pair(c, t);
343 }
344 input_file_.close();
345 } else {
346 cerr << "Impossible to open file " << lut_file_name_ << endl;
347 }
348}
349
350double
352 double x, double x1, double x2, double y1, double y2)
353{
354 double m = (y1 - y2) / (x1 - x2);
355 double q = y1 - m * x1;
356 return m * x + q;
357}
358
359double
361 double beta_, double min_depth_, double max_depth_)
362{
363 if (debug_)
364 std::cout << NOW << " UwOpticalMPropagation::getLambertBeerGain_"
365 "variableC min_depth_ = "
366 << min_depth_ << " max_depth_ = " << max_depth_
367 << " beta_ = " << beta_ << std::endl;
368 double PCgain = 1;
369 double c_med;
370 double dist_top = 0;
371 double dist_bottom = 0;
372
373 // if(min_depth_ < ((lut_c_.begin()) -> first) || max_depth_ >
374 // ((--lut_c_.end()) -> first) )
375 if ((lut_c_.empty() == true) ||
376 (min_depth_ < ((lut_c_.begin())->first) ||
377 (max_depth_ > ((lut_c_.rbegin())->first))))
378 return NOT_FOUND_C_VALUE;
379 LUT_c_iter lower = lut_c_.lower_bound(min_depth_);
380 assert(lower != lut_c_.end());
381 if (lower->first > min_depth_) {
382 assert(lower != lut_c_.begin());
383 lower--;
384 }
385 LUT_c_iter upper = (--lut_c_.lower_bound(max_depth_));
386 assert(upper != lut_c_.end());
387 if (upper->first > max_depth_) {
388 assert(upper != lut_c_.begin());
389 upper--;
390 }
391
392 double temp_depth = lower->first;
393 double c_temp = lower->second.first;
394 ++lower;
395 double prev_c = linearInterpolator(
396 min_depth_, temp_depth, lower->first, c_temp, lower->second.first);
397
398 temp_depth = upper->first;
399 c_temp = upper->second.first;
400 ++upper;
401 double c_up = linearInterpolator(
402 max_depth_, temp_depth, upper->first, c_temp, upper->second.first);
403
404 double temp_c = 0;
405 temp_depth = 0;
406
407 for (; lower != upper; ++lower) {
408 temp_c = lower->second.first;
409 c_med = (prev_c + temp_c) / 2;
410 prev_c = temp_c;
411 temp_depth = lower->first;
412 dist_bottom = (temp_depth - min_depth_) / sin(beta_);
413 PCgain = exp(-c_med * (dist_bottom - dist_top)) * PCgain;
414 dist_top = dist_bottom;
415 }
416
417 c_med = (prev_c + c_up) / 2;
418 dist_bottom = (max_depth_ - min_depth_) / sin(beta_);
419 double cosBeta = omnidirectional_ ? 1 : cos(beta_);
420 // MATTEO: L_rx = omnidirectional_ ? dist_bottom : 2*dist_bottom*(cos(beta_)
421 // - (sin(beta_)/tan(2*beta_)));
422 double L_ = dist_bottom /
423 cosBeta; // FILIPPO: sono equivalenti (provare per credere)
424 PCgain = exp(-c_med * (dist_bottom - dist_top)) * PCgain;
425 return (PCgain * 2 * Ar_ * cosBeta /
426 (M_PI * pow(L_, 2) * (1 - cos(theta_)) + 2 * At_));
427}
428
429double
431{
432 if (!variable_c_ || lut_c_.empty() == true)
434 LUT_c_iter it = lut_c_.lower_bound(depth);
435 assert(it != lut_c_.end());
436 if (it->first == depth) {
437 return it->second.second;
438 }
439 it--;
440 double d_low = it->first;
441 double t_low = it->second.second;
442 double d_up = (++it)->first;
443 double t_up = it->second.second;
444 return linearInterpolator(depth, d_low, d_up, t_low, t_up);
445}
Class that represents the binding with the tcl configuration script.
TclObject * create(int, const char *const *)
Creates the TCL object needed for the tcl language interpretation.
UwOpticalMPropagationClass()
Constructor of the class.
Class used to represents the UWOPTICAL_MPROPAGATION.
virtual double getGain(Packet *p)
Calculate the gain following the Lambert and Beer's law.
bool variable_c_
Flag to set whether the attenuation is constant or not.
double theta_
Transmitting beam diverge angle [rad].
double linearInterpolator(double x, double x1, double x2, double y1, double y2)
Calculate the linear interpolation between two 2-D points.
char lut_token_separator_
LUT token separator.
virtual double getLambertBeerGain(double d, double beta_)
Calculate the gain following the Lambert and Beer's law.
double getLambertBeerGain_variableC(double beta_, double min_depth_, double max_depth_)
Calculate the gain following the Lambert and Beer's law in the case of variable c model.
virtual void initializeLUT()
Inizialize LUT of c_variable values.
bool omnidirectional_
Flag to set whether the system is omnidirectional or not.
double getC(Packet *p=NULL)
Provide the attenuation coefficient.
bool use_woss_
Flag to set the woss.
double getWossOrientation(Position *src, Position *dest)
Calculate the inclination angle between the transmitter and the receiver.
virtual void setWoss(bool flag)
double getTemperature(double depth)
Provide the temperature from LUT.
void updateC(double d)
Set the attenuation coefficient from lookup table when both the nodes are alligned and at the same de...
bool isOmnidirectional()
Provide if we are assuming omnidirectional tx and rx or not.
double c_
Beam light attenuation coefficient c = a + b [m^-1].
virtual int command(int, const char *const *)
TCL command interpreter.
string lut_file_name_
LUT file name.
LUT_c lut_c_
Lookup table map of the attenuation coefficient and the temperature versus the depth.
double getBeta(Packet *p)
Provide angle between transmitter and receiver.
UwOpticalMPropagation()
Constructor of the UwOpticalMPropagation class.
double At_
Transmitter size [m^2].
double Ar_
Receiver area [m^2].
UwOpticalMPropagationClass class_UwOpticalMPropagation
Definition of UwOpticalMPropagation class.
#define NOT_VARIABLE_TEMPERATURE
LUT_c::iterator LUT_c_iter
#define NOT_FOUND_C_VALUE
const double q