DESERT 3.5.1
Loading...
Searching...
No Matches
uwranging_tdoa.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 "uwranging_tdoa.h"
40#include "uwtap_clmsg.h"
41#include <clmsg-discovery.h>
42#include <clmsg-stats.h>
43#include <clsap.h>
44#include <cmath>
45#include <mac.h>
46#include <mmac.h>
47#include <tclcl.h>
48#include <uwphysical.h>
49#include <uwsmposition.h>
50#include <uwstats-utilities.h>
51
52// define a macro to print debug messages
53// 0: NONE - 1: ERR - 2: DBG
54#define DEBUG(level, text) \
55 { \
56 if (debug_tdoa >= level) { \
57 std::cout << NOW << " UwRangingTDOA(" << node_id << "): " << text \
58 << std::endl; \
59 } \
60 }
64static class UwRangingTDOAModuleClass : public TclClass
65{
66
67public:
72 : TclClass("Module/UW/RANGING_TDOA")
73 {
74 }
79 TclObject *
80 create(int, const char *const *)
81 {
82 return (new UwRangingTDOA());
83 }
84
86
87void
89{
90 module->throttleTX();
91}
92
94 : Module()
95 , scheduler_active(false)
96 , debug_tdoa(0)
97 , node_id(0)
98 , packet_id(0)
99 , n_nodes(0)
100 , dist_num(0)
101 , range_entries(0)
102 , poisson_traffic(0)
103 , range_pkts_sent(0)
104 , range_bytes_sent(0)
105 , range_pkts_recv(0)
106 , range_pkts_err(0)
107 , saved_entries(0)
108 , phy_id(0)
109 , queue_size(0)
110 , send_timer(this)
111 , mac2phy_delay(1e-6)
112 , max_tt(5)
113 , max_age(10e4)
114 , range_period(10)
115 , delay_start(0)
116 , full_pkt_tx_dur(0)
117 , soundspeed(1500.)
118 , tof_map()
119 , entries_mat()
120 , times_mat()
121 , last_ids()
122 , time_of_flights()
123 , entries_timestamps()
124 , entry_last_tx()
125 , tx_timestamp()
126 , ber()
127{
128 bind("n_nodes_", (int *) &n_nodes);
129 bind("debug_tdoa", (int *) &debug_tdoa);
130 bind("mac2phy_delay_", (double *) &mac2phy_delay);
131 bind("max_tt", (double *) &max_tt);
132 bind("range_period", (double *) &range_period);
133 bind("delay_start_", (double *) &delay_start);
134 bind("poisson_traffic", (int *) &poisson_traffic);
135 bind("range_entries", (int *) &range_entries);
136 bind("soundspeed", (double *) &soundspeed);
137
138 if (n_nodes < 0 || n_nodes > std::numeric_limits<uwrange_node_t>::max()) {
139 DEBUG(0, "Negative or too big number of nodes, setting default to 0")
140 n_nodes = 0;
141 }
142
143 dist_num = (n_nodes * (n_nodes - 1) / 2);
144 entries_mat.resize(n_nodes,
145 std::vector<std::vector<tdoa_entry>>(
146 PKTIDMAX, std::vector<tdoa_entry>(n_nodes, tdoa_entry())));
147 times_mat.resize(n_nodes, std::vector<double>(PKTIDMAX, -1.));
148 last_ids.resize(n_nodes, -1);
149 time_of_flights.resize(dist_num, -1.0);
150 entries_timestamps.resize(dist_num, -0.0);
151 entry_last_tx.resize(n_nodes, 0.0);
152 ber.resize(n_nodes, 0.0);
153
154 tof_map.resize(n_nodes, std::vector<int>(n_nodes, -1));
155 int temp = 0;
156
157 for (int ni = 0; ni < n_nodes; ni++) {
158 for (int nj = ni + 1; nj < n_nodes; nj++) {
159 tof_map[ni][nj] = temp;
160 tof_map[nj][ni] = temp++;
161 }
162 }
163}
164
165void
167{
168 hdr_cmn *ch = HDR_CMN(p);
169
170 if (ch->direction() == hdr_cmn::UP) {
171 if (ch->ptype() != PT_UWRANGING_TDOA)
172 sendUp(p);
173 else
174 Packet::free(p); // Already processed in recvSyncClMsg from UwTAP
175 } else if (ch->direction() == hdr_cmn::DOWN) {
176 sendDown(p);
177 }
178}
179
180void
181UwRangingTDOA::recv(Packet *p, Handler *h)
182{
184}
185
186int
188{
189 if (m->type() == CLMSG_TAP_PKT) {
190 ClMsgTapPkt *msg = dynamic_cast<ClMsgTapPkt *>(m);
191
193 Packet *p = msg->pkt;
194
195 if (p) {
196 hdr_cmn *ch = HDR_CMN(p);
197
198 if (ch->ptype() == PT_UWRANGING_TDOA) {
199 DEBUG(2,
200 "recvSyncClMsg::updating deltas on outgoing packet")
201
203 }
204 }
205
206 } else if (msg->clmsg_type == clmsg_tap_type::END_RX) {
207 const Packet *p = msg->pkt;
208
209 if (p) {
210 hdr_cmn *ch = HDR_CMN(p);
211 if (ch->ptype() == PT_UWRANGING_TDOA) {
213 int pkt_node_id = rangh->source_node_id;
214 int pkt_id = rangh->source_pkt_id;
215
216 if (range_entries <= 0) {
217 ClMsgStats stats_clmsg = ClMsgStats(phy_id, UNICAST);
218
219 sendSyncClMsg(&stats_clmsg);
220
221 if (stats_clmsg.getStats()->type_id ==
223 const UwPhysicalStats *stats =
224 dynamic_cast<const UwPhysicalStats *>(
225 stats_clmsg.getStats());
226
227 if (stats != 0)
228 ber[pkt_node_id] = stats->last_ber;
229
230 }
231 }
232 if (ch->error()) {
233 DEBUG(1,
234 " RX ERRORED ping with pkt_token_id "
235 << pkt_id << " from node "
236 << pkt_node_id)
237
239
240 } else {
242
243 DEBUG(2,
244 "recvSyncClMsg::RX ping with pkt_token_id "
245 << pkt_id << " from node "
246 << pkt_node_id)
247
248 rangeRX(p);
249 }
250 }
251 }
252 }
253
254 return 0;
255
256 } else if (m->type() == CLMSG_TRIGGER_STATS) {
257 return 0;
258 }
259
260 return Module::recvSyncClMsg(m);
261}
262
263double
264UwRangingTDOA::entryWeight(int entry, int pkt_size, int mode) const
265{
266 double weight = 0;
267
268 if (mode == 0) // weight considers only PER
269 {
270 weight = (pow(1 - ber[entry], pkt_size));
271
272 DEBUG(2,
273 "entry " << entry << " PER " << pow(1 - ber[entry], pkt_size)
274 << " age " << NOW - entry_last_tx[entry]
275 << " weight: " << weight)
276
277 } else if (mode == -1) // weight considers only AGE
278 {
279 weight = (NOW - entry_last_tx[entry]);
280
281 DEBUG(2,
282 "entry " << entry << " PER " << pow(1 - ber[entry], pkt_size)
283 << " age " << NOW - entry_last_tx[entry]
284 << " weight: " << weight)
285
286 } else if (mode == -2) // weight considers PER * AGE
287 {
288 weight = (pow(1 - ber[entry], pkt_size) * (NOW - entry_last_tx[entry]));
289
290 DEBUG(2,
291 "entry " << entry << " PER " << pow(1 - ber[entry], pkt_size)
292 << " age " << NOW - entry_last_tx[entry]
293 << " weight: " << weight)
294 }
295
296 return weight;
297}
298
299int
300UwRangingTDOA::calcOptEntries(std::vector<int> *sorted_entries) const
301{
302 int opt_n_entries = (range_entries > 0 ? range_entries : n_nodes - 1);
303
304 if (range_entries <= 0)
305 {
306 std::multimap<double, int, std::greater<double>> sorted_pairs;
307 double max_weight = 0.0;
308
309 for (int n_entries = 1; n_entries < n_nodes; n_entries++) {
310 sorted_pairs.clear();
311
312 int pkt_size = 8 * hdr_ranging_tdoa::getSize(n_entries);
313
314 for (int entry = 0; entry < n_nodes; entry++) {
315 if (entry == node_id)
316 continue;
317
318 double w = entryWeight(entry, pkt_size, 0); // weight is just PDR
319
320 sorted_pairs.insert(std::pair<double, int>(w, entry));
321 DEBUG(2,
322 "entryWeight(" << entry << "," << n_entries
323 << ")= " << w << "")
324 }
325
326 double weight = 0.0;
327 std::multimap<double, int>::iterator iter = sorted_pairs.begin();
328
329 for (int i = 0; i < n_entries; i++) // was i < n_entries for considering only best entries
330 {
331 weight += 1 * (iter->first); // was without n_entries for considering only best entries
332 iter++;
333 if (iter == sorted_pairs.end())
334 break;
335 }
336
337 if (weight > max_weight) {
338 max_weight = weight;
339 opt_n_entries = n_entries;
340 }
341
342 DEBUG(2,
343 "N entries: " << n_entries << " weight: " << weight << "")
344 }
345 }
346
347 int pkt_size = 8 * hdr_ranging_tdoa::getSize(opt_n_entries);
348
349 std::multimap<double, int, std::greater<double>> sorted_pairs;
350
351 for (int entry = 0; entry < n_nodes; entry++) {
352 if (entry == node_id)
353 continue;
354
355 sorted_pairs.insert(std::pair<double, int>( entryWeight(entry, pkt_size, range_entries), entry));
356 }
357
358 std::multimap<double, int>::iterator iter = sorted_pairs.begin();
359
360 if (sorted_entries) {
361 for (int i = 0; i < opt_n_entries; i++) {
362 sorted_entries->push_back(iter->second);
363 iter++;
364 }
365 }
366
367 DEBUG(2, "calcOptEntries::opt_n_entries = " << opt_n_entries)
368
369 return opt_n_entries;
370}
371
372void
374{
375 DEBUG(2, "rangeTX")
376 Packet *p = Packet::alloc();
377 hdr_cmn *ch = HDR_CMN(p);
378 hdr_mac *mach = HDR_MAC(p);
380 ch->ptype() = PT_UWRANGING_TDOA;
381 mach->macDA() = MAC_BROADCAST;
382 mach->macSA() = node_id;
383 mach->ftype() = MF_DATA;
384 rangh->source_pkt_id = packet_id;
385 rangh->source_node_id = node_id;
386 rangh->times_size_ = range_entries;
387
388 tx_timestamp.emplace((tx_timestamp.begin() + rangh->source_pkt_id), NOW);
389
390 std::vector<int> sorted_entries;
391 int j = 0;
392
393 DEBUG(2, "rangeTX::calling calcOptEntries rangeID: " << packet_id)
394
395 calcOptEntries(&sorted_entries);
396 saved_entries += (n_nodes - 1) - sorted_entries.size();
397
398 DEBUG(2,
399 "rangeTX::OPT SIZE: " << sorted_entries.size()
400 << " n_nodes: " << n_nodes)
401
402 for (auto i : sorted_entries) {
403 DEBUG(2,
404 "rangeTX::times_mat[" << i << "][" << last_ids[i]
405 << "] = " << times_mat[i][last_ids[i]])
406 if (isValid(times_mat[i][last_ids[i]]) && isValid(last_ids[i])) {
407 tdoa_entry new_entry =
408 tdoa_entry(NOW - times_mat[i][last_ids[i]], i, last_ids[i]);
409
410 (*rangh).times_[j] = new_entry;
411 entries_mat[node_id][packet_id][i] = new_entry;
412 j++;
413
414 DEBUG(2,
415 "rangeTX::entries_mat["
416 << node_id << "][" << packet_id << "][" << i
417 << "].time\t= "
418 << entries_mat[node_id][packet_id][i].time)
419 } else {
420 DEBUG(1,
421 "rangeTX::entry not valid for node "
422 << i << " times_mat:" << times_mat[i][last_ids[i]]
423 << " last_ids:" << last_ids[i])
424 }
425 }
426
427 ch->size() += rangh->getSize();
428 DEBUG(2,
429 "rangeTX::queueing range packet with pkt_id: "
430 << (int) rangh->source_pkt_id << " and size: " << ch->size()
431 << " with # entries: " << (int) rangh->times_size_);
432
433 packet_id = (packet_id + 1) % PKTIDMAX;
435
436 if (!isValid(rangh->source_pkt_id))
437 DEBUG(1,
438 "ERROR! invalid pkt_id: " << rangh->source_pkt_id
439 << " from node " << rangh->source_node_id)
440
441 ++queue_size;
442 sendDown(p);
443
445 DEBUG(1,
446 "ERROR! packet period set as: " << range_period
447 << " but must be >0!!!")
448 range_period = 10;
449 }
450}
451
452void
453UwRangingTDOA::updateHoldoverTime(Packet *p, double tx_duration)
454{
455 if (p == NULL) {
456 DEBUG(1, "ERROR! updateHoldoverTime() called with NULL packet!")
457 return;
458 }
459
461 --queue_size;
463 range_bytes_sent += rangh->getSize();
464
465 DEBUG(2,
466 "updateHoldoverTime::sending range packet with pkt_id: "
467 << (int) rangh->source_pkt_id)
468 for (int i = 0; i < rangh->times_size(); i++) {
469 DEBUG(2, "updateHoldoverTime::elem[" << i << "]")
470 auto &elem = (*rangh).times_[i];
471
472 DEBUG(2, "updateHoldoverTime::elem.time = " << elem.time)
473
474 elem.time += NOW + tx_duration + mac2phy_delay
475 - tx_timestamp[rangh->source_pkt_id];
476 entries_mat[node_id][rangh->source_pkt_id][elem.node].time = elem.time;
477
478 DEBUG(2, "updateHoldoverTime::tx_duration = " << tx_duration)
479 DEBUG(2, "updateHoldoverTime::mac2phy_delay = " << mac2phy_delay)
480 DEBUG(2,
481 "updateHoldoverTime::tx_timestamp = "
482 << tx_timestamp[rangh->source_pkt_id])
483 DEBUG(2,
484 "updateHoldoverTime::entries_mat["
485 << node_id << "][" << (int) rangh->source_pkt_id << "]["
486 << (int) elem.node << "].time = " << elem.time)
487
488 entry_last_tx[elem.node] = NOW;
489 }
490
491 times_mat[node_id][rangh->source_pkt_id] = NOW + tx_duration;
492
493 DEBUG(2,
494 "updateHoldoverTime::times_mat["
495 << node_id << "][" << (int) rangh->source_pkt_id
496 << "] = " << times_mat[node_id][rangh->source_pkt_id])
497
498 if (rangh->times_size() == n_nodes - 1)
499 full_pkt_tx_dur = tx_duration;
500}
501
502void
504{
506 int pkt_node_id = rangh->source_node_id;
507 int pkt_id = rangh->source_pkt_id;
508
509 times_mat[pkt_node_id][pkt_id] = NOW;
510 last_ids[pkt_node_id] = pkt_id;
511
512 if (!isValid(pkt_id))
513 DEBUG(1, "ERROR! invalid pkt_id: "
514 << pkt_id << " from node " << pkt_node_id)
515
516 for (size_t i = 0; i < entries_mat[pkt_node_id][pkt_id].size(); ++i) {
517 // reset all entries relative to the incoming packet present in the matrix
518 entries_mat[pkt_node_id][pkt_id][i] = tdoa_entry(-1, i, -1);
519 }
520
521 double spherical_tof = -1.;
522 double spherical_timestamp = -1.;
523 for (int i = 0; i < rangh->times_size(); i++) {
524 auto &elem = (*rangh).times_[i];
525
526 entries_mat[pkt_node_id][pkt_id][elem.node] = elem;
527
528 DEBUG(2, "rangeRX::elem[" << i << "]")
529 DEBUG(2,
530 "rangeRX::entries_mat[" << pkt_node_id << "][" << pkt_id << "]["
531 << (int) elem.node
532 << "].time = " << elem.time)
533
534 if (elem.node == node_id) {
535 // if packet referred in elem.id is not too old
536 if (NOW - times_mat[node_id][elem.id] < max_age) {
537 spherical_tof =
538 (NOW - times_mat[node_id][elem.id] - elem.time) / 2.;
539 spherical_timestamp = (NOW + times_mat[node_id][elem.id]) / 2.;
540
541 DEBUG(2,
542 "rangeRX::times_mat["
543 << node_id << "][" << (int) elem.id
544 << "] = " << times_mat[node_id][elem.id])
545 DEBUG(2, "rangeRX::elem.time = " << elem.time)
546 DEBUG(2, "rangeRX::spherical_tof = " << spherical_tof)
547
548 if (spherical_tof >= -1e-3 && spherical_tof < max_tt) {
549 time_of_flights[tof_map[pkt_node_id][node_id]] =
550 std::abs(spherical_tof);
551 entries_timestamps[tof_map[pkt_node_id][node_id]] =
552 spherical_timestamp;
553 } else {
554 DEBUG(1, "Negative spherical range tt!!! ");
555 }
556 }
557 }
558 }
559
560 for (int i = 0; i < rangh->times_size(); i++) {
561 auto &elem = (*rangh).times_[i];
562
563 if (isValid(elem) && elem.node != node_id && isValid(spherical_tof)
564 && isValid(times_mat[elem.node][elem.id])
565 && isValid(time_of_flights[tof_map[elem.node][node_id]])) {
566
567 DEBUG(2, "rangeRX::elem[" << i << "]")
568
569 double hyperbolic_tof = (NOW -
570 times_mat[elem.node][elem.id] // RX time from elem.node
571 - spherical_tof // time distance from source node
572 + time_of_flights[tof_map[elem.node][node_id]] // time distance from elem.node
573 - elem.time // holdover between elem.node and source node
574 + mac2phy_delay / (n_nodes-1));
575
576 DEBUG(2,
577 "rangeRX::times_mat[" << (int) elem.node << "]["
578 << (int) elem.id << "] "
579 << times_mat[elem.node][elem.id])
580 DEBUG(2, "rangeRX::spherical_tof = " << spherical_tof)
581 DEBUG(2,
582 "rangeRX::time_of_flights["
583 << tof_map[elem.node][node_id] << "] = "
584 << time_of_flights[tof_map[elem.node][node_id]])
585 DEBUG(2, "rangeRX::elem.time = " << elem.time)
586 DEBUG(2, "rangeRX::hyperbolic_tof = " << hyperbolic_tof)
587
588 if (hyperbolic_tof >= -1e-3) {
589 time_of_flights[tof_map[pkt_node_id][elem.node]] =
590 std::abs(hyperbolic_tof);
591 entries_timestamps[tof_map[pkt_node_id][elem.node]] =
592 std::min( spherical_timestamp,
593 entries_timestamps[tof_map[elem.node][node_id]]);
594 } else {
595 DEBUG(1, "Negative hyp range from node "
596 << (int) elem.node << " to " << pkt_node_id);
597 }
598 }
599 }
600}
601
602bool
603UwRangingTDOA::isValid(double value) const
604{
605 return (value >= 0);
606}
607
608bool
610{
611 return (entry.id >= 0 && entry.node >= 0 && entry.time >= 0);
612}
613
614int
615UwRangingTDOA::command(int argc, const char *const *argv)
616{
617 Tcl &tcl = Tcl::instance();
618 if (argc == 2) {
619 if (strcasecmp(argv[1], "start") == 0) {
620 start();
621 return TCL_OK;
622 }
623 if (strcasecmp(argv[1], "stop") == 0) {
624 stop();
625 return TCL_OK;
626 }
627 if (strcasecmp(argv[1], "sendRange") == 0) {
628 rangeTX();
629 return TCL_OK;
630 }
631 if (strcasecmp(argv[1], "getRangePktsTx") == 0) {
632 tcl.resultf("%d", range_pkts_sent);
633 return TCL_OK;
634 }
635 if (strcasecmp(argv[1], "getRangePktsRx") == 0) {
636 tcl.resultf("%d", range_pkts_recv);
637 return TCL_OK;
638 }
639 if (strcasecmp(argv[1], "getRangeBytesTx") == 0) {
640 tcl.resultf("%d", range_bytes_sent);
641 return TCL_OK;
642 }
643 if (strcasecmp(argv[1], "getRangePktsErr") == 0) {
644 tcl.resultf("%d", range_pkts_err);
645 return TCL_OK;
646 }
647 if (strcasecmp(argv[1], "getFullPktTime") == 0) {
648 tcl.resultf("%f", full_pkt_tx_dur);
649 return TCL_OK;
650 }
651 if (strcasecmp(argv[1], "getSavedEntries") == 0) {
652 tcl.resultf("%d", saved_entries);
653 return TCL_OK;
654 }
655 if (strcasecmp(argv[1], "calcOptEntries") == 0) {
656 tcl.resultf("%d", calcOptEntries());
657 return TCL_OK;
658 }
659 }
660 if (argc == 3) {
661 if (strcasecmp(argv[1], "setId") == 0) {
662 node_id = atoi(argv[2]);
663
664 if (node_id < 0 || node_id > std::numeric_limits<uwrange_node_t>::max())
665 return TCL_ERROR;
666
667 return TCL_OK;
668 }
669 if (strcasecmp(argv[1], "setPHYId") == 0) {
670 phy_id = atoi(argv[2]);
671
672 if (phy_id < 0)
673 return TCL_ERROR;
674
675 return TCL_OK;
676 }
677 }
678 if (argc == 4) {
679 if (strcasecmp(argv[1], "get_distance") == 0) {
680 int n1 = atoi(argv[2]);
681 int n2 = atoi(argv[3]);
682
683 if (n1 >= 0 && n1 < n_nodes && n2 >= 0 && n2 < n_nodes) {
684 if (n1 == n2) {
685 tcl.resultf("%.17f", 0.);
686 } else {
687 tcl.resultf("%.17f", time_of_flights[tof_map[n1][n2]]);
688 }
689 return TCL_OK;
690 }
691 return TCL_ERROR;
692 }
693 }
694 return Module::command(argc, argv);
695}
696
697void
699{
700 scheduler_active = true;
701 send_timer.resched(1.0 + delay_start * node_id);
702}
703
704void
706{
707 scheduler_active = false;
708 send_timer.force_cancel();
709}
710
711void
713{
715 {
716 int nextTX = range_period;
717 if (poisson_traffic) {
718 double u = RNG::defaultrng()->uniform_double();
719 double lambda = 1. / range_period;
720 nextTX = (-log(u) / lambda);
721 }
722
723 if (queue_size == 0)
724 rangeTX();
725
726 send_timer.resched(nextTX);
727 } else {
728 send_timer.force_cancel();
729 }
730}
clmsg_tap_type clmsg_type
packet to send via clmsg to other layers.
Definition uwtap_clmsg.h:98
Packet * pkt
Verbosity level.
Definition uwtap_clmsg.h:97
double tx_duration
rx or tx timestamp
double last_ber
SINR of the last received packet.
Definition uwphysical.h:106
virtual void expire(Event *e)
Class that represent the binding of the protocol with tcl.
UwRangingTDOAModuleClass()
Constructor of the TDOAGenericModule class.
TclObject * create(int, const char *const *)
Creates the TCL object needed for the tcl language interpretation.
Class that represents a UwRangingTDOA Node.
double delay_start
Starting delay in seconds.
int dist_num
Number of distances each node computes.
virtual void updateHoldoverTime(Packet *p, double tx_duration)
Update the holdover time with the actual time of transmission.
double full_pkt_tx_dur
TX duration for a full range packet.
virtual void recv(Packet *) override
Performs the reception of packets from upper and lower layers.
virtual int calcOptEntries(std::vector< int > *sorted_entries=nullptr) const
Compute the optimal number of entries for the ranging message.
std::vector< double > entries_timestamps
int phy_id
Id of the PHY module.
virtual void rangeRX(const Packet *p)
int range_pkts_recv
Counter of received ranging packets.
double max_tt
Floating numbers within this value won't be discarded by NNLS.
virtual void stop()
Stop to send packets.
virtual int recvSyncClMsg(ClMessage *m) override
Retrieve packets from other modules.
int range_entries
Number of entries per ranging packet, if <= 0 enable adaptive payload size.
int n_nodes
Number of nodes.
virtual void rangeTX()
Send a ranging message down to the MAC layer.
UwRangingTDOA()
Constructor of the UwRangingTDOA class.
UwRangeTimer send_timer
Timer that schedules ranging packet transmissions.
int range_pkts_sent
Counter of sent ranging packets.
int packet_id
id of the last ranging packet sent (= node_id + k*n_nodes)
const size_t PKTIDMAX
Max number of ranging packets that can be saved.
std::vector< double > entry_last_tx
Vector of the last (actual) TX times of each entry.
std::vector< std::vector< int > > tof_map
std::vector< double > time_of_flights
bool scheduler_active
True if the ranging scheduler is been activated with Tcl "start" command.
int saved_entries
Total number of entries not sent in the ranging packets.
int range_bytes_sent
Counter of sent ranging bytes.
double max_age
Max age of a ranging packet in seconds.
virtual int command(int argc, const char *const *argv) override
TCL command interpreter.
std::vector< int > last_ids
int range_pkts_err
Counter of lost ranging packets.
double range_period
Ranging period in seconds.
std::vector< std::vector< double > > times_mat
virtual double entryWeight(int entry, int pkt_size, int mode) const
Compute the weight of the entry given the packet size in bits.
virtual bool isValid(double value) const
Check if value is not negative.
int poisson_traffic
If true the ranging packets are sent according to a poisson process with rate range_period.
std::vector< std::vector< std::vector< tdoa_entry > > > entries_mat
virtual void start()
Start to send packets.
int node_id
Id of the current node.
std::vector< uwrange_time_t > tx_timestamp
Vector of the TX timestamp for each packet to be sent.
double soundspeed
Speed of sound in m/s.
virtual void throttleTX()
Schedule the transmission of a rangig message.
int queue_size
Counts the packet sent to the MAC waiting to be transmitted.
std::vector< double > ber
Header of the token bus protocol.
size_t getSize() const
Returns the size of a ranging header with all the entries.
uwrange_node_t times_size_
uwrange_pkt_t source_pkt_id
Ranging packet id.
uwrange_node_t source_node_id
Source node id.
Define the struct of a single tdoa payload entry.
uwrange_pkt_t id
Id of the packet.
uwrange_time_t time
Holdover time.
uwrange_node_t node
Id of the source node.
Definition of UwPhysical class.
UwRangingTDOAModuleClass class_module_uwrangingtdoa
Provides the definition of the class UwRangingTDOA.
#define HDR_RANGING_TDOA(p)
alias defined to access the hdr_ranging_tdoa HEADER
Provides the definition of the class UWSMPosition.
Utilities to manage stats.
#define DEBUG(level, text)