Webcam-server en Ubuntu 11.10

enero 16, 2012 1 comentario

Estamos tratando de montar una demostración para un laboratorio distribuido. Me di a la tarea de hacer funcionar una realimentación a través de una webcam usando el software  webcam-server. Los pasos son los siguientes:

  1. Descargar webcam-server_0.50-3_amd64.deb (o la variante para i386, según corresponda).
  2. Instalar el paquete con doble click o a través de dpkg -i.
  3. Copiar los ficheros /usr/share/doc/webcam-server/applet/webcam.html y /usr/share/doc/webcam-server/applet/applet.jar para alguna carpeta debajo de /var/www (el apache debe estar instalado).
  4. Ejecutar el comando export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libv4l/v4l1compat.so (export LD_PRELOAD=/usr/lib/i386-linux-gnu/libv4l/v4l1compat.so) para evitar errores de compatibilidad con las nuevas versiones de Video4Linux.
  5. Ejecutar webcam-server desde el terminal.
  6. Cargar en el navegador la página webcam.html que copiamos en el paso 3.

Para que la imagen se vea continua modificamos la línea <param name=FPS value=”1″> para que sea <param name=FPS value=”60″>.

En nuestro caso en particular la aplicación web corre en una PC con windows y la webcam en otra con ubuntu. Debido a las restricciones de los navegadores los applets solo pueden establecer conexiones con el servidor de donde provienen. Para solucionar este inconveniente hemos desarrollado esta pequeña aplicación de Python + Qt, cortesía de Dariov, que puede ejecutada desde la máquina donde se controla remotamente el laboratorio.

#! /usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt4 import QtCore, QtGui
from datetime import datetime
import urllib2
import sys

WEBCAM_SERVER = "http://localhost:8888"
CACHE = "cache"
INTERVAL = 100 # ms
#VALIDATOR = QtCore.QRegExpValidator()

class ImageCanvas(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ImageCanvas, self).__init__(parent)
        timer = QtCore.QTimer(self)
        QtCore.QObject.connect(timer, QtCore.SIGNAL('timeout()'), self, \\
           QtCore.SLOT('update()'))
        timer.start(INTERVAL)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
	try:
	  download_file = urllib2.urlopen(WEBCAM_SERVER).read()
	  cache_file = open(CACHE, 'wb')
	  cache_file.write(download_file)
	  cache_file.close()
	except:
	  print "%s No se pudo descargar el fichero a la cache." % \\
           (datetime.now())

	image = QtGui.QImage(CACHE)
	if image.isNull():
	    print "%s No se puede cargar el fichero de la cache." % \\ 
           (datetime.now())
	    return
        painter.drawImage(QtCore.QPoint(0,0), image)

class ImageViewer(QtGui.QMainWindow):
    def __init__(self):
        super(ImageViewer, self).__init__()
        text, ok = QtGui.QInputDialog.getText(self, "IP de la WebCam",
                "IP:", QtGui.QLineEdit.Normal,
                QtCore.QDir.home().dirName())
        if ok and text != '':
            WEBCAM_SERVER = "http://"+text
        self.imageCanvas = ImageCanvas(self)
        self.setCentralWidget(self.imageCanvas)
        self.setWindowTitle("WebCamViewer")
        self.resize(320,240)

app = QtGui.QApplication(sys.argv)
imageViewer = ImageViewer()
imageViewer.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
imageViewer.show()
sys.exit(app.exec_())
Categorías:Docencia

Configurando la TINI desde 0

diciembre 22, 2011 Deja un comentario

Expongo mis experiencias para configurar la TINI desde cero. Sucede que cada vez que me alejo y quiero volver a utilizarla me paso dos o tres noches sin dormir. Aunque es un producto muy bien documentado, siempre me toma bastante entender lo que se necesita.

Tarjeta Tini

  • Primero que todo debemos tener instalado en Linux una máquina virtual de java (default-jre en ubuntu).
  • Luego debemos crear un cable rs232 directo que enlace las patas de la 2 a la 5. Conectamos el DB9 hembra de la TINI con el puerto serie de la PC. La conexión se hace Rx-Rx y Tx-Tx (esto es raro pero es así), la tierra por la pata 5 y la pata 4 para resetear a la TINI.
  • Ejecutamos chmod 666 /dev/ttyS0 para autorisar a la aplicación a usar el puerto serie.
  • Ejecutar el comando java JavaKit dentro de la carpeta JavaKitRxTx que ya cuenta con la librería para manejar el puerto serie. En esta se modificaron las dependencias para gnu.io en lugar de java.io.

JavaKit

  • Luego abrimos el puerto y damos reset. Todos los parámetros pueden ser dejados tal cual.

Nada eso es todo, lo demás está bastante evidente.

Categorías:Docencia, Investigación

Control Systems Library for Python en Sage

noviembre 22, 2011 Deja un comentario

Sage es una excelente herramienta para la matemática que se necesita en la carrera de Ingeniería Eléctrica (tanto más porque solo se necesita instalado en el servidor), por eso me he dado a la tarea de preparar una hoja de trabajo demostrando sus ventajas en la solución de los problemas típicos de la especialidad. Un paso definitivo es el uso de herramientas para el análisis de sistemas como la ToolBox de control de matlab, aquí es donde se inserta Control Systems Library for Python. El uso de esta librería de python requiere además la instalación de Slycot, un wrapper de SLICOT, que es necesario compilar a partir del código fuente en FORTRAN. Esto me tuvo algunos días trabajando y a continuación expongo las dependencias que deben estar instaladas (para distribuciones derivadas de debian):

  • python-scipy
  • python-dev
  • liblapack
  • python-setuptools

Lamentablemente aunque esta librería funciona bien para pylab, no funciona bien sobre Sage, fundamentalmente por los tipos de datos que maneja este último. Una solución sería reprogramar la clase Matlab.py de Control Systems Library for Python. Esa tarea puede ser un buen tema para trabajo con alumnos ayudantes.

Categorías:Docencia

Un problema con la PC

Resulta que hoy descubrimos que la máquina donde está corriendo el simulador del radar se apaga sola sin previo aviso. Como el programa corre todo antes de guardar (Estimo que eso dure unas 12hrs), se pierde todo.

Soluciones:

  1. Cambiar de máquina (Descartada, la máquina es un hierro).
  2. Hacer el programa inmune a esto.

Como la máquina tiene prestaciones muy buenas y por otro lado, eso de no ir guardando los progreso es una chapucería. Decidí guardar cada vuelta y además dejar una traza cuando se guarde, indicando el ángulo de elevación de la última vuelta guardada.

Lo único significativo en este arreglo es que fue necesario cerrar la piscina (pool) en el lazo exterior para guardar y abrir una nueva al comienzo del mismo. Lo demás fue cuestión de ponerlo a correr en rc.local para que si se reinicia empiece de nuevo. Ya está corriendo de nuevo.

 

# -*- coding: utf-8 -*-
from Punto import Servicio, Punto
from multiprocessing import Pool
from time import time
from Datos import Fichero
from numpy import arange, pi     

file = Fichero()

result = [] #: Variable que almacena los resultados
def cb(punto): #optional: callback function
    result.append(punto)
   
ClaseServicio = Servicio()
def f(Azimut, Elevacion, range):
    Clase = Punto(ClaseServicio, Azimut, Elevacion, range)
    return Clase.integrate()
   
currtime = time()

angulos = arange(ClaseServicio.InitialAzimuth,ClaseServicio.InitialAzimuth\
				+ClaseServicio.NumRay*ClaseServicio.AzimtuhStep,ClaseServicio.AzimtuhStep)#: Lista con los ángulos de cada rayo en azimut
distancias = arange(ClaseServicio.InitialRange,ClaseServicio.InitialRange+\
				ClaseServicio.NumCell*ClaseServicio.RangeStep,ClaseServicio.RangeStep)#: Lista con las distancias de cada celda

# Comprobando si existe una corrida sin terminar
try:
    resultado_previo = file.openFile('elevacion.dat')
    ElevationAngles = ClaseServicio.ElevationAngles[ClaseServicio.ElevationAngles>resultado_previo]
    result = file.openFile('resultado.dat')
except:
    ElevationAngles = ClaseServicio.ElevationAngles
    
for elevacion in ElevationAngles:
    po = Pool()
    for azimut in angulos:
        for range in distancias:
            po.apply_async(f, (azimut,elevacion,range),{},cb)
    po.close()
    po.join()
    file.saveFile('resultado.dat',result)
    file.saveFile('elevacion.dat',elevacion)

print time()-currtime

 

Categorías:Doctorado, Investigación

Primera corrida del simulador

Hoy puse a andar la primera corrida del simulador del radar en su segunda versión. Esta vez está escrita en python y corre en paralelo, lo cual es bastante fácil puesto que es paralelización de datos. Tiene además corregido el problema de la cota de error, que ahora está limitada a 0,1dBZ.

Al ser orientada a objetos tiene muchas facilidades con respecto al manejo de la salida y la versatilidad de la función de reflectividades en el espacio.

Luego de unas pruebas para un solo ángulo de azimut parece bastante rápido. El resultado de esta corrida, si es satisfactoria, va a servir de objeto de estudio para el próximo artículo de la investigación.

Categorías:Doctorado, Investigación

Exposición en el Consejo Científico de la Facultad

El jueves 29 de septiembre de 2011 hice la primera presentación del la investigación del doctorado. Fue ante el consejo científico de la facultad.

Presentación en Diapositivas

Captura de la Presentación

Los principales señalamientos fueron:

  • La referencia de “On Optimal Radar Refelctivity Processing” de Torlaski y Zawadzki es muy vieja. (Ahora estoy siguiendo las trazas de las citas)
  • Hay que argumentar la necesidad de un dato primario de radar con mejor resolución.
  • Realizar presentaciones en la CUJAE y el ITM y traer dictamen por escrito.

Es en buen paso porque causó buena impresión pero hay que trabajar en las deficiencias y darle una ojeada al diseño metodológico de la investigación.

Hay que clasificar las novedades en teóricas y prácticas.

Categorías:Doctorado, Investigación