un Sistema TPV
controlado con
“Leap Motion”
Al segundo, por facilitarme desinteresadamente una licencia sin coste para poder
desarrollar con su software durante todo el período de creación de la propuesta.
- A Rubén, por transmitirme conocimientos acerca de una versión de GeneXus con la que
yo no estaba familiarizada, y también su ayuda desinteresada con cualquier cuestión que
podía surgir.
A todos los que de alguna forma se han implicado desinteresadamente en esto, ¡gracias!
Universidad de Alicante – Escuela Politécnica Superior 0
ÍNDICE DE CONTENIDOS
1. INTRODUCCIÓN ................................................................................................... 8
1.1. ¿Qué es un Sistema TPV? ............................................................................. 8
1.1.1. Componentes de un sistema TPV ........................................................... 9
1.2. Nacimiento de la propuesta de TFG ............................................................... 9
1.3. Ideas generales y objetivos del proyecto ...................................................... 10
1.4. Fases del desarrollo del proyecto ................................................................. 10
2. METODOLOGÍA Y TECNOLOGÍAS UTILIZADAS ............................................... 11
2.1. ‘Leap Motion’: el sensor de control gestual ................................................... 11
2.1.1. Partes físicas del dispositivo (hardware) ................................................ 12
2.1.2. Funcionamiento del controlador ............................................................. 15
2.1.3. Resumen de la API del sensor (v3.2.1_win) .......................................... 18
2.1.3.1 Objeto Hand (mano) .......................................................................... 20
2.1.3.2 Objeto Arm (brazo) ............................................................................ 22
2.1.3.3 Objeto Finger (dedo) .......................................................................... 23
2.1.3.4 Objeto Frame ..................................................................................... 25
2.1.3.5 Interfaz de comunicación entre la aplicación y el dispositivo .............. 27
2.1.3.6. Los gestos que interpreta Leap Motion .............................................. 28
2.1.4. Arquitectura del sistema ........................................................................ 29
2.1.4.1 Interfaz nativa .................................................................................... 29
2.1.4.2 Interfaz web (WebSocket) .................................................................. 30
2.2. Lenguajes de programación y herramientas ................................................. 32
2.2.1. GeneXus: el generador de código ......................................................... 32
2.2.1.1 ¿Qué es y para qué sirve GeneXus? ................................................. 32
2.2.1.2 ¿Por qué GeneXus? .......................................................................... 34
2.2.1.3 La base de conocimiento de una aplicación en GeneXus (Knowledge
Base - KB)........................................................................................................ 35
2.2.1.4 Objeto Transacción en GeneXus ....................................................... 36
2.2.1.5 Generando una aplicación con GeneXus ........................................... 38
2.2.2. Microsoft SQL Server (servidor BBDD) .................................................. 41
2.3. Conexión entre GeneXus y un sistema DAQ ................................................ 43
2.3.1. Importación de los objetos de la API de Leap Motion desde GeneXus .. 43
3. EL SISTEMA TPV................................................................................................ 48
3.1. Prototipo de la aplicación original (v.0.1.) ..................................................... 48
3.1.1. El Developer Menu de GX ..................................................................... 48
3.1.2. Inicio ...................................................................................................... 49
3.1.3. Interfaz de usuario: clientes ................................................................... 51
ÍNDICE DE FIGURAS
Figura 30. Opción habilitar / inhabilitar a las aplicaciones el acceso al servidor WebSocket.
................................................................................................................................................ 31
Figura 31. Logo GeneXus X Evolution 2. ............................................................................. 32
Figura 32. Definiendo GeneXus 1. ........................................................................................ 33
Figura 33. Lenguajes de programación soportados en función de la plataforma destino. ..... 33
Figura 34. Lenguajes de programación y clientes de BBDD soportados en función de la
plataforma destino. ................................................................................................................. 33
Figura 35. Ejemplo real de definición de transacción GeneXus. Transacción Pedido de
nuestra app TPV. .................................................................................................................... 37
Figura 36. Ejemplo real de definición de transacción GeneXus. Transacción Mesas de
nuestra app TPV. .................................................................................................................... 37
Figura 37. Ejemplo real de Web Form dentro de la definición de una transacción GeneXus.
................................................................................................................................................ 37
Figura 38. Generando una aplicación con GeneXus. ............................................................. 38
Figura 39. Especificación de los objetos GeneXus. ............................................................... 38
Figura 40. Generación de los objetos GeneXus a clases en el lenguaje para el que generemos
la app. ..................................................................................................................................... 39
Figura 41. Compilación de las clases generadas por GeneXus. ............................................. 39
Figura 42. Ejecutando la aplicación 1 ►. .............................................................................. 39
Figura 43. Ejecutando la aplicación 2 ►. .............................................................................. 40
Figura 44. Ejecutando la aplicación 3 ►. Web Form creado para la transacción Pedido. .... 40
Figura 45. Propiedades de conexión de la base de datos utilizada por la app. ....................... 41
Figura 46. Configuración de la base de datos en GeneXus. ................................................... 42
Figura 47. Objetos Externos importados a la KB................................................................... 44
Figura 48. Importación de una DLL utilizando Objetos Externos 1. ..................................... 44
Figura 49. Importación de una DLL utilizando Objetos Externos 2. ..................................... 45
Figura 50. Importación de una DLL utilizando Objetos Externos 3. ..................................... 45
Figura 51. Importación de una DLL utilizando Objetos Externos 4. ..................................... 46
Figura 52. Importación de una DLL utilizando Objetos Externos 5. ..................................... 46
Figura 53. Importación de una DLL utilizando Objetos Externos 6. ..................................... 47
Figura 54. Objeto Externo creado a partir de la importación del método Finger desde la API
Leap Motion. .......................................................................................................................... 47
Figura 55. Menú raíz de la aplicación que conforma el sistema TPV.................................... 48
Figura 56. Menú raíz de la aplicación que conforma el sistema TPV (2). ............................. 49
Figura 57. Estructura de la transacción Empresa en GX........................................................ 49
Figura 58. Tabla generada por GX a partir de la transacción Empresa.................................. 50
Figura 59. Tabla impactada por GX en BBDD a partir de la tabla generada a partir de la
transacción Empresa. ............................................................................................................. 50
Figura 60. Flujo de acciones GX desde que se crea un objeto tipo transacción hasta que lo
vemos reflejado en BBDD. .................................................................................................... 50
Figura 61. Interfaz del Menú principal para un perfil de cliente............................................ 51
Figura 62. Interfaz del MENÚ. .............................................................................................. 52
Figura 63. Tabla paramétrica para los tipos de menús en BBDD. ......................................... 52
Figura 64. Interfaz con los productos del Menú del día. ........................................................ 53
Figura 65. Contenido de la tabla MenuItem con MenuId = 31 (menú del día). ..................... 53
Figura 66. Contenido de la tabla CategoriasMenu. ................................................................ 54
Figura 67. Pop-up COMPLEMENTOS del menú. ................................................................ 54
Figura 68. Tabla que contiene la parametría de los productos clasificados como
COMPLEMENTOS. .............................................................................................................. 55
Figura 69. Pop-up MODOS del menú.................................................................................... 55
Figura 70. Tabla que contiene la parametría de los productos clasificados como MODOS. . 56
Figura 71. PEDIDO con ítems añadidos. ............................................................................... 56
Figura 72. Categorías tradicionales que componen una carta. ............................................... 57
Figura 73. PEDIDO con ítems añadidos desde la carta. ........................................................ 57
Figura 74. Interfaz del Menú principal para un perfil de empleado. ...................................... 58
Figura 75. Interfaz del modo ADMINISTRAR para perfiles de empleado. .......................... 58
Figura 76. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña
PEDIDOS. .............................................................................................................................. 59
Figura 77. Tabla “Pedido” en BBDD. .................................................................................... 60
Figura 78. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña
PEDIDOS, botón Mantenimiento. ......................................................................................... 61
Figura 79. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña
PEDIDOS, filtro Estado. ........................................................................................................ 61
Figura 80. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña
PEDIDOS, filtro Fecha. ......................................................................................................... 61
Figura 81. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña ITEMS. 62
Figura 82. Tabla “Item” en BBDD. ....................................................................................... 62
Figura 83. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña
CATEGORIAS, Carta. ........................................................................................................... 63
Figura 84. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña
CATEGORIAS, Menu. .......................................................................................................... 63
Figura 85. Panel de Control de Leap Motion → Resolución de problemas → Device Status 64
Figura 86. Ejecutando por primera vez… (1) ........................................................................ 65
ÍNDICE DE TABLAS
1. INTRODUCCIÓN
Este proyecto pretende acercar parte de estas nuevas funcionalidades ya existentes al sector
y complementarlas con un enfoque distinto, el cual se centra principalmente en una zona
concreta de los locales de restauración: la cocina.
Este nuevo enfoque consiste en controlar las pantallas táctiles que se utilizan para actualizar
los estados de las comandas (las cuales ya existen en la mayoría de estos espacios -cocinas-), de
una forma totalmente innovadora: únicamente con control gestual.
La utilidad de la propuesta es evidente si suponemos que las personas que trabajan dentro de
estos espacios tienen ocupadas sus manos durante la mayor parte del tiempo, como para hacer uso
de una pantalla táctil constantemente. Leap Motion es un controlador de movimiento capaz de
evitar que perdamos tiempo cada vez que necesitemos actualizar la comanda, incrementando así
también la productividad, y de ese modo eludir además ensuciar la pantalla táctil del sistema TPV
tradicional, ya que con este dispositivo seríamos capaces de controlar el sistema solamente
con gestos y sin entrar en contacto físico con dicha pantalla.
A nivel comercial, un sistema informático de este tipo es el que nos permite gestionar todo el
proceso de venta (tickets, facturas, ventas, cobros, generar informes, etc,…).
Un TPV eficaz sirve para acelerar y organizar las tareas ligadas a cualquiera de estos procesos
de venta, de forma que las operaciones comerciales se pueden hacer de forma mucho más fácil
que con las ya antiguas cajas registradoras.
Los numerosos tipos de TPV (dependen de hacia qué sector comercial esté enfocado su uso)
que nos podemos encontrar hacen que tengamos una serie de requisitos técnicos o componentes
que debemos tener en cuenta cuando creamos o instalamos un sistema de este tipo, y no baste
solamente con descargarnos un programa para utilizarlo correctamente.
Llegados a este punto, por lo tanto, en un sistema TPV deberemos diferenciar entre:
- Software instalado.
- Componentes Hardware, necesarias para un buen servicio al cliente.
La idea de realizar este tipo de proyecto nace de la mezcla de 2 situaciones, las cuales vamos
a describir a continuación.
- Y en segundo lugar, por la demanda que me venía haciendo desde hacía tiempo un buen
amigo cocinero. Su propuesta era poner en marcha el sistema TPV entero para su local,
con lo que dándole vueltas después, se me ocurrió hacerlo y además aprovechando e
introduciendo la tecnología que iba a usar en mi TFG.
La idea y propósito general de este trabajo de fin de grado es prototipar una aplicación capaz
de conseguir una comunicación desde cocina con el exterior solamente realizando gestos,
haciendo uso de un sensor captador de movimientos de manos, dedos y objetos que
posteriormente describiremos.
La realidad es que los cocineros cuotidianamente tienen las manos ocupadas y embrutecidas,
así que de esta forma les sería mucho más cómodo poder actualizar el estado de los pedidos y
comandas de forma rápida. Con esto conseguiremos ser más productivos en la cocina, y, además,
contribuiremos a cuidar el estado de los aparatos que intervienen en un sistema TPV convencional
(p. ej más limpios), donde generalmente, se interactúa a través de una pantalla o incluso pantalla
+ algún otro tipo de hardware (ratones, teclados, …).
El proyecto se ha desarrollado durante varios meses, los cuales han estado organizados por un
plan de trabajo que se dividió en 9 fases:
- Fase 1: Definición de los requerimientos mínimos del prototipo del sistema TPV.
- Fase 2: Documentación sobre el dispositivo Leap Motion. Consistió en obtener
información sobre el modo de funcionamiento del dispositivo que íbamos a usar, así como
de su API asociada, la cual nos facilitaba el fabricante.
- Fase 3: Implementación y codificación del prototipo web del TPV con GeneXus. En esta
etapa se crea también el servidor de base de datos (localhost) con el que trabajará la
aplicación
- Fase 4: Generación de la aplicación en C# web con GeneXus.
- Fase 5: Pruebas del sistema TPV.
- Fase 6: Instalación de los productos Leap Motion y prueba de su entorno de desarrollo a
partir de ejemplos básicos ‘Hola Mundo’ que encontramos en la web oficial del
dispositivo. En nuestro caso, en C#.
- Fase 7: Definición y desarrollo de los casos de prueba definidos sobre los desarrollos
realizados para el dispositivo Leap Motion.
- Fase 8: Análisis funcional para la integración del dispositivo Leap Motion con la
aplicación TPV web desarrollada.
- Fase 9: Generación de la documentación. Se incluye la presente memoria, resúmenes en
castellano e inglés, póster y presentación utilizada en la defensa frente al tribunal.
Una vez introducido el contexto funcional del proyecto, así como su hipotética finalidad y
objetivos, vamos a detallar a continuación la metodología y tecnologías de las que se va a hacer
uso durante todo el proceso de elaboración de nuestra aplicación.
Como se puede observar en la Figura 2, Leap cuenta con un sensor del tamaño de un pendrive,
el cual se enchufa en el puerto USB y detecta el movimiento de nuestras manos sobre él,
interpretando los gestos que vayamos haciendo como acciones en nuestra máquina.
Figura 3. Escenificación del funcionamiento del sensor ‘Leap Motion’. (Fuente: www.realidad-virtual.net)
En esta primera parte del estudio de Leap, vamos a analizar los componentes principales que
forman el hardware y, próximamente, veremos también el principio de funcionamiento y un
resumen de la API del controlador.
Figura 4. Interior del dispositivo – Esquema distribución cámaras, LEDs. (Fuente: ncbi.nlm.nih.gov)
Cada una de estas cámaras cuenta con un sensor monocromático sensible a la luz infrarroja,
con una longitud de onda de 850 nm. Estos sensores pueden trabajar a una velocidad de hasta 200
fps, dependiendo del rendimiento del ordenador/tablet al que conectemos el dispositivo.
Además, cada sensor es de tipo CMOS. Algunas de las características principales que hacen
que este tipo de sensor sea el utilizado y no los CCD, son, por ejemplo:
• La digitalización de los píxeles en un sensor CMOS se produce dentro de cada celda, por
lo que no es necesario un chip externo (como ocurriría en el caso de utilizar sensores
CCD). Esto se traduce en mayor velocidad para capturar imágenes y en menor espacio
para albergar los sensores.
• Estos sensores son más económicos que los sensores CCD.
• En este tipo de sensor no se produce el fenómeno blooming, al contrario que en los
sensores CCD. Este fenómeno se produce cuando una celda se satura de luz y hace que
las celdas de alrededor también se saturen.
• La lectura simultánea de celdas en los CMOS es mayor que en los CCD.
• El consumo eléctrico de los CMOS es menor que el de los CCD.
Por lo general, los únicos objetos que verá Leap son los directamente iluminados por los
LED. Sin embargo, las bombillas incandescentes, los halógenos y la luz del día también podrán
iluminar la escena en infrarrojo. Los LED trabajan en el espectro de luz infrarroja a una longitud
de onda de 850 nm que, como es lógico, es la misma a la que son sensibles los sensores ópticos
de las cámaras.
▪ MICROCONTROLADOR CPU
Se trata de un circuito integrado que se suele utilizar para hacer la función de BIOS (MXIC
MX25L3206E–32M-bit CMOS SERIAL FLASH).
Figura 5. Placa base del dispositivo Leap Motion 1. Microcontrolador. (Fuente: image-sensors-world.blogspot.com)
En este caso, el integrado contiene el programa que controla todo el dispositivo Leap (para,
entre otras cosas, regular la iluminación) y se encarga de recoger la información de los sensores
para luego enviarla al driver instalado en el ordenador.
▪ CONTROLADOR USB
Leap Motion cuenta con un controlador USB para que el ordenador pueda reconocer el
dispositivo. Este controlador es de alta velocidad, y puede soportar USB 3.0.
Figura 7. Placa base del dispositivo Leap Motion 2. Controlador USB. (Fuente: learn.sparkfun.com)
Figura 8. Placa base del dispositivo Leap Motion 3. Puertos de E/S datos.
(Fuente: image-sensors-world.blogspot.com)
Como ya hemos visto en el apartado 2.1.1., Leap ilumina la zona de cobertura mediante una
luz infrarroja emitida a través de sus tres LEDs, con una longitud de onda de 850 nm. Esta zona
de cobertura está limitada por el ángulo de visión de los sensores (lo veremos en el apartado
2.1.3.) y por la corriente máxima que puede entregar la conexión USB.
Cuando un objeto es iluminado, se produce una reflexión de luz que llega al dispositivo e
incide sobre las lentes de las dos cámaras. Estas lentes, de tipo biconvexas, concentran los rayos
en el sensor de cada cámara y los datos recogidos por los sensores se almacenan en una matriz
(imagen digitalizada) en la memoria del controlador USB, en donde se realizan los ajustes de
resolución adecuados mediante el microcontrolador del dispositivo.
Una vez ajustada la resolución, los datos de los sensores se envían directamente
al driver instalado en el ordenador. Estos datos representan un valor de intensidad luminosa por
cada píxel de la imagen capturada, y se guardan en un buffer. El valor de intensidad luminosa se
cuantifica a 8 bits para generar una imagen RAW en escala de grises (por lo tanto, hay un total de
256 posibles valores de luminosidad).
Cada imagen tiene un tamaño de 640 x 120 px, con lo que en total hay 76.800 píxeles por
imagen. Como las imágenes no son tratadas en el propio dispositivo, si no que solamente se
recogen y se envían, el tamaño de estas no afectará a su rendimiento. Por eso Leap sigue siendo
igual rápido.
Una vez que las imágenes de las dos cámaras llegan al driver, son analizadas para identificar
las manos y los dedos a partir de un modelo matemático de caracterización anatómico; así como
también obtiene la profundidad del objeto mediante otro algoritmo.
Para realizar dichos cálculos correctamente hay que tener en cuenta que las lentes del
dispositivo producen una distorsión en la imagen óptica, deformando el objeto capturado. En este
caso, Leap produce lo que conocemos como distorsión compleja (o de mostacho).
Por lo tanto, cada buffer de datos de imagen que se envía al driver va acompañado de
otro buffer que contiene los datos de distorsión.
Para mejorar esta distorsión, el sensor tiene una opción de calibrado mediante la cual se
obtiene un mapa de mallado de puntos de calibrado que se superpone a la imagen captada por
cada sensor.
Figura 10. Imagen recogida por el sensor con el mapa de mallado de puntos superpuesto.
(Fuente: developer-archive.leapmotion.com)
Encontramos una rejilla de 64 x 64 puntos con dos valores de 32 bits cada uno. Cada uno de
estos puntos representa un rayo proyectado en la cámara. El valor de un punto del mallado define
la luminosidad de un píxel en la imagen, y se pueden obtener los datos de luminosidad de todos
los píxeles mediante interpolación.
Una vez que han llegado las imágenes, las hemos corregido debidamente y el driver ha
identificado las manos y los dedos, podemos determinar la posición de estas en el sistema de
coordenadas cartesianas de Leap a través de técnicas de visión estereoscópica. Básicamente, un
sistema estereoscópico funciona del siguiente modo: gracias a la separación de las dos cámaras
en el eje X se obtienen dos imágenes con pequeñas diferencias.
Figura 11. Imágenes Ii e Id (dispares) cuya fuente son dos cámaras separadas en el eje X.
Como se puede observar en la imagen anterior, las dos cámaras (representadas por Oi y Od)
están en el mismo plano Z, sobre la línea base. Si trazamos una línea epipolar entre las dos
imágenes Ii e Id, dado que Oi y Od están en el mismo plano Z y las dos cámaras tienen la misma
distancia focal, podemos ver la proyección del punto P en las dos imágenes.
Por lo tanto, se puede obtener un valor de disparidad d para cada par de puntos emparejados
Pi(xi,yi) y Pd(xd,yd) dado por d = XI-XD.
Figura 12. Diagrama representando los parámetros que intervienen en el cálculo de la disparidad entre imágenes.
Considerando igual la distancia focal f en las dos cámaras y conociendo la distancia entre
cámaras b:
𝑏
+ 𝑋 𝑥𝑖 𝑓 𝑏 𝑓·𝑏
𝑂𝑖 : 2 = 𝑥𝑖 = (𝑋 + ) 𝑑 = 𝑥𝑖 − 𝑥𝐷 =
𝑍 𝑓 𝑍 2 𝑍
𝑏
− 𝑋 𝑥𝐷 𝑓 𝑏 𝑓·𝑏
𝑂𝐷 : − 2 = 𝑥𝐷 = (𝑋 − ) 𝑍=
𝑍 𝑓 𝑍 2 𝑑
Ecuación 1.
Como vemos, a partir del sistema estereoscópico podemos obtener las coordenadas del
punto P.
En resumen, los pasos básicos que realiza Leap para devolvernos la información de los objetos
que captura es la siguiente:
1. Obtiene las imágenes desde los sensores de las cámaras del dispositivo.
2. Aplica una corrección de la distorsión que producen los sensores.
3. Aplica un modelo para determinar la configuración de cada mano y ejecuta un algoritmo
de visión estereoscópica entre cada par de imágenes para obtener la posición en el plano
tridimensional.
Como ya hemos comentado en los apartados anteriores, este dispositivo es capaz de reconocer
y rastrear manos, dedos y objetos. Está basado en un sistema de coordenadas cartesianas (diestro),
y funciona con muy alta precisión gracias a sus sensores ópticos y de luz infrarroja. Estos sensores
se dirigen a lo largo del eje Y (hacia arriba, cuando el controlador se encuentra en su posición de
funcionamiento estándar); y tienen un campo de visión de aproximadamente 150º de izquierda a
derecha y 120º desde atrás hacia adelante.
El software combina sus datos físicos obtenidos de los sensores con un modelo interno de la
mano humana para ayudarlo a sobrellevar las difíciles condiciones de rastreo posibles.
Figura 13. Puntos del esqueleto del modelo interno de la mano definida por el controlador Leap Motion,
funcionamiento del cual está basado en el sistema de coordenadas cartesianas. (Fuente: www.mdpi.com)
A—Dedo pulgar, B—Índice, C—Medio, D—Anular, E—Meñique, F—Posición punta, G—Posición de la palma, H—
Posición de la muñeca, I—Brazo, J—Falange distal, K—Falange medial, L—Falange proximal, M—Hueso
metacarpiano. Las marcas J, K, L, M correspondientes a las falanges se encuentran en los 5 dedos del modelo.
El origen del sistema de coordenadas está centrado en la parte superior del controlador. Los
ejes X y Z se encuentran en el plano horizontal, con el eje X paralelo al borde largo del
dispositivo.
El eje Y es vertical, con valores positivos que aumentan hacia arriba (al contrario que la
mayoría de los sistemas de coordenadas gráficas virtuales, cuya orientación positiva suele ser
hacia abajo).
La API de ‘Leap Motion’ mide magnitudes físicas con las siguientes unidades,
Figura 14. Lenguajes permitidos por la API para hacer uso de Leap
Como Leap rastrea las manos, los dedos y los objetos dentro de su campo de visión,
proporciona actualizaciones como un conjunto de datos representado en un tipo de objeto Frame.
Figura 15. Contexto de los objetos que contiene la API (Fuente: blog.leapmotion.com).
A continuación veremos qué datos obtiene Leap de cada tipo de los principales objetos para
representarnos y devolvernos la información de cada uno de ellos.
El modelo de mano está representado por la clase Hand, y proporciona información sobre la
identidad, posición, velocidad de la palma y otras características de una mano detectada.
(Fuente: developer-archive.leapmotion.com)
Además, Hand también recoge datos del brazo (objeto Arm) al que está sujeta la mano y de
los dedos (objeto Finger) asociados a dicha mano.
Parámetros:
id ID de la mano.
pinchDistance Distancia (mm) entre las puntas de los dedos índice y pulgar al pellizcar.
Como ya hemos comentado en el apartado 2.1.3., el software usa un modelo interno de una
mano humana (Figura 13) para proporcionar un seguimiento predictivo, incluso cuando partes de
una mano no son visibles. El modelo siempre proporciona posiciones para cinco dedos, aunque
el seguimiento es óptimo cuando la silueta de una mano y todos sus dedos son claramente
visibles. El software usa las partes visibles de la mano, su modelo interno y observaciones pasadas
para calcular las posiciones más probables de las partes que no están dentro del campo de visión
del sensor en un momento dado.
El software permite que puedan aparecer más de dos manos en la lista de manos para un frame.
Sin embargo, se recomienda mantener como máximo dos manos en el campo de visión del
sensor para obtener una calidad de seguimiento de movimiento óptima.
Parámetros:
Leap proporciona información sobre cada dedo de una mano. Si la totalidad o parte de un dedo
no es visible, como pasaba con los tipos de objeto anteriores, las características del dedo se
estiman en base a las observaciones recientes y el modelo anatómico de la mano definido. Los
dedos se identifican por el nombre del dedo real, es decir: pulgar, índice, centro (corazón), anular
y meñique.
Figura 20. Vectores que proporcionan información sobre la posición y dirección de un dedo.
(Fuente: developer-archive.leapmotion.com)
En general, no se debería crear objetos Finger propiamente dichos, ya que estos no tendrán
datos de seguimiento válidos. La información se debe obtener desde un objeto Hand (mano)
contenido en un frame.
Parámetros:
isExtended Nivel de extensión del dedo (si está más o menos recto).
metacarpal Primer hueso del dedo (teniendo la muñeca como referencia, ver
Figura 4).
A nivel anatómico, un pulgar real tiene un hueso menos que los otros dedos. Sin embargo,
para facilitar la programación, el modelo de pulgar del controlador incluye un hueso metacarpiano
de longitud cero para que el pulgar tenga el mismo número de huesos en los mismos índices que
los otros dedos.
(Fuente: commons.wikimedia.org).
En definitiva, el objeto Finger nos devolverá por cada dedo definido dentro de un objeto Hand
(mano) información sobre los siguientes parámetros:
El objeto Frame es el cuadro que contiene cualquier mano rastreada, y esencialmente la raíz
del modelo de datos del dispositivo. Representa un conjunto de datos de seguimiento de manos y
dedos detectados, detallando sus propiedades en un instante temporal.
A continuación, podemos ver un diagrama de la relación entre el objeto Frame y otros objetos
a los que se puede acceder a través de él:
Figura 22. Diagrama que representa la relación con otros objetos del objeto ‘Frame’.
Como podemos ver en la Figura 22, Frame nos da la posibilidad de acceder a todas las
clases List, a partir de las cuales se puede acceder a una lista de objetos del mismo tipo y que
aparecen en cada Frame.
id ID del frame.
La clase InteractionBox representa una región en forma de caja, completamente dentro del
campo de visión del controlador. Dicha región está definida por un centro y dimensiones a lo
largo de los ejes x, y, z.
Usar un modo u otro dependerá de si queremos analizar o no todos los frames que lleguen
desde Controller. Si queremos analizarlos todos, accederemos a la información del objeto Frame
a través de Listener; pero, si por el contrario, queremos analizar un objeto Frame solamente cada
cierto tiempo, accederíamos desde el objeto Controller.
La clase Listener define un conjunto de funciones para responder a eventos enviados por
el objeto Controller.
No es necesario que se implementen respuestas a las llamadas desde Controller para eventos
que no nos interesan.
Otro método interesante es el onFrame(), evento que se produce cada vez que el dispositivo
captura una imagen. Este es el evento principal, ya que dentro de este se pueden implementar
todas las acciones que queremos hacer sobre los objetos ya vistos anteriormente (manos, dedos,
brazos, etc.).
Llegados a este punto, toca explicar qué tipo de gestos son con los que realmente trabaja e
interpreta Leap a través de los sensores, cálculos, objetos, etc,… anteriormente descritos.
Figura 26. Tipos de gesto interpretados por Leap Motion. (Fuente: github.com)
El reconocimiento por parte de Leap de este tipo de gesto necesita de la información del
método vector de dirección paralelo al movimiento de deslizamiento, direction(). Es posible
comparar los componentes del vector para clasificar el deslizamiento según corresponda para
una cierta aplicación. Por ejemplo, si se está usando deslizamientos para desplazamiento
bidimensional, se puede comparar los valores de los ejes x e y para determinar si el
deslizamiento es principalmente horizontal o vertical.
En Windows, el software de Leap Motion se ejecuta como un servicio más. Para otros
sistemas operativos (Linux y Macintosh), como daemon.
El SDK proporciona dos variedades de API para obtener datos de seguimiento del servicio
de Leap: una interfaz nativa y una interfaz WebSocket (web).
La interfaz nativa es una biblioteca dinámica que se puede usar para crear aplicaciones
nuevas habilitadas para Leap. Esta biblioteca se conecta al servicio Leap Motion y proporciona
datos de seguimiento a su aplicación.
Figura 27. Aplicaciones habilitadas con Leap a través de la interfaz nativa del dispositivo.
(Fuente: developer-archive.leapmotion.com)
1. El servicio Leap Motion recibe datos del dispositivo controlador a través del bus
USB. Procesa esa información y la envía a ejecutar aplicaciones habilitadas para
Leap. De forma predeterminada, el servicio sólo envía datos de seguimiento a la
aplicación en primer plano. Sin embargo, las aplicaciones pueden solicitar que reciban
datos en segundo plano (esta solicitud puede ser denegada por el usuario si así lo
requiere).
2. La aplicación Panel de Control de Leap Motion se ejecuta por separado del servicio, y
permite al usuario configurar su instalación. Dicha aplicación es un applet del Panel de
Control en Windows, y una aplicación en la barra de menús en Macintosh y Linux.
La interfaz WebSocket permite crear aplicaciones web habilitadas para Leap. El servicio
ejecuta un servidor WebSocket en el dominio localhost, puerto 6437. Esta interfaz proporciona
datos de seguimiento en forma de mensajes JSON (notación de Objetos de JavaScript), un formato
Está disponible una biblioteca de cliente JavaScript leap.js que consume los mensajes JSON
y presenta los datos de seguimiento como objetos regulares de JavaScript.
Figura 29. Aplicaciones web habilitadas para Leap a través de la interfaz WebSocket.
(Fuente: developer-archive.leapmotion.com)
Figura 30. Opción habilitar / inhabilitar a las aplicaciones el acceso al servidor WebSocket.
Esta interfaz está destinada principalmente para aplicaciones web, pero cualquier aplicación
que pueda establecer una conexión WebSocket puede usarla. El servidor cumple con el protocolo
estándar RFC6455 contenido en The WebSocket Protocol.
Llegados a este punto, como se puede intuir, una herramienta muy importante de desarrollo
que va a ser utilizada en este proyecto es la API que nos proporciona el fabricante de Leap Motion
y todo lo que esta contiene. Además, para codificar la aplicación TPV usaremos el lenguaje de
programación C# con ayuda de un generador de código llamado GeneXus, del cual explicaremos
su funcionamiento y características en el apartado 2.2.1.
El objetivo de GeneXus es lograr que las aplicaciones estén funcionando en el menor tiempo
y con la mejor calidad posible.
aquellas tareas realmente difíciles y no automatizables, como comprender las necesidades y los
problemas de los usuarios.
Los lenguajes para los cuales se puede generar código incluyen C#, COBOL, Java (incluso
para Android y BlackBerry), Swift para iOS, Objective-C, RPG, Ruby, Visual Basic, etc,...
Figura 33. Lenguajes de programación soportados en función de la plataforma destino. (Fuente: genexus.com)
Los sistemas gestores de bases de datos más populares están soportados, como SQL
Server, Oracle, DB2, Informix, PostgreSQL y MySQL.
Figura 34. Lenguajes de programación y clientes de BBDD soportados en función de la plataforma destino.
(Fuente: genexus.com)
Cuando nos solicitan desarrollar una aplicación informática, el cliente nos plantea el
problema que quiere resolver de acuerdo a su visión particular. Lo primero que debemos hacer es
interpretar la realidad que nuestro cliente nos describe, construir un modelo y luego diseñar una
solución que represente lo mejor posible esa realidad. También es importante que el producto
desarrollado sea capaz de adaptarse a los cambios que sufre esa realidad, y que esos cambios los
podamos realizar en un tiempo razonable.
Si la realidad cambia, debemos volver a realizar un análisis del modelo de datos, cambiar su
implementación, volver a hacer un análisis funcional y cambiar la codificación de los programas.
Todo esto lleva mucho tiempo, por lo cual, la metodología tradicional deja de ser eficiente
frente a cambios frecuentes en los requerimientos del usuario.
GeneXus nos ofrece una alternativa. A partir de los requerimientos de los usuarios, el
desarrollador analiza e interpreta sus ideas, y luego lo sistematiza con objetos generalmente de
tipo Transacción (que al final se materializa en una tabla de BBDD + un web panel) en una base
de conocimiento en lenguaje GeneXus (Knowledge Base). A partir de esta, el software en forma
automática crea el modelo de datos en una base de datos, y construye los programas básicos de la
aplicación para cubrir las necesidades funcionales requeridas.
Por lo tanto, resumiendo, algunas de las razones por las que hemos elegido este software para
implementar nuestro sistema TPV son las siguientes:
En definitiva, GeneXus es un buen aliado para ser más productivos y estar actualizados
tecnológicamente.
Además, otra razón por la que decidimos elegir este software para desarrollar nuestro proyecto
fue contar con más de 3 años de experiencia laboral con esta tecnología, aunque no en la versión
X Evolution 2, si no en la 9.0. Gracias a esta experiencia nos ha sido más fácil adaptarnos a la
versión más actual (que ha sido la que hemos utilizado para generar nuestra aplicación).
El motivo para cambiar de versión y utilizar una que no dominábamos fue básicamente el
poder usar las funcionalidades nuevas con las que cuenta GeneXus a partir de la versión X, la
mayoría de ellas relacionadas con la generación automática de aplicaciones para móviles y
herramientas para crear aplicaciones responsive.
La primera tarea cuando se empieza a desarrollar una aplicación con GeneXus es crear una
base de conocimiento. Una base de conocimiento o Knowledge Base (KB, es el término más
utilizado para nombrarla) corresponde al concepto de proyecto.
Durante este proceso de creación de la KB, GeneXus crea automáticamente también una base
de datos que almacenará información relativa a nuestra base de conocimiento (objetos creados,
etc,...). Es importante decir que no se trata de la base de datos de nuestra aplicación, sino que
es una base de datos que almacenará la información asociada a las definiciones que hagamos en
nuestra base de conocimiento. Por ejemplo, si creamos dominios nuevos o reglas de cálculo.
Después de crear la base de conocimiento, el siguiente paso consiste en describir los objetos
de la realidad identificados para implementar en nuestra aplicación mediante objetos GeneXus.
Por cada objeto de la realidad identificado, en nuestra aplicación crearemos un objeto GeneXus
llamado transacción.
Por ejemplo, para nuestro TPV podríamos definir varios objetos de la realidad importantes,
como pueden ser el Restaurante, Menú, la Carta, las Mesas o los Pedidos. Por cada uno de estos
objetos deberemos crear un objeto transacción, la cual los identificará dentro de nuestra
aplicación.
Dentro de cada transacción se debe definir los atributos característicos de cada objeto de la
realidad representado. Por ejemplo, para una transacción Pedido podríamos definir atributos que
nos aporten información significativa del objeto, tales que: ID de pedido, fecha del pedido, hora
del pedido, importe, estado, mesa, etc,…
Además del conjunto de atributos definidos en una transacción, hay que identificar cuáles de
ellos identifican de forma única al objeto transacción (en este caso, a la transacción Pedido).
Equivale a una clave primaria PK en BBDD. En otras palabras, por ejemplo, si identificamos el
atributo ID como PK, no será posible ingresar dos pedidos con el mismo ID.
Cada vez que creamos un objeto transacción, se genera automáticamente un Web Form
(formulario web) asociado a dicha transacción. Contiene los atributos definidos dentro de esta, y
realiza las siguientes acciones con los datos:
- Ingreso.
- Eliminación.
- Modificación.
Por eso GeneXus es tan eficaz: simplemente con definir una transacción y sus
correspondientes atributos, él mismo ya se encarga de generarse el web form y los procesos
necesarios para realizar estas acciones, sin que nosotros hayamos codificado ni una línea.
Teniendo en cuenta todo lo anterior, parece obvio que la esencia de una aplicación
desarrollada con GeneXus esté basada en la dependencia entre objetos distintos del tipo
transacción. Esto es, por ejemplo, el Pedido no tiene sentido si no está asociado a una Mesa, y lo
mismo con el Menú y la Carta, que no podrían existir sin un Restaurante.
Figura 35. Ejemplo real de definición de transacción GeneXus. Transacción Pedido de nuestra app TPV.
Figura 36. Ejemplo real de definición de transacción GeneXus. Transacción Mesas de nuestra app TPV.
Figura 37. Ejemplo real de Web Form dentro de la definición de una transacción GeneXus.
Una vez introducidos los puntos clave y objetos básicos que necesita GeneXus para empezar
a desarrollar una aplicación, ha llegado la hora de ver cómo relaciona a todos ellos y cuál es el
resultado cuando decidimos generar una aplicación.
Cuando generamos una aplicación con GeneXus se producen 3 eventos, de los cuales se
puede seguir su estado a través de la consola del programa.
- Lo primero que hace GeneXus es especificar los objetos que forman la base de
conocimiento de la aplicación que estamos generando.
Durante este proceso, GeneXus detecta qué objetos necesitan ser especificados (sólo se
especifican si han sufrido cambios respecto a la última especificación hecha) y si necesita
reorganizar en BBDD alguna tabla nueva o una existente que haya sufrido modificaciones.
Figura 40. Generación de los objetos GeneXus a clases en el lenguaje para el que generemos la app.
La página principal que genera GeneXus por defecto contiene todos los objetos creados en
la base de conocimiento. Se llama Developer Menu.
Si vamos a abrir el objeto Pedido, que es con el que estábamos desarrollando el ejemplo, nos
encontramos lo siguiente:
Figura 44. Ejecutando la aplicación 3 ►. Web Form creado para la transacción Pedido.
accedemos a través del Menú principal, nos sirve para ver cómo crea GeneXus la estructura de
los formularios web y los botones que implementa automáticamente junto a los procedimientos
asociados para que se realicen las acciones correspondientes en cada botón.
El gestor de base de datos que vamos a utilizar en nuestra aplicación es Microsoft SQL Server
2012, con las versiones de los componentes que lo conforman que indicamos en la siguiente tabla:
Tabla 6. Versión de instalación de los componentes asociados al SQL Server que utilizaremos en la app.
Para que la aplicación funcione bien, en GeneXus debemos apuntar a dicha conexión, y en
concreto a la base de datos que va a contener la información de nuestro desarrollo. En nuestro
caso la hemos llamado tpvweb2. Esto se hace dentro de las Propiedades de nuestro proyecto:
Es decir, dentro de tpvweb2 tenemos guardada en tablas de datos la información que cuando
la aplicación está corriendo consultamos, grabamos, eliminamos y modificamos continuamente.
También contiene tablas paramétricas, por ejemplo, para guardar la información de los
productos de la carta, o el número de mesas que tenemos.
Existe una extensa gama de sistemas informáticos que obtienen su información directamente
del mundo real, a partir de dispositivos que recaban la información de un evento físico. Esta
información la digitalizan, la envían al ordenador y luego el software se encarga de su
procesamiento. Los sistemas que capturan datos por sí mismos se llaman genéricamente Sistemas
de Adquisición de Datos (DAQ), y un ejemplo de ello es nuestro dispositivo Leap Motion.
Los fabricantes de este tipo de sistemas generalmente proveen una API para poder acceder a
estos dispositivos desde nuestro lenguaje de programación. Esta API puede ser una DLL, una
clase Java o un wrapper para otros lenguajes como Python, Visual Basic, etc. En el caso de Leap,
su API es tan completa que dependiendo del lenguaje que vayamos a utilizar se proporciona o
bien una DLL o bien clases Java.
El recurso técnico de la creación de Objetos Externos nos permite interactuar con la API que
nos provee el fabricante de interfases de adquisición de datos y usar GeneXus para leer
información de eventos físicos o para controlar procesos. Dado que la mayoría de estos fabricantes
de hardware de DAQ provee una DLL o una clase Java, podemos importar estas funciones y
utilizar el objeto externo para acceder a los comandos que controlan los puertos de entrada y
salida, analógicos o digitales, más otros recursos que estas interfases multi-propósito
normalmente tienen, como temporizadores y contadores internos.
Como acabamos de comentar en el apartado 2.3., para interactuar a través de GeneXus con
sistemas DAQ debemos hacerlo a través de los llamados Objetos Externos (External Objects,
EO).
El proceso para incluir un programa externo dentro de una base de conocimiento consta de dos
partes:
Cabe destacar, que la existencia de este objeto donde se centraliza toda la información del
objeto externo, brinda una mayor facilidad y flexibilidad en la programación.
2. Nos aparece el inspector anteriormente mencionado. Le damos la ruta del archivo que nos
hemos descargado de https://developer.leapmotion.com para C# y damos Next.
3. Agregamos el prefijo con el que se crearán los nombres de los objetos y la carpeta de la
KB donde se generarán.
4. Nos trae todas las clases y métodos que contiene la DLL que nos hemos descargado. Los
marcamos todos y los importamos.
Dicha carpeta APILeap contiene X objetos externos, uno por cada método o clase importado
desde la DLL de Leap.
5. Ejemplo de objeto externo creado mediante la importación de un método que contiene una
biblioteca de una aplicación externa. Elegimos un objeto conocido como es Finger,
analizado en el apartado 2.1.3.3.
Figura 54. Objeto Externo creado a partir de la importación del método Finger desde la API Leap Motion.
3. EL SISTEMA TPV
Una vez introducido todo el marco teórico que influye en este proyecto, vamos a centrarnos
en describir nuestra aplicación y la manera en la que esta se ha desarrollado.
El formato que vamos a seguir para describir nuestro prototipo de sistema TPV va a ser
separando por partes cada funcionalidad de nuestra aplicación. Por cada parte, analizaremos:
- La interfaz y su funcionalidad.
- Qué tipo de objetos GX intervienen en la creación de dicha interfaz y pequeña
descripción de su labor dentro de esta.
- Si estos objetos están relacionados con alguna tabla en base de datos.
Como ya vimos en el apartado 2.2.1.5., cuando GX nos genera una aplicación web, lo
primero que vemos cuando abre el navegador es el Developer Menu (Figura 43).
Se trata de una página principal que GX nos crea por defecto, y que contiene todos los
principales objetos que él entiende que conforman la aplicación, de forma que podemos abrir
cualquiera de ellos (para ver su estructura, por ejemplo) sin necesidad de seguir el flujo lógico
que debe seguir dicha aplicación para su correcto funcionamiento.
En nuestro caso, como generamos para C# y .NET, GX muestra todos los objetos .aspx que
ha creado automáticamente (Figura 43) a raíz de toda la información que hemos introducido en
forma de objetos en la KB de nuestro sistema TPV.
Para seguir un orden lógico de funcionamiento, nuestra aplicación debe abrir como Menú
raíz la clase “Inicio” (inicio.aspx).
3.1.2. Inicio
Figura 56. Menú raíz de la aplicación que conforma el sistema TPV (2).
La interfaz que conforma el Menú raíz se basa en mostrar los datos del restaurante a modo
de información, y la única acción que permite hacer al usuario es elegir el idioma con el que
quiere interactuar. Este prototipo solamente trabaja con el español, las otras banderas se
encuentran a modo de ejemplo de funcionamiento.
▪ La pantalla en sí es una MasterPage, que obtiene los datos del restaurante a partir de
la tabla de BBDD Empresa y los guarda en variables que son las que printeamos
con la distribución que se muestra.
▪ Las imágenes originales para mostrar los idiomas están contenidas en la carpeta
Resources de la KB, y se representan con atributos de tipo Imagen a través de un
control ContentPlaceHolder.
▪ La tabla Empresa se crea en GX y BBDD a partir de la transacción definida en GX
con el mismo nombre. Su estructura es la siguiente:
La estructura de las tablas generadas, tanto en GX como en base de datos, queda definida por
las siguientes figuras.
Figura 59. Tabla impactada por GX en BBDD a partir de la tabla generada a partir de la transacción Empresa.
Figura 60. Flujo de acciones GX desde que se crea un objeto tipo transacción hasta que lo vemos reflejado en
BBDD.
A esta interfaz tendrán acceso tanto los clientes como los empleados, por lo que ambos
podrán realizar las mismas acciones si nos encontramos dentro de esta serie de menús.
Desde esta interfaz es donde los clientes desde sus respectivas mesas realizarán por ellos
mismos sus pedidos, sin necesidad de estar presente la figura del camarero.
Esta pantalla es muy simple, ya que solamente se basa en la interacción con botones que nos
conducen a otras pantallas o envían notificaciones.
Su estructura es un objeto de tipo web panel, al que se le han añadido 7 botones con las
siguientes funcionalidades:
- MENÚ, que conduce a otra pantalla donde podremos elegir entre los menús disponibles
para tomar.
- CARTA, que conduce a otra pantalla con una serie de productos disponibles para tomar.
- Inicio, que vuelve al menú raíz del que hemos partido. Es decir, a la pantalla para elegir
un idioma cuando inicia la aplicación.
- Volver, para retroceder dentro de la misma interfaz al menú principal.
- Ocio, enfocado al entretenimiento del cliente durante la espera de su pedido. Ahora
mismo no tiene implementado nada, se encuentra a modo de prototipo.
- CAMARERO, que tampoco tiene implementación todavía, y que está enfocado a enviar
una notificación al camarero asignado a la mesa concreta que haga la llamada para que
acuda.
- ADMINISTRAR, que en modo cliente se encuentra invisible.
• Click en MENÚ
Esta interfaz es muy parecida a su predecesora, ya que se basa en un web panel y botones o
links para moverse a otras pantallas. La diferencia que existe en este caso, es que la lista de menús
disponibles es dinámica. Dichos menús están parametrizados en la tabla Menu, con lo cual, el
web panel carga los tipos en función de los registros que tenga dicha tabla cargados en BBDD.
Si hacemos click sobre cualquiera de los menús disponibles nos aparecen los distintos
platos que entran, los productos que contienen y sus precios. Por ejemplo, para el Menú del día:
Figura 64. Interfaz con los productos del Menú del día.
Para cualquier menú que elijamos, la página a la que nos va a llevar es la misma
(mainitemmenu.aspx?X, donde X = ID del menú que hayamos elegido en la tabla Menu). Lo que
muestre la tabla de productos que se carga dinámicamente dependerá de lo que tenga
parametrizado en la tabla MenuItem cada tipo de menú. A su vez, cada ID de Item tiene relación
con la tabla CategoriasMenu.
Es decir, en la Figura 63 se observa como cada tipo de Menú tiene un ID asignado. Cada vez
que elijo un tipo de menú, iré a la tabla MenuItem filtrando con ese mismo ID, y filtraré los ítems
que necesita tener ese menú. Por ejemplo, para el Menú del día ID = 31:
Figura 65. Contenido de la tabla MenuItem con MenuId = 31 (menú del día).
Comprobamos en la Figura 64, que la tabla dinámica del web panel debería tener, al menos,
las categorías Primer Plato, Segundo Plato, Postres, Cafés y Bebidas. Coincide con lo mostrado.
En cuanto a los botones azules y verdes que nos encontramos dentro de la interfaz de los
registros por tipo de plato del menú (Figura 64), su funcionalidad es la siguiente:
▪ Botón COMPLEMENTOS
Lanza un evento que abre un pop-up en la pantalla, la cual nos permite elegir entre varias
guarniciones.
Figura 68. Tabla que contiene la parametría de los productos clasificados como COMPLEMENTOS.
▪ Botón MODOS
Lanza un evento que abre un pop-up en la pantalla, la cual nos permite elegir entre varios
modos de preparar la comida.
Figura 70. Tabla que contiene la parametría de los productos clasificados como MODOS.
▪ Botón AÑADIR
Cada vez que se genera un registro dentro de la lista del pedido, se genera automáticamente
también un control X para poder eliminar un ítem si nos hemos equivocado y el producto no
debería de haber sido añadido.
Una vez que tenemos la lista del PEDIDO completa, con el botón AÑADIR se creará un
nuevo pedido en la sección de pedidos que más tarde veremos en la interfaz de empleado.
• Click en CARTA
Cuando elegimos una categoría, por ejemplo Bebidas, nos lleva a otro web panel con una
estructura y funcionalidad idénticas a la de los ítems por menú que hemos visto en el punto
anterior.
Al contrario que pasaba con la serie de menús anteriores, a esta interfaz solamente podrán
acceder los usuarios que tengan un perfil de empleado.
Como ya hemos comentado, el empleado podrá realizar las mismas funciones que un perfil
de cliente dentro de la interfaz de menús y carta. La diferencia viene dada por el botón
ADMINISTRAR, cuyas funcionalidades disponibles describiremos en el siguiente apartado.
Esta interfaz para empleados la forman un grupo de 9 pestañas, donde cada una de estas se
representa a través de un objeto web panel distinto.
Lo que contiene el web panel es, de nuevo, una tabla que se modifica dinámicamente
cargando más o menos filas en función de los datos que se encuentran grabados en BBDD sobre
las tablas paramétricas.
TRABAJO FIN DE GRADO - MEMORIA BENAVENTE DOMENECH, PATRICIA
59 Sistema TPV controlado con ‘Leap Motion’
▪ Pestaña 1: MENÚS
Esta pestaña básicamente trabaja con lo explicado, sobre una tabla dinámica sobre la que va
cargando información de registros que encuentra en BBDD. La tabla a la que corresponde la
información es Menú (Figura 63).
Añadido, se integra en el web panel un textbox que hace funciones de filtro, para buscar un
menú dentro de la lista dinámica (por nombre).
Como se puede observar en la figura 75, el usuario tendrá un botón (verde) para agregar un
menú nuevo (acción INSERT en BBDD); y sobre cada registro menú ya existente, dos botones
más: uno para modificar la información sobre este (acción UPDATE en BBDD) y otro para
eliminarlo (acción DELETE en BBDD). Esto lo encontraremos en TODAS LAS PESTAÑAS.
▪ Pestaña 2: PEDIDOS
Figura 76. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña PEDIDOS.
De nuevo, el web panel está formado por una tabla dinámica, pero en este caso no se limita
únicamente a leer y representar la información desde tablas en BBDD, si no que también es capaz
de interpretar el estado de la comanda para asignar un color a la fila, e incorpora botones que
realizan acciones sobre el registro concreto del pedido leído.
Todas estas acciones sobre los botones son entendidos como un UPDATE en la tabla de
datos BBDD que representa al pedido, “Pedido”,
excepto el botón de la columna de Mantenimiento, que redirecciona hacia otro web panel
que nos permite modificar un pedido.
Figura 78. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña PEDIDOS, botón Mantenimiento.
Como se puede ver en la figura 76, la pestaña PEDIDOS también cuenta con dos objetos que
representan filtros.
- Uno de ellos es de tipo combo box, para filtrar por estado del pedido.
Figura 79. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña PEDIDOS, filtro Estado.
Figura 80. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña PEDIDOS, filtro Fecha.
▪ Pestaña 3: ITEMS
Figura 81. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña ITEMS.
De nuevo, volvemos a estar frente a un web panel que contiene una tabla dinámica que carga
líneas en función de lo que encuentra en la tabla de BBDD que lee. En este caso, la tabla base que
recorre es “Item”.
▪ Pestaña 4: CATEGORÍAS
Figura 83. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña CATEGORIAS, Carta.
Figura 84. Interfaz del modo ADMINISTRAR para perfiles de empleado. Pestaña CATEGORIAS, Menu.
Como se puede observar, ambas contienen los mismos tipos de objetos, los cuales, de nuevo
como en casos anteriores se basan en una tabla dinámica que extrae las líneas de los registros que
encuentra en las tablas base en BBDD y un filtro a través de un textbox.
Todas las pestañas que siguen tienen exactamente la misma estructura y composición de
componentes que las dos de la pestaña CATEGORÍAS. Solamente cambia la tabla base a la que
van a buscar datos en la BBDD y la implementación de los filtros para cada caso.
En este apartado explicaremos nuestras primeras experiencias con Leap, cómo nos
familiarizamos con el tratamiento a nivel de código con los objetos que maneja la API y cuáles
son sus posibilidades para hacer uso de ellas y aprovecharlas al máximo de cara al futuro; ya sea
mejorando el presente proyecto, o usándolas para otro tipo de aplicaciones. Además, analizaremos
el procedimiento para la integración de Leap con nuestra aplicación TPV.
Nuestros primeros pasos se basaron en cómo conectarse al controlador Leap Motion y acceder
a los datos básicos de seguimiento, tales que: nº de frames que ha detectado hasta ahora, el tiempo
que ha estado activo o las manos que aparecen en un momento dado en la pantalla, etc.
Para ello, lo que hicimos fue empezar a trabajar con un ejemplo ‘Hola Mundo’ que nos facilitan
en la web oficial de desarrolladores. Básicamente, lo único que hay que tener en cuenta para que
empiece a funcionar es lo siguiente:
• Las clases que generemos y las librerías correspondientes que nos proporcionan
deben estar en la misma ruta. Si no es así, la compilación funcionará, pero la
ejecución posterior no será buena. En el caso de la versión 3, las librerías que
necesitamos son Leap.dll y LeapC.dll.
Para ejecutar el ejemplo dado, y en general, cualquier clase implementada que queramos
probar, seguiremos los pasos que se enumeran a continuación.
cd C:\LeapDeveloperKit_3.2.1_win\LeapDeveloperKit_3.2.1+45911_win\LeapSDK\samples
Sample2.cs es nuestra clase a compilar. Ojo, porque el ejemplo es para nuestro caso. Para
cualquier otro, habrá que tener en cuenta la plataforma del sistema (x32, x64, x86,…) el formato
de salida de la clase compilada y el nombre de esta, que será diferente en cada caso.
Como se puede observar, es una aplicación muy básica, que lo que hace es obtener información
acerca de cuántos frames lleva capturados ya el dispositivo y en cuánto tiempo. Además, nos
proporciona información del número de manos que están visibles en ese momento.
En el momento que introducimos una mano dentro del campo de visión del sensor, la
apariencia de la aplicación cambia y aparece mucha más información acerca de la mano, los dedos
y el brazo capturados.
Si volvemos a quitar la(s) mano(s), la pantalla vuelve a tener el mismo formato que en la
Figura x anterior.
Como recordatorio, durante todo el proceso explicado, es muy importante que el dispositivo
esté conectado por USB y con el Device Status (visto en el apartado 4.1.) correcto para un buen
funcionamiento, tanto de ejecución de la aplicación como de compilación de clases y generación
previa de esta.
Si por lo que sea Leap Motion no consiguiese iniciar automáticamente cuando es conectado,
en Windows se puede forzar a mano iniciando el Servicio que usa de la siguiente forma:
Si no la encontramos a través del Menú de Windows, se puede acceder a través del ejecutador
(Ejecutar / Run) de la siguiente manera:
Realizando estos pasos ya nos debería quedar conectado. Lo podemos comprobar a través del
Device Status (como ya hemos comentado, en la aplicación Leap Motion Control Panel) o
simplemente comprobando el color verdecito del dispositivo conectado en la barra de
herramientas de Windows:
Dado que la aplicación de ejemplo se ejecuta a través de la “pantalla negra”, resulta bastante
difícil seguir la información de los datos de los gestos que nos va devolviendo Leap.
Para resolverlo, vamos a crear un proyecto en Visual Studio 2012, y a aplicar más o menos las
mismas funcionalidades, pero dentro de un marco de aplicación más real y sobre todo más visual.
3. Una vez tenemos las librerías cargadas como Referencia, vamos a modificar las
propiedades del proyecto. Para eso, hacemos click derecho sobre el nombre de este en el
Menú de la derecha,
y para todos los casos, dentro de la pestaña Eventos de compilación, añadir la siguiente
sentencia al textbox de la Línea de comandos del evento posterior a la compilación:
Al igual que pasaba con el caso del apartado 4.1.1. ejecutando desde la consola, usando
VS2012 también es necesario que Leap Motion esté conectado al ordenador para que la
compilación funcione correctamente.
Como se puede observar, el error viene dado por el comando del evento que hemos introducido
como requisito para que haga posterior a la compilación.
Una vez tenemos el controlador instalado y funcional dentro del entorno de desarrollo VS2012,
empezamos a crear nuestra propia versión del “Hola Mundo”. El objetivo es conseguir una
aplicación similar a la dada, pero pudiendo ver con claridad y de forma ordenada la información
que nos devuelve el sensor cuando realizamos un gesto. En otras palabras, conseguir tener el
control de lo que se está ejecutando en cada momento.
• Caso 1
Para ello, sobre el código del Form1 que se nos ha generado al guardar el proyecto nuevo que
hemos creado en el punto 4.1.2.1., hemos implementado un programa (código disponible en el
anexo 7.2.) para que el controlador nos devuelva la siguiente información:
• ID frame.
• Tiempo total que ha estado activo el sensor.
• Los FPS que estamos captando.
• El nº de manos dentro del campo de visión del sensor.
• Un objeto PictureBox definido con un bitmap, y que muestra la imagen que estamos
capturando.
La estructura del Form1 para el primer caso de prueba mencionado queda de la siguiente
manera:
• Caso 2
Para generar el Caso 2, hemos aprovechado el código del Caso 1 sobre el que hemos añadido
más líneas (código disponible en el anexo 7.3.). La información que hemos añadido sirve para
obtener datos sobre los siguientes campos, además de los que ya teníamos:
Hemos reutilizado las mismas funciones del caso anterior. La única que ha sido modificada es
la “madre”, de donde sacamos información a partir del Frame. El resultado obtenido tras compilar
y ejecutarse la aplicación ha sido el siguiente:
Como obtenemos los datos a partir de Controller, dicha información de las manos y dedos
pertenecerá al último frame detectado hasta el momento.
Si quisiéramos obtener la información para todos los frames detectados, tendríamos que
obtener la información a partir de un objeto Listener (como ya vimos en el apartado 2.1.3.5.). A
nivel desarrollo, la primera versión del ‘Hola Mundo’ que nos proporcionan en la web oficial
(visto en el apartado 4.1.1.) es un buen ejemplo (código disponible en el anexo 7.1.).
Vamos a hacer un análisis de los resultados obtenidos para cada caso de prueba planteado a
continuación.
Para comprobar que lo que hemos implementado funciona correctamente, nos hemos definido
una serie de casos de prueba donde veremos si realmente nuestro código hace lo que esperamos
en cada momento.
La definición de cada uno de estos casos de prueba se realiza teniendo en cuenta en todo
momento la estructura principal del programa y lo que se espera que esta nos muestre.
• Caso de prueba 1
Objetivo: Comprobar que la información obtenida para una mano detectada es correcta.
Resultado:
✓ Nro. Manos
✓ ID mano
✓ Posición mano
Nro. Dedos
✓ Inclinación (front / back)
✓ Inclinación (eje vertical)
✓ Inclinación eje horizontal
El único error detectado corresponde al nº de dedos visibles que cuenta Leap para una mano
detectada. Dicho “error” viene dado por la cuestión que ya hemos estado planteando durante toda
la memoria, cuando obtenemos la información de un frame lo podemos hacer a través de
Controller o de Listener (que también será un método de Controller).
En este caso, como hemos obtenido el campo a través de Controller, la información que
estamos recogiendo corresponde con el último frame detectado. Si quisiéramos estar
monitorizando cada cambio y recogiendo todos esos datos, tendríamos que hacer una
implementación usando el método Listener y asignando a Controller todos los eventos que va
devolviendo para que nos los muestre.
Dicho lo anterior, asumimos que nos enfrentamos a un error que tenemos controlado y que
no corresponde a un error de desarrollo en sí, sino del modo en el que la aplicación está definida
para recoger la información.
En cuanto a las pruebas para validar los distintos tipos de inclinación, se han basado en mover
la mano por cada eje afectado, en las dos direcciones de las que recogemos información.
Figura 108. Analizando los resultados obtenidos. Casos de prueba. (2). Inclinación mano (front / back)
Figura 109. Analizando los resultados obtenidos. Casos de prueba. (3). Inclinación mano (eje vertical)
Figura 110. Analizando los resultados obtenidos. Casos de prueba. (4). Inclinación mano (eje horizontal)
• Caso de prueba 2
Resultado:
✓ Dirección
✓ Pos. Muñeca
✓ Pos. Codo
Figura 111. Analizando los resultados obtenidos. Casos de prueba. (5). Dirección brazo.
Figura 112. Analizando los resultados obtenidos. Casos de prueba. (6). Posición de la muñeca.
Figura 113. Analizando los resultados obtenidos. Casos de prueba. (7). Posición del codo.
• Caso de prueba 3
Objetivo: Comprobar que la información obtenida para una lista de dedos detectados es
correcta.
Resultado:
✓ ID dedo
✓ Tipo dedo
✓ Largo
✓ Ancho
✓ Dedo extendido
Como era de esperar, todos los datos obtenidos y que correspondan con información de los
dedos van a estar afectados por el mismo error que hemos detectado en el caso de prueba 1. Es
decir, estamos obteniendo siempre la información del último dedo leído dentro del frame, que en
este caso siempre es el meñique.
Figura 114. Analizando los resultados obtenidos. Casos de prueba. (8). Información dedos.
Una vez probado y vistas las capacidades que muestra nuestro sensor, vamos a analizar de qué
formas se podría implementar su funcionalidad dentro del sistema TPV. También elegiremos la
que -a priori- será la mejor de ellas, siempre respecto al hipotético modo de funcionamiento del
sistema planteado.
Para analizar el “cómo”, primero debemos plantear el “qué”. En este apartado vamos a definir
una serie de requisitos de control gestual que nuestro TPV deberá tener.
Dado que este proyecto está enfocado al uso de Leap desde la cocina, vamos a centrarnos en
definir acciones solamente sobre la parte de la aplicación que se vaya a usar desde dicho espacio.
Dentro de nuestro prototipo del sistema TPV, la ventana principal con la que teóricamente se
trabajaría desde cocina será la que nos permite gestionar el estado de los pedidos, formada por la
interfaz que representa la figura anterior.
Vista la estructura con la que tendremos que interactuar, definimos una lista de un total de 6
gestos para implementar usando los recursos que nos proporciona Leap.
1. Funcionalidad “click”, que deberá poder realizarse para cada componente que lo
permita normalmente (botones) dentro de esta interfaz, excepto para el desplegable del
filtro por “Estado” del pedido.
2. El filtro “Estado” unirá dos tipos de gestos para una misma funcionalidad: un gesto corto
y rápido hacia abajo para realizar el desplegado + un click para elegir la componente del
filtro que queremos utilizar.
3. Funcionalidad que nos permita arrastrar objetos para reubicarlos en otra zona de la
pantalla. Un ejemplo de esto sería poder intercambiar la posición que ocupan los pedidos,
de forma que los organicemos como mejor nos convenga.
4. Funcionalidad que nos permita hacer el paginado realizando un gesto de derecha a
izquierda o al contrario, dependiendo de hacia qué lado queremos paginar. Emulará la
tarea que hacen los botones de control de paginado.
5. Funcionalidad de despacho rápido de un pedido, que consistirá en hacer un gesto
rápido hacia la izquierda sobre el pedido concreto del cual queremos cambiar su estado.
Emulará la tarea del botón columna “Atender”.
6. Funcionalidad de cambio de estado de un pedido una vez que está despachado, que
consistirá en hacer un gesto rápido hacia la derecha sobre el pedido concreto para el que
queramos revertir el avance de su estado. Emulará la tarea del botón columna “Retornar”.
Analizaremos en el siguiente apartado cuáles son las posibles soluciones para cada modo de
funcionamiento planteado. En caso de que contemos con más de una posibilidad de
implementación para alguno de ellos, debatiremos entre todos los cómos y nos quedaremos con
la versión que consideremos la mejor para nuestro sistema TPV, teniendo en cuenta factores como
por ejemplo el rendimiento o la complejidad del desarrollo.
Vistos los requisitos gestuales con los que queremos que nuestra aplicación sea capaz de
trabajar, vamos a enumerar ahora una serie de posibles soluciones que podrían ser válidas y servir
de guía de cara a la implementación de código para la integración del sensor con el sistema.
Si hacemos memoria, en el apartado 2.1.3.6. vimos que la API de Leap Motion incluía por
defecto 4 objetos que emulaban tipos de gestos. Uno de ellos es ScreenTapGesture, que si
recordamos, era el que representaba un click sobre la pantalla.
Dicho objeto cuenta con una serie de funciones públicas que nos devuelven información sobre
el movimiento detectado y que se pueden usar. Para nuestro caso concreto, la información que
necesitamos obtener a través de este objeto es la siguiente:
• El frame que contiene el evento del gesto que se acaba de producir. Objeto tipo Frame.
• Lista de manos asociada al gesto, objeto tipo HandList.
A través del objeto HandList se puede acceder a toda la información respecto a los dedos que
han realizado el gesto, que en nuestro caso controlaremos que solamente lo pueda hacer el dedo
índice.
La API de Leap también cuenta con un tipo de gesto que se llama KeyTapGesture, el cual
también ya comentamos en el apartado 2.1.3.6. En este caso, se representaba un desplazamiento
rápido y corto hacia abajo, por lo que nos sirve perfectamente para abrir el desplegable.
La información que necesitamos que devuelva KeyTap para que funcione correctamente es la
misma que para un evento click: el frame, la mano, el dedo concreto y la posición de la pantalla
donde se ha realizado el gesto. Todos ellos están disponibles y son perfectamente accesibles,
como en el caso anterior.
Dado que Leap no tiene ninguna función predefinida para hacer movimientos en vertical, en
este caso lo tenemos más complicado.
Lo que planteamos para generar este tipo de gesto es, mediante los datos de posición de la
mano y los dedos que se nos proporciona durante el rastreo, generar un algoritmo que nos permita
reconocer cuándo la mano se mueve en el eje vertical (da igual el sentido). También, usando los
datos de su posición inicial y final, para saber desde dónde y hasta dónde tiene que moverse el
objeto. Añadido, tendremos que comparar la posición de la mano con la del objeto dentro de la
lista de pedidos para identificar cuál es que queremos mover.
Como no tenemos ningún movimiento más que vaya a necesitar de este eje (a excepto de
KeyTap, pero este ya es reconocido por Leap de forma automática) nos debería facilitar la
casuística a la hora de implementar este algoritmo. Si en un futuro queremos implementar otro
tipo de gesto que utilice directamente el eje vertical, tendríamos que afinar mucho más en qué
caso estamos y qué condiciones y particularidades de movimiento tiene cada uno para que puedan
ser reconocidos correctamente y no haya confusión entre gestos.
Para realizar el paginado podríamos pensar que la implementación debe ser la misma que para
el caso anterior, pero sobre el eje horizontal y sin tener en cuenta posiciones inicial y final, porque
no las requerimos. Se podría implementar creando un algoritmo así, pero por suerte la API de
Leap sí que cuenta con un objeto reconocible para detectar gestos de este tipo.
Para realizar este gesto podríamos pensar que nos vale el que ya incluye la API y ya hemos
visto anteriormente, KeyTap, pero en este caso deberemos tener en cuenta muchos más factores
además de la información que este método nos proporciona.
Por ejemplo, tenemos que saber sobre qué pedido estamos actuando, por lo que necesitamos
comparar las posiciones de nuestro dedo y el objeto por el que el pedido está representado en la
interfaz para saber a qué comanda afectamos.
Además, también debemos tener presente la dirección hacia la que se está realizando el gesto
(izquierda o derecha), ya que en función del lado al que se dirija se lanzará un evento u otro
(avanzar o retroceder el estado del pedido).
Sobre la API…
Todos los gestos mencionados y reconocidos en la API están contenidos en una estructura de
datos tipo Enum en la librería “LeapC.dll”, dentro de la clase “Gestures”. Dicha estructura puede
ser de dos tipos: Type o State.
• Las estructuras tipo Type recogen información sobre los tipos de gestos, que como ya
hemos visto, son los siguientes:
- TYPE_INVALID
- TYPE_SWIPE
- TYPE_CIRCLE
- TYPE_SCREEN_TAP
- TYPE_KEY_TAP
• Las estructuras tipo State recogen información acerca de los posibles tipos de estado en los
que se pueden encontrar los gestos. Por cada gesto, tenemos 4 estados posibles:
- STATE_INVALID
- STATE_START
- STATE_UPDATE
- STATE_STOP
En cuanto al funcionamiento general, nuestra aplicación almacenará los datos de los tipos de
gestos que usa, para que al realizar un movimiento compare con los gestos que ya tenemos
registrados.
Cuando se graban los gestos, se tendrán que almacenar los datos en algún fichero de tipo
JSON, BVH, XML o CSV con un formato predeterminado, para posteriormente poder ser
reconocidos fácilmente desde dentro de nuestra aplicación según la estructura definida.
Como nuestro TPV tiene un formato web, el fichero que contenga los gestos será de tipo JSON.
Su formato predeterminado (tracking data) debe seguir la estructura definida en el Anexo 7.4. de
esta memoria.
Es un sensor poco conocido, pero que por su bajo precio y a su vez gran desempeño podría
estar funcionando en sistemas donde podría ser súper útil; como por ejemplo en la industria, donde
cada vez se usa más el tratamiento de imágenes para realizar funciones de cualquier tipo.
Mediante las diferentes pruebas realizadas con una parte de su extensa API, pudimos observar
que el sensor es intuitivo, funciona correctamente y cuenta con las validaciones suficientes para
evitar errores por parte de los usuarios.
Sinceramente, no entendemos cómo con los años que lleva comercializándose su uso no se
haya extendido más. A pesar de permitir casi todos los lenguajes de programación, suponemos
que la razón podría deberse a otro tipo de dispositivos todavía más baratos y potentes dentro del
mercado. Un ejemplo pueden ser las placas de Arduino, con las que se puede programar casi
cualquier cosa con un rendimiento brutal.
En cuanto a las mejoras que proponemos para nuestro prototipo de sistema, las
diferenciamos en dos tipos:
➢ Puntos pendientes, que incluyen las funcionalidades requeridas y que ya nacieron con
el prototipo inicial de la aplicación.
✓ Implementación real de la funcionalidad del sensor sobre la aplicación.
➢ Mejoras evolutivas, a nivel aplicación, haciendo uso de recursos que tenemos en nuestra
mano y que nos permitirían un mayor alcance comercial de nuestro TPV. Por ejemplo:
✓ Parte funcional con Leap más visual y mejora de la interfaz del sistema en general.
✓ Aprovechar las funcionalidades que presenta GeneXus, como por ejemplo la
facilidad de generar aplicaciones móviles a partir de la original en cualquier lenguaje.
✓ Comunicación con Mesas por IP.
✓ Sistema de perfiles. Funcionalidades habilitadas distintas dentro de la aplicación
para cada tipo de usuario logueado.
6. BIBLIOGRAFÍA Y REFERENCIAS
[1]. SparkFun start something, “Leap Motion Teardown”, «sparkfun». [En Línea].
Available: https://learn.sparkfun.com/tutorials/leap-motion-teardown/you-got-guts-
kid.
[2]. Image Sensors World, news and discussions about image sensors, «blogspot»
2013. [En Línea]. Available: http://image-sensors-
world.blogspot.com/2013/08/haptix-follows-leapmotion-steps.html.
[3]. Frank Weichert, Daniel Bachmann, Bartholomäus Rudak and Denis Fisseler
(2013). “Analysis of the Accuracy and Robustness of the Leap Motion Controller”.
[En Línea]. Available: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3690061/.
[4]. Almà, A. “Interacción 3D con Leap Motion”. inLab talent & tech, Centre d’Innovació
i Tecnologia de la Universitat Politècnica de Catalunya, «inLab» 2014. [En Línea].
Available: https://inlab.fib.upc.edu/es/blog/interaccion-3d-con-leap-motion.
[5]. Leap Motion / Developers, «Leap Motion» 2018. [En Línea]. Available:
https://developer-archive.leapmotion.com.
[6]. MTF Mapper, “A brief overview of lens distortion correction”, «blogspot» 2017. [En
Línea]. Available: http://mtfmapper.blogspot.com/2017/08/a-brief-overview-of-
lens-distortion.html.
[7]. López-Flores, Juan E. (2016). “Control por gestos usando Leap Motion”. Instituto
Tecnológico y de Estudios Superiores de Occidente. [En Línea]. Available:
https://rei.iteso.mx/bitstream/handle/11117/4079/TOG+Control+por+gestos+usan
do+Leap+Motion.pdf?sequence=3.
[8]. Laazizi Ruiz, K. (2014). “Desarrollo de un prototipo usando como dispositivo de
interacción Leap Motion”. Universidad Politécnica de Madrid. [En Línea]. Available:
http://oa.upm.es/30975/1/PFC_KARIM_LAAZIZI_RUIZ.pdf.
[9]. Akcasu, A. (2014). “Introduction to Programming the LeapMotion”. Interactive
Business Systems, Inc. «slideshare». [En Línea]. Available:
https://www.slideshare.net/IBS_corp/leap-motion-aydin-akcasu-ibs.
[10]. Tina Running Blog, “General Introduction to Leap Motion (Java) API AND Your first
JAVA program with Leap Motion API –“Hello world”. «wordpress» 2015. [En
Línea]. Available: https://xiaotingrunning.wordpress.com/2015/03/23/leap-motion-
tutorial-java2-general-introduction-and-hello-world/.
[11]. SHOWLEAP TECHNOLOGIES, Un proyecto pensado para cambiar el mundo,
2015. [En Línea]. Available: http://blog.showleap.com.
7. ANEXOS
class Sample {
class SampleListener {
Console.WriteLine(
"Frame id: {0}, timestamp: {1}, hands: {2}",
frame.Id, frame.Timestamp, frame.Hands.Count
);
// Get fingers
foreach (Finger finger in hand.Fingers) {
Console.WriteLine(
" Finger id: {0}, {1}, length: {2}mm, width: {3}mm",
finger.Id,
finger.Type.ToString(),
finger.Length,
finger.Width
);
if (frame.Hands.Count != 0){
Console.WriteLine("");
}
}
//Para compilar:
/*csc /platform:x64 /target:exe Sample2.cs ..\src\*.cs Sample2.cs*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Leap;
namespace LeapMotionPrueba {
public Form1() {
InitializeComponent();
controller.EventContext = WindowsFormsSynchronizationContext.Current;
controller.FrameReady += newFrameHandler;
controller.ImageReady += onImageReady;
controller.ImageRequestFailed += onImageRequestFailed;
controller.RequestImages(frame.Id, Leap.Image.ImageType.DEFAULT,
imagedata);
}
controller.RequestImages(frame.Id, Leap.Image.ImageType.DEFAULT,
imagedata);
//Caso 2 - I
foreach (Hand hand in frame.Hands){
this.displayHandID.Text = hand.Id.ToString();
this.displayPalmPosition.Text = hand.PalmPosition.ToString();
this.displayHandFingers.Text = hand.Fingers.Count.ToString();
this.displayFingerID.Text = finger.Id.ToString();
this.displayFingerTipo.Text = finger.Type.ToString();
this.displayFingerL.Text = finger.Length.ToString();
this.displayFingerA.Text = finger.Width.ToString();
this.displayFingerExt.Text = finger.IsExtended.ToString();
} //foreach (Finger)
} //foreach (Hand)
//Caso 2 - F
} // newFrameHandler
"currentFrameRate": float
"id": float
"s": float
"timestamp": integer
"id": integer
"pointableIds": array
"armWidth: float
"confidence: float
"grabStrength: float
"id": integer
"pinchStrength: float
"s": float
"sphereRadius": float
"timeVisible": float
"interactionBox": object
"bases": the 3 basis vectors for each bone, in index order, wrist to tip,
(array of vectors).
"handId": integer
"id": integer
"length": float
"timeVisible": float
"touchDistance": float
"width": float