Social Icons

twitterfacebookgoogle plusemail

viernes, 24 de mayo de 2013

Redes Sensoras


Para esta entrada se hablará sobre el tema de redes sensoras, en donde
se desarrolló una simulación de una red sensora. En la simulación se
tomaron en cuenta 3 dimensiones en el eje x, y y z en el que z a que
tanta altura se encuentra el nodo; Imaginemos que los nodos son unas
antenas que se encuentran de manera estática en el aire dichas antenas
pueden percibir objetos pero con una cierta altitud de diferencia,
digamos que un objeto no identificado llamemosló enemigo dicho enemigo
pasa a 30 metros de la antena en donde su radio de percepción
onmidireccional es de cierto alcance 20 metros, entonces el enemigo
pasará desapercibido.


Esta simulación puede ser comparada en situaciones reales como la
detección de ciertos enemigos aereos usando UAVs en donde cada UAV
tiene cierto rango de alcance de vista.


A continuación mostrare la simulación en un video, donde se tienen dos
opciones en la primera parte que tuve problemas en donde se tenía que
tener una cierta matriz en donde cada cuadro tenía que tener un cierta
rango de altitud que al final simplemente se los incormporé a cada
nodo, y cada nodo puede transmitir un mensaje de propagación siempre y
cuando se encuentre en su rango de comunicación.

Video.



Ahora veamos algo de código (el cual se encuentra comentado).

from random import randint, random
from threading import Thread
from time import sleep
from sys import argv
from math import cos, sin, fabs
import pygame
#Metodo que retorna un color en RGB dado un numero
def asignColor(grupo):
return ((grupo * 5 + 7) % 256, (grupo * 13 + 41) % 256, (grupo * 29 + 13) % 256)
#Metodo que nos regresa un color verde en RGB
def verde():
return (0,255,0)
#Metodo que nos regresa un color rojo en RGB
def rojo():
return (255,0,0)
#Metodo que nos regresa un color amarillo en RGB
def amarillo():
return (255,255,0)
#clase del enemigo
class Enemigo:
#En el constructor tomamos como parametro
# coordenadas (x, y), el color, el radio, una id que se genera de manera incremental y una vida
def __init__(self, ( x,y, z), color, radio, id, vida):
self.x = x
self.y = y
self.z = z
self.color = color
self.radio = radio
self.id = id
self.vida = vida
self.visible = True #Nos sirve para determinar si el nodo esta por ser removido
return
#Nos sirve para desplegar el enemigo en el canvas
def display(self):
#Dibuja el enemigo
pygame.draw.circle(WIN, self.color, (self.x, self.y), self.radio, 1)
#Dibuja un estatus del enemigo
WIN.blit( pygame.font.SysFont("Arial",10 ).render("ENEMIGO %s A: %s VIDA %s"%(self.id, self.z, self.vida),True,(0, 0, 0), (255, 255, 255) ), (self.x, self.y))
#Barra de vida
pygame.draw.rect( WIN, (0, 0, 0), ( (self.x, self.y+10), (self.radio *2, self.radio * 0.5) ) )
pygame.draw.rect( WIN, obtenerColorVida(self.vida), ( (self.x, self.y+10), ( ( (self.radio * 2 ) * ( ( self.vida ) * 1.0 / 100) ) , ( self.radio * 0.5 ) ) ) )
return
#clase del nodo
class Nodo:
#En el constructor tomamos como parametro
# coordenadas (x, y), el color, el radio, una id que se genera de manera incremental y una vida
def __init__(self, (x, y, z), color, radio, id, vida):
self.x = x
self.y = y
self.z = z
self.color = color
self.radio = radio
self.id = id
self.vida = vida
self.mensaje = ''
self.estado = verde()
self.visible = True #Nos sirve para determinar si el nodo esta por ser removido
return
#Metodo que dado una lista de nodos verifica que se encuentren
#dentro del rango de transmision en caso de ser asi les pasa el mensaje
#y se le resta el costo de energia segun su tamanio y radio
def transmite(self, nodos):
for nodo in nodos:
if radioDeTransmision(self.radio, self.x, self.y, self.z, (nodo.x, nodo.y, nodo.z) ):
nodo.mensaje = self.mensaje
nodo.estado = nodo.cambiaAmarillo()
self.vida -= obtenerCostoEnergia(self.radio, self.mensaje)
#En caso quese obtenga vida de menos se le asigna un 0 para evitar confusiones
if self.vida < 0:
self.vida = 0
return nodos
#Nos sirve para desplegar el nodo en el canvas
def display(self):
#Se dibuja el nodo (circulo) dado su radio y color
pygame.draw.circle(WIN, self.color, (self.x, self.y), self.radio, 1)
#Hardcoded Tuve unos problemas con la asignacion de color en lugar del color RGB deberian ir self.estado
if self.mensaje != '':
pygame.draw.circle(WIN, (255,0,0), (self.x, self.y), 5, 0)
else:
pygame.draw.circle(WIN, (0,255,0), (self.x, self.y), 5, 0)
#Se pinta el estatus del nodo
WIN.blit( pygame.font.SysFont("Arial",10 ).render("ID %s A %s VIDA %s MSG %s "%(self.id, self.z, self.vida, self.mensaje),True,(0, 0, 0), (255, 255, 255) ), (self.x, self.y))
#Barra de vida del nodo
pygame.draw.rect( WIN, (0, 0, 0), ( (self.x, self.y+10), (self.radio*0.5, self.radio * 0.1) ) )
pygame.draw.rect( WIN, obtenerColorVida(self.vida), ( (self.x, self.y+10), ( ( (self.radio * 0.5 ) * ( ( self.vida ) * 1.0 / 100) ) , ( self.radio * 0.1 ) ) ) )
return
#Metodo que regresa el estado del nodo
def getEstado(self):
return self.estado
#Metodo que cambia de color el estado por rojo
def cambiaRojo(self):
self.estado = (255,0,0)#rojo()
return
#Metodo que cambia de color el estado a amarillo
def cambiaAmarillo(self):
self.estado = amarillo()
return
#Metodo que cambia de color el estado a verdde
def cambiaVerde(self):
self.estado = verde()
return
#Dada una coordenada se verifica que esten dentro de un radio
# y ademas de que se encuentre con una diferencia de altitud(z) dentro
#del porcentaj establecido regresa un True en otro caso sera un False
def radioDeTransmision(radio, xc, yc, zc, coordenada):
global porcentaje
x, y, z = coordenada
if ( ( ( x - xc ) ** 2 ) + ( ( y - yc ) ** 2 ) ) < ( radio ** 2 ) and (fabs(zc - z) < ( zc * porcentaje)):
return True
return False
#Segun la cantidad de vida dado nos regresara
#un color determinado en RGB
def obtenerColorVida(vida):
if vida >= 66:
color = ( 0, 255, 0 )
elif vida < 66 and vida > 33:
color = ( 255, 245, 0 )
else:
color = ( 255, 0, 0 )
return color
#Tomando el radio y el largo del mensaje se obtendra
#el costo de transmision
def obtenerCostoEnergia(radio, mensaje):
return ( len(mensaje) * ( radio / 100 ) )
#clase de Simulacion que hereda de la clase Thread
class Simulacion(Thread):
def __init__(self):
Thread.__init__(self)
self.nodos = list()
self.enemigos = list()
self.contador_enemigos = 0
self.contador_nodos = 0
self.altitudes = {}
return
def run(self):
#Toma el canvas (WIN), tiempo de retraso, el color de FONDO y la propabilodad de que a paresca un nodo
global WIN, tiempo, FONDO, p, pe
run = True
self.creaGrid()
#Se crea un nodo
self.creaNodo()
#Se despliega el nodo
self.nodos[0].display()
#Se actualiza el canvas
pygame.display.update()
#Se coloca un tiempo de retraso configurado
sleep(tiempo)
#Se crea una lista para enemigos por eliminar del canvas
enemigosEliminar = list()
#Se crea una lista para nodos por eliminar del canvas
nodosEliminar = list()
#Mientras run siga siendo True corre
while run:
#Itera cada evento seleccionado
for event in pygame.event.get():
#En caso de usar QUIT cambiamos run a False
if event.type == pygame.QUIT:
run = False
#Limpieza del canvas
WIN.fill(FONDO)
self.creaGrid()
#Se iteran los enemigos
for e in xrange(len(self.enemigos)):
#En caso de que el enemigo no sea visible
#brinca el enemigo
if not self.enemigos[e].visible:
continue
#Se iteran los nodos
for n in xrange(len(self.nodos)):
#En caso de que los nodos no sea visible
#brinca el nodo
if not self.nodos[n].visible:
continue
#En caso de que el enemigo se encuentre en el radio del nodo se coloca
# como mensaje al nodo en el que se encuentra el enemigo
if radioDeTransmision(self.nodos[n].radio, \
self.nodos[n].x, \
self.nodos[n].y, \
self.nodos[n].z,
(self.enemigos[e].x, self.enemigos[e].y, self.enemigos[e].z)):
# Se cambio de estado a rojo
self.nodos[n].cambiaRojo()
#DEBUG
print self.nodos[n].estado
#Cambia mensaje
self.nodos[n].mensaje = 'Enemigo en zona de %s '%(self.nodos[n].id)
#Mientras el random nos de un numero menor a la probabilidad de nodo
#este generara un nuevo nodo
if random() < p:
self.creaNodo()
#Mientras el random nos de un numero menor a la probabilidad de enemigo
#este generara un nuevo enemigo
if random() < pe:
self.creaEnemigo()
#Por cada enemigo se le quita cierta vida
#en caso que tenga vida menor a 0 se le coloca
# en su propiedad de que ya no sera visible
#despues se pintan los enemigos visibles
for e in xrange(len(self.enemigos)):
if self.enemigos[e].vida > 5:
self.enemigos[e].vida -= 5
else:
enemigosEliminar.append(self.enemigos[e])
self.enemigos[e].visible = False
if not self.enemigos[e].visible:
continue
self.enemigos[e].display()
#Se iteran todos los nodos se le quita cierta vida
#en caso que tenga vida menor a 0 se le coloca
#en su propiedad de que ya no sera visible
#despues se pintan los nodos visibles
for n in xrange(len(self.nodos)):
print self.nodos[n].id, self.nodos[n].vida
if self.nodos[n].vida > 0:
self.nodos[n].vida -= 5
if self.nodos[n].mensaje != '':
self.nodos[n].transmite(self.nodos)
else:
nodosEliminar.append(self.nodos[n])
self.nodos[n].visible = False
if not self.nodos[n].visible:
continue
self.nodos[n].display()
#Se actualiza el canvas
pygame.display.update()
#Se crea un retraso
sleep(tiempo)
#Se remueven los enemigos en la lista de enemigosEliminar
for e in enemigosEliminar:
try:
self.enemigos.remove(e)
except:
pass
#Se remueven los nodos en la lista de nodosEliminar
for n in nodosEliminar:
try:
self.nodos.remove(n)
except:
pass
return
#Pinta los nodos que se han comunicado
def pintaRedComunicacion(self, comunicacion):
global WIN
if len(comunicacion) >= 3:
print comunicacion
for i in xrange(len(comunicacion)):
if len(comunicacion) != i+1:
x1, y1 = comunicacion[i]
x2, y2 = comunicacion[i+1]
pygame.draw.line(WIN , (255, 0, 0), (x1, y1), (x2, y2), 1 )
return
#Se crea un nodo enemigo
def creaEnemigo(self):
#Se toma la configuracion de su radio (re), vida (vidaEnemigo), porcentaje (margen)
global re, vidaEnemigo, porcentaje
#Contador de los enemigos creados
self.contador_enemigos += 1
#Se le da una posicion al enemigo de manera aleatoria con un color rojo en RGB, una id con numero de enemigos y una vida propia
enemigo = Enemigo( ( randint( DIM * 0.10 , DIM * porcentaje ), randint( DIM * 0.10, DIM * porcentaje ), randint(0, altitude ) ), (255, 0, 0), re, self.contador_enemigos, vidaEnemigo)
#Se agrega a la lista de enemigos los enemigos
self.enemigos.append( enemigo )
return
def creaNodo(self):
#Se toma la configuracion de su radio (re), vida (vidaEnemigo), porcentaje (margen)
global r, vidaNodo, porcentaje, altitude
#Contador de los nodos creados
self.contador_nodos+=1
#Se le da una posicion al nodo de manera aleatoria con un color en RGB obtenido a partir del contador de nodos , una id osea el numero de nodos y una vida propia
nodo = Nodo( ( randint( DIM * 0.10 , DIM * porcentaje ), randint( DIM * 0.10, DIM * porcentaje ), randint(0, altitude ) ), asignColor( self.contador_nodos ), r, self.contador_nodos , vidaNodo)
#Se agrega el nodo a la lista de nodos
self.nodos.append( nodo )
return
#Metodo que crea una red de cuadro en el que cada cuadro tiene una altitud establecida
def creaGrid(self):
#Se toman las variables de ventana, dimensiones, pedasos en que se partira la ventana y la altitude maxima
global WIN, DIM, CHUNKS, altitude
#Se obtienen las partes de la ventana
CHUNK = DIM/CHUNKS
print len(self.altitudes)
#En caso de ser la primera vez en dibujar la matriz se guardan en un dictionary las altitudes
# que se guardaran de manera aleatoria
if len(self.altitudes) == 0:
for y in xrange(CHUNKS):
for x in xrange(CHUNKS):
print ( (x * CHUNK, y), (x * CHUNK, y * CHUNK) )
self.altitudes[( (x * CHUNK, y), (CHUNK, CHUNK) )] = ((randint(0, altitude)),( ( (x * CHUNK, y * CHUNK), (CHUNK * y, (x+1) * CHUNK) ) ))
#for c in xrange(CHUNKS):
# pygame.draw.line(WIN, (255, 0, 0), (CHUNK * c, 0), (CHUNK * c, CHUNK * CHUNKS))
# pygame.draw.line(WIN, (255, 0, 0), (0, CHUNK * c), (CHUNK * CHUNKS, CHUNK * c))
altiud, tam, aux, c = None, None, None, None
#Aqui se colocan los colores de los cuadros
for y in xrange(CHUNKS):
for x in xrange(CHUNKS):
altitud, tam = self.altitudes[( (x * CHUNK, y), (CHUNK,CHUNK) )]
print 'Creando rectangulos: ',altitud, tam
pygame.draw.rect(WIN, asignColor(altitud), tam, 100)
#Aqui se colocan los textos, se colocaron de esta manera porque si los iteraba en el
#for se iban a empalmar
for y in xrange(CHUNKS):
for x in xrange(CHUNKS):
altitud, tam = self.altitudes[( (x * CHUNK, y), (CHUNK,CHUNK) )]
c, aux = tam
cx, cy = c
cx = cx+CHUNKS/2.0
cy = cy+CHUNKS/2.0
# c = cx +10, cy +10
WIN.blit( pygame.font.SysFont("Arial",10 ).render("%s"%(altitud), True, (0, 0, 0), (255, 255, 255) ), (cx, cy) )
return
#Dimensiones del canvas
DIM = 1000
#porcentaje del canvas
porcentaje = 0.6
#color de fondo(blanco)
FONDO = ( 255, 255, 255)
#inicia pygame
pygame.init()
#se crea el canvas
WIN = pygame.display.set_mode((DIM, DIM))
#Se coloca un titulo al canvas
pygame.display.set_caption('Simulacion de redes sensoras')
#Se rellena de un color al canvas
WIN.fill(FONDO)
#Parametro de tiempo
try:
tiempo = float(argv[1])
except:
tiempo = 3
#Parametro de probabilidad de nodo
try:
p = float(argv[2])
except:
p = 0.6
#Parametro de radio del nodo
try:
r = float(argv[3])
except:
r = 200
#Parametro de probabilidad de enemigo
try:
pe = float(argv[4])
except:
pe = 0.4
#Parametro de radio de enemigo
try:
re = float(argv[5])
except:
re = 10
#Parametro de vida del nodo
try:
vidaNodo = int(argv[6])
except:
vidaNodo = 100
#Parametro de vida del enemigo
try:
vidaEnemigo = int(argv[7])
except:
vidaEnemigo = 20
#Parametro de velocidad
try:
velocidad = int(argv[8])
except:
velocidad = 10
#Parametro de pedasos a partir la ventana
try:
CHUNKS = int(argv[9])
except:
CHUNKS = 20
#Parametro para la altitude maxima
try:
altitude = int(argv[10])
except:
altitude = 200
def main():
#Crea una simulacion
s = Simulacion()
#corre simulacion
s.run()
main()

1 comentarios:

  1. Lo de mapear colores a alturas en principio es una buena idea, pero aquí es algo difícil interpretarlas. Yo hubiera esperado más nodos y mayor actividad entre ellos. 11 pts.

    ResponderEliminar