Escolar Documentos
Profissional Documentos
Cultura Documentos
Título
Director/es
Titulación
Departamento
Ingeniería Eléctrica
Curso Académico
2012-2013
Diseño de una aplicación didáctica para la monitorización y simulación del
robot STAÜBLI RX-60, proyecto fin de carrera
de Francisco Ochoa Bueno , dirigido por Carlos Elvira Izurrategui (publicado por la
Universidad de La Rioja), se difunde bajo una Licencia
Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported.
Permisos que vayan más allá de lo cubierto por esta licencia pueden solicitarse a los
titulares del copyright.
© El autor
© Universidad de La Rioja, Servicio de Publicaciones, 2013
publicaciones.unirioja.es
E-mail: publicaciones@unirioja.es
DISEÑO DE UNA APLICACIÓN PARA LA MONITORIZACIÓN Y SIMULACIÓN DEL ROBOT STAÜBLI RX-60
UNIVERSIDAD DE LA RIOJA
Resumen
El presente proyecto trata de facilitar el aprendizaje de elementos básicos de la robótica
a través de una aplicación informática. Consiste, por tanto, en la creación de un software
didáctico para adquirir conocimientos básicos sobre robótica, tanto en forma de simulación
como interactuando con un robot real, en este caso un brazo robot Staübli RX-60.
Para poder alcanzar esta meta, antes se realiza un repaso a las principales librerías
gráficas 3D y simuladores de robótica existentes en la actualidad. Por un lado, el estudio de
las librerías gráficas aporta conocimientos sobre la forma de crear entornos virtuales de
simulación y la forma de trabajar con ellos, permitiendo seleccionar para el desarrollo de la
aplicación en cuestión aquel que ofrezca unas características más interesantes y acordes al
proyecto. Por otro lado, un repaso de otros softwares de robótica similares proporciona
información sobre cómo están diseñadas las interfaces de usuario y sobre qué funcionalidades
se pueden ofrecer al usuario.
Cinemática
Cadena cinemática
Interfaz de usuario
Librería gráfica 3D
Simulación
DOCUMENTO 1.
ÍNDICE GENERAL
1. Índice de Figuras
Figura 1 Brazo robot Staübli RX-60 .................................................................................................................. 19
Tabla 1 Comparación de distintas librerías 3D ................................................................................................ 25
Figura 2 Arquitectura general del sistema utilizado en el proyecto ................................................................ 28
Figura 3 Partes del robot Staübli RX-60 ........................................................................................................... 30
Figura 4 Equivalencias entre brazo humano y brazo robot ............................................................................ 31
Figura 5 Dimensiones del robot Staübli RX-60 (en mm) ................................................................................. 32
Tabla 2 Límites de amplitud, velocidad y resolución ....................................................................................... 33
Figura 6 Brazo robot Staübli RX-60 instalado en la UR.................................................................................. 33
Figura 7 Volumen de trabajo del brazo robot .................................................................................................. 34
Tabla 3 Capacidad de carga ............................................................................................................................... 35
Tabla 4 Inercia de las articulaciones 5 y 6 ......................................................................................................... 35
Figura 8 Detalle de las articulaciones extremas del robot................................................................................ 35
Figura 9 Aspecto del Controlador CS7 .............................................................................................................. 36
Tabla 5 Configuración de parámetros del puerto serie .................................................................................... 37
Tabla 6 Resumen de comandos utilizados ......................................................................................................... 38
Figura 10 Qt Designer ......................................................................................................................................... 39
Figura 11 Aplicación ejecutándose y mostrando la visualización con OpenSceneGrpah ............................. 40
Figura 12 Descripción de la posición ................................................................................................................. 41
Figura 13 Descripción de posición + orientación .............................................................................................. 42
Tabla 7 Composición de rotaciones. Primero 0 a 1, después 1 a 2 .................................................................. 42
Figura 14 Composición de rotaciones en orientación tipo Roll-Pitch-Yaw .................................................... 43
Figura 15 Partes de un robot PUMA ................................................................................................................. 45
Figura 16 Sistema de coordenadas de elementos y sus parámetros ................................................................ 45
Figura 17 Pasos en la selección de los marcos de referencia para D-H........................................................... 47
Tabla 8 Parámetros DH del robot Staübli RX-60 ............................................................................................. 48
Figura 18Posición de ángulos nulos ................................................................................................................... 48
Figura 19 Programa PolyTrans 3D mostrando el eslabón 2 del robot ........................................................... 49
Figura 20 Posibilidad de mostrar cuatro visores .............................................................................................. 51
Figura 21Aspecto de la aplicación ...................................................................................................................... 52
Figura 22 A la derecha panel de cinemática directa ......................................................................................... 53
Figura 23 Diversas configuraciones del robot ................................................................................................... 54
Figura 24 Panel de la versión inicial de cinemática directa a la derecha abajo y en medio la cinemática
directa .......................................................................................................................................................... 54
Figura 25 Panel de cinemática inversa a la derecha ......................................................................................... 55
Figura 26 Línea de envío por el puerto serie ..................................................................................................... 55
Figura 27 Ventana para enviar programas ....................................................................................................... 56
Figura 28 Panel de puerto serie equivalente en la versión ampliada .............................................................. 56
Figura 29 Conectores serie RS-232 (a la izquierda de 25 pines y a la derecha de 9) ..................................... 58
Tabla 9 Funcionalidad de pines del puerto serie .............................................................................................. 58
Figura 30 Conectores serie ................................................................................................................................. 59
Tabla 10Pasos en la planificación del proyecto ................................................................................................. 61
Figura 31Diagrama de Gantt del proyecto ........................................................................................................ 62
Figura 32Pipeline general en gráficos 3D .......................................................................................................... 69
Figura 33. Capa de abstracción simplificada de Direct3D ............................................................................... 72
Figura 34 Versión simplificada del pipeline de OpenGL ................................................................................. 74
Figura 35 Capa de abstracción simplificada en OpenGL ................................................................................ 75
2. Índice de Tablas
Tabla 1 Comparación de distintas librerías 3D ................................................................................................ 25
Tabla 2 Límites de amplitud, velocidad y resolución ....................................................................................... 33
Tabla 3 Capacidad de carga ............................................................................................................................... 35
Tabla 4 Inercia de las articulaciones 5 y 6 ......................................................................................................... 35
Tabla 5 Configuración de parámetros del puerto serie .................................................................................... 37
Tabla 6 Resumen de comandos utilizados ......................................................................................................... 38
Tabla 7 Composición de rotaciones. Primero 0 a 1, después 1 a 2 .................................................................. 42
Tabla 8 Parámetros DH del robot Staübli RX-60 ............................................................................................. 48
Tabla 9 Funcionalidad de pines del puerto serie .............................................................................................. 58
Tabla 10Pasos en la planificación del proyecto ................................................................................................. 61
Tabla 11 Cuafro precios software .................................................................................................................... 214
Tabla 12 Cuadro de precios horas trabajadas ................................................................................................ 215
Tabla 13 Cuadro de precios hardware ............................................................................................................ 215
Tabla 14 Presupuesto software ......................................................................................................................... 218
Tabla 15 Presupuesto horas trabajadas .......................................................................................................... 219
Tabla 16 Presupuesto hardware ....................................................................................................................... 219
DOCUMENTO 2.
MEMORIA
UNIVERSIDAD DE LA RIOJA
ESCUELA DE INGENIERÍA INDUSTRIAL
TÍTULO
“DISEÑO DE UNA APLICACIÓN DIDÁCTICA PARA LA MONITORIZACIÓN Y SIMULACIÓN DEL
ROBOT STAÜBLI RX-60”
DIRECTOR
CARLOS ELVIRA IZURRATEGUI
AUTOR
FRANCISCO OCHOA BUENO
1. ÍNDICES DE MEMORIA
1.1 ÍNDICE DE CONTENIDO
DOCUMENTO 2. MEMORIA ......................................................................................................................... 7
1. ÍNDICES DE MEMORIA............................................................................................................................... 9
1.1 ÍNDICE DE CONTENIDO ........................................................................................................................... 9
2. OBJETO ......................................................................................................................................................... 11
3. ALCANCE...................................................................................................................................................... 12
4. ANTECEDENTES ......................................................................................................................................... 15
5. NORMAS Y REFERENCIAS ...................................................................................................................... 16
5.1 DISPOSICIONES LEGALES Y NORMAS APLICADAS .................................................................................. 16
5.2 BIBLIOGRAFÍA ...................................................................................................................................... 16
5.2.1 Libros o documentos ............................................................................................................................ 16
5.2.2 Páginas web ......................................................................................................................................... 16
5.3 PROGRAMAS DE CÁLCULO .................................................................................................................... 17
6. DEFINICIONES Y ABREVIATURAS ....................................................................................................... 18
6.1 DEFINICIONES ....................................................................................................................................... 18
6.2 ABREVIATURAS .................................................................................................................................... 18
7. REQUISITOS DE DISEÑO .......................................................................................................................... 19
8. ANÁLISIS DE SOLUCIONES ..................................................................................................................... 20
8.1 LENGUAJE DE PROGRAMACIÓN ............................................................................................................. 20
8.1.1 Alternativas analizadas........................................................................................................................ 20
8.1.2 Solución adoptada ............................................................................................................................... 21
8.2 COMPILADOR ........................................................................................................................................ 22
8.2.1 Soluciones estudiadas .......................................................................................................................... 22
8.2.2 Solución adoptada ............................................................................................................................... 23
8.3 TIPO DE CONEXIÓN ............................................................................................................................... 23
8.3.1 Soluciones estudiadas .......................................................................................................................... 23
8.3.2 Solución adoptada ............................................................................................................................... 23
8.4 DISEÑO DE LA INTERFAZ DE USUARIO .................................................................................................. 24
8.5 LIBRERÍA GRÁFICA 3D .......................................................................................................................... 24
8.5.1 Listado de librerías gráficas analizadas .............................................................................................. 24
8.5.2 Tabla comparativa ............................................................................................................................... 25
8.5.3 Solución adoptada ............................................................................................................................... 26
8.6 ELEMENTOS Y FUNCIONALIDADES DE LAS APLICACIONES DE ROBÓTICA .............................................. 26
9. RESULTADOS FINALES ............................................................................................................................ 27
9.1 INTRODUCCIÓN ..................................................................................................................................... 27
9.2 ARQUITECTURA GENERAL DEL SISTEMA ............................................................................................... 27
9.3 ELEMENTOS DEL SISTEMA..................................................................................................................... 29
9.3.1 Resumen de componentes empleados .................................................................................................. 29
9.3.2 Componentes hardware ....................................................................................................................... 29
2. OBJETO
El objetivo de este proyecto se puede resumir en el desarrollo de una aplicación de
usuario que permita la monitorización de la posición del robot y la simulación de la
cinemática, del robot Staübli RX-60 de que dispone la Universidad de La Rioja (UR) y que se
encuentra ubicado en el laboratorio L-102 de la ampliación del edificio Departamental.
De esta forma los objetivos principales del proyecto quedan indicados en los siguientes
puntos:
3. ALCANCE
El ámbito de este proyecto se centra en el desarrollo de una aplicación informática que
permita comunicar al usuario de la misma mediante comandos básicos con el robot Staübli
RX-60 que se encuentra montado en la UR. El carácter de la aplicación se plantea de un modo
didáctico, teniendo una finalidad educativa en la materia de robótica y permitiendo que sea
empleada en las prácticas de la asignatura “Control y Programación de Robots” que se
imparte en la UR.
Para lograr dicho fin es necesario que se analicen las aplicaciones ya existentes y que
cumplen, al menos en parte, funciones similares. Es por tanto parte de este proyecto:
o Priorizar entre las que admitan varios sistemas operativos para permitir una sencilla
portabilidad a otros sistemas diferentes de aquél en el que se realiza.
o Priorizar entre las de alto rendimiento para poder trabajar casi a “tiempo real”.
Obtener conclusiones sobre las librerías y programas que se van a adoptar para el
desarrollo final de la aplicación.
o Controlar las acciones del usuario mediante la interfaz, así como visionar los datos
calculados.
o Realizar una interfaz simple para la ejecución sencilla y guiada de los comandos
básicos y más habituales disponibles para el controlador del robot.
o Elección del lenguaje de programación que más se adecue a las necesidades del
proyecto que concierne.
Diseño 3D de los modelos para representación virtual del robot. Serán obtenidos de la
página del fabricante.
Detección de colisiones entre piezas del robot o con elementos del entorno.
4. ANTECEDENTES
A continuación se describen los componentes del proyecto que se toman como base de
partida o que vienen impuestos por las características de los elementos que lo componen, y
partir de los cuales y de los requisitos de diseño, se han determinado las diferentes
alternativas.
Brazo robot
El brazo robot real empleado para interactuar con la aplicación es un modelo industrial
RX-60 tipo PUMA de la marca STAÜBLI. Éste brazo robótico es el que se encuentra
disponible para las prácticas de “Control y Programación de Robots”.
La comunicación empleada será por puerto serie mediante protocolo RS-232 debido a
que es la que ya se encuentra instalada y disponible en el laboratorio donde se
encuentra el brazo robot. El controlador del robot también dispone como alternativa a
la comunicación serie de comunicación Ethernet. Sin embargo se opta por la
comunicación serie debido a los conocimiento con que ya cuenta el autor relativos a
ese tipo de comunicación y que se trata de una aplicación didáctica que no requiere una
eficiencia máxima.
Plataforma de trabajo
5. NORMAS Y REFERENCIAS
5.1 DISPOSICIONES LEGALES Y NORMAS APLICADAS
Este proyecto está basado en la norma española UNE-157001, que establece una serie
de criterios generales para la elaboración de proyectos.
5.2 BIBLIOGRAFÍA
[1] Richard S. Wright Jr., Michael Sweet. “OpenGL SuperBible Second Edition”. 2ª ed.,
Waite Group PRESS (2000).
[2] Josie Wernecke. The Inventor Mentor. 2ª ed., Addison Wesley (1995).
Programación
[3] H. M. Deitel, P. J. Deitel. Como programar en C/C++. 2ª ed., Prentice Hall (1995).
[4] Escuela Superior de Ingenieros Técnicos Industriales de San Sebastián. Aprenda C++
como si estuviera en primero.Universidad de Navarra, San Sebastián (1998).
Robótica
[6] V+ Language Users Guide. Versión 11, Manual de referencia del lenguaje de
programación del robot Staübli RX-60.
Simuladores de robótica
[8] http://www.tecnun.es/asignaturas/grafcomp/presentaciones/pdf/libreriasGraficas6.pdf
[10] http://es.scribd.com/doc/59505333/a-Grafica-en-Tiempo-Real
[11]
http://sabia.tic.udc.es/gc/Contenidos%20adicionales/trabajos/MotoresGraficos/MotoresGrafic
os/introduccion.html
[12] http://www.ciens.ucv.ve/escueladecomputacion/documentos/archivo/65
[13] http://www.mendozajullia.com/papers/El%20pipeline%20grafico.pdf
[14] http://books.openlibra.com/pdf/WebGL.pdf
[15] Carlos González Morcillo, Javier A. Albusac Jiménez, Sergio Pérez Camacho, Jorge
López González, César Mora Castro. Desarrollo de videojuegos Programación Gráfica.
Universidad de Castilla- La Mancha.
Programación
[17] C++ con clase. (Curso de programación en C++). Disponible en: http://c.conclase.net/
[18] http://www.americati.com/doc/ventajas_c.pdf
Photoshop CS4
Diagrama de Gantt
GanttProject 2.6.1
Cálculo matricial
Matlab 2008
Mathematica 7
6. DEFINICIONES Y ABREVIATURAS
6.1 DEFINICIONES
Applet
Cadena cinemática
Grados de libertad
Licencia GPL
Licencia LGPL
Licencia MIT
Layout
Robot
Widget
6.2 ABREVIATURAS
DH: Denavit-Hartenberg
7. REQUISITOS DE DISEÑO
Las premisas del proyecto se plantean el desarrollo de una aplicación bajo entorno
Windows® cuyos requisitos iniciales incluyen las siguientes funcionalidades:
Existirán unos paneles para el manejo básico de la cinemática directa e inversa del
brazo robot.
La aplicación será didáctica, por lo que deberá ser de fácil utilización y de manejo
intuitivo.
8. ANÁLISIS DE SOLUCIONES
8.1 LENGUAJE DE PROGRAMACIÓN
Dada la complejidad en cuanto a la necesidad de uso de varias librerías de programación
y al tamaño del proyecto, aun sin incluir muchas funcionalidades, se decide buscar un
lenguaje de programación con el que ya se tuviese cierta familiaridad, siempre que fuera
posible. Esta elección evita la necesidad de tener que partir de cero en el estudio del lenguaje
y permite que se programe con mayor fluidez y que se pueda estudiar y utilizar algún aspecto
más avanzado del lenguaje en cuestión.
8.1.1.1 C++
Por otro lado se trata de un lenguaje que emplea expresiones algo complejas y que no es
fácil de aprender a utilizar bien, siendo especialmente problemático con el uso de punteros si
no tiene un conocimiento adecuado. Sin embargo existe muchísima información sobre su uso
y es fácil encontrar ejemplos para muchos problemas que puedan surgir.
Destaca especialmente en la eficiencia, ya que trabaja a más bajo nivel que los otros
lenguajes anteriormente mencionados, lo que hace posible que un mismo código equivalente
se ejecute con mayor velocidad en este lenguaje.
8.1.1.2 Java
Destaca por su portabilidad a otros sistemas y cuenta con una buena modularidad y es
relativamente sencillo en comparación con C++. Sin embargo su rendimiento es bueno, pero
no lo suficiente para aplicaciones que sean bastante exigentes.
Tiene acceso directo a la API gráfica 3D DirectX, aunque también es posible trabajar
con OpenGL mediante el uso de un componente no oficial.
Una característica muy importante de este lenguaje es que es uno de los lenguajes de
alto nivel más rápido. A pesar de que la aplicación no requerirá una velocidad de
procesado muy alta, sí que es conveniente que se trabaje de forma rápida en el caso de
que se esté monitorizando en tiempo real la posición del robot.
Mayor conocimiento por parte del autor del proyecto de este lenguaje.
8.2 COMPILADOR
Este compilador ha sido uno de los completos para C++, si bien actualmente ha sido
claramente desplazado por el equivalente de Microsoft.
Microsoft Visual C++ proporciona un entorno de desarrollo eficaz y flexible para crear
aplicaciones basadas en Microsoft Windows y en Microsoft .NET. Se puede utilizar como un
sistema de desarrollo integrado o como un conjunto de herramientas individuales. Visual C++
se compone de compilador, una serie de bibliotecas estándar y otras propias como MFC.
La biblioteca MFC permite crear interfaces de forma visual, pero estos componentes
sólo pueden ser ejecutados en plataformas Windows en las versiones modernas de Visual
C++, por lo que esto no es una ventaja.
Las versiones más modernas disponen de una versión gratuita muy completa.
1 puerto DeviceNet
Existen otras similares, por lo que la decisión tampoco es muy decisiva, sin embargo
esta librería dispone de muchísima información bien organizada y estructurada en su página
web y numerosos ejemplos y foros. Es por ello, además de ser multiplataforma y disponer de
muchas útiles funciones que se selecciona esta.
Las librerías seleccionadas para analizar son las que aparecen en el “Anexo III-Estudio
de librerías gráficas existentes en el mercado”. Se han descartado las librerías de bajo nivel
debido a que son más complejas de utilizar cuando se trabaja con escenas que contienen
bastantes elementos y a que es más complejo utilizar características avanzadas. Por el
contrario los grafos de escena ofrecen mejor organización y permiten emplear características
avanzadas sin conocer en detalle qué es lo que sucede a bajo nivel.
Ogre
OpenGL Performer
Open Inventor
OpenSG
OpenSceneGraph
OPENGL
CARACTERÍSTICAS JAVA 3D OGRE OPEN INVENTOR OPENSG OPENSCENEGRAPH
PERFORMER
Sí. Windows, Linux, IRIX, FreeBSD,
Sí (se ejecuta en Sí. Windows, Linux , Sí. Windows, Linux,
Multiplataforma IRIX, Linux, Windows IRIX, Linux, Windows Mac, Solaris, HP-Ux, AIX,
navegador) Mac Solaris, Mac
Playstation 2
Comercial (primeras
Licencia Libre GPLv2 Libre MIT Comercial Libre LGPL Libre LGPL
versiones LGPL)
Eficiencia Alta Media Óptima Media Muy Alta Muy Alta
De entre todas las posibles opciones de la Tabla 1, se han descartado las librerías
comerciales.
Las librerías Java 3D y Ogre también quedan eliminadas debido a que su eficiencia es
un poco menor que la del resto y en este caso interesa la rapidez de procesamiento,
especialmente en el caso de futuras ampliaciones de la aplicación. Tampoco es imprescindible
la capacidad para incrustar la visualización en un navegador ya que queda fuera del propósito
de este proyecto.
9. RESULTADOS FINALES
9.1 INTRODUCCIÓN
Una vez seleccionados los elementos que formarán parte de este proyecto se procede a
explicar la arquitectura general del sistema, es decir, la relación existente entre los elementos
que lo conforman y también se indican algunos aspectos destacables tanto del hardware como
del software que involucra este proyecto.
Se trata de realizar una herramienta útil y a la vez sencilla para aprender los principios
básicos sobre el manejo del brazo robot Stäubli RX60.
Existen distintos programas para distintos sistemas que permiten controlar el brazo
robot, pero debido a la finalidad didáctica del sistema, se opta por el desarrollo de una
aplicación propia.
Software
Software Okino Polytrans 4.1.2 para realizar conversiones entre formatos de modelos
3D
Autocad 2011
El brazo robot al que hace referencia este proyecto es un brazo de tipo PUMA del
fabricante suizo Staübli, concretamente se trata del modelo RX-60. Dispone de seis grados de
libertad, empleando los tres primeros para fijar la posición y los tres últimos, correspondientes
a la muñeca del robot, se utilizan para establecer la orientación.
Los distintos elementos del brazo son: La base (A), el hombro (B), el brazo (C), el codo
(D), el antebrazo (E) y la muñeca (F), véase la Figura 3 y la Figura 4.
Condiciones de trabajo
Articulación
Jt1 Jt2 Jt3 Jt4 Jt5 Jt6
Amplitud [º] 320 255 269 540 230 540
A B C D E F
Distribución del rango +120.5 /
+/-127.5 +/-134.5 +/-270 +/-270
de trabajo [º] +/-160 -109.5
Velocidad Nominal
287 287 319 410 320 700
[º/s]
Resolución angular
0.724 0.724 0.806 1.177 0.879 2.747
[º·10-3]
Tabla 2 Límites de amplitud, velocidad y resolución
El brazo está preparado para obtener las máximas amplitudes angulares. No obstante, la
amplitud de las articulaciones puede ser limitada voluntariamente mediante software.
En las siguientes tablas (véase tabla Tabla 3 y Tabla 4) se refleja la capacidad de carga del
brazo en función de la velocidad y la inercia para las articulaciones 5 y 6 (las cuales pueden
apreciarse en la ).
De entre todas las posibilidades que ofrece el RX60 para realizar la comunicación entre
el sistema de control del brazo robot RX60 y un PC externo que desea controlar de manera
remota el brazo, se menciona y describe la forma de comunicación de más bajo nivel basada
en el establecimiento de un comunicación a través del puerto serie, enviando byte a byte por
medio del puerto RS232.
Comando Acción
Habilita el brazo para poder usarlo. A continuación hay que
enable power
pulsar el botón de encendido del controlador.
disable power Deshabilita el brazo.
where Permite conocer la posición del brazo.
point a Permite definir un punto utilizando coordenadas de
orientación/posición cartesianas {x, y, z, yaw, pitch, roll}.
Permite definir un punto utilizando ángulos de articulación
point #a
{Jt1…Jt6}.
Permite definir la velocidad de sistema como porcentaje de la
speed %vel
velocidad máxima.
do ready Desplaza cada miembro del brazo a su posición de reposo.
Desplaza el miembro eje el número de grados indicado en grad
do drive eje,
al porcentaje de velocidad indicado en vel referido a la
Dgrad,% vel
velocidad de sistema.
do move a Desplaza el brazo a la posición indicada en el punto a, definido a
Después de cada comando, que es tratado como una cadena de caracteres, es necesario
enviar los caracteres ‘\n’ y ‘ \r’ para indicar el fin de comando.
OpenSceneGraph, la cual permitirá desarrollar la interfaz virtual del brazo robot RX-60
en un entorno 3D.
Posee una larga lista de características (ver ANEXO II- Librerías para el desarrollo de la
interfaz de usuario) y a continuación se destacan las más importantes.
Es una librería libre y de código abierto, por lo que se puede ver y modificar cualquiera
de los elementos que la componen. Es una librería madura que ya se ha empleado en múltiples
aplicaciones como Adobe Photshop Album, KDE, Mathematica, Scribus, Skype, VLC Media
Player, etc.
Además posee un editor visual que permite configurar los elementos de la interfaz de
forma sencilla (ver Figura 10).
Figura 10 Qt Designer
Otro aspecto a tener en cuenta es la capacidad que tiene esta librería para trabajar con
“señales” y “ranuras”. Además de los métodos tradicionales de C++ para intercambiar datos
entre funciones, Qt permite conectar señales que envían unos determinados datos a funciones
que recogen y procesan la información, como si se tratase de dispositivos electrónicos
conectados entre sí intercambiando señales a través de sus pines.
Esta librería tiene una alta eficiencia y permite trabajar con múltiples hilos de
procesamiento, lo que aporta un beneficio al rendimiento de la aplicación.
9.6.1 Introducción
Inicialmente, una vez seleccionados los elementos que forman parte del proyecto, se
dedica un tiempo al estudio de aspectos básicos del lenguaje de programación C++ y de las
librerías de software utilizadas.
Esto permite poder abarcar adecuadamente los siguientes pasos, que se han divido en
módulos o elementos más o menos desarrollados de forma independiente y que
posteriormente se han ensamblado para conformar el resultado final.
9.6.2.1.1 Posición
( )
9.6.2.1.2 Traslación
9.6.2.1.3 Orientación
Como ejemplo, la siguiente matriz hace referencia al cambio de orientación del punto 2
visto desde el punto 1:
( )
Las rotaciones no son independientes del orden en el tienen lugar. Se demuestra [ ] que
para rotaciones referidas al sistema relativo de la anterior transformación, la concatenación de
rotaciones da lugar a una matriz de rotación igual al producto matricial de todas ellas en el
orden en el que se han producido. Por el contrario, si las rotaciones son referidas a un marco
de referencia fijo, el resultado será el producto matricial de todas ellas en el orden inverso al
que se han producido.
( )
Consiste en realizar un giro sobre X, otro sucesivo en Y y uno más en Z, todos ellos
respecto a un sistema fijo.
Consiste en realizar un giro sobre el eje Z, otro sucesivo en Y y uno más en Z, todos
ellos respecto al nuevo sistema tras el cambio.
( )
De aquí que para un manipulador con N grados de libertad hay N pares articulación-
elemento con el enlace 0 (no considerado parte del robot) unido a una base soporte donde se
suele establecer un sistema de coordenadas inercial para este sistema dinámico, y el último
elemento está unido a la herramienta. Las articulaciones y elementos se enumeran hacia
afuera desde la base; así la articulación 1 es el punto de conexión entre el elemento 1 y la
base soporte. Cada elemento se conecta, a lo más, a otros dos, así pues no se forman lazos
cerrados.
En general, dos elementos se conectan mediante un tipo de articulación que tiene dos
superficies deslizantes, una sobre la otra, mientras permanecen en contacto. Únicamente son
posibles seis tipos diferentes de articulaciones, siendo la más común en manipuladores la
giratoria.
En resumen, se asocian cuatro parámetros, ai, αi, di y i, con cada elemento de un
manipulador. Si se ha establecido un convenio de signo para cada uno de estos parámetros,
entonces constituyen un conjunto suficiente para determinar completamente la configuración
cinemática de cada elemento del brazo del robot. Obsérvese que estos cuatro parámetros van
apareados: los parámetros del elemento (ai, αi) que determinan la estructura del elemento y los
parámetros de la articulación (di, i) que determinan la posición relativa de los elementos
vecinos.
( )
( ) ( ) ( )
( ) ( )
La cinemática inversa calcula los ángulos que deben tomar las articulaciones a partir de
una posición y orientación indicadas para el extremo de la pinza.
https://secure.staubli.com/Intranet_Applications/Robotics/Group/RobDoc.nsf/ea05b3f4b301f597c1256d5
f005665e8/bc3707ec036c9f6bc12576c700327958/$FILE/page.html
Una vez obtenidos los modelos en formato STEP o IGES, son importados al programa
Okino PolyTrans que realiza la conversión a formato .obj que sí es aceptado por
OpenSceneGraph.
mapeoVistaActiva->setMapping( _filtros[i] , i );
_visores[i]->installEventFilter( _filtros[i] );
}
Para la adición de los modelos se han tenido que realizar transformaciones inversas que
compensen las relativas de cada nodo al que se acoplan para seguir su movimiento, ya que los
modelos venían fijos en una posición y no se pueden asociar a los nodos directamente, sus
transformaciones no se corresponderían con las del robot real.
9.6.4.1 Escena
Esta versión permite definir cuál de los marcos de cada eslabón del robot será el de
referencia y cual el observado. De esa forma se puede observar la posición y orientación no
sólo del extremo final respecto a la base, sino entre cualquier eslabón.
9.6.4.4 Comunicación
Desde el panel se pueden enviar instrucciones de forma libre, de entre todas las que
admite el controlador en lenguaje V+. Desde el panel enviar programa es posible escribir
9.6.4.5 Monitorización
A través del panel de puerto serie se pueden leer estados del robot, por ejemplo
utilizando las instrucciones “STATUS” o “WHERE”.
Es obvio que si se desea disponer de esta funcionalidad, se debe poder acceder al puerto
serie del ordenador e implementar un procedimiento de control del mismo que permita tanto
enviar como recibir secuencias de caracteres que atendiendo al protocolo indicado, tendrán un
significado concreto. En este caso, como ya se ha comentado, se utiliza la librería
QExtSerialPort para tal fin y se programa una interfaz sobre ella.
Cada pin puede ser de entrada o de salida, teniendo una función específica cada uno de
ellos. Las más importantes se muestran en la presentada a continuación.
Pin Descripción
TXD Transmitir Datos
RXD Recibir Datos
DTR Terminal de Datos Listo
DSR Equipo de Datos Listo
RTS Solicitud de Envío
CTS Libre para Envío
DCD Detección de Portadora
Tabla 9 Funcionalidad de pines del puerto serie
Las señales TXD, DTR y RTS son de salida, mientras que RXD, DSR, CTS y DCD
son de entrada. La masa de referencia para todas las señales es SG (Tierra de Señal).
Finalmente, existen otras señales como RI (indicador de llamada), y otras poco comunes que
no se explican en este texto por rebasar el alcance del mismo.
Para controlar al puerto serie, la CPU emplea direcciones de puertos de E/S y líneas de
interrupción (IRQ), estando definido en el estándar las direcciones de los puertos COM1 y
COM2, por lo que al añadir posteriormente otros puertos serie (COM3-COM4), las IRQ no
están especificadas. Cada usuario debe elegirlas de acuerdo a las que tenga libres o el uso que
vaya a hacer de los puertos serie.
Mediante los puertos de E/S se pueden intercambiar datos, mientras que las IRQ
producen una interrupción para indicar a la CPU que ha ocurrido un evento (por ejemplo, que
ha llegado un dato, o que ha cambiado el estado de algunas señales de entrada). La CPU debe
responder a estas interrupciones lo más rápido posible, para que dé tiempo a recoger el dato
antes de que el siguiente lo sobrescriba. Sin embargo, las UART 16550A incluyen unos
buffers de tipo FIFO, dos de 16 bytes (para recepción y transmisión), donde se pueden
guardar varios datos antes de que la CPU los recoja. Esto también disminuye el número de
interrupciones por segundo generadas por el puerto serie.
Tanto el aparato a conectar como el ordenador (o el programa terminal) tienen que usar
el mismo protocolo serie para comunicarse entre sí. Puesto que el estándar RS-232 no
permite indicar en qué modo se está trabajando, es el usuario quien tiene que decidirlo y
configurar ambas partes. Como ya se ha visto, los parámetros que hay que configurar son:
Este último puede ser por hardware (handshaking RTS/CTS) o bien por software
(XON/XOFF, el cual no es muy recomendable ya que no se pueden realizar transferencias
binarias). La velocidad del puerto serie no tiene por qué ser la misma que la de transmisión de
los datos, de hecho debe ser superior. Por ejemplo, para transmisiones de 1200 baudios es
recomendable usar 9600, y para 9600 baudios se pueden usar 38400 (o 19200).
Detección de colisiones.
Conexión remota.
Etc…
DURACIÓN
CÓDIGO DEPENDENCIA DESCRIPCIÓN DE LA ACTIVIDAD
(días)
A - Repaso y estudio de C++ 60
B - Cálculo del modelo cinemático 8
C - Análisis de librerías gráficas 3D 30
D - Análisis de herramientas de robótica 30
E - Análisis de librería para interfaz 30
F C Estudio de librería 3D seleccionada 60
G A Estudio de librería para interfaz seleccionada 60
H (grupo tareas) Desarrollo de la aplicación de software -
H.1 B, F Creación del modelo virtual 3D 30
H.2 G Desarrollo de la interfaz de usuario 60
H.3 H.1 Cinemática directa del robot 30
H.4 H.3 Cinemática inversa del robot 30
H.5 G Comunicación serie RS232 con el controlador 45
H.6 H.3, H.4, H.5 Creación de funciones de comandos V+ 30
I H Pruebas de simulación 15
J I Pruebas de monitorización 15
K I, J Redacción de la documentación 50
Tabla 10Pasos en la planificación del proyecto
DOCUMENTO 3.
ANEXOS
Enero 2013 Ingeniería Técnica Industrial Electrónica
MEMORIA
DISEÑO DE UNA APLICACIÓN PARA LA MONITORIZACIÓN Y SIMULACIÓN DEL ROBOT STAÜBLI RX-60
0. ÍNDICE DE ANEXOS
DOCUMENTO 3. ...................................................................................................... ANEXOS ¡ERROR!
0. ÍNDICE DE ANEXOS .................................................................... ¡ERROR! MARCADOR NO DEFINIDO.
1. ANEXO I – ESTUDIO DE LIBRERÍAS GRÁFICAS EXISTENTES EN EL MERCADO¡ERROR! MARCADOR NO
1.1 CONCEPTOS GENERALES DE LAS LIBRERÍAS GRÁFICAS 3D .............. ¡ERROR! MARCADOR NO DEFINIDO.
1.1.1 Conceptos de librerías gráficas ............................................................. ¡Error! Marcador no definido.
1.2 LIBRERÍAS GRÁFICAS DE BAJO NIVEL EXISTENTES EN EL MERCADO PARA LOS DISTINTOS SISTEMAS
OPERATIVOS ................................................................................................. ¡ERROR! MARCADOR NO DEFINIDO.
1.2.1 Direct3D ................................................................................................ ¡Error! Marcador no definido.
1.2.2 OpenGL (+OpenGL Shading Language, +OpenGL ES) ....................... ¡Error! Marcador no definido.
1.2.3 VRML y X3D .......................................................................................... ¡Error! Marcador no definido.
1.2.4 WebGL ................................................................................................... ¡Error! Marcador no definido.
1.3 LIBRERÍAS GRÁFICAS DE ALTO NIVEL EXISTENTES EN EL MERCADO PARA LOS DISTINTOS SISTEMAS
OPERATIVOS ................................................................................................. ¡ERROR! MARCADOR NO DEFINIDO.
1.3.1 Java 3D .................................................................................................. ¡Error! Marcador no definido.
1.3.2 Ogre ....................................................................................................... ¡Error! Marcador no definido.
1.3.3 OpenGL Performer ................................................................................ ¡Error! Marcador no definido.
1.3.4 Open Inventor ........................................................................................ ¡Error! Marcador no definido.
1.3.5 OpenSG .................................................................................................. ¡Error! Marcador no definido.
1.3.6 OpenSceneGraph ................................................................................... ¡Error! Marcador no definido.
2. ANEXO IV- LIBRERÍAS PARA EL DESARROLLO DE LA INTERFAZ DE USUARIO¡ERROR! MARCADOR NO
2.1.1 Fast Light Toolkit (FLTK) ..................................................................... ¡Error! Marcador no definido.
2.1.2 GTK+ (Gimp Toolkit) ............................................................................ ¡Error! Marcador no definido.
2.1.3 Qt ¡Error! Marcador no definido.
2.1.4 wxWidgets .............................................................................................. ¡Error! Marcador no definido.
3. ANEXO V – ANÁLISIS DE APLICACIONES DE MONITORIZACIÓN Y SIMULACIÓN
COMERCIALES Y GRATUITAS EXISTENTES ........................... ¡ERROR! MARCADOR NO DEFINIDO.
3.1 APLICACIONES DE MONITORIZACIÓN Y SIMULACIÓN COMERCIALES EXISTENTES¡ERROR! MARCADOR NO DEFINIDO.
3.1.1 ABB RobotStudio ................................................................................... ¡Error! Marcador no definido.
3.1.2 FANUC Robotic’s ROBOGUIDE .......................................................... ¡Error! Marcador no definido.
3.1.3 KUKA Sim Pro ....................................................................................... ¡Error! Marcador no definido.
3.1.4 Microsoft Robotics Studio (MRS) .......................................................... ¡Error! Marcador no definido.
3.2 APLICACIONES DE MONITORIZACIÓN Y SIMULACIÓN EDUCATIVAS EXISTENTES¡ERROR! MARCADOR NO DEFINIDO.
3.2.1 RoboAnalyzer ......................................................................................... ¡Error! Marcador no definido.
3.2.2 RoboUALab ........................................................................................... ¡Error! Marcador no definido.
4. ANEXO IX – CÓDIGO DE LA APLICACIÓN .......................... ¡ERROR! MARCADOR NO DEFINIDO.
DOCUMENTO 4. PLANOS ............................................................. ¡ERROR! MARCADOR NO DEFINIDO.
0. ÍNDICE DE PLANOS .................................................................... ¡ERROR! MARCADOR NO DEFINIDO.
Librerías basadas en grafos de escena. Suelen estar basadas en librerías de bajo nivel y
su utilización es más sencilla que las anteriores debido a que realizan una abstracción
mayor de los procesos. Permiten crear escenas virtuales en forma de árbol ramificado,
donde unos elementos pueden depender de otros anteriores.
Toolkits. Suelen ser las más fáciles de aprender a usar e incorporan múltiples
herramientas además de los gráficos 3D, como puede ser sonido, conexión a red,
control de periféricos, etc. Son herramientas más específicas, que no son tan eficientes
pero que permiten abarcar proyectos gráficos complejos que de otra forma serían muy
difíciles de realizar.
Culling:
Codificado que logra que los objetos que no se ven en un determinado momento de la
proyección no sean procesados para que no tomen tiempo en el renderizado, así se
reduce la cantidad del trabajo. Hay varios tipos de culling que pueden ser utilizados.
Entre ellos, merecen citarse el culling de caras traseras (backface culling), culling por
pirámide truncada (frustum culling), culling por portales, culling por oclusión y culling
por contribución.
Doble buffering:
Frame:
En una animación, cada uno de los cuadros o imágenes generadas para simular
movimiento y que se reproducen de forma secuencial.
Modelado geométrico:
Proceso por el que se crean modelos virtuales de elementos reales. Pueden ser en 2D
mediante líneas, puntos y polígonos; o en 3D, mediante mallas poligonales y
subdivisión de superficies.
Modo retenido:
Normal Mapping:
Es la aplicación de una técnica 3D que permite dar una iluminación y relieve muy
detallado a la superficie de un objeto.
Pipeline:
Conjunto de procesos que se desarrollan desde el modelo de la escena virtual hasta que
se representa una parte de ella en la pantalla. Existen una serie de etapas funcionales
que se realizan secuencialmente, sin embargo algunas pueden ejecutarse en paralelo,
aumentando la velocidad de procesado de cada frame.
o Proyección en perspectiva.
Primitivas:
Proceso por el cual se convierten las primitivas en fragmentos que quedan finalmente
como pixeles en el dispositivo de salida.
Renderizado:
Es el proceso de pasos que ejecuta una librería gráfica para representar una escena en
una pantalla. Se compone de:
o Texturas.
o Color.
Shaders:
Stencil Buffer:
Textura:
Junto con la iluminación y sombreado dotan al modelo de más realismo. La textura son
imágenes que se ponen sobre los polígonos.
Viewport:
Z-buffering:
1.2.1 Direct3D
1.2.1.1 Descripción
En 1992, Servan Keondjian fundó RenderMorphics, una compañía que desarrollaba una
API de gráficos 3D llamada Reality Lab. Esta API se usaba en programas de CAD y
representación de imágenes médicas. En febrero de 1995, Microsoft compró RenderMorphics,
incorporando a Keondjian a la compañía para implementar un motor gráfico para Windows
95. El resultado fue la primera versión de Direct3D, incluida en DirectX 2.0 y DirectX 3.0.
Alto rendimiento.
Gracias al modelo COM es independiente del lenguaje, ya que los objetos COM son
simples librerías de código binario.
Más complejo de programar que OpenGL al no ocultar ciertos aspectos de bajo nivel,
pero al mismo tiempo esto aporta una mayor flexibilidad.
Difícil de programar en C.
1.2.2.1 Descripción
En principio Silicon Graphics desarrolló una librería para sus estaciones graficas Iris
que disponían de un hardware especialmente optimizado para visualización de gráficos,
transformadas de matrices, etc. Con el uso de esta librería llamada "Iris GL" conseguían la
independencia del hardware entre sus distintas estaciones Irix.
Fue en 1992 cuando Silicon Graphics presentó una librería llamada OpenGL, evolución
de la antigua Iris GL. En su desarrollo pusieron especial énfasis en su portabilidad,
posibilidades de expansión y por supuesto su rendimiento.
Una de las principales ventajas que aporta OpenGL es que se trata de un estándar
industrial. Gracias a la OpenGL ARB es realmente una tecnología abierta, lo que supone una
ventaja inestimable frente a otras tecnologías. El ARB se fundó en 1992 y estaba formado por
un nutrido conjunto de empresas interesadas en la creación de una API consistente y
ampliamente disponible, entre las que destacan, además de Silicon Graphics, grandes
compañías como Compaq, IBM, Intel, Microsoft, HP, Sun Microsystems, Apple, y
fabricantes de tarjetas gráficas como por ejemplo ATI, nVidia o 3D labs.
Por otra parte, los años que lleva de desarrollo hacen que exista una extensa base de
conocimientos a su alrededor. Durante todo este tiempo se han producido cambios en la
librería, pero OpenGL siempre asegura una compatibilidad "marcha atrás". De esta forma, una
aplicación que se desarrolló usando la primera implementación de la librería, compilaría y
funcionaria con la última versión de la misma.
Por otro lado OpenGL ES hace posible emplear la API OpenGL en dispositivos
embebidos como móviles, portátiles, etc.
Alto rendimiento.
Código libre.
Estándar abierto.
Dispone de la librería GLUT que permite gestionar los eventos de ratón y teclado, así
como trabajar con elementos visuales de interfaz de usuario, todo ello de forma
independiente de la plataforma.
Tiene una arquitectura cliente – servidor, de manera que un programa (cliente) solicita
comandos y éstos son interpretados y procesados por el sistema OpenGL (servidor). No
es necesario que el servidor se sitúe en el mismo ordenador que el cliente, permitiendo
a la especificación OpenGL ser “transparente a la red”.
1.2.3.1 Descripción
Tras una serie de debates en los que se discutieron diferentes propuestas, la alternativa
presentada por Silicon Graphics fue la que consiguió un mayor número de votos,
convirtiéndose de este modo en la base del nuevo estándar. Esta propuesta consistía en utilizar
como punto de partida el lenguaje en el que estaba basado Inventor, un producto de dicha
compañía. Finalmente, en octubre de 1994 se presentó la especificación de VRML 1.0.
A principios de 1996, Silicon Graphics pone a disposición del dominio público QvLib,
el cual se convirtió en el primer parser VRML capaz de traducir el texto de una escena virtual
a un formato entendible por un navegador. Posteriormente aparecería WebSpace, el primer
navegador capaz de leer e interpretar todo el estándar VRML.
La especificación es de 2004.
X3D es una librería gráfica gratuita de estándares abiertos ISO en lo relativo al formato
de ficheros y la arquitectura de trabajo que permite representar y comunicar escenas 3D y
objetos utilizando XML.
VRML es:
o Un navegador VRML/X3D.
Dispone de XML integrado, clave para integrar la librería con servicios web, redes
distribuidas o transferir datos o ficheros entre aplicaciones y distintas plataformas.
Formado por múltiples componentes de manera que sólo es necesario cargar aquellos
que se vayan a utilizar, permitiendo bajo consumo en tiempo de ejecución.
Trabaja con gráficos de alta calidad y en tiempo real, siendo interactiva y permite
incluir audio y video a los datos 3D.
Elementos soportados:
o Gráficos 2d y CAD.
1.2.4 WebGL
1.2.4.1 Descripción
WebGL fue creado inicialmente por Mozilla, y más tarde estandarizado por el grupo
tecnológico Khronos Group, el mismo grupo responsable de OpenGL y OpenGL ES. El
primer prototipo fue diseñado por Mozilla en el año 2006 y a principios del 2009, Mozilla y
Khronos Group comenzaron el WebGL Working Group. Además de los ya mencionados,
actualmente los principales fabricantes de navegadores, Apple (Safari), Google (Chrome) y
Opera (Opera), así como algunos proveedores de hardware son miembros del grupo de trabajo
WebGL o WebGL Working Group. Todos ellos están interesados en verificar que el
contenido WebGL pueda correr tanto en sistemas de escritorio como en hardware de
dispositivos móviles.
1.2.4.2 Características
Es un estándar web.
Puede existir algún problema de seguridad, aunque esto está siendo evaluado
actualmente. Se abre una línea directa desde Internet a la GPU del sistema, abriendo un
gran hueco de seguridad.
1.3.1 Java 3D
Intel, Silicon Graphics, Apple y Sun ya desarrollaban APIs de grafos de escena en modo
retenido en 1996. Debido a que estas compañías deseaban una versión en Java, decidieron
colaborar para obtenerla, iniciándose así el proyecto Java 3D, que comenzó en 1997. La
primera versión apareció en 1998. Desde mediados de 2003 hasta mediados de 2004 se detuvo
su desarrollo y a partir del verano de 2004 Java 3D fue liberado como un proyecto
comunitario, es decir, sólo se liberaba para los miembros de la comunidad que por lo general
son universidades o marcas comerciales, no desarrolladores independientes.
Desde la versión 1.2 viene siendo desarrollado por Java Community Process (JPC) y
desde 2008 el código completo se considera libre y se desarrolla bajo licencia GPL v2.
En comparación a otras soluciones, Java 3D no sólo es una envoltura sobre una API
gráfica, sino que es una interfaz que encapsula la programación de gráficos usando una
aproximación real de orientada a objetos. De esta forma, una escena se construye tomando un
grafo de escena que es una representación de los objetos que van a mostrarse. Este grafo de
escena se estructura como un árbol que contiene varios elementos que son necesarios para
visualizar los objetos. Además, Java 3D ofrece un amplio soporte al sonido espacial.
Bases
Diseño
o Alto rendimiento.
Es multiplataforma.
Es una API genérica para aplicaciones en tiempo real, siendo válida tanto para juegos
como visualizaciones 3D.
Stencil buffer.
Capacidad de importar desde los formatos más típicos como 3DS, OBJ, VRML, X3D,
NWN y FLT.
1.3.2 Ogre
Esta librería trabaja con diseño orientado a objetos y frecuentemente utiliza patrones de
diseño. El equipo encargado del desarrollo del núcleo se mantiene en un número pequeño de
personas de forma intencionada y todos sus miembros son ingenieros de software con amplia
experiencia en el mundo real durante años. Los parches se reciben desde miembros de la
comunidad, pero se someten a una rigurosa revisión de calidad y cohesión con la filosofía de
OGRE antes de poder ser aceptados.
OGRE no asume qué tipo de aplicación se desea desarrollar, sino que usa una jerarquía
de clases flexible que permite realizar cualquier tipo de escena, ofreciendo la posibilidad de
diseñar plugins para ajustar la organización de la escena.
Existe una importante lista de librerías externa que pueden ser integradas y que aportan
funcionalidades extra.
Licencia MIT que permite utilizarla de forma libre siempre y cuando se distribuya una
copia incluyendo el contenido original, aunque no necesariamente las modificaciones
realizadas.
Productividad
o Sistema extensible que hace que las aplicaciones se ejecuten de forma rápida y
simple.
o Soporta las plataformas Windows (todas las versiones principales), Linux y Mac
OSX.
o Carga de texturas en varios formatos de imagen: PNG, JPEG, TGA, BMP o DDS.
También se admiten algunos formatos inusuales como texturas 1D, texturas
volumétricas, mapas cúbicos (“cubemaps”) y texturas comprimidas (DXT o
S3TC).
o Las texturas pueden ser proporcionadas y actualizadas en tiempo real por plugins.
Meshes (Mallas)
Animación
Escenas
o Escenas jerárquicas. Los nodos permiten a los objetos ser unidos entre sí y hacer
que unos objetos sigan los movimientos de otros, crear estructuras articuladas, etc.
Efectos especiales
Funciones misceláneas
o Cuenta con ejemplos para integrar otras librerías externas, como ODE que permite
calcular físicas y colisiones.
Otras características
OpenGL Performer apareció en 1991, año en el que un grupo del proyecto Open
Inventor de SGI decidió enfocarse en el rendimiento gráfico más que en la facilidad de
programación. Performer se centró en un trabajar como un grafo de escena que permitiera
reorganizar y cambiar la gestión de los elementos sobre la marcha, permitiendo que los
distintos pasos en la tarea de renderizado se ejecutaran en paralelo en múltiples hilos. Es
Diseñada para optimizar al máximo la utilización del hardarwe gráfico. Es una librería
muy orientada al mercado de la simulación visual, siendo su mayor prioridad la obtención de
tasas de refresco muy altas, llegando a mantener constantes tasas de 50 frames/segundo.
Esta librería está disponible en varias plataformas: IRIX, Linux, y varias versiones de
Microsoft Windows.
1.3.3.1 Características
Se trata de una API 3D de modo retenido orientado a objetos y que emplea el lenguaje
de programación C++. Actualmente también admite lenguaje .NET y Java.
Diseñada por SGI sobre 1988-1989 con la finalidad de proporcionar una capa de
abstracción para programar OpenGL.
Sus objetivos se basan en una mayor facilidad y comodidad a la hora de programar así
como en la eficiencia. Su estrategia estaba basada en la idea de que la gente desarrollaba
pocas aplicaciones en 3D debido al considerable tiempo que conllevaba su desarrollo con la
interfaz de bajo nivel IRIS GL. Lo que interesaba principalmente era conseguir una gran
facilidad de uso, incluso por encima de eficiencia de uso de recursos del sistema.
Gracias a la librería OpenGL, de bajo nivel, era ya posible tomar listas de polígonos
simples y renderizarlos tan rápido como fuera posible. Pero para que el programador pudiera
dibujar objetos más complejos era necesario que los dividiera en grupos y tomase cada uno de
éstos como una lista de instrucciones simples para ser enviada al motor de renderizado. El
problema que conlleva este método es que puede resultar algo complejo a la par que
ineficiente si no se tiene un conocimiento avanzado de la forma en que trabaja OpenGL. El
rendimiento depende mucho de la forma en que se envía esas instrucciones y de su orden y
además obliga a descartar los datos que no van a ser visibles en la imagen resultante. De esta
manera se requería una gran cantidad de código nada más que para iniciar un sencillo
programa.
Open Inventor (OI) fue escrito para evitar este problema y para proporcionar una base
desde la que partir al desarrollar programas 3D. Dispone de una serie de objetos predefinidos
y se pueden crear subclases a partir de estos transformándolos de manera sencilla en otras
figuras o formas.
OI dispone de un formato propio para almacenar las escenas y cuenta con funciones
para guardar y cargar de forma automática estos datos.
Por todo lo anterior, esta librería permite desarrollar programas en muchas menos
líneas de código. Por otro lado tiende a resultar más lenta que el código de bajo nivel ya que
es difícil optimizar bien de forma automática. Otro problema que surge es que no
necesariamente se trabaja con un único formato de archivo, por lo que se obliga a los
desarrolladores a escribir conversores que permitan el cambio de los datos.
Inventor prima la usabilidad sobre el rendimiento. Está formado por un conjunto muy
elaborado de nodos de uso muy sencillo, pero no proporciona un buen rendimiento en tiempo
real (al menos comparado con otros sistemas como OpenGL Performer).
Inicialmente sólo admitía el lenguaje de programación C++ pero las últimas versiones
también admiten .NET y Java.
Las primeras versiones de SGI tienen licencia GNU LGPL, las últimas de VSG tienen
licencia comercial aunque existe una versión de prueba con tiempo limitado.
Alto rendimiento.
Es extensible de tal modo que es posible crear nuevos tipos de primitivas y objetos.
1.3.5 OpenSG
Uno de los factores más importantes desde el punto de vista de sus desarrolladores es el
deseo de disponer de un sistema gráfico que pueda ser utilizado en multitud de plataformas.
Soporta las plataformas Windows, Linux, Solaris y MacOS X y está basada en OpenGL.
Figura 44 Aplicación creada con OpenSG que permite visualizar un tumor cerebral en renderizado
volumétrico obtenido a partir de una tomografía computerizada
Al igual que la mayoría de los grafos de escena, OpenSG cuenta con una serie de
características comunes a la mayoría de ellos como pueden ser crear nodos de distintos tipos,
posibilidad de cargar geometrías prediseñadas, situarlas en la escena y renderizarlas. Por
tanto, la mayor parte de elementos o funciones que están a disposición del usuario en esta
librería, en torno al 80%, también lo están en otras similares. Pero en lo que destaca es los
elementos que la diferencian, principalmente por su extensibilidad, funcionamiento seguro en
múltiples hilos de procesamiento y capacidad de distribuir el procesamiento entre varias
estaciones de trabajo.
Sus inicios se basan en el proyecto Microsoft Farenheit al contrario que la librería Open
SceneGraph la cual inicialmente se basó en OpenGL Performer. OpenSG pretende hacer los
gráficos más generales y flexibles.
Basada en OpenGL.
Alto rendimiento.
1.3.6 OpenSceneGraph
Fue inicialmente creada por Don Burns en 1998 con la finalidad de poder realizar un
simulador de ala delta, que originalmente fue desarrollado para el sistema operativo IRIX de
SGI ejecutándose con Performer en un PC con Linux. Posteriormente creció y atrajo a una
comunidad en su desarrollo. Este aumento de interés llevó a que uno de los autores, Robert
Osfield, creara una empresa para su soporte. Desde entonces ha existido un continuo esfuerzo
Bases
o Portabilidad. El núcleo del grafo de escena ha sido diseñado para tener una mínima
dependencia en cualquier plataforma específica, requiriendo poco más que C++
Estándar y OpenGL. Este hecho a permitido que esta librería pueda ser convertida
rápidamente a un amplio rango de plataformas (originalmente desarrollado en
IRIX, luego portada a Linux, después a Windows, y posteriormente a FreeBSD,
Mac OSX, Solaris, HP-UX, AIX e incluso Playstation 2).
Licencia
Otras
Los formatos de imagen soportados son .rgb, .gif, .jpg, .png, .tiff, .pic, .bmp, .dds
(incluyendo grupos de imágenes comprimidas), .tga y quicktime (bajo OSX).
También es posible cargar una amplia gama de fuente de alta calidad con
“antialiasing” mediante el plugin freetype e imágenes basadas en fuentes a través
del plugin .txf.
Los usuarios también pueden generar bases de datos geoespaciales de gran escala
mediante el proyecto relacionado denominado VirtualPlanetBuilder y pueden
utilizar la paginación de bases de datos nativa de OpenScenGrpah para visualizar
estas bases de datos.
o Documentación.
Se trata de una librería para desarrollo de interfaces en C++ que soporta sistemas
Windows, Linux/Unix y MacOS.
Se trata de una librería de rápido funcionamiento, muy bajo consumo de memoria y que
ocupa muy poco tamaño, siendo especialmente útil para utilizar en sistemas Linux embebidos.
La priorización de velocidad y consumo de recursos con que cuenta sin embargo suponen
algunas restricciones de apariencia y funcionalidad.
http://www.fltk.org/index.php
Principalmente pensada para entornos gráficos GNOME, XFCE y ROX, se puede usar
también en Windows, Linux, MacOS y otras plataformas móviles (OpenMoko para teléfonos
móviles y Maemo para tablets).
Escrita en C, pero permite trabajar también con otros lenguajes como, C++, C#, Perl,
Python, Java, Javascript, PHP, Ruby, Pascal, R, etc. Con la herramienta “Glade GUI Builder”
es posible diseñar interfaces en GTK+ de forma visual e interactiva.
La licencia que posee es LGPL, software libre y gratuito que debe mantenerse libre aun
cuando se emplee dentro de aplicaciones propietarias por las cuales se cobre.
Se trata de una librería estable ya que lleva más de una década de desarrollo (desde
1998), tiene buen rendimiento y es soportada por una gran comunidad de desarrolladores.
Otras funciones que admite gracias a estar basada en la librería GLib son: trabajo con
objetos, dispone de un” loop” principal, soporte de “threads” o hilos de procesamiento en
paralelo, “timers”, listas, vectores, tablas, árboles, dispone de intérprete XML, etc.
Cuenta con una amplia documentación con imágenes y algunos ejemplos de código. A
esto hay que añadir algunos tutoriales los cuales no están todos disponibles o completos ya
que se van completando poco a poco por la comunidad. Existe también algún libro para
aprender a utilizar esta librería.
http://www.gtk.org/
2.1.3 Qt
Figura 48
Se trata de software libre y de código abierto con licencia LGPL, aunque existen
también licencias comerciales. Soportada por la comunidad y varias empresas como Nokia,
Digia y otras.
Su API dispone de métodos para acceder a bases de datos mediante SQL, uso de XML,
soporte de red, gestión de múltiples hilos de procesamiento, manipulación de archivos de
forma unificad en las distintas plataformas, manejo de ficheros y directorios y estructuras de
datos típicas.
Se trata de una librería muy grande, que si bien aporta muchos elementos y soluciones
es costosa de conocer en profundidad.
2.1.4 wxWidgets
Se trata de una librería en C++ que permite a los desarrolladores crear aplicaciones en
Es posible programar con otros lenguajes, siendo algunos de los más populares Python,
Perl y Ruby.
Contiene widgets simples y otros más avanzados como árboles, listas, soporte
multidocumento, barras de herramientas, etc. Admite extensiones y mejoras.
Tiene otras características avanzadas como: soporte para multithread, bases de datos,
modelo vista/documento, manejar de archivos y directorios, manejo de HTML y redes
TCP/IP, gráficos 2d, integración de OpenGL, diseño de diagramas, idiomas, etc.
Cuenta con herramientas que ayudan a depurar las aplicaciones desarrolladas. Soporta la
mayoría de los compiladores.
Existen herramientas que permiten diseñar la interfaz de forma visual con wxWidgets,
algunas gratuitas como wxFormBuilder, wxDev-C++, o wxGlade y otras propietarias como
wxDesigner o wxForms.
Se trata de una librería con amplia experiencia, ya que se lleva desarrollando desde el
año 1992.
La herramienta ABB RobotStudio permite trabajar con los robots de la marca ABB,
haciendo posible la realización de tareas reales con conexión al robot o la simulación de esas
tareas mediante el uso de un controlador virtual.
Reducción de riesgos
Aumento de la productividad
RobotStudio se basa en el controlador virtual de ABB, una copia exacta del software
real que emplean los robots en la producción. Ello permite ejecutar simulaciones muy
realistas, utilizando programas de robots reales y archivos de configuración idénticos a los
que se emplean en la fábrica.
3.1.1.1 Características
Importación de CAD desde los principales formatos como IGES, STEP, VRML,
VDAFS, ACIS y CATIA. Esto permite trabajar con modelos generados con gran
precisión.
AutoPath es una función que permite al importar una pieza CAD, que se calcule de
manera totalmente automatizada y en poco tiempo la trayectoria que debe seguir la
herramienta del robot para seguir la curva de la pieza.
Detección de colisiones.
Carga y descarga reales de los programas al sistema real sin necesidad de ninguna
conversión.
Puede crear Tablas de Eventos, una herramienta ideal para verificar la estructura del
programa y su lógica. Cuando se ejecuta el programa, se pueden visualizar los estados
de las E/S de su célula de trabajo. Las E/S se pueden conectar a los eventos de
simulación permitiendo la simulación del robot y de todo el equipamiento de la célula
de trabajo. Es una herramienta muy interesante para los trabajos de depuración.
Visual Basic for Applications (VBA) hace posible adaptar y ampliar la funcionalidad
RobotStudio. VBA permite la creación de plugins, macros o interfaces de usuario
personalizados para adaptarse a las necesidades del usuario.
Las aplicaciones específicas permiten trabajar de forma muy eficiente en las tareas para
las que han sido diseñadas.
3.1.2.1 Características
o Fácil de utilizar con Virtual Teach Pendant (menús y pantallas iguales a las del
robot real).
Unidad de aprendizaje virtual, fácil de utilizar y con menús y pantallas iguales a las del
robot real. Fácil de utilizar, no es necesario una formación especial.
Incluye una herramienta de visión por ordenador, la cual permite simular una cámara
acoplada al extremo del robot y ofrece opciones de aprendizaje y detección de objetos a
través de los elementos virtuales de la simulación.
Simulación de alta precisión de todos los comandos de los robots FANUC soportados.
Figura 51
3.1.3.1 Características
Modularidad
o La biblioteca incluye una amplia gama de componentes eficientes que no son sólo
geométricos, sino que además tienen en parte una estructura paramétrica y cuentan
con un comportamiento que puede aplicarse directamente en la simulación (p. ej.
cintas transportadoras, barreras luminosas, etc.). Este principio modular evita que
los componentes tengan que ser dibujados de nuevo y supone por lo tanto un
ahorro considerable de tiempo.
o KUKA Sim Pro dispone, además, de un lenguaje abierto para crear archivos de
órdenes, Python 2.6, con el que puede ampliarse el comportamiento de los
componentes de forma flexible.
o Los formatos CAD estándar que pueden importarse son: STL (Binario/ASCII),
3DS, VRML1, Robface y Google Sketchup.
o KUKA Sim Pro dispone de una amplia gama de funciones API y COM con las que
se pueden programar y utilizar Plug-Ins propios para KUKA Sim Pro.
Simulación
o Es posible utilizar las funciones de KUKA Sim Pro y KUKA OfficeLite para crear
un programa de robot KRL.
Ficheros CAD
o Con KUKA. Sim Pro pueden importarse los siguientes ficheros CAD opcionales:
CATIA V5, CATIA V4, Siemens NX, JT, STEP, Parasolid, ProE, SolidWorks,
ACIS, IDEAS, IGES.
Comunicación
o Una vez elaborado el diseño, es posible crear un fichero PDF 3D con el software
KUKA Sim. Los ficheros PDF 3D pueden abrirse y visualizarse con Adobe
Acrobat Reader. El proceso creado en la célula de trabajo se muestra en el PDF en
forma de animación tridimensional. El complemento perfecto para poner los
resultados de su simulación a disposición de sus clientes.
Es un software que presenta gran compatibilidad con todos los kits de desarrollo que
existen en el mercado, intentando presentarse como el entorno de programación común entre
los diversos kits de desarrollo.
Uno de los puntos destacados es que gracias a la utilización de una biblioteca, basada en
.NET, se consigue que el desarrollo de aplicaciones asíncronas sea algo sencillo. También hay
que remarcar, la arquitectura orientada a servicios y basada en mensajes, que facilita en gran
medida el acceso al estado de los sensores y actuadores del robot tanto a través de un
navegador Web como a través de la programación. Esto se consigue debido a que el entorno
está compuesto de modelos que permiten construir funciones de alto nivel usando
componentes sencillos y facilitando la reutilización del código de los módulos, la calidad y la
sencilla sustitución del mismo.
Figura 52
3.1.4.1 Características
El renderizado 3D utiliza XNA, que implementa DirectX. XNA es una API para el
desarrollo de videojuegos para PC.
Controla dispositivos de entrada, como son webcam, teclado, controles xbox entre
otros.
3.2.1 RoboAnalyzer
3.2.2 RoboUALab
#ifndef VENTANAPRINCIPAL_H
#define VENTANAPRINCIPAL_H
// CABECERAS
//---------------------------------------------------------------------
#include <QtGui/QMainWindow>
#include <QtGui/QMenu>
#include <QtGui/QAction>
#include <QtGui/QKeySequence>
#include "ui_ventanaPrincipal.h"
#include "qosgwidget.h" //clase de visor 3D
namespace Ui {
class ventanaPrincipal;
}
public:
explicit ventanaPrincipal(QWidget *parent = 0);
~ventanaPrincipal();
Ui::ventanaPrincipal *getUiHandler();
private:
//definiendo la interfaz de la clase como un puntero
//es posible el encapsulamiento haciendo los miembros
//de la interfaz privados y ademas permite un facil
//cambio de interfaz en caso de ser necesario
Ui::ventanaPrincipal *ui;
QAction *_accionSalir;
QAction *_accionMover;
QAction *_accionProgramar;
QMenu *_menuArchivo;
QMenu *_menuPaneles;
ViewerWidget **_visores3D;
void _crearAcciones();
void _crearMenus();
public slots:
void ocultaItems(bool);
void verPanelMover();
void verPanelPrograma();
ViewerWidget* visor3D(int fil=0, int col=0);
#endif // VENTANAPRINCIPAL_H
#ifndef VENTANAPRINCIPAL_H
#define VENTANAPRINCIPAL_H
// CABECERAS
//---------------------------------------------------------------------
#include <QtGui/QMainWindow>
#include <QtGui/QMenu>
#include <QtGui/QAction>
#include <QtGui/QKeySequence>
#include "ui_ventanaPrincipal.h"
#include "qosgwidget.h" //clase de visor 3D
namespace Ui {
class ventanaPrincipal;
}
public:
explicit ventanaPrincipal(QWidget *parent = 0);
~ventanaPrincipal();
Ui::ventanaPrincipal *getUiHandler();
private:
//definiendo la interfaz de la clase como un puntero
//es posible el encapsulamiento haciendo los miembros
//de la interfaz privados y ademas permite un facil
//cambio de interfaz en caso de ser necesario
Ui::ventanaPrincipal *ui;
QAction *_accionSalir;
QAction *_accionMover;
QAction *_accionProgramar;
QMenu *_menuArchivo;
QMenu *_menuPaneles;
ViewerWidget **_visores3D;
void _crearAcciones();
void _crearMenus();
public slots:
void ocultaItems(bool);
void verPanelMover();
void verPanelPrograma();
ViewerWidget* visor3D(int fil=0, int col=0);
};
#endif // VENTANAPRINCIPAL_H
#ifndef VENTANAPRINCIPAL_H
#define VENTANAPRINCIPAL_H
// CABECERAS
//---------------------------------------------------------------------
#include <QtGui/QMainWindow>
#include <QtGui/QMenu>
#include <QtGui/QAction>
#include <QtGui/QKeySequence>
#include "ui_ventanaPrincipal.h"
#include "qosgwidget.h" //clase de visor 3D
namespace Ui {
class ventanaPrincipal;
}
public:
explicit ventanaPrincipal(QWidget *parent = 0);
~ventanaPrincipal();
Ui::ventanaPrincipal *getUiHandler();
private:
//definiendo la interfaz de la clase como un puntero
//es posible el encapsulamiento haciendo los miembros
//de la interfaz privados y ademas permite un facil
//cambio de interfaz en caso de ser necesario
Ui::ventanaPrincipal *ui;
QAction *_accionSalir;
QAction *_accionMover;
QAction *_accionProgramar;
QMenu *_menuArchivo;
QMenu *_menuPaneles;
ViewerWidget **_visores3D;
void _crearAcciones();
void _crearMenus();
public slots:
void ocultaItems(bool);
void verPanelMover();
void verPanelPrograma();
ViewerWidget* visor3D(int fil=0, int col=0);
};
#endif // VENTANAPRINCIPAL_H
// CABECERAS
//---------------------------------------------------------------------
#include "ventanaPrincipal.h" //clase de ventana principal
#include "ventanaMensajes.h" //clase de ventana de mensajes de
depuracion
#include "panelSerie.h" //clase de panel de conexion y transmision
por el puerto serie RS232
#include "qosgwidget.h" //clase de visor 3D
#include "StaubliRX60.h" //clase de robot Staubli - modelo RX60
// VARIABLES GLOBALES
//---------------------------------------------------------------------
// Punteros a ventanas y sus interfaces
ventanaPrincipal *v_Principal; //para acceder a la ventana principal
Ui::ventanaPrincipal *guiMain; //para acceder a la interfaz de la
ventana principal
StaubliRX60 *robot;
// PROGRAMA PRINCIPAL
//---------------------------------------------------------------------
int main( int argc, char** argv )
{
// Crear la aplicacion principal
QApplication app(argc, argv);
// Traduccion ...?
/*
ViewerWidget *visor3D_2 = new ViewerWidget();
visor3D_2 = v_Principal->visor3D(1,2);
robot = new StaubliRX60( visor3D_2 );
visor3D_2->sceneRead(robot->readRoot());
*/
#ifndef STAUBLIRX60_H
#define STAUBLIRX60_H
#include <QtCore/QObject>
#include <QtCore/QSignalMapper>
#include <osgDB/ReadFile>
#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>
#include "ventanaPrincipal.h"
#include "ui_ventanaPrincipal.h"
#include "qosgwidget.h"
public:
StaubliRX60(ViewerWidget *viewWidget);
void createScene();
void coordenadas_extremo();
void cinemDirecta();
private:
//TIPO DE CONFIGURACIÓN
bool brazoIzq; // true: Brazo Izquierdo, false: Brazo
Derecho
bool codoAbajo; // true: Codo Abajo, false: Codo
Arriba
bool wrist;
//REPRESENTACION 3D
//---------------------------------------
//Puntero al visor OSG
ViewerWidget *vOSG;
osg::ref_ptr<osg::Geode> center6;
//Ejes
QSignalMapper *signalMapper;
osg::MatrixTransform* jAxis0;
osg::MatrixTransform* jAxis1;
osg::MatrixTransform* jAxis2;
osg::MatrixTransform* jAxis3;
osg::MatrixTransform* jAxis4;
osg::MatrixTransform* jAxis5;
osg::MatrixTransform* jAxis6;
osg::ref_ptr<osg::Geode> destino;
osg::ref_ptr<osg::ShapeDrawable> shapeDestino;
osg::ref_ptr<osg::Box> puntoDestino;
//Punto que indica la posicion a alcanzar por la muñeca
osg::ref_ptr<osg::Geode> Wrist;
osg::ref_ptr<osg::ShapeDrawable> shapeWrist;
osg::ref_ptr<osg::Box> puntoWrist;
//---------------------------------------
public slots:
void changeAngle1_actual();
void changeAngle2_actual();
void changeAngle3_actual();
void changeAngle4_actual();
void changeAngle5_actual();
void changeAngle6_actual();
void GBox_accion();
void animar();
void animacion();
void habilitar_botones();
void actualizarMinMax();
void resetPosicion();
void cinemInversa();
void changeBrazoIzq(int);
void changeCodoAbajo(int);
void changeWrist(int);
void visibleAxis(int);
signals:
void value1Changed(QString str_ang1);
};
#endif // STAUBLIRX60_H
#include "StaubliRX60.h"
#include <QString>
StaubliRX60::StaubliRX60(ViewerWidget *viewWidget)
{
//Vectores unitarios
vecUnit_i = osg::Vec3f( 1.0f, 0.0f, 0.0f ); //otra forma de
inicializar
//vecUnit_i.set( 1.0f, 0.0f, 0.0f );
vecUnit_j.set( 0.0f, 1.0f, 0.0f );
vecUnit_k.set( 0.0f, 0.0f, 1.0f );
/*
angulo1 = 0.0; ang1max = 360.0; ang1min = -360.0;
angulo2 = 0.0; ang2max = 360.0; ang2min = -360.0;
angulo3 = 0.0; ang3max = 360.0; ang3min = -360.0;
angulo4 = 0.0; ang4max = 360.0; ang4min = -360.0;
angulo5 = 0.0; ang5max = 360.0; ang5min = -360.0;
angulo6 = 0.0; ang6max = 360.0; ang6min = -360.0;
*/
//guiMain->DSpinBox1_actual->setMaximum(ang1max);
guiMain->DSpinBox1_actual->setMaximum(ang1max);
guiMain->DSpinBox2_actual->setMaximum(ang2max);
guiMain->DSpinBox3_actual->setMaximum(ang3max);
guiMain->DSpinBox4_actual->setMaximum(ang4max);
guiMain->DSpinBox5_actual->setMaximum(ang5max);
guiMain->DSpinBox6_actual->setMaximum(ang6max);
guiMain->DSpinBox1_actual->setMinimum(ang1min);
guiMain->DSpinBox2_actual->setMinimum(ang2min);
guiMain->DSpinBox3_actual->setMinimum(ang3min);
guiMain->DSpinBox4_actual->setMinimum(ang4min);
guiMain->DSpinBox5_actual->setMinimum(ang5min);
guiMain->DSpinBox6_actual->setMinimum(ang6min);
guiMain->DSpinBox1_max->setValue(ang1max);
guiMain->DSpinBox2_max->setValue(ang2max);
guiMain->DSpinBox3_max->setValue(ang3max);
guiMain->DSpinBox4_max->setValue(ang4max);
guiMain->DSpinBox5_max->setValue(ang5max);
guiMain->DSpinBox6_max->setValue(ang6max);
vel = 0.0;
//-----------------------------------------------------------------
---
this->createScene();
//Conexiones para modificar los valores max y min de los angulos desde
la interfaz
connect( guiMain->DSpinBox1_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox1_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox2_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox2_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox3_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox3_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox4_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox4_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox5_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox5_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox6_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox6_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
void StaubliRX60::createScene()
{
//Las coordenadas globales en OSG creo que corresponden con
//la del sistema de referencia xyz0
root->addChild ( center0 );
root->addChild ( model_base );
root->addChild ( joint1 );
joint1->addChild ( center1 );
joint1->addChild ( model_hombro );
joint1->addChild ( joint2 );
joint2->addChild ( center2 );
joint2->addChild ( model_brazo );
joint2->addChild ( joint3 );
joint3->addChild ( center3 );
joint3->addChild ( model_codo );
joint3->addChild ( joint4 );
joint4->addChild ( center4 );
joint4->addChild ( model_antebrazo );
joint4->addChild ( joint5 );
joint5->addChild ( center5 );
joint5->addChild ( model_eje5 );
joint5->addChild ( joint6 );
joint6->addChild ( center6 );
joint6->addChild ( model_eje6 );
//-------------------------------------------------------------------------
------
//------------------------------------------ EJES -------------------------
------
//eje0 fijo de referencia
jAxis0 = new osg::MatrixTransform;
root->addChild( jAxis0 );
this->createAxis(jAxis0); //ejes
this->createAxis(jAxis1); //ejes
this->createAxis(jAxis2); //ejes
this->createAxis(jAxis3); //ejes
this->createAxis(jAxis4); //ejes
this->createAxis(jAxis5); //ejes
this->createAxis(jAxis6); //ejes
//this->createAxis(joint2);//borrarrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
//Punto destino
MTdestino = new osg::MatrixTransform();
destino = new osg::Geode;
shapeDestino = new osg::ShapeDrawable;
puntoDestino = new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f),0.1f);
this->createAxis(MTdestino,0.4,0.01);
//Punto muñeca
MTWrist = new osg::MatrixTransform();
Wrist = new osg::Geode;
shapeWrist = new osg::ShapeDrawable;
puntoWrist = new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f),0.1f);
this->createAxis(MTWrist,0.4,0.01);
void StaubliRX60::changeAngle1_actual()
{
angulo1 = guiMain->DSpinBox1_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
void StaubliRX60::changeAngle2_actual()
{
angulo2 = guiMain->DSpinBox2_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle3_actual()
{
angulo3 = guiMain->DSpinBox3_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle4_actual()
{
angulo4 = guiMain->DSpinBox4_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle5_actual()
{
angulo5 = guiMain->DSpinBox5_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle6_actual()
{
angulo6 = guiMain->DSpinBox6_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::coordenadas_extremo()
{
//ejecutar esto al principio
float extremoX , extremoY , extremoZ;
extremoX = posExtremo.x();
extremoY = posExtremo.y();
extremoZ = posExtremo.z();
//----------------------------
void StaubliRX60::GBox_accion()
{
if ( guiMain->act_botones->isChecked() && nrbton!=0 )
{
habilitar_botones();
nrbton = 0;
return;
}
void StaubliRX60::animar()
{
guiMain->DSpinBox1_actual->disconnect();
guiMain->DSpinBox2_actual->disconnect();
guiMain->DSpinBox3_actual->disconnect();
guiMain->DSpinBox4_actual->disconnect();
guiMain->DSpinBox5_actual->disconnect();
guiMain->DSpinBox6_actual->disconnect();
guiMain->btn_home->disconnect();
guiMain->btn_situar->disconnect();
void StaubliRX60::animacion()
{
if (angulo1 >= 360) { angulo1 = angulo1 - 360; }
this->angulo1 += vel;
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::habilitar_botones()
{
vOSG->_timer.disconnect(this); //detiene la animacion
v_Principal->disconnect();
//Se emiten señales cuando cambian los valores de los SpinBox o cuando
se pulsa Enter
QObject::connect( guiMain->DSpinBox1_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle1_actual()));
QObject::connect( guiMain->DSpinBox2_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle2_actual()));
QObject::connect( guiMain->DSpinBox3_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle3_actual()));
QObject::connect( guiMain->DSpinBox4_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle4_actual()));
QObject::connect( guiMain->DSpinBox5_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle5_actual()));
QObject::connect( guiMain->DSpinBox6_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle6_actual()));
void StaubliRX60::actualizarMinMax()
{
guiMain->DSpinBox1_actual->setMinimum( guiMain->DSpinBox1_min->value()
);
guiMain->DSpinBox2_actual->setMinimum( guiMain->DSpinBox2_min->value()
);
guiMain->DSpinBox3_actual->setMinimum( guiMain->DSpinBox3_min->value()
);
guiMain->DSpinBox4_actual->setMinimum( guiMain->DSpinBox4_min->value()
);
guiMain->DSpinBox5_actual->setMinimum( guiMain->DSpinBox5_min->value()
);
guiMain->DSpinBox6_actual->setMinimum( guiMain->DSpinBox6_min->value()
);
guiMain->DSpinBox1_actual->setMaximum( guiMain->DSpinBox1_max->value()
);
guiMain->DSpinBox2_actual->setMaximum( guiMain->DSpinBox2_max->value()
);
guiMain->DSpinBox3_actual->setMaximum( guiMain->DSpinBox3_max->value()
);
guiMain->DSpinBox4_actual->setMaximum( guiMain->DSpinBox4_max->value()
);
guiMain->DSpinBox5_actual->setMaximum( guiMain->DSpinBox5_max->value()
);
guiMain->DSpinBox6_actual->setMaximum( guiMain->DSpinBox6_max->value()
);
}
void StaubliRX60::resetPosicion()
{
//angulo1, angulo2, angulo3, angulo4, angulo5, angulo6 = 0.0;
guiMain->DSpinBox1_actual->setValue(0.0);
changeAngle1_actual();
changeAngle2_actual();
changeAngle3_actual();
changeAngle4_actual();
changeAngle5_actual();
changeAngle6_actual();
void StaubliRX60::cinemDirecta()
{
//Hay que escribir las matrices por columnas en lugar de por filas, es
decir,
//como si fueran las traspuestas para que los calclculos en C++ y OSG
sean correctos
osg::Matrixf A01 ( sin(ang1), -cos(ang1), 0.0f, 0.0f,
0.0f, 0.0f, -1.0f,
0.0f,
cos(ang1), sin(ang1), 0.0f, 0.0f,
0.0f, 0.0f, d1, 1.0f
);
MActualState = A06;
}
previousJoint->addChild(zmt);
osg::ShapeDrawable *zShape = new osg::ShapeDrawable(new
osg::Cylinder(osg::Vec3(0.0f,0.0f,height/2),radius,height),hints);
osg::ShapeDrawable *zCone = new osg::ShapeDrawable(new
osg::Cone(osg::Vec3(0.0f,0.0f,0.0f),radius*3,0.2),hints);
zmtCone->setMatrix( osg::Matrix::translate(0.0,0.0,height));
previousJoint->addChild(xmt);
xmtCone->setMatrix( osg::Matrix::translate(0.0,0.0,height));
//-------------------------------------------------------------------------
--------------------------
osg::MatrixTransform *ymt = new osg::MatrixTransform();
previousJoint->addChild(ymt);
ymtCone->setMatrix( osg::Matrix::translate(0.0,0.0,height));
#include "StaubliRX60.h"
#include <QString>
StaubliRX60::StaubliRX60(ViewerWidget *viewWidget)
{
//Vectores unitarios
vecUnit_i = osg::Vec3f( 1.0f, 0.0f, 0.0f ); //otra forma de
inicializar
//vecUnit_i.set( 1.0f, 0.0f, 0.0f );
vecUnit_j.set( 0.0f, 1.0f, 0.0f );
vecUnit_k.set( 0.0f, 0.0f, 1.0f );
/*
angulo1 = 0.0; ang1max = 360.0; ang1min = -360.0;
angulo2 = 0.0; ang2max = 360.0; ang2min = -360.0;
angulo3 = 0.0; ang3max = 360.0; ang3min = -360.0;
angulo4 = 0.0; ang4max = 360.0; ang4min = -360.0;
angulo5 = 0.0; ang5max = 360.0; ang5min = -360.0;
angulo6 = 0.0; ang6max = 360.0; ang6min = -360.0;
*/
//guiMain->DSpinBox1_actual->setMaximum(ang1max);
guiMain->DSpinBox1_actual->setMaximum(ang1max);
guiMain->DSpinBox2_actual->setMaximum(ang2max);
guiMain->DSpinBox3_actual->setMaximum(ang3max);
guiMain->DSpinBox4_actual->setMaximum(ang4max);
guiMain->DSpinBox5_actual->setMaximum(ang5max);
guiMain->DSpinBox6_actual->setMaximum(ang6max);
guiMain->DSpinBox1_actual->setMinimum(ang1min);
guiMain->DSpinBox2_actual->setMinimum(ang2min);
guiMain->DSpinBox3_actual->setMinimum(ang3min);
guiMain->DSpinBox4_actual->setMinimum(ang4min);
guiMain->DSpinBox5_actual->setMinimum(ang5min);
guiMain->DSpinBox6_actual->setMinimum(ang6min);
guiMain->DSpinBox1_max->setValue(ang1max);
guiMain->DSpinBox2_max->setValue(ang2max);
guiMain->DSpinBox3_max->setValue(ang3max);
guiMain->DSpinBox4_max->setValue(ang4max);
guiMain->DSpinBox5_max->setValue(ang5max);
guiMain->DSpinBox6_max->setValue(ang6max);
vel = 0.0;
//-----------------------------------------------------------------
---
this->createScene();
//Conexiones para modificar los valores max y min de los angulos desde
la interfaz
connect( guiMain->DSpinBox1_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox1_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox2_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox2_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox3_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox3_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox4_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox4_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox5_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox5_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox6_min, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
connect( guiMain->DSpinBox6_max, SIGNAL(valueChanged(double)), this,
SLOT(actualizarMinMax()) );
void StaubliRX60::createScene()
{
//Las coordenadas globales en OSG creo que corresponden con
//la del sistema de referencia xyz0
root->addChild ( center0 );
root->addChild ( model_base );
root->addChild ( joint1 );
joint1->addChild ( center1 );
joint1->addChild ( model_hombro );
joint1->addChild ( joint2 );
joint2->addChild ( center2 );
joint2->addChild ( model_brazo );
joint2->addChild ( joint3 );
joint3->addChild ( center3 );
joint3->addChild ( model_codo );
joint3->addChild ( joint4 );
joint4->addChild ( center4 );
joint4->addChild ( model_antebrazo );
joint4->addChild ( joint5 );
joint5->addChild ( center5 );
joint5->addChild ( model_eje5 );
joint5->addChild ( joint6 );
joint6->addChild ( center6 );
joint6->addChild ( model_eje6 );
//-------------------------------------------------------------------------
------
//------------------------------------------ EJES -------------------------
------
//eje0 fijo de referencia
jAxis0 = new osg::MatrixTransform;
root->addChild( jAxis0 );
this->createAxis(jAxis0); //ejes
this->createAxis(jAxis1); //ejes
this->createAxis(jAxis2); //ejes
this->createAxis(jAxis3); //ejes
this->createAxis(jAxis4); //ejes
this->createAxis(jAxis5); //ejes
this->createAxis(jAxis6); //ejes
//this->createAxis(joint2);//borrarrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
//Punto destino
MTdestino = new osg::MatrixTransform();
destino = new osg::Geode;
shapeDestino = new osg::ShapeDrawable;
puntoDestino = new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f),0.1f);
this->createAxis(MTdestino,0.4,0.01);
//Punto muñeca
MTWrist = new osg::MatrixTransform();
Wrist = new osg::Geode;
shapeWrist = new osg::ShapeDrawable;
puntoWrist = new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f),0.1f);
this->createAxis(MTWrist,0.4,0.01);
void StaubliRX60::changeAngle1_actual()
{
angulo1 = guiMain->DSpinBox1_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
void StaubliRX60::changeAngle2_actual()
{
angulo2 = guiMain->DSpinBox2_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle3_actual()
{
angulo3 = guiMain->DSpinBox3_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle4_actual()
{
angulo4 = guiMain->DSpinBox4_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle5_actual()
{
angulo5 = guiMain->DSpinBox5_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::changeAngle6_actual()
{
angulo6 = guiMain->DSpinBox6_actual->value();
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::coordenadas_extremo()
{
//ejecutar esto al principio
float extremoX , extremoY , extremoZ;
extremoX = posExtremo.x();
extremoY = posExtremo.y();
extremoZ = posExtremo.z();
//----------------------------
void StaubliRX60::GBox_accion()
{
if ( guiMain->act_botones->isChecked() && nrbton!=0 )
{
habilitar_botones();
nrbton = 0;
return;
}
void StaubliRX60::animar()
{
guiMain->DSpinBox1_actual->disconnect();
guiMain->DSpinBox2_actual->disconnect();
guiMain->DSpinBox3_actual->disconnect();
guiMain->DSpinBox4_actual->disconnect();
guiMain->DSpinBox5_actual->disconnect();
guiMain->DSpinBox6_actual->disconnect();
guiMain->btn_home->disconnect();
guiMain->btn_situar->disconnect();
void StaubliRX60::animacion()
{
if (angulo1 >= 360) { angulo1 = angulo1 - 360; }
this->angulo1 += vel;
this->coordenadas_extremo();
this->cinemDirecta();
}
void StaubliRX60::habilitar_botones()
{
vOSG->_timer.disconnect(this); //detiene la animacion
v_Principal->disconnect();
//Se emiten señales cuando cambian los valores de los SpinBox o cuando
se pulsa Enter
QObject::connect( guiMain->DSpinBox1_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle1_actual()));
QObject::connect( guiMain->DSpinBox2_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle2_actual()));
QObject::connect( guiMain->DSpinBox3_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle3_actual()));
QObject::connect( guiMain->DSpinBox4_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle4_actual()));
QObject::connect( guiMain->DSpinBox5_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle5_actual()));
QObject::connect( guiMain->DSpinBox6_actual,
SIGNAL(valueChanged(double)), this,
SLOT(changeAngle6_actual()));
void StaubliRX60::actualizarMinMax()
{
guiMain->DSpinBox1_actual->setMinimum( guiMain->DSpinBox1_min->value()
);
guiMain->DSpinBox2_actual->setMinimum( guiMain->DSpinBox2_min->value()
);
guiMain->DSpinBox3_actual->setMinimum( guiMain->DSpinBox3_min->value()
);
guiMain->DSpinBox4_actual->setMinimum( guiMain->DSpinBox4_min->value()
);
guiMain->DSpinBox5_actual->setMinimum( guiMain->DSpinBox5_min->value()
);
guiMain->DSpinBox6_actual->setMinimum( guiMain->DSpinBox6_min->value()
);
guiMain->DSpinBox1_actual->setMaximum( guiMain->DSpinBox1_max->value()
);
guiMain->DSpinBox2_actual->setMaximum( guiMain->DSpinBox2_max->value()
);
guiMain->DSpinBox3_actual->setMaximum( guiMain->DSpinBox3_max->value()
);
guiMain->DSpinBox4_actual->setMaximum( guiMain->DSpinBox4_max->value()
);
guiMain->DSpinBox5_actual->setMaximum( guiMain->DSpinBox5_max->value()
);
guiMain->DSpinBox6_actual->setMaximum( guiMain->DSpinBox6_max->value()
);
}
void StaubliRX60::resetPosicion()
{
//angulo1, angulo2, angulo3, angulo4, angulo5, angulo6 = 0.0;
guiMain->DSpinBox1_actual->setValue(0.0);
changeAngle1_actual();
changeAngle2_actual();
changeAngle3_actual();
changeAngle4_actual();
changeAngle5_actual();
changeAngle6_actual();
void StaubliRX60::cinemDirecta()
{
//Hay que escribir las matrices por columnas en lugar de por filas, es
decir,
//como si fueran las traspuestas para que los calclculos en C++ y OSG
sean correctos
osg::Matrixf A01 ( sin(ang1), -cos(ang1), 0.0f, 0.0f,
0.0f, 0.0f, -1.0f,
0.0f,
cos(ang1), sin(ang1), 0.0f, 0.0f,
0.0f, 0.0f, d1, 1.0f
);
MActualState = A06;
}
previousJoint->addChild(zmt);
osg::ShapeDrawable *zShape = new osg::ShapeDrawable(new
osg::Cylinder(osg::Vec3(0.0f,0.0f,height/2),radius,height),hints);
osg::ShapeDrawable *zCone = new osg::ShapeDrawable(new
osg::Cone(osg::Vec3(0.0f,0.0f,0.0f),radius*3,0.2),hints);
zmtCone->setMatrix( osg::Matrix::translate(0.0,0.0,height));
previousJoint->addChild(xmt);
xmtCone->setMatrix( osg::Matrix::translate(0.0,0.0,height));
//-------------------------------------------------------------------------
--------------------------
osg::MatrixTransform *ymt = new osg::MatrixTransform();
previousJoint->addChild(ymt);
ymtCone->setMatrix( osg::Matrix::translate(0.0,0.0,height));
/* qesptest.h
**************************************/
#ifndef _panelSerie_H_
#define _panelSerie_H_
#include "QtExtSerialPort/qextserialport.h"
#include "QtExtSerialPort/qextserialenumerator.h"
#include <QtGui/QWidget>
#include <QtGui>
#include "InterpreteComandos.h"
class QLineEdit;
class QTextEdit;
class QextSerialPort;
class QSpinBox;
virtual ~panelSerie();
//private:
public:
QTimer *timeout; //Permite controlar el tiempo de respuesta a un
comando por puerto serie
QextSerialPort *port;
QStringList *portList;
QLabel *stateCOM;
QLineEdit *message;
QTextEdit *sent_msg;
QTextEdit *received_msg;
//QSpinBox *delaySpinBox;
QComboBox *selectPort;
QPushButton *actCOMButton;
QPushButton *addCOMButton;
QPushButton *configCOMButton;
QPushButton *CRButton;
QPushButton *LFButton;
QPushButton *transmitButton;
QPushButton *receiveButton;
QPushButton *commandButton;
QPushButton *openButton;
QPushButton *closeButton;
int baud, bits, par, stop, flow; //datos almacenados del puerto actual
char buffLectura[1024];
QString sigComando;
//InterpreteComandos interprete;
signals:
void comandoCompleto();
//private slots:
public slots:
void transmitMsg();
void receiveMsg();
void commandMsg();
void appendCR(); // inserta CR en la linea de texto de entrada
void appendCRcad( QString &cadena ); // inserta CR a una cadena de
texto
void appendLF();
void appendLFcad( QString &cadena );
void closePort();
void openPort();
//public
void detectCOMPorts();
void defaultConfigCOM(QString);
void EnablePort();
void showConfigCOMDialog();
void showAddCOMDialog();
void addCOMPort(QString);
void configCOMPort(QList<int>);
void handleSerialData();
void reportWritten(qint64);
void closedAddCOMDialog();
void closedConfigCOMDialog();
#endif
/* panelSerie.cpp
**************************************/
#include <QtGui/QLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QTextEdit>
#include <QtGui/QPushButton>
#include <QtGui/QComboBox>
#include <QtGui/QLabel>
#include <QtGui/QListWidget>
#include <QtGui/QMessageBox>
#include <QtCore/QList>
#include "panelSerie.h"
#include "addCOMDialog.h"
#include "configCOMDialog.h"
panelSerie::panelSerie(QWidget* parent)
: QWidget(parent)
/*
//.......................................................................
if (this->port->open(QIODevice::ReadWrite) == true) {
connect(this->port, SIGNAL(readyRead()), this,
SLOT(handleSerialData()));
//transmit receive
transmitButton = new QPushButton("Enviar");
receiveButton = new QPushButton("Recibir");
commandButton = new QPushButton("Enviar Comando");
//CR LF
CRButton = new QPushButton("CR");
LFButton = new QPushButton("LF");
//open close
openButton = new QPushButton("Abrir");
closeButton = new QPushButton("Cerrar");
setLayout(myVBox);
//En modo EventDriven se recibe de forma automatica -> habra que quitar
el boton de recibir
receiveButton->setDisabled(true);
sigComando.clear();
}
panelSerie::~panelSerie()
{
delete port;
//port = NULL;
}
void panelSerie::transmitMsg()
{
// this->appendCR();
// this->appendLF();
/* Con este metodo se separa la linea de texto a enviar del envio real
que
contiene los caracteres CR + LF en la terminacion. Asi no aparecen
lineas en blanco en la caja de texto enviado ni en el historial de
comandos enviados. */
// QString *cadenaEnviar = new QString("");
// cadenaEnviar->append( message->text() );
// this->appendCRcad( cadenaEnviar );
// this->appendLFcad( cadenaEnviar );
sent_msg->append(message->text());
////////////////////////
for ( int k=0; k<cadenaEnviar.length(); k++ ) {
qDebug() << "Caracter " + QString::number(k) + ": " +
QString(cadenaEnviar.at(k));
}
/////////////////////////
message->clear();
/*
QMutex m;
m.lock();
//port->flush();
int i = port->write( (message->text()).toAscii(), (message-
>text()).length());
//port->flush();
qDebug()<<"transmitted: "<<i;
m.unlock();
*/
/*
int i = port->write((message->text()).toAscii(),
(message->text()).length());
qDebug("trasmitted : %d", i);
*/
//message->clear();*/
}
/*
timeout->setInterval( 5000 ); // tiempo se espera maximo a una
respuesta de comando en ms
///////////////////////////////////////////////////////////////////////////
//////
void panelSerie::receiveMsg() //No sirve en modo Event Driven
{
//char buff[1024]; ya definido en la declaracion de clase
numBytes = port->bytesAvailable();
if(numBytes > 1024)
numBytes = 1024;
//-------------------------------------
// se pasa a sigComando los datos del buffer de lectura, que puede ser
un
// comando completo o una parte
// Se va añadiendo hasta que se detecta que se trata de un comando
completo
sigComando.append( buffLectura );
//-------------------------------------
void panelSerie::appendCR()
{
message->insert("\x0D");
}
void panelSerie::appendLF()
{
message->insert("\x0A"); // insert o append mejor ???
}
void panelSerie::closePort()
{
selectPort->setEnabled(true); //Evita poder activar otro puerto
mientras el actual permanece abierto
port->close();
qDebug() << port->portName() << "abierto?: " << int(port->isOpen());
stateCOM->setText(port->portName() + " activo - (Cerrado)");
CRButton->setDisabled(true);
LFButton->setDisabled(true);
transmitButton->setDisabled(true);
commandButton->setDisabled(true);
}
void panelSerie::openPort()
{
//Creo que asi no accede al buffer físico, por tanto habra que emplear
uno por software
if ( (this->port->open(QIODevice::ReadWrite | QIODevice::Unbuffered))
== true )
{
selectPort->setDisabled(true); //Evita poder activar otro puerto
mientras el actual permanece abierto
CRButton->setEnabled(true);
LFButton->setEnabled(true);
transmitButton->setEnabled(true);
commandButton->setEnabled(true);
}
else {
qDebug() << "Fallo al abrir el puerto:" << this->port-
>errorString();
}
}
void panelSerie::detectCOMPorts()
{
//selectPort->addItem("Selecciona un puerto COM...");
//Si ejecutamos esto aqui como estaba vacio el combobox se activa la
señal de valueChanged
openButton->setEnabled(true);
closeButton->setEnabled(true);
}
}
void panelSerie::showAddCOMDialog()
{
addCOMButton->disconnect(); //evita que se abran varios paneles
de añadir puerto
addCOMDialog *insertPort = new addCOMDialog();
insertPort->show();
selectPort->clear();
selectPort->addItem("Selecciona un puerto COM...");
void panelSerie::closedAddCOMDialog()
{
connect( addCOMButton, SIGNAL(clicked()), this,
SLOT(showAddCOMDialog()) );
}
void panelSerie::showConfigCOMDialog()
{
//debe haberse activado algún puerto y estar cerrado para poderse
configurar
if ( (port == NULL) || (port->isOpen()) )
{
int ret = QMessageBox::warning(this, tr("Aviso"),
tr("No se ha activado ningún puerto o el
puerto activo está abierto."),
QMessageBox::Close ,
QMessageBox::Close);
return;
}
this->baud = list.at(0);
this->bits = list.at(1);
this->par = list.at(2);
this->stop = list.at(3);
this->flow = list.at(4);
//Se debe haber activado un puerto antes, sino la variable port tendrá
NULL y dara error lo siguiente
port->setBaudRate( myBaudRateType.at(baud) );
port->setDataBits( myDataBitsType.at(bits) );
port->setParity( myParityType.at(par) );
void panelSerie::closedConfigCOMDialog()
{
connect( configCOMButton, SIGNAL(clicked()), this,
SLOT(showConfigCOMDialog()) );
}
//----------------------------------------------------------------
void panelSerie::handleSerialData()
{
// comprobamos que se puede leer del puerto, caso que no, se sale de
la funcion
if (! port->isOpen())
return;
/*BORRAR*/ //numBytes = 2;
if (numBytes > 0)
{
char buffer[1024];
if (numBytes > 1023)
{
numBytes = 1023;
qDebug() << "Aviso: Se ha superado el tamaño del buffer.";
}
/*
/// ESTO ES DE PRUEBA BORRAR.... para leer respuesta comando where
buffer[0] = 0x77; buffer[1] = 0x68; buffer[2] = 0x1b;
buffer[3] = 0x5b; buffer[4] = 0x34; buffer[5] = 0x6c;
buffer[6] = 0xd; buffer[7] = 0xa; buffer[8] = 0x20;
buffer[9] = 0x20; buffer[10] = 0x20; buffer[11] = 0x20;
buffer[12] = 0x20; buffer[13] = 0x20; buffer[14] = 0x58;
buffer[15] = 0x20; buffer[16] = 0x20; buffer[17] = 0x20;
buffer[18] = 0x20; buffer[19] = 0x20; buffer[20] = 0x20;
buffer[21] = 0x20; buffer[22] = 0x20; buffer[23] = 0x20;
buffer[24] = 0x59; buffer[25] = 0x20; buffer[26] = 0x20;
buffer[27] = 0x20; buffer[28] = 0x20; buffer[29] = 0x20;
buffer[30] = 0x20; buffer[31] = 0x20; buffer[32] = 0x20;
////--------------------------------------------------------
//buffer[numBytes] = '\0';
*/
buffer[numBytes] = '\0';
//received_msg->append( QString(buffer) );
received_msg->insertPlainText( QString(buffer) );
received_msg->ensureCursorVisible();
qDebug("bytes available: %d", numBytes);
qDebug("received: %d", i);
}
}
//----------------------------------------------------------------
// NO FUNCIONA
//??????????????????????????????????????
bool panelSerie::eventFilter( QObject *object, QEvent *event )
{
if ( object == message ) {
if ( event->type() == QEvent::KeyPress ) {
QKeyEvent *eventoTeclado = dynamic_cast<QKeyEvent*>( event );
// ???? NO SE POR QUE METE LINEAS EN BLANCO
if ( eventoTeclado->key() == Qt::Key_Up ) {
message->undo();
if ( message->text() == "" ) {
message->undo();
}
return true;
}
return true;
}
}
}
return false;
}
#ifndef PANELPROGRAMA_H
#define PANELPROGRAMA_H
#include <QtGui/QMainWindow>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QFileDialog>
#include <QtCore/QTextStream>
#include <QtCore/QFile>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
#include <QtCore/QTimer>
#include "CodeEditor.h"
namespace Ui {
class panelProgramar;
}
public:
panelPrograma( QWidget *parent = 0, Qt::WFlags flags = 0 );
~panelPrograma();
private:
Ui::panelProgramar *ui;
bool finTiempo;
QTimer timer;
CodeEditor *cajaTexto;
// variables
QFont fuente;
private slots:
void abrirFichero();
void guardarFicheroPC();
void panelConfig();
void cambiarFuente();
void enviarProg();
void finalizarTiempo();
};
#endif
#include "panelPrograma.h"
#include "ui_panelProgramar.h"
#include "panelSerie.h"
extern panelSerie *wSerial;
fichActual = NULL;
/// Conexiones
// Menus
// Menu Archivo
ui->actionAbrir->setDisabled(true);
ui->actionGuardar_como->setDisabled(true);
ui->actionCerrar->setDisabled(true);
ui->actionDeshacer->setDisabled(true);
ui->actionRehacer->setDisabled(true);
ui->actionCortar->setDisabled(true);
ui->actionCopiar->setDisabled(true);
ui->actionPegar->setDisabled(true);
ui->actionEnviar_y_ejecutar->setDisabled(true);
ui->actionAlmacenar_en_memoria->setDisabled(true);
ui->actionLeer_de_memoria->setDisabled(true);
ui->actionVer_directorio->setDisabled(true);
connect( ui->actionAbrir,SIGNAL(triggered()),this,SLOT(abrirFichero())
);
connect( ui->actionGuardar,SIGNAL(triggered()),this,
SLOT(guardarFicheroPC()) );
connect( ui->actionSalir,SIGNAL(triggered()),this,SLOT(close()) );
connect( ui-
>actionConfigurar,SIGNAL(triggered()),this,SLOT(panelConfig()) );
// Botones
connect( ui->pbGuardar,SIGNAL(clicked()),this,SLOT(guardarFicheroPC())
);
connect( ui->pbCargar,SIGNAL(clicked()),this,SLOT(abrirFichero()) );
connect( ui->pbEnviar ,SIGNAL(clicked()),this,SLOT(enviarProg()) );
panelPrograma::~panelPrograma()
{
void panelPrograma::abrirFichero()
{
nombreFichAct = QFileDialog::getOpenFileName( this,
tr("Abrir Programa"), "", tr("Fichero de programa VSS60
(*.vssp);;") +
tr("Archivo de texto (*.txt)") );
if ( nombreFichAct != "" ) {
if ( fichActual != NULL)
{ delete fichActual; }
fichActual = new QFile;
fichActual->setFileName( nombreFichAct );
if ( fichActual->open(QIODevice::ReadWrite) ) {
cajaTexto->clear();
void panelPrograma::guardarFicheroPC()
{
if ( fichActual != NULL)
{ delete fichActual; }
fichActual = new QFile;
if ( nombreFichAct != "" ) {
fichActual->setFileName( nombreFichAct );
ui->lineEdit->setText( nombreFichAct );
if ( fichActual->open(QIODevice::ReadWrite) ) {
QTextStream stream( fichActual) ;
stream << cajaTexto->toPlainText();
fichActual->flush();
fichActual->close();
}
else {
QMessageBox::critical( this, tr("Error"),
tr("No se pudo guardar el fichero.") );
return;
}
}
void panelPrograma::enviarProg()
{
// Creo que sera mejor hacer el panel como widget y meterlo dentro de
la
// ventana ppal. Ver si es mejor asi (lo de variable globales no me
// convence, a no ser que sea algo muy especifico)
mensaje.append( "\x0D" ); // CR
mensaje.append( "\x0A" ); // LF
connect(&timer,SIGNAL(timeout()),this,SLOT(finalizarTiempo()));
finTiempo = false;
timer.start(0.01); // 1 ms
//timer.stop();
///-------------------------------------------------
//Mostrar
wSerial->sent_msg->append( mensaje );
}
}
else
{
QMessageBox::warning( this, tr("Aviso"),
tr("No se ha configurado ningún puerto serie.") );
}
}
// Si está vacío sólo muestra un aviso
else
{
QMessageBox::warning( this, tr("Aviso"),
tr("El programa está vacío.") );
}
void panelPrograma::finalizarTiempo()
{
finTiempo = true;
//qDebug() << "FIN DEL TIEEEEEEEEEEEEEEEEEEEEEEEEEMPO";
}
void panelPrograma::panelConfig()
{
void panelPrograma::cambiarFuente()
{
PANELMOVER.H
#ifndef PANELMOVER_H
#define PANELMOVER_H
#include <QtGui/QDockWidget>
#include <QtGui/QSlider>
#include <QtCore/QSignalMapper>
#include <QtCore/QTimer>
namespace Ui {
class panelMover;
}
public:
explicit panelMover(QWidget *parent = 0, Qt::WFlags flags = 0);
~panelMover();
QTimer *tiempo;
private:
Ui::panelMover *ui;
QSignalMapper *mapper_spinB;
QSlider *p_slider;
public slots:
void cambioSpin(double);
void cambioSlider(int);
void moverEslabones();
void mostrar(bool);
void seguir(bool);
void preguntarPosicion();
void interpretarPosicion();
};
#endif
#include <QtCore/QString>
#include "panelMover.h"
#include "ui_panelMover.h"
#include "panelSerie.h"
extern panelSerie *wSerial;
#include "StaubliRX60.h"
extern StaubliRX60 *robot;
extern Ui::ventanaPrincipal *guiMain;
// ui->rBtn_mostrar->setChecked(true);
//mostrar(true); NO FUNCIONA LA PRIMERA VEZ
panelMover::~panelMover()
{
delete ui;
}
void panelMover::cambioSpin(double d)
{
//El parametro de entrada "d" no se usa, solo es necesario para poder
llamar al slot
//desde la señal valueChanged()
void panelMover::cambioSlider(int i)
{
//El parametro de entrada "i" no se usa, solo es necesario para poder
llamar al slot
//desde la señal valueChanged()
//SUPONIENDO SOLO PUEDE CAMBIAR UN ANGULO CADA VEZ QUE SE PULSA EL BOTON DE
MOVER
//if ( tiempo->isActive() )
//{
// tiempo->stop();
// this->disconnect( tiempo, SIGNAL(timeout()), this,
SLOT(preguntarPosicion()) );
//}
connect(ui->spinbJ1, SIGNAL(valueChanged(double)),
guiMain->DSpinBox1_actual, SLOT(setValue(double)));
connect(ui->spinbJ2, SIGNAL(valueChanged(double)),
guiMain->DSpinBox2_actual, SLOT(setValue(double)));
connect(ui->spinbJ3, SIGNAL(valueChanged(double)),
guiMain->DSpinBox3_actual, SLOT(setValue(double)));
connect(ui->spinbJ4, SIGNAL(valueChanged(double)),
guiMain->DSpinBox4_actual, SLOT(setValue(double)));
connect(ui->spinbJ5, SIGNAL(valueChanged(double)),
guiMain->DSpinBox5_actual, SLOT(setValue(double)));
connect(ui->spinbJ6, SIGNAL(valueChanged(double)),
guiMain->DSpinBox6_actual, SLOT(setValue(double)));
if (tiempo->isActive())
{
tiempo->stop();
}
}
}
void panelMover::seguir(bool b)
{
if (b == true) {
void panelMover::preguntarPosicion()
{
//si no hay envios ni se esta recibiendo, se pregunta la posicion
if ( (wSerial->port->bytesToWrite() == 0) &&
(wSerial->port->bytesAvailable() == 0) ) {
// Pregunta la posicion
wSerial->message->insert( "WH" );
wSerial->transmitMsg();
}
// SE CONGELA
void panelMover::interpretarPosicion()
{
QString respuesta;
respuesta = wSerial->sigComando;
/**
* @file ventanaMensajes.h
* @brief Message Window.
* @see ventanaMensajes
* @author Micha³ Policht
*/
#ifndef ventanaMensajes_H_
#define ventanaMensajes_H_
#include <QtGui/QDockWidget>
#include <QtGui/QTextEdit>
#include <QtCore/QEvent>
/**
* Message Window. Handling errors and other messages.
*/
class ventanaMensajes: public QDockWidget
{
Q_OBJECT
private:
static QString QtMsgToQString(QtMsgType type, const char *msg);
protected:
/**
* Handle custom events. ventanaMensajes hadles custom events
listed in
* EventType enum.
*/
virtual void customEvent(QEvent* event);
/**
* Default constructor.
* @param parent parent widget.
* @param flags widget flags.
*/
ventanaMensajes(QWidget* parent = 0, Qt::WFlags flags = 0);
/**
* Append message wrapper. Since ISO forbids casting member
functions
* to C functions, wrapper is needed to use this class as
QtMsgHandler.
* This method is thread-safe but not reentrant.
* @param type message type.
* @param msg message string.
*/
/**
* Post message event to the main event loop. This function
encapsulates
* message into MessageEvent object and passes it to the main event
loop.
* @param type message type.
* @param msg message string.
*/
void postMsgEvent(QtMsgType type, const char *msg);
};
/**
* Message Event. Custom event used by @ref ventanaMensajes to provide
multi-threaded
* access. Encapsulates message inside @a msg variable.
*/
class MessageEvent: public QEvent
{
public:
QString msg; ///< Message string.
/**
* Contructor.
* @param msg message to post.
*/
MessageEvent(QString & msg);
};
#endif /*ventanaMensajes_H_*/
/**
* @file ventanaMensajes.cpp
* @brief ventanaMensajes Implementation.
* @see ventanaMensajes.h
* @author Micha³ Policht
*/
/*
==============
<INIT>
==============
*/
#include "ventanaMensajes.h"
#include <QtGui/QMessageBox>
#include <QtCore/QCoreApplication>
#include <QtCore/QMutexLocker>
/*
==============
<CONSTRUCTORS>
==============
*/
ventanaMensajes::MsgHandler = this;
/*
==============
<DESTRUCTOR>
==============
*/
/*
==============
<SLOTS>
==============
/*
==============
<METHODS>
==============
*/
//static
QString ventanaMensajes::QtMsgToQString(QtMsgType type, const char *msg)
{
switch (type) {
case QtDebugMsg:
return QString("Debug: ")+QString(msg);
case QtWarningMsg:
return QString("Warning: ")+QString(msg);
case QtCriticalMsg:
return QString("Critical: ")+QString(msg);
case QtFatalMsg:
return QString("Fatal: ")+QString(msg);
default:
return QString("Unrecognized message type: ")+QString(msg);
}
}
//static
void ventanaMensajes::AppendMsgWrapper(QtMsgType type, const char* msg)
{
static QMutex mutex;
QMutexLocker locker(&mutex);
if (ventanaMensajes::MsgHandler != NULL)
return ventanaMensajes::MsgHandler->postMsgEvent(type, msg);
else
fprintf(stderr, ventanaMensajes::QtMsgToQString(type,
msg).toAscii());
}
/*
==============
<HELPERS>
==============
*/
#ifndef CONFIGCOMDIALOG_H
#define CONFIGCOMDIALOG_H
#include <QtGui/QDialog>
namespace Ui {
class configCOMDialog;
}
public:
explicit configCOMDialog(QWidget *parent = 0);
~configCOMDialog();
//QString getCOMToAdd(); //devuelve el nombre del puerto COM a
añadir
public slots:
void acceptClicked();
private:
Ui::configCOMDialog *ui;
//public slots:
//void addClicked(); //añade al combobox el nuevo puerto COM
signals:
void paramsCOM(QList<int>);
void finishConfigCOM();
private:
void closeEvent(QCloseEvent*);
};
#endif // CONFIGCOMDIALOG_H
#include "configCOMDialog.h"
#include "ui_configCOMDialog.h"
#include <QtCore/QList>
QList<int> stringlist;
emit paramsCOM(stringlist);
configCOMDialog::~configCOMDialog()
{
delete ui;
}
void configCOMDialog::acceptClicked()
{
/*QString comPort = QString::number( numSpin->value() );
comPort = "COM" + comPort;*/
QList<int> paramsList;
emit paramsCOM(paramsList);
this->close();
}
#include <QtGui/QWidget>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QPainter>
#include <QtGui/QTextBlock>
public:
CodeEditor(QWidget *parent = 0);
protected:
void resizeEvent(QResizeEvent *event);
private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void highlightCurrentLine();
void updateLineNumberArea(const QRect &, int);
private:
QWidget *lineNumberArea;
};
#include "CodeEditor.h"
protected:
void paintEvent(QPaintEvent *event) {
codeEditor->lineNumberAreaPaintEvent(event);
}
private:
CodeEditor *codeEditor;
};
updateLineNumberAreaWidth(0);
highlightCurrentLine();
}
int CodeEditor::lineNumberAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;
}
return space;
}
if (rect.contains(viewport()->rect()))
updateLineNumberAreaWidth(0);
}
QRect cr = contentsRect();
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(),
lineNumberAreaWidth(), cr.height()));
}
void CodeEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection,
true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}
setExtraSelections(extraSelections);
}
block = block.next();
top = bottom;
bottom = top + (int) blockBoundingRect(block).height();
++blockNumber;
}
}
#ifndef ADDCOMDIALOG_H
#define ADDCOMDIALOG_H
#include <QDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include <QPushButton>
#include <QApplication>
#include <QDesktopWidget>
public:
addCOMDialog(QWidget *parent = 0);
QString getCOMToAdd(); //devuelve el nombre del puerto COM a
añadir
public slots:
void addClicked(); //añade al combobox el nuevo puerto COM
signals:
void newCOM(QString);
void finishNewCOM();
private:
QPushButton *addButton;
//QLineEdit *nameEdit;
QSpinBox *numSpin;
QString nameText;
void closeEvent(QCloseEvent*);
//void acceptCliked();
};
#endif // ADDCOMDIALOG_H
#include "addCOMDialog.h"
#include "panelSerie.h"
extern panelSerie *wSerial; //puntero al widget PuertoSerie
addCOMDialog::addCOMDialog(QWidget *parent)
: QWidget(parent)
{
QLabel *label = new QLabel("Introducir puerto COM -> ");
void addCOMDialog::addClicked()
{
QString comPort = QString::number( numSpin->value() );
comPort = "COM" + comPort;
emit newCOM(comPort);
this->close();
/*void addCOMDialog::acceptCliked()
{
emit finishNewCOM();
}*/G_H
DOCUMENTO 4.
PLANOS
0. ÍNDICE DE PLANOS
DOCUMENTO 5.
PLIEGO DE
CONDICIONES
2. ESPECIFICACIONES DE MATERIALES Y
ELEMENTOS CONSTITUTIVOS DEL OBJETO
DEL PROYECTO
2.1 LISTADO DE MATERIALES EMPLEADOS
2.1.1 Hardware
Robot PUMA Staübli Rx-60
Controlador CS7
2.1.2 Software
Visual Studio C++ 2008 Profesional
Librería Qt 4.8
2.2 REQUISITOS
DOCUMENTO 6.
ESTADO DE
MEDICIONES
DOCUMENTO 7.
PRESUPUESTO
1 PRESUPUESTO
1.1 DESARROLLO DEL SOFTWARE DE MONITORIZACIÓN Y
SIMULACIÓN DEL ROBOT STAÜBLI RX-60
________________________________________________________________
EL INGENIERO AUTOR