Diferencia entre revisiones de «PyBot»

De Proyecto Butiá
Saltar a: navegación, buscar
(Diseño)
m (Código)
Línea 1: Línea 1:
 
Butiá puede utilizarse de muchas formas, como un servicio consumible mediante la red como es el caso de pybot server o utilizando directamente la biblioteca usb4butia.
 
Butiá puede utilizarse de muchas formas, como un servicio consumible mediante la red como es el caso de pybot server o utilizando directamente la biblioteca usb4butia.
 +
 +
El código puede ser obtenido clonando el repositorio:
 +
 +
git clone git://git.code.sf.net/p/butia/code
 +
 +
''(Al día de hoy 10/11/13 la carpeta pesa 98MB es un poco pesada)''<br>
 +
El código se encuentra en "/lugar/de/clonado/turtlebots/pybot"
 +
  
 
==Diseño==
 
==Diseño==

Revisión del 15:59 10 nov 2013

Butiá puede utilizarse de muchas formas, como un servicio consumible mediante la red como es el caso de pybot server o utilizando directamente la biblioteca usb4butia.

El código puede ser obtenido clonando el repositorio:

git clone git://git.code.sf.net/p/butia/code

(Al día de hoy 10/11/13 la carpeta pesa 98MB es un poco pesada)
El código se encuentra en "/lugar/de/clonado/turtlebots/pybot"


Diseño

Pybot consta de distintos módulos que se encargan de una parte específca:

baseboard.py        funciones inerentes a la placa USB4Butia
com_usb.py          implementa la comunicación usb
device.py              abstracción de un dispositivo (botón, motores) conectado a la placa
drivers/
    hotplug/             drivers de módulos abiertos automáticamente por la placa
        button.py       driver del sensor botón
        light.py          driver del sensor de luz
        -----
    motores.py      driver del módulo de motores
    butia.py        driver del módulo butiá
    -----
functions.py        funciones comunes entre el cliente y la usb4butia
pybot_client.py     aplicación cliente
pybot_server.py     aplicación servidor
usb/                librería PyUsb
usb4butia.py        módulo principal (core) que implementa las funciones

Usando Pybot localmente

Cuando se va a ejecutar Pybot y quién lo usa en la misma máquina, no es recomendable tener una arquitectura cliente-servidor. Para ese caso se dispone de una alternativa: usar directamente el módulo usb4butia dentro de Pybot.

Si no estamos en la carpeta donde está la librería PyBot podemos usar este truco para poder importar Pybot sin problemas desde cualquier lado:

   import sys
   sys.path.insert(0, '/home/olpc/Activities/TurtleBots.activity/plugins/butia')

Esa es la ruta por defecto cuando el .XO se instala en Sugar, puede variar en otras computadoras. El paquete .deb instala TurtleBots en '/usr/share/sugar/activities' por lo que la ruta debe ser:

   sys.path.insert(0, '/usr/share/sugar/activities/TurtleBots.activity/plugins/butia')

Importando el módulo:

   from pybot import usb4butia

Instanciando la clase:

   robot = usb4butia.USB4Butia()

A partir de este momento tenemos las mismas llamadas que en pybot_client. Por ejemplo, para obtener la versión del Firmware:

   version = robot.getFirmwareVersion()

El módulo USB4Butia nos provee algunas propiedades "privadas" que pueden resultar útiles:

  robot._bb                               # Lista de placas detectadas
  robot._drivers_loaded                   # Diccionario de drivers
  robot._debug                            # Bandera de debug, por defecto es False
  robot._get_all_drivers()                # Función para cargar los drivers
  robot._get_driver()                     # Función para obtener un driver específico
  robot._hotplug                          # Lista de módulos hotplug
  robot._modules                          # Lista de módulos
  robot._openables                        # Lista de módoulos "openables"

Usando Pybot server

Levantamos el servidor desde una consola (debemos estar dentro de la carpeta pybot):

   python pybot_server.py DEBUG

En este caso con la bandera de DEBUG para ver la salida del lado del servidor.

Luego nos encargamos del cliente:

   from pybot impoty pybot_client

Instanciamos el cliente:

   robot = pybot_client.robot()

A partir de ahora tenemos las mismas funciones que en la versión local, por ejemplo:

   version = robot.getFirmwareVersion()

Funciones USB4Butiá - Pybot Client

Funciones útiles:

  robot.close()                            # cierra todas las placas instanciadas
  robot.find_butias()                      # busca placas conectadas y las instancia
  robot.getBatteryCharge()                 # devuelve el nivel de carga de la batería (si no hay motores-> -1)
  robot.getFirmwareVersion()               # devuelve la versión del firmware dentro del PIC
  robot.getVersion()                       # devuelve la versión del módulo butiá (arduino: 20, usb4butia:22)
  robot.getButiaCount()                    # devuelve la cantidad de placas conectadas
  robot.getModulesList()                   # devuelve la lista de dispositivos conectados (en todas las placas)
  robot.isPresent(device)                  # chequea si un dispositivo en particular está conectado
  robot.loopBack(data)                     # envía una string 'data' a la placa y devuelve lo mismo
  robot.reconnect()                        # no hace nada en usb4butia / en el cliente hace un reconnect del socket
  robot.refresh()                          # actualiza la lista de placas conectadas
  robot.callModule(modulename, board_number, number, function, params)  #llamada a un módulo

Sensores

  robot.getButton(port)                    # obtiene el valor del sensor botón conectado en el puerto port
  robot.getDistance(port)                  # obtiene el valor del sensor de distancia conectado en el puerto port
  robot.getGray(port)                      # obtiene el valor del sensor de grises conectado en el puerto port
  robot.getLight(port)                     # obtiene el valor del sensor de luz conectado en el puerto port
  robot.getResistance(port)                # obtiene el valor del sensor de resistencia conectado en el puerto port
  robot.getTemperature(port)               # obtiene el valor del sensor temperatura conectado en el puerto port
  robot.getVoltage(port)                   # obtiene el valor del sensor volyaje conectado en el puerto port
  robot.setLed(port, on)                   # si on es 1, prende el LED, si es 0, apaga el LED conectado en el puerto port

Hack pins

  robot.modeHack(pin, mode)                # establece el modo del pin: si mode es 0 es entrada y 1 salida
  robot.setHack(pin, value)                # establece el valor del pin: pin en GND si es 0 y en +5v si es 1
  robot.getHack(pin)                       # lee el valor del pin: pin

Motores

  robot.set2MotorSpeed(leftSense, leftSpeed, rightSense, rightSpeed)   #sense is 0 or 1, speed is between 0 and 1023
  robot.setMotorSpeed(idMotor, sense, speed)                           #idMotor 0 for left motor, 1 for right

Drivers en PyBot

Los drivers de PyBot son escritos en python. Dentro de la carpeta /drivers se encuentran todos aquellos que no son PNP (plug and play). Los módulos que son abiertos automáticamente por la placa, por ejemplo cuando uno conecta un sensor de grises, van dentro de /drivers/hotplug.
Cada función en el driver se define como una función Python utilizando el "def" y recibe como primer parámetro el dispositivo ("dev") con el cual se va a comunicar.
Este es el ejemplo del driver del sensor de grises, el cuál tiene dos funciones: getVersion y getValue

Captura del código del driver de grises

Esta es una captura parcial del código del driver de los hack points (hackp):

Captura parcial del código del driver de hackp

Como se puede observar, la función "setMode" recibe como primer argumento el "dev" y luego el resto de los parámetros: el número de "pin" y el "value" que es el modo. Se guarda en "msg" la lista con el "código de operación" SET_MODE y se le agregan los otros parámetros.

   msg = [SET_MODE, pin, value]

Esto se le envía al módulo con la función "send":

   dev.send(msg)

Luego se leen 2 bytes: el primero, como en todas las funciones es el mismo "código de operación" que fue enviado y el segundo es en este caso, el código de error (si es -1, hubo un error).

   raw = dev.read(2)

Y solo se retorna el segundo byte que es el el importante:

   return raw[1]