Yo elegí simular el control de incendios en un área montañosa, la idea funciona de la siguiente manera: Supongamos que tenemos un área muy grande de bosque en dónde es difícil acceder a ella y darse cuenta que hay algún incendio, y cuando ya nos podemos dar cuenta de ello el incendio ya esta muy avanzado y hay graves daños al ecosistema.
Lo que se busca es con ayuda de la nueva tecnología poder controlar este tipo de situaciones, para esto diseñé una pequeña simulación buscando encontrar la solución en el uso de una red sensora.
Fractal
Lo primero que se realizó es la elaboración del terreno con la ayuda de un fractal, el código es el siguiente:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Fractal: | |
""" | |
""" | |
def __init__(self): | |
self.w = 150 | |
self.h = 150 | |
self.image = Image.new("L", (self.w,self.h)) | |
self.roughness = random.randint(2,3) | |
def adjust(self, xa, ya, x, y, xb, yb): | |
if(self.image.getpixel((x,y)) == 0): | |
d=math.fabs(xa-xb) + math.fabs(ya-yb) | |
v=(self.image.getpixel((xa,ya)) + self.image.getpixel((xb,yb)))/2.0 + (random.random()-0.5) * d * self.roughness | |
c=int(math.fabs(v) % 256) | |
self.image.putpixel((x,y), c) | |
def subdivide(self, x1,y1,x2,y2): | |
if(not((x2-x1 < 2.0) and (y2-y1 < 2.0))): | |
x=int((x1 + x2)/2.0) | |
y=int((y1 + y2)/2.0) | |
self.adjust(x1,y1,x,y1,x2,y1) | |
self.adjust(x2,y1,x2,y,x2,y2) | |
self.adjust(x1,y2,x,y2,x2,y2) | |
self.adjust(x1,y1,x1,y,x1,y2) | |
if(self.image.getpixel((x,y)) == 0): | |
v=int((self.image.getpixel((x1,y1)) + self.image.getpixel((x2,y1)) + self.image.getpixel((x2,y2)) + self.image.getpixel((x1,y2)))/4.0) | |
self.image.putpixel((x,y),v) | |
self.subdivide(x1,y1,x,y) | |
self.subdivide(x,y1,x2,y) | |
self.subdivide(x,y,x2,y2) | |
self.subdivide(x1,y,x,y2) |
Y el resultado es la siguiente imagen:

Teniendo esto podemos graficarlo en 3D con la ayuda de matplotlib y queda de la siguiente manera:
![]() |
Simulación de montañas con un fractal |
Redes sensoras
Se distribuyeron sensores por todo el terreno de manera aleatoria, también se decidió tener una base elegida también de manera aleatoria que es a la que deben de llegar los mensajes de incendio para poder avisar a las partes correspondientes.
El punto rojo inicial indica que hay algún incendio en alguna parte y rápidamente el sensor que este mas cercano y siempre y cuando tenga el alcance necesario empieza a distribuir todo el mensaje hasta llegar a la base.
Para esta parte se tomaron en cuenta los mismos aspectos de la entrada pasada solo que ahora se agrego la parte adaptativa, es decir si el mensaje no llega a la estación entonces se manda un mensaje para aumentar el TTL y aumentar las posibilidades de llegar a la base.
El triangulo naranja es la base.
Los nodos amarillos son los que pasan el mensaje.
Se tomó en cuenta para que se mueran los nodos la Batería, el ciclo de vida , TTL, Intensidad de señal.
Los nodos grises son los sensores muertos.
Este ejemplo tiene TTL = 10
TTL=2
![]() |
Los nodos grises significan que los sensores ya no funcionan |
![]() |
No se llegó a la base |
![]() |
La base es el triángulo naranja |
Código
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from PIL import Image | |
import math | |
import random | |
#from mpl_toolkits.mplot3d import axes3d | |
from mpl_toolkits.mplot3d import Axes3D | |
from matplotlib import cm | |
import matplotlib.pyplot as plt | |
import numpy as np | |
import itertools | |
import time | |
import matplotlib.lines as mlines | |
import pylab | |
################################### | |
#Se genera el fractal creando una | |
#imagen con PIL | |
################################### | |
class Fractal: | |
""" | |
""" | |
def __init__(self): | |
self.w = 150 | |
self.h = 150 | |
self.image = Image.new("L", (self.w,self.h)) | |
self.roughness = random.randint(2,3) | |
def adjust(self, xa, ya, x, y, xb, yb): | |
if(self.image.getpixel((x,y)) == 0): | |
d=math.fabs(xa-xb) + math.fabs(ya-yb) | |
v=(self.image.getpixel((xa,ya)) + self.image.getpixel((xb,yb)))/2.0 + (random.random()-0.5) * d * self.roughness | |
c=int(math.fabs(v) % 256) | |
self.image.putpixel((x,y), c) | |
def subdivide(self, x1,y1,x2,y2): | |
if(not((x2-x1 < 2.0) and (y2-y1 < 2.0))): | |
x=int((x1 + x2)/2.0) | |
y=int((y1 + y2)/2.0) | |
self.adjust(x1,y1,x,y1,x2,y1) | |
self.adjust(x2,y1,x2,y,x2,y2) | |
self.adjust(x1,y2,x,y2,x2,y2) | |
self.adjust(x1,y1,x1,y,x1,y2) | |
if(self.image.getpixel((x,y)) == 0): | |
v=int((self.image.getpixel((x1,y1)) + self.image.getpixel((x2,y1)) + self.image.getpixel((x2,y2)) + self.image.getpixel((x1,y2)))/4.0) | |
self.image.putpixel((x,y),v) | |
self.subdivide(x1,y1,x,y) | |
self.subdivide(x,y1,x2,y) | |
self.subdivide(x,y,x2,y2) | |
self.subdivide(x1,y,x,y2) | |
def hip(x1,x2,y1,y2,z1,z2,alcance): | |
"""saber si el mensaje se puede pasar | |
""" | |
d = (abs(x1-x2)**2 + abs(y1-y2)**2 + abs(z1-z2)**2)**0.5 | |
if d < alcance: | |
return True | |
else: | |
return False | |
class Nodo(): | |
def __init__(self): | |
self.x = 0 | |
self.y = 0 | |
self.z = 0 | |
self.padre = None | |
self.hijo = None | |
self.ttl = 3 | |
self.vivo = True | |
self.tiempo = time.time() | |
self.alcance = 80 | |
self.sabe = False | |
self.base = False | |
def pasar_mensaje(self, destino): | |
enterado = hip(self.x,destino.x,self.y,destino.y,self.z,destino.z,self.alcance) | |
if enterado and destino.vivo: | |
destino.padre = self | |
self.hijo = destino | |
destino.ttl = self.ttl - 1 | |
if destino.ttl > 0: | |
destino.vivo = True | |
self.sabe = True | |
#Nodo aun vivo y alcanzado por el mensaje" | |
return 1 | |
else: | |
#Ya no puede enviar | |
return 2 | |
else: | |
"Nodo no alcanzado" | |
return 3 | |
def grafica(imagen): | |
x = [] | |
y = [] | |
z = [] | |
pixeles = imagen.load() | |
xx, yy = imagen.size | |
for a in range(xx): | |
for b in range(yy): | |
x.append(a) | |
y.append(b) | |
z.append(pixeles[a,b]) | |
colo = np.arange(len(z)) | |
fig = plt.figure() | |
ax = fig.add_subplot(111, projection='3d') | |
ax.scatter(x,y,z, s=35,c = z, cmap=cm.winter, marker='_', alpha=0.5) | |
plt.savefig(str(time.time())+".png") | |
return x, y, z, ax,fig | |
def sensores(x,y,z,ax): | |
num = 20 | |
sensors = [] | |
for i in range(num): | |
#se crea el sensor | |
sensor = Nodo() | |
sel = random.randint(0,len(x)-1) | |
sensor.x, sensor.y, sensor.z = x[sel],y[sel],z[sel]+20 | |
ax.scatter(x[sel],y[sel],z[sel]+20, marker='o',c='black',s=100) | |
sensors.append(sensor) | |
sel = random.randint(0,len(x)-1) | |
ax.scatter(x[sel],y[sel],z[sel]+20, marker='o',c='red',s=100) | |
#se crea un activador | |
evento = Nodo() | |
evento.x, evento.y, evento.z = x[sel],y[sel],z[sel]+20 | |
plt.savefig('1.png') | |
return sensors, evento | |
def main(): | |
""" | |
""" | |
fractal = Fractal() | |
fractal.image.putpixel((0,0),random.randint(0, 255)) | |
fractal.image.putpixel((fractal.w-1,0),random.randint(0, 255)) | |
fractal.image.putpixel((fractal.w-1,fractal.h-1),random.randint(0, 255)) | |
fractal.image.putpixel((0,fractal.h-1),random.randint(0, 255)) | |
fractal.subdivide(0,0,fractal.w-1,fractal.h-1) | |
fractal.image.save("plasma.png", "PNG") | |
x,y,z,ax,fig = grafica(fractal.image) | |
sensors, evento = sensores(x,y,z,ax) | |
sel = random.randint(0,len(x)-1) | |
ax.scatter(x[sel],y[sel],z[sel]+20, marker='^',c='orange',s=300) | |
#se crea base | |
base = Nodo() | |
base.x, base.y, base.z = x[sel],y[sel],z[sel]+20 | |
eventos = [] | |
base.base = True | |
sensors.append(base) | |
eventos.append(evento) | |
while len(eventos)>0: | |
evento = eventos.pop() | |
for sensor in sensors: | |
if sensor.sabe: | |
continue | |
eleccion = evento.pasar_mensaje(sensor) | |
if eleccion == 1 and not sensor.sabe: | |
if sensor.base: | |
print "Mensaje llego a la base en (%s, %s, %s)" %(sensor.x, sensor.y, sensor.z) | |
ax.scatter(sensor.x,sensor.y-1,sensor.z, marker='^',c='orange',s=400) | |
plt.savefig(str(time.time())+".png") | |
ax.scatter(sensor.x,sensor.y-1,sensor.z, marker='^',c='orange',s=500) | |
plt.savefig(str(time.time())+".png") | |
ax.scatter(sensor.x,sensor.y-1,sensor.z, marker='^',c='orange',s=600) | |
plt.savefig(str(time.time())+".png") | |
ax.scatter(sensor.x,sensor.y-1,sensor.z, marker='^',c='orange',s=700) | |
plt.savefig(str(time.time())+".png") | |
return | |
else: | |
print "Mensaje recibido por sensor ubicado en (%s, %s, %s)" %(sensor.x, sensor.y, sensor.z) | |
ax.scatter(sensor.x,sensor.y-1,sensor.z, marker='o',c='yellow',s=200) | |
plt.savefig(str(time.time())+".png") | |
eventos.append(sensor) | |
elif eleccion == 2: | |
print "El nodo ubicado en (%s, %s, %s) ya no puede enviar mensajes \n no tiene bateria o su ttl = 0" %(sensor.x, sensor.y, sensor.z) | |
ax.scatter(sensor.x,sensor.y-1,sensor.z, marker='o',c='gray',s=200) | |
plt.savefig(str(time.time())+".png") | |
sensors.remove(sensor) | |
else: | |
pass | |
print "Con ttl de %s no fue posible llegar a la base" %base.ttl | |
plt.show() | |
main() |
Conclusiones
Podemos ver que entre más alcance tengan los sensores es más rápido la detección del incendio, también que es conveniente que se adapte para saber cuando el TTL no llega pues ajustarlo para que sea posible llegar siempre a la base.
Referencias
Elisa Schaeffer - Redes sensoras
Referencias
Elisa Schaeffer - Redes sensoras
Me hubiera gustado ver una visualización en video. 15 pts.
ResponderEliminarGreat information. This works great for me. Thanks for sharing this :)
ResponderEliminar