def add_node(self, node=None, pos=None, ori=None, commRange=None): """ Add node to network. Attributes: `node` -- node to add, default: new node is created `pos` -- position (x,y), default: random free position in environment `ori` -- orientation from 0 to 2*pi, default: random orientation """ if (not node): node = Node(commRange=commRange) assert(isinstance(node, Node)) if not node.network: node.network = self else: logger.warning('Node is already in another network, can\'t add.') return None pos = pos if pos is not None else self.find_random_pos(n=100) ori = ori if ori is not None else rand() * 2 * pi ori = ori % (2 * pi) if (self._environment.is_space(pos)): Graph.add_node(self, node) self.pos[node] = array(pos) self.ori[node] = ori self.labels[node] = str(node.id) logger.debug('Node %d is placed on position %s.' % (node.id, pos)) self.recalculate_edges([node]) else: logger.error('Given position is not free space.') return node
def _setup(self, settings_module=None): """ Load the settings module pointed to by the environment variable. This is used the first time we need any settings at all, if the user has not previously configured the settings manually. """ if settings_module is None: try: settings_module = os.environ[ENVIRONMENT_VARIABLE] if not settings_module: # If it's set but is an empty string. raise KeyError except KeyError: settings_module = None logger.warning("Environment variable %s is undefined, using " "global_settings." % ENVIRONMENT_VARIABLE) else: logger.info("Settings module is specified in environment" "variable %s." % (ENVIRONMENT_VARIABLE)) if settings_module is not None: logger.info("Using module %s to override global_settings."\ % (settings_module)) self._wrapped = Settings(settings_module)
def environment(self, environment): """ If net environment is changed all nodes are moved into and corresponding channelType environment must be changed also. """ self._environment = environment self.channelType.environment = environment for node in self.nodes(): self.remove_node(node) self.add_node(node) logger.warning('All nodes are moved into new environment.')
def __init__(self, n_count=None, n_min=0, n_max=Inf, connected=True, degree=None, comm_range=None, method="random_network", **kwargs): """ Arguments: n_count (int): number of nodes, if None settings.N_COUNT is used n_min (int): minimum number of nodes n_max (int): maximum number of nodes connected (bool): if True network must be fully connected degree (int): average number of neighbors per node comm_range (int): nodes communication range, if None settings.COMM_RANGE is used and it is a signal that this value can be changed if needed to satisfy other wanted properties (connected and degree) method (str): sufix of the name of the method used to generate network kwargs can be network and node __init__ kwargs i.e.: environment (:class:`Environment`): environment in which the network should be created, if None settings.ENVIRONMENT is used channelType (:class:`ChannelType`) algorithms (tuple) commRange (int): overrides `comm_range` sensors (tuple) Basic usage: >>> net_gen = NetworkGenerator() >>> net = net_gen.generate() """ self.n_count=n_count if n_count else settings.N_COUNT if self.n_count<n_min or self.n_count>n_max: raise NetworkGeneratorException('Number of nodes must be between ' 'n_min and n_max.') if degree and degree>=n_max: raise NetworkGeneratorException('Degree % d must be smaller than ' 'maximum number of nodes %d.' % (degree, n_max)) #TODO: optimize recalculation of edges on bigger commRanges if degree and degree>16 and n_count!=Inf: logger.warning("Generation could be slow for large degree" "parameter with bounded n_max.") self.n_min = n_min self.n_max = n_max self.connected = connected self.degree = degree self.comm_range = kwargs.pop('commRange', comm_range) #TODO: use subclass based generators instead of method based self.generate = self.__getattribute__("generate_" + method) self.kwargs = kwargs
def add_node(self, node=None, pos=None, ori=None, commRange=None, find_random=False): """ Add node to network. Attributes: `node` -- node to add, default: new node is created `pos` -- position (x,y), default: random free position in environment `ori` -- orientation from 0 to 2*pi, default: random orientation """ if (not node): node = Node(commRange=commRange or self.comm_range) if not node.commRange: node.commRange = commRange or self.comm_range assert (isinstance(node, Node)) if not node.network: node.network = self else: logger.warning('Node is already in another network, can\'t add.') return None pos = pos if (pos is not None and not isnan(pos[0])) else self.find_random_pos(n=100) ori = ori if ori is not None else rand() * 2 * pi ori = ori % (2 * pi) got_random = False if find_random and not self._environment.is_space(pos): pos = self.find_random_pos(n=100) got_random = True if (self._environment.is_space(pos)): Graph.add_node(self, node) self.pos[node] = array(pos) self.ori[node] = ori self.labels[node] = ('C' if node.type == 'C' else "") + str( node.id) logger.debug('Node %d is placed on position %s %s %s' % (node.id, pos, '[energy=%5.3f]' % node.power.energy if node.power.energy != EnergyModel.E_INIT else '', 'Random' if got_random else '')) self.recalculate_edges([node]) else: Node.cid -= 1 logger.error('Given position is not free space. [%s] %s' % (Node.cid, pos)) node = None return node
def get_current_algorithm(self): """ Try to return current algorithm based on algorithmState. """ if len(self.algorithms) == 0: logger.warning('There is no algorithm defined in a network.') return None if self.algorithmState['finished']: if len(self.algorithms) > self.algorithmState['index'] + 1: self.algorithmState['index'] += 1 self.algorithmState['step'] = 1 self.algorithmState['finished'] = False else: return None return self.algorithms[self.algorithmState['index']]
def get_current_algorithm(self): """ Try to return current algorithm based on algorithmState. """ if len(self.algorithms) == 0: logger.warning("There is no algorithm defined in a network.") return None if self.algorithmState["finished"]: if len(self.algorithms) > self.algorithmState["index"] + 1: self.algorithmState["index"] += 1 self.algorithmState["step"] = 1 self.algorithmState["finished"] = False else: return None return self.algorithms[self.algorithmState["index"]]
def add_node(self, node=None, pos=None, ori=None, commRange=None, find_random=False): """ Add node to network. Attributes: `node` -- node to add, default: new node is created `pos` -- position (x,y), default: random free position in environment `ori` -- orientation from 0 to 2*pi, default: random orientation """ if (not node): node = Node(commRange=commRange or self.comm_range) if not node.commRange: node.commRange = commRange or self.comm_range assert(isinstance(node, Node)) if not node.network: node.network = self else: logger.warning('Node is already in another network, can\'t add.') return None pos = pos if (pos is not None and not isnan(pos[0])) else self.find_random_pos(n=100) ori = ori if ori is not None else rand() * 2 * pi ori = ori % (2 * pi) got_random = False if find_random and not self._environment.is_space(pos): pos = self.find_random_pos(n=100) got_random = True if (self._environment.is_space(pos)): Graph.add_node(self, node) self.pos[node] = array(pos) self.ori[node] = ori self.labels[node] = ('C' if node.type == 'C' else "") + str(node.id) logger.debug('Node %d is placed on position %s %s %s' % (node.id, pos, '[energy=%5.3f]' %node.power.energy if node.power.energy != EnergyModel.E_INIT else '', 'Random' if got_random else '')) self.recalculate_edges([node]) else: Node.cid -= 1 logger.error('Given position is not free space. [%s] %s' % (Node.cid, pos)) node = None return node
def get_crb(net, sensor, compass='******', loc_type='anchor-free', anchors=[]): """ Calculates Cramer-Rao lower bound on covariance matrix of unbiased multihop location estimator based on sensor (distance/angle) measurement between in-commrange neighbors. POS is n by 2 matrix of X and Y coordinates of n nodes SIGMA is standard deviation on measurement vector. Arguments: `compass` -- 'off' (default) or 'on' which means all nodes have compass `loc_type` -- 'anchor-free' (default) or 'anchored' `anchors` -- list of anchor nodes, used only when loc_type is 'anchored' References: Savvides2003 - Savvides et al, On the Error Characteristics of Multihop Node Localization in Ad-Hoc Sensor Networks, 2003 Patwari2005 - Patwari et al, Locating the nodes: cooperative localization in wireless sensor networks Chang2006 - Chen Chang et al, Cramer-Rao-Type Bounds for Localization, 2006 """ if loc_type == 'anchored' and not anchors: raise Exception('Anchors not defined.') if loc_type == 'anchor-free' and anchors: logger.warning('Anchors are ignored') anchors = [] nodes = [node for node in net.nodes() if node not in anchors] if sensor.name()=='AoASensor' and compass=='off': u = 3 # x, y, theta else: # DistSensor or AoASensor with compass on u = 2 # x, y G = construct_G(net.pos, net.edges(), u, sensor.name()) for s in nodes[0].compositeSensor.sensors: if s.name() == sensor.name(): sigma = s.probabilityFunction.scale break else: raise Exception('Sensor not found in nodes') J = (dot(G.T, G)) / sigma ** 2 #print matrix_rank(J) if loc_type == 'anchor-free': cov = pinv(J) elif loc_type=='anchored': cov = inv(J) # Chang2006 (28) di = diag(cov) # extract only position from cov di = concatenate((di[::3], di[1::3])) #return is lower bound on rms -> sqrt(1/n*sum_i^n((x_i'-x_i)^2+(y_i'-y_i)^2)) return sqrt(2*mean(di))
def __init__(self, n_count=None, n_min=0, n_max=32000, connected=True, degree=None, comm_range=None, method=None, **kwargs): """ Arguments: n_count (int): number of nodes, if None settings.N_COUNT is used n_min (int): minimum number of nodes n_max (int): maximum number of nodes connected (bool): if True network must be fully connected degree (int): average number of neighbors per node comm_range (int): nodes communication range, if None settings.COMM_RANGE is used and it is a signal that this value can be changed if needed to satisfy other wanted properties (connected and degree) method (str): sufix of the name of the method used to generate network kwargs can be network and node __init__ kwargs i.e.: environment (:class:`Environment`): environment in which the network should be created, if None settings.ENVIRONMENT is used channelType (:class:`ChannelType`) algorithms (tuple) commRange (int): overrides `comm_range` sensors (tuple) Basic usage: >>> net_gen = NetworkGenerator() >>> net = net_gen.generate() """ self.name = "Unknown" self.n_count=n_count if n_count else settings.N_COUNT if self.n_count<n_min or self.n_count>n_max: raise NetworkGeneratorException('Number of nodes must be between ' 'n_min and n_max.') if degree and degree>=n_max: raise NetworkGeneratorException('Degree % d must be smaller than ' 'maximum number of nodes %d.' % (degree, n_max)) #TODO: optimize recalculation of edges on bigger commRanges if degree and degree>16 and n_count!=Inf: logger.warning("Generation could be slow for large degree" "parameter with bounded n_max.") self.n_min = n_min self.n_max = n_max self.connected = connected self.degree = degree self.comm_range = kwargs.pop('commRange', comm_range) #TODO: use subclass based generators instead of method based if (method): self.generate = self.__getattribute__("generate_" + method) self.kwargs = kwargs self.area = 0 self.net_density = 0
def get_crb(net, sensor, compass='******', loc_type='anchor-free', anchors=[]): """ Calculates Cramer-Rao lower bound on covariance matrix of unbiased multihop location estimator based on sensor (distance/angle) measurement between in-commrange neighbors. POS is n by 2 matrix of X and Y coordinates of n nodes SIGMA is standard deviation on measurement vector. Arguments: `compass` -- 'off' (default) or 'on' which means all nodes have compass `loc_type` -- 'anchor-free' (default) or 'anchored' `anchors` -- list of anchor nodes, used only when loc_type is 'anchored' References: Savvides2003 - Savvides et al, On the Error Characteristics of Multihop Node Localization in Ad-Hoc Sensor Networks, 2003 Patwari2005 - Patwari et al, Locating the nodes: cooperative localization in wireless sensor networks Chang2006 - Chen Chang et al, Cramer-Rao-Type Bounds for Localization, 2006 """ if loc_type == 'anchored' and not anchors: raise Exception('Anchors not defined.') if loc_type == 'anchor-free' and anchors: logger.warning('Anchors are ignored') anchors = [] nodes = [node for node in net.nodes() if node not in anchors] if sensor.name() == 'AoASensor' and compass == 'off': u = 3 # x, y, theta else: # DistSensor or AoASensor with compass on u = 2 # x, y G = construct_G(net.pos, net.edges(), u, sensor.name()) for s in nodes[0].compositeSensor.sensors: if s.name() == sensor.name(): sigma = s.probabilityFunction.scale break else: raise Exception('Sensor not found in nodes') J = (dot(G.T, G)) / sigma**2 #print matrix_rank(J) if loc_type == 'anchor-free': cov = pinv(J) elif loc_type == 'anchored': cov = inv(J) # Chang2006 (28) di = diag(cov) # extract only position from cov di = concatenate((di[::3], di[1::3])) #return is lower bound on rms -> sqrt(1/n*sum_i^n((x_i'-x_i)^2+(y_i'-y_i)^2)) return sqrt(2 * mean(di))