I am trying to write a code for 60 nodes and 1 mobile sink among which 18 nodes act as high-tier nodes or Backbone nodes. The mobile sink updates the location periodically to only the Backbone nodes and other nodes can query the sink location at the time of need.
#node creation
#Node 1 to 18 are backbone nodes
#nodes 19 to 59 are normal sensor nodes
#node 60 is the mobile sink
set node_(0) [$ns node]
set node_(1) [$ns node]
.
.
.
#node no 60 is the mobile sink..
set node_(60) [$ns node]
#node X Y coordinate initialized
$node_(0) set X_ 2
$node_(0) set Y_ 3
$node_(1) set X_ 517
$node_(1) set Y_ 299
.
.
$node_(63) set X_ 306
$node_(63) set Y_ 178
proc distBN {n1 n2 nid1 nid2} {
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
#checking that it is in the transmission range i.e 100m
if {$d<100} {
if {$nid2!=$nid1} {
return $d;
}
}
}
#This function starts the transmission of Mobile Sink location every 5 seconds
proc locTrans {} {
global ns
set dist_min 101
set dist 101
set sink_loc 60
puts "[$ns now] : Finding the nearest backbone node to sink node $sink_loc..."
for {set j 0} {$j < 19} {incr j} {
set dist [expr "distBN $node_($sink_loc) $node_($j) $sink_loc $j"]; ## <<< THIS LINE
puts "Distance between sink and node $j is $dist...\n"
if{$dist_min > $dist} {
set dist_min $dist
}
puts "Running loop for $j time...\n"
}
puts "The smallest distance is $dist_min between node_(60) and node_($j)\n"
puts "[$ns now] : transmitting sink location to nearest backbone node...\n"
$ns at [expr [$ns now] + 3.0] "locTrans"
}
The procedure locTrans() calls another function distBN() to calculate the distance between the nodes passed in arguments. But running the code gives the following error:
> ns: locTrans: can't read "node_(60)": no such variable
while executing
"expr "distBN $node_($sink_loc) $node_($j) $sink_loc $j""
(procedure "locTrans" line 9)
invoked from within
"locTrans"
The problem is that the global node_
array isn't in scope inside the procedure (because Tcl only makes non-local variables available if you explicitly ask for them). Luckily the fix is easy: update the global ns
command a few lines above to:
global ns node_
Also be aware that you have a couple of bugs in your code: you don't handle the case where you measure the distance from a node to itself correctly (right now, you're effectively returning the empty string; I bet you don't want that!) and you have written the call to distBN
wrong and should do:
set dist [distBN $node_($sink_loc) $node_($j) $sink_loc $j]
What you wrote was... not going to work.