You are on page 1of 152

Universidad de Costa Rica

Facultad de Ingeniera
Escuela de Ingeniera Elctrica

IE 0502 Proyecto Elctrico

Desarrollo de un modelo y simulador tridimensional


del brazo robot Stubli RX 90 L

Por:

David Cuenca Alpzar

Ciudad Universitaria Rodrigo Facio


Julio del 2006
Desarrollo de un modelo y simulador tridimensional
del brazo robot Stubli RX 90 L

Por:
David Cuenca Alpzar

Sometido a la Escuela de Ingeniera Elctrica


de la Facultad de Ingeniera
de la Universidad de Costa Rica
como requisito parcial para optar por el grado de:

BACHILLER EN INGENIERA ELCTRICA

Aprobado por el Tribunal:

_________________________________
Ing. Federico Ruiz Ugalde, Lic.
Profesor Gua

_________________________________ _________________________________
Ing. Francisco Siles Canales, Lic. Ing. Andrs Daz Soto
Profesor lector Profesor lector

ii
DEDICATORIA

A mi familia y amigos.

iii
NDICE GENERAL

NDICE DE FIGURAS ................................................................................vi


NDICE DE CUADROS ........................................................................... viii
GLOSARIO ..................................................................................................ix
RESUMEN....................................................................................................xi
CAPTULO 1: Introduccin.........................................................................1
1.1 Justificacin ..................................................................................................................1
1.2 Objetivos.......................................................................................................................2
1.2.1 Objetivo general.................................................................................................2
1.2.2 Objetivos especficos .........................................................................................2
1.3 Metodologa ..................................................................................................................2
CAPTULO 2: Desarrollo terico ................................................................4
2.1 El sistema operativo GNU/Linux .................................................................................4
2.2 El lenguaje de programacin C ....................................................................................5
2.3 Las interfaces de programacin de aplicaciones (APIs)..............................................5
2.3.1 La interfaz OpenGL ............................................................................................5
2.3.2 La interfaz DIRECTX.........................................................................................9
2.3.3 Comparacin general entre OpenGL y Direct3D ...............................................9
2.4 Teora de modelado tridimensional aplicada a computadoras....................................11
2.4.1 Las coordenadas homogneas...........................................................................12
2.4.2 Los sistemas de coordenadas Cmara, Global y Objeto...................................12
2.4.3 Trasladar, rotar y escalar objetos ......................................................................16
2.4.4 Sistemas grficos ..............................................................................................19
2.4.5 Arquitectura Grfica (PIPELINE) ....................................................................20
2.5 Introduccin a OpenGL, GLUT y GTK .....................................................................22
2.5.1 La ventana de despliegue utilizando GLUT .....................................................22
2.5.2 La ventana de despliegue utilizando GTK........................................................23
2.5.3 Primitivas y vrtices..........................................................................................24
2.5.4 La matriz CTM .................................................................................................25
2.5.5 La matriz de transformacin del modelo ..........................................................26
2.5.6 Transformacin de la visin y proyeccin de la escena. ..................................27

iv
CAPTULO 3: La robtica .........................................................................30
3.1 Las bases de los robots................................................................................................30
3.2 El brazo robot..............................................................................................................31
3.2.1 El brazo robot Stubli RX90.............................................................................32
3.2.2 Geometra de brazo robot Stubli RX90...........................................................33
CAPTULO 4: Desarrollo de la aplicacin de simulacin ........................36
4.1 Simulador del brazo robot Stubli RX90 L ................................................................38
4.1.1 El brazo robot Stubli como un modelo jerrquico ..........................................39
4.1.2 El modelado del brazo robot Stubli RX90 L...................................................42
4.1.3 El mtodo de deteccin de colisiones ...............................................................51
CAPTULO 5: La interfaz grfica de usuario de la aplicacin ................64
5.1 Los botones de configuracin del simulador .............................................................68
5.2 Creacin, edicin y ejecucin de rutinas ....................................................................70
5.3 Envo de ordenes al simulador por medio del teclado y el ratn................................72
CAPITULO 6: Pruebas finales y sus resultados........................................74
6.1 Pruebas destructivas....................................................................................................74
6.2 Pruebas de velocidad ..................................................................................................74
6.3 Pruebas de memoria....................................................................................................77
CAPITULO 7: Conclusiones y Recomendaciones .....................................78
7.1 Conclusiones...............................................................................................................78
7.2 Recomendaciones .......................................................................................................80
BIBLIOGRAFA.........................................................................................81
APNDICES ...............................................................................................82

v
NDICE DE FIGURAS

Figura 2.1 Plano 2D y espacio 3D ....................................................................................11


Figura 2.2 La cmara y el mundo .....................................................................................13
Figura 2.3 La cmara, el mundo y el objeto .....................................................................13
Figura 2.4 Sistemas de coordenadas Cmara, Global y Objeto........................................15
Figura 2.5 Rotacin y Traslacin......................................................................................18
Figura 2.6 Elementos tpicos de un sistema grfico .........................................................19
Figura 2.7 Arquitectura Grfica (pipeline) .......................................................................20
Figura 2.8 Polgono y puntos............................................................................................25
Figura 2.9 Analoga entre cmara y computadora ............................................................28
Figura 2.10 Volumen de visin especificado por gluPerspective() ..................................29
Figura 3.1 Ejemplo de brazo robot con cuatro grados de libertad ....................................32
Figura 3.2 Partes del brazo robot Stubli RX90 ...............................................................33
Figura 3.3. Medidas geomtricas del brazo robot Stubli RX90......................................34
Figura 3.4 Distribucin de trabajo de las amplitudes de giro ...........................................35
Figura 4.1 Diagrama de flujo de la aplicacin de simulacin virtual ...............................37
Figura 4.2 Modelo de brazo robot de tres grados de libertad ...........................................39
Figura 4.3 Primer modelo creado del brazo robot. ...........................................................42
Figura 4.4 Principales componentes del brazo Stubli RX90. .........................................43
Figura 4.5 Esfera con iluminacin y sin iluminacin. ......................................................49
Figura 4.6 Modelo del brazo robot Stubli RX90 L. ........................................................50
Figura 4.7 Tipos de figuras de control ..............................................................................51
Figura 4.8 Figuras de control en el modelo del brazo robot .............................................52
Figura 4.9 Figuras de control (esquemtico) ....................................................................52
Figura 4.10 Zonas de precaucin ......................................................................................56
Figura 4.11 Orillas del hombro del brazo robot................................................................58

vi
Figura 4.12 Prueba de colisin de orillas (1) ....................................................................59
Figura 4.13 Prueba de colisin de orillas (2) ....................................................................59
Figura 4.14 Prueba de colisin de orillas (3) ....................................................................60
Figura 5.1 La aplicacin grfica de usuario del simulador...............................................64
Figura 5.2 Los botones de configuracin del simulador...................................................68
Figura 5.3 Introduccin de una base externa ....................................................................69
Figura 5.4 Introduccin del margen de error ....................................................................70
Figura 5.5 Ventana 1 de la aplicacin...............................................................................70

vii
NDICE DE CUADROS

Cuadro 3.1 Amplitudes de giro y velocidades nominales y mximas ..............................35


Cuadro 4.1 Puntos y figuras de control.............................................................................53
Cuadro 4.2 Niveles de jerarqua de las figuras de control ................................................54
Cuadro 4.3 Condiciones y resultados de la prueba de colisin de orillas.........................61
Cuadro 5.1 Envo de ordenes por medio del teclado ........................................................73

viii
GLOSARIO

GNU/Linux: Denominacin para el sistema operativo que utiliza kernel


<<linux>>. Es un sistema multitarea multiusuario para PCs.
Linux es una implementacin del sistema operativo UNIX.

UNIX: Sistema operativo multitareas, multiusuario y portable. Unix fue


desarrollado a finales de los sesenta en los laboratorios Bell y
hasta principios de los ochenta su uso estuvo restringido
fundamentalmente al entorno acadmico.

OpenGL: OpenGL es una biblioteca grfica desarrollada originalmente por


Silicon Graphics Incorporated (SGI). OpenGL significa Open
Graphics Library o en espaol: biblioteca abierta de grficos. Se
utiliza para la creacin y despliegue y manejo de primitivas
geomtricas.

API: Un API (Application Programming Interface) o interfaz de


programacin de aplicaciones, es un conjunto de especificaciones
de comunicacin entre componentes software. Generalmente est
compuesto por un grupo de funciones dedicadas un rea
especfica, por ejemplo la comunicacin con el sistema de
ventanas.

GLUT: GLUT (OpenGL Utility Toolkit) es una API multiplataforma que


provee una reducida funcionalidad para el manejo de ventanas e
interaccin por medio de teclado y ratn.

GTK: Inicialmente creado para construir el programa grfico GIMP,


GTK es la abreviatura de GIMP toolkit y es muy usada por los
programadores de sistemas Linux para desarrollar interfaces
grficas de usuario.

ix
RGBA: RGBA es el termino utilizado para definir el modelo de color, en
el cual los colores primarios (rojo, verde y azul: <<Red Blue
Green>>) son combinados en forma especfica con el fin de
obtener algn color determinado. La A en RGBA se refiere al
termino alfa, que define la transparencia de los colores.

Buffer: Un buffer es un espacio de memoria, en el que se almacenan


datos, con el fin de evitar que el recurso que los requiere, ya sea
hardware o software, se quede en algn momento sin datos. Los
buffers tambin son llamados almacenadores intermedios.

Direct3D: Es una interfaz de programacin de aplicaciones, desarrollada


por Microsoft, que facilita el manejo y trazado de primitivas
grficas elementales, as como la utilizacin de transformaciones
geomtricas sobre las primitivas desplegadas.

textview: Objeto de la librera Gtk que se utiliza para desplegar texto


dentro de una ventana.

IDE: Un IDE es un entorno integrado de programacin, generalmente


consiste en un editor de cdigo, un compilador, un depurador y
un constructor de interfaz grfica.

x
RESUMEN
La creacin de un modelo tridimensional y un simulador virtual del brazo robot
Stubli RX90 L es el objetivo principal de este proyecto. Para el desarrollo del programa de
simulacin se emple OpenGL como herramienta principal de trabajo. El cdigo de la
aplicacin fue desarrollado en su totalidad en el lenguaje de programacin C.
La primera fase del proyecto la comprendi el estudio de la teora de modelado
tridimensional en computadoras. Con ayuda de la informacin obtenida durante esta etapa,
se comenz la bsqueda y anlisis de las herramientas necesarias para el desarrollo de la
aplicacin.
Se eligi la interfaz de programacin de aplicaciones grficas OpenGL, como la
librera principal para la creacin del programa de simulacin virtual. Se estudi y comenz
a experimentar con las funciones brindadas por la librera. A partir de este punto, en el cual
ya se tena un mejor conocimiento de la teora de modelado y de las herramientas al
alcance, se dio inicio a la estructuracin de la aplicacin a desarrollar.
El siguiente paso fue analizar la geometra del brazo robot Stubli RX90 L, con el
fin de determinar cuales caractersticas geomtricas de ste son las ms influyentes en los
procesos de colisin. Despus del estudio del objeto real, se procedi a crear un modelo
virtual tridimensional de ste.
A partir de este punto se establecieron dos objetivos principales: la creacin de un
motor de ejecucin de espacio virtual, en el cual se pudiera manejar el modelo del brazo
robot Stubli y la implementacin de un mtodo de deteccin de colisiones al motor de
ejecucin.
Para alcanzar el segundo objetivo se tuvo que desarrollar un mtodo nuevo de
deteccin de colisiones, el cual result ser, adems de altamente efectivo y flexible,
verdaderamente simple en comparacin con otros mtodos existentes.
Una vez creados el motor de ejecucin y los algoritmos de deteccin de colisiones,
se inici la estructuracin de una interfaz grfica de usuario, que no solo facilitara el uso de
la aplicacin, sino que permitiera una futura unin con otras aplicaciones, en especial con
otros programas desarrollados para el mismo brazo robot. La interfaz se desarroll
utilizando la librera GTK.
Una vez finalizada la aplicacin, se llev a cabo una serie de pruebas mediante las
cuales se descubrieron algunos problemas, solucionados posteriormente.
Se logr cumplir con el objetivo de crear una aplicacin de simulacin para el
sistema operativo GNU/Linux. La librera grfica OpenGL y el lenguaje de programacin
C demostraron poseer las cualidades necesarias para el desarrollo de aplicaciones grficas
complejas. Los mtodos de deteccin de colisiones implementados en el programa,
mostraron un buen funcionamiento durante la etapa de prueba.

xi
CAPTULO 1: Introduccin

1.1 Justificacin
El campo de la robtica se encuentra en constante crecimiento. Los robots se han
convertido en asistentes imprescindibles en muchas reas. Se encargan de tareas que
pueden ser tediosas, pesadas, difciles e inclusive imposibles para un ser humano.
Los avances tecnolgicos de los ltimos aos han permitido que los sistemas
electromecnicos controlables puedan ser aplicados a diferentes reas. Desde la industria
del entretenimiento, hasta la exploracin espacial, desde la industria automotriz, hasta las
ciencias mdicas, los robots afectan nuestras vidas muchas veces sin darnos cuenta.
Una parte imprescindible en el desarrollo de nuevas tecnologas robticas y la
implementacin de stas, es el modelado y la simulacin. Saber como se comportar el
sistema ante diferentes situaciones es indispensable tanto para el diseador como para el
usuario. Mediante el uso de simuladores, los desarrolladores pueden detectar errores y
corregirlos antes del proceso de fabricacin. Por otro lado los usuarios pueden utilizar
modelos virtuales del equipo para verificar previamente si las rdenes que se enviarn
tendrn el resultado deseado. Simular con anterioridad los movimientos que se le ordenarn
a un robot, incrementa no solo la eficiencia del proceso, sino que tambin ayuda a
resguardar la seguridad de los usuarios y del robot mismo, ya que mediante la
representacin virtual se puede determinar si la ejecucin de cierta orden por parte del
equipo, presenta algn riesgo para las personas alrededor o para el equipo mismo.
El uso de sistemas operativos propietarios no solo encarece el proceso de desarrollo
de aplicaciones, sino que tambin resta flexibilidad al producto final, ya que muchas de las
herramientas y aplicaciones desarrolladas sobre sistemas propietarios no pueden ser
implementadas en otros sistemas. El hecho de utilizar una plataforma abierta, para crear
modelos virtuales de equipos electromecnicos, presenta ventajas tanto para el
desarrollador como para el usuario.
Las observaciones anteriores representan algunas de las razones para el desarrollo
de este proyecto. La creacin de un motor de ejecucin y un modelo tridimensional del
brazo robot Stubli RX90 L, adems de la implementacin de un mtodo de deteccin de
colisiones, ayudar a incrementar la eficiencia y seguridad de los movimientos del brazo
robot. Adems, la utilizacin del sistema operativo GNU/Linux y la biblioteca grfica de
cdigo abierto OpenGL, como bases del simulador virtual, incrementa la versatilidad y
estabilidad de la aplicacin y permite que el cdigo desarrollado pueda ser portado, sin
mayor complicacin, a proyectos futuros e implementado en otras aplicaciones.
Aun cuando el objetivo especfico de este proyecto sea la creacin de un simulador
virtual del brazo Robot Stubli RX90 L, el trabajo aqu desarrollado podra utilizarse como
base para crear modelos virtuales de otros sistemas elctricos controlables.

1
2

1.2 Objetivos

1.2.1 Objetivo general

Crear un modelo tridimensional y un simulador virtual del brazo robot Stubli


RX90 L.

1.2.2 Objetivos especficos

Investigar teora del modelado tridimensional aplicado en computadoras.


Investigar acerca de las interfaces para programacin de aplicaciones (APIs)
grficas.
Crear un motor de ejecucin de un espacio tridimensional virtual, para
implementar el modelo del brazo robot Stubli RX90 L, capaz de acatar rdenes
de movimiento enviadas por el usuario.
Implementar al motor de ejecucin un mtodo de deteccin de colisiones capaz
de indicar cuando el brazo choca contra el piso o consigo mismo.
Utilizar el sistema operativo de licencia libre GNU/Linux para desarrollar la
aplicacin grfica.
Desarrollar la estructura de la aplicacin de manera que se facilite una futura
unin entre sta y el programa desarrollado en [4].

1.3 Metodologa

La metodologa empleada para la realizacin del proyecto fue la siguiente:

Se determina el objetivo general y los objetivos especficos del proyecto y se


utilizan como base para crear una estructuracin de ste.
Se investiga acerca del sistema operativo GNU/Linux y de las interfaces de
programacin de aplicaciones grficas en tercera dimensin, principalmente
OpenGL y DirectX.
Se realiza un estudio profundo de la teora del modelado tridimensional aplicado
en computadoras. Con base en la informacin obtenida durante las
3

investigaciones bibliogrficas referentes al tema, se decide utilizar la interfaz de


programacin OpenGL.
Se investiga acerca del brazo robot Stubli RX90L y se lleva a cabo una
recopilacin y un estudio de los proyectos y tesis anteriores, referentes al tema.
Se desarrolla un modelo inicial del brazo robot y un motor de ejecucin, que
permite controlar el modelo utilizando el teclado y el ratn de la computadora.
Se investiga acerca de los mtodos de deteccin de colisiones de objetos
virtuales, utilizados en aplicaciones grficas.
Se desarrolla un algoritmo de deteccin de colisiones para el brazo robot virtual
y se implementa el algoritmo al motor de ejecucin del espacio virtual.
Se lleva a cabo varias pruebas, para comprobar la eficiencia del mtodo de
deteccin de choques.
Se crea una interfaz de usuario para la aplicacin y se adapta sta, de manera
que en un futuro pueda funcionar de forma conjunta a la aplicacin desarrolla en
[4].
Se lleva a cabo algunas pruebas finales del funcionamiento de la aplicacin
desarrollada en el proyecto.
De forma simultnea al desarrollo de los puntos anteriores, se lleva a cabo el
desarrollo del informe final del proyecto.
CAPTULO 2: Desarrollo terico

2.1 El sistema operativo GNU/Linux

GNU/Linux o Linux son los nombres que suele recibir el sistema operativo de
distribucin libre y cdigo abierto desarrollado en un principio por Linus Torvalds a
principio de los aos noventa (1991) y el proyecto GNU fundado por Richard Stallmann en
1983. El trmino Linux se refiere estrictamente al ncleo o kernel creado en un principio
por Linus Torvalds y GNU/Linux al sistema operativo final, que utiliza bibliotecas y
herramientas desarrolladas por el proyecto GNU y muchos otros proyectos y grupos de
software. La palabra Linux tambin es usada comnmente para referirse a las diferentes
distribuciones Linux, las cuales son colecciones de software que suelen contener grandes
cantidades de paquetes adems del ncleo.
La coleccin de utilidades para la programacin de GNU es por mucho la familia de
compiladores ms utilizada en Linux. Tiene la capacidad de compilar C, C++, Java, Ada
entre muchos otros lenguajes. Existen varios ambientes integrados de desarrollo disponibles
para Linux, entre ellos estn Anjuta, Kdevelop, NetBeans IDE y Eclipse.
Aunque originalmente Linux fue diseado solamente para soportar procesadores
Intel 80386, actualmente soporta una gran variedad de arquitecturas, convirtindose en uno
de los sistemas operativos con mayor portabilidad.
El soporte tcnico para usuarios de Linux normalmente se provee a travs de foros
en lnea, grupos de noticias y listas de correos electrnicos. Los grupos de usuarios Linux
LUGs (por sus siglas en ingls: Linux Users Groups) tradicionalmente prestan soporte
local para los usuarios de Linux y para las personas que desean introducirse en el mundo
del software libre.
Su alta eficiencia, gran portabilidad, variada gama de software libre compatible y
muchas otras caractersticas, hacen que el sistema Linux represente una gran plataforma de
investigacin y desarrollo de aplicaciones.
Al ser un sistema operativo de cdigo abierto, el sistema Linux ha sufrido un
crecimiento acelerado. Programadores provenientes de diferentes lugares del mundo se han
unido al desarrollo y mejoramiento del sistema y las aplicaciones que este soporta. Para el
desarrollo del kernel del sistema Linux se utiliza el lenguaje de programacin C.

4
5

2.2 El lenguaje de programacin C 1


El lenguaje C, el cual fue creado en 1963 por Ken Thompson y Dennis M. Ritchie
en los laboratorios Bell, est basado en los lenguajes de programacin BCPL y B. C est
orientado a la implementacin de sistemas operativos, concretamente Unix. C es el
lenguaje de programacin ms utilizado para crear software de sistemas, se aprecia por la
eficiencia del cdigo que produce.
Es un lenguaje de medio nivel, pero con muchas caractersticas de bajo nivel.
Dispone de las estructuras tpicas de los lenguajes de alto nivel, pero tambin dispone de
construcciones del lenguaje que permiten un control a muy bajo nivel.
Entre algunas de las ventajas de C se encuentra el hecho de que es un lenguaje muy
eficiente, ya que es posible utilizar caractersticas de bajo nivel para realizar
implementaciones ptimas. A pesar de su bajo nivel es el lenguaje ms portado en
existencia, existiendo compiladores para casi todos los sistemas operativos conocidos.
Proporciona facilidades para realizar programas modulares y adems de la posibilidad de
utilizar cdigo o bibliotecas existentes.

2.3 Las interfaces de programacin de aplicaciones (APIs)

2.3.1 La interfaz OpenGL


OpenGL es una especificacin estndar, la cual define un API multilenguaje y
multiplataformas para desarrollar aplicaciones grficas con objetos de dos y tres
dimensiones. La interfaz consiste en ms de 250 funciones que pueden ser utilizadas para
crear complejos grficos tridimensionales a partir de simples primitivas geomtricas.
OpenGL se extiende mas all de las PCs y computadoras marca Apple, a muchos tipos de
sistemas UNIX.
Desde un punto de vista bsico, OpenGL es una especificacin, es decir que es
simplemente un documento que describe un conjunto de funciones y el comportamiento
preciso que stas deben tener. A partir de esta especificacin, los desarrolladores de
hardware crean implementaciones, bibliotecas de funciones desarrolladas de manera que
respeten las especificaciones descritas por OpenGL. Los productores de hardware deben
someter sus programas a diferentes pruebas, para poder calificar sus implementaciones
como implementaciones de OpenGL.
En comparacin a Direct3D 2, OpenGL no es un API de alto nivel. Su propsito es
dibujar objetos. Las tareas de edicin de objetos y entradas y salidas de archivos
(<<Input/Output>>) son relegadas a otras aplicaciones, como por ejemplo Open Inventor,
propiedad de Silicon Graphics. La interfaz OpengGL es multiplataforma, es decir que
1
Fuente: Programacin en C y C++, http://www.cprogramming.com/
2
Direct3D: Biblioteca grfica desarrollada por Microsoft.
6

puede ser utilizada sobre diferentes sistemas operativos, como por ejemplo Windows, Mac
OS-X, PlayStation 3, Linux y otros sistemas en base UNIX. Las funciones de OpenGL
pueden ser llamadas desde varios lenguajes, entre ellos C/C++, FORTRAN, Ada y Java.
El API OpenGL, comenz como una iniciativa de la empresa Silicon Graphics para
crear una sola interfaz de programacin grfica, independiente de desarrolladores de
hardware. Antes de la introduccin de OpenGL, muchos vendedores de hardware
utilizaban diferentes libreras grficas, lo cual encareca el proceso de crear programas
compatibles con diferentes plataformas de hardware. Esto llevo a Silicon Graphics a crear
OpenGL, aplicacin cuya base original es la biblioteca grfica IRIS. OpenGL empez
como una especificacin, luego Silicon Graphics cre una implementacin, que poda se
utilizada por los creadores de hardware para desarrollar sus propias implementaciones. Los
desarrolladores de software no necesitan una licencia para utilizar OpenGL en sus
aplicaciones, mientras que los desarrolladores de hardware si deben adquirir una licencia
para poder crear una implementacin de OpenGL. Por ejemplo, Mesa 3D es un API cuyo
cdigo es compatible con OpenGL, sin embargo para evitar el pago de licencias por
creacin de una implementacin de OpenGL, no es llamada como una implementacin
directa de OpenGL, sino como un API muy similar.
Una de la caractersticas ms interesantes de OpenGL es que utiliza un mecanismo
de servidor y cliente para procesar los grficos. El cliente grfico utiliza OpenGL y el
sistema operativo para trasmitir las primitivas grficas, coordenadas de vrtices, colores y
texturas al servidor. En el servidor se utiliza la informacin obtenida para generar los
pxeles, los cuales luego son sometidos a las pruebas de mapeo de texturas, pruebas de
profundidad, pruebas de unin de colores , entre otras.
Aunque normalmente el cliente y el servidor se encuentran en la misma
computadora, la ventaja de la separacin del proceso es que hace posible que una mquina
de bajo costo transmita, a travs de una red, comandos de OpenGL a una mquina ms
costosa y de mayor eficiencia, sobre la cual corre el proceso del servidor, luego las
imgenes finales pueden ser devueltas a la mquina de menor eficiencia para su despliegue.
OpenGL se puede manejar bajo dos tipos de modos, modo inmediato en el cual una
aplicacin enva un comando a OpenGL y sta los ejecuta inmediatamente y el modo de
retencin, en el cual secuencias de comandos grficos son almacenadas en estructuras de
datos conocidas como lista de despliegue o listas de exhibicin. El uso de estas listas
presenta dos ventajas importantes. Si se debe graficar un objeto complicado de manera
frecuente, solamente es necesario referirse a la lista que posee la informacin del objeto,
adems al estar la informacin de objeto en una lista, sta se puede enviar rpidamente a
travs de una red. La desventaja de las listas de exhibicin es que si un objeto est
destinado a sufrir modificaciones frecuentemente, se deben generar nuevas descripciones
del objeto de igual manera.
OpenGL elimina la complejidad que representa para el usuario interactuar con
diferentes tarjetas grficas, presentando al programador una interfaz nica y uniforme para
7

el desarrollo y programacin de grficos tridmensionales. Adems esconde las diferentes


capacidades que poseen diversas plataformas de hardware, ya que es requerido que todas
las implementaciones oficiales soporten todo el conjunto de funciones de OpenGL,
inclusive utilizando emulacin de software si es necesario.
OpenGL es un API de proceso de bajo nivel, por lo que requiere que el
programador le dicte los pasos necesarios para crear una escena. Esto contrasta con las
APIs descriptivas, las cuales solo necesitan que el programador describa la escena y la
librera se encarga del resto de la representacin de la escena. Tal caracterstica de OpenGL
hace necesario que el programador posea un buen conocimiento del modelado
tridimensional, pero tambin da un cierto nivel de libertad para implementar nuevos
algoritmos de representacin grfica.
OpenGL fue desarrollada como una aplicacin multiplataforma, por lo que trabaja
independiente del sistema de ventanas, razn por la cual no contiene comandos que
interacten con ste. Funciones como abrir, escalar, dar forma y cerrar ventanas, determinar
la posicin del mouse o cursor y determinar las entradas del teclado, son acciones que
deben ser relevadas a otras libreras. Existen varias libreras que han sido desarrolladas con
el propsito de brindar funcionalidad extra a los programadores que utilizan OpenGL.
GLUT, una librera que contiene utilidades y herramientas desarrolladas para trabajar en
conjunto con OpenGL, se encarga de todos los procesos de comunicacin entre las
aplicaciones OpenGL y el sistema de ventanas del sistema operativo. Al igual que GLUT
existen muchas otras libreras, por ejemplo SDL, GLU, GLUI y FLTK, entre muchas otras,
que se encargan de aadir funcionalidad extra al API OpenGL.
La especificacin de OpenGL es desarrollada y vigilada actualmente por ARB
(OpenGL Architecture Review Board), junta que fue formada en el ao 1992. ARB est
constituida por diferentes compaas, las cuales estn interesadas en crear un API
consistente, que se mantenga disponible durante un largo periodo. En abril del ao 2006,
algunos miembros de ARB con poder de voto eran: Silicon Graphics, 3DLabs, ATI
Technologies, NVIDIA, Intel, IBM, Apple Computer, Dell y Sun Microsystems. Microsoft
quien fuera uno de los miembros fundadores, abandon el grupo en marzo del ao 2003. A
parte de estas corporaciones, otras compaas son invitadas a formar parte del grupo
OpenGL ARB durante periodos de un ao. Con tantas compaas involucradas,
representando intereses tan diversos, OpenGL se ha convertido en un API con un amplia
gama de capacidades. Est planeado que la especificacin de OpenGL pase a ser
controlada por el grupo Khronos, a finales del ao 2006, esto con el fin de incrementar el
mercado y eliminar algunas barreras en el desarrollo de OpenGL y OpenGL ES, la cual es
un API derivada de la original, creada para ser implementada en sistemas mviles, tales
como telfonos celulares, PDAs y consolas de juegos de video.
Gran parte de la popularidad de OpenGL se debe a la excelente documentacin
oficial existente. OpenGL ARB ha publicado una serie de manuales, los cuales son
actualizados constantemente. Esto manuales son conocidos por los colores de sus portadas.
8

Algunas de las opciones implementadas en OpenGL son las siguientes:


Las primitivas geomtricas, las cuales permiten construir descripciones
matemticas de objetos. Las primitivas que actualmente se encuentran
implementadas en OpenGL son: puntos, polgonos, imgenes y mapas de bits
(<<bitmaps>>).
OpenGL permite la codificacin de color en los modos RGB y el modo de color
indexado.
Existe la posibilidad de mover la cmara por el espacio de la escena.
Se pueden utilizar texturas , para as incrementar el realismo de la escena que se
esta construyendo.
La iluminacin, la cual es indispensable para poder distinguir entre un objeto
tridimensional y uno de dos dimensiones, est provista en OpenGL a travs de
una serie de comandos que permiten calcular el color y las propiedades de los
materiales, as como las fuentes de luz en la escena.
Para lograr crear animaciones que luzcan continuas en el tiempo es necesario
utilizar la tcnica del doble <<buffering>>. Esta tcnica, la cual es posible
utilizar en OpenGL, consiste en construir cada cuadro de la escena en un
<<buffer>> separado de la memoria. Una vez terminado el cuadro de la escena,
el <<buffer>> con la informacin nueva remplaza al <<buffer>> que se muestra
actualmente en la pantalla, evitando de esta manera el parpadeo en la animacin.
La tcnica del anti-rizado, la cual permite reducir los bordes escalonados en las
lneas del dibujo, producto de la baja resolucin.
El sombreado de Gouraud, que se aplica para crear sombras suaves en objetos
tridimensionales y as generar diferencias entre los colores de su superficie.
El <<buffer>> Z o <<buffer>> de fondo, el cual mantiene un registro de la
coordenada Z de cada vrtice, lo que permite establecer la proximidad entre el
observador y el objeto y eliminar las superficies que se encuentran ocultas para
el observador.
Efectos especiales como humo y neblina, los cuales aaden realismo a la escena.
La mezcla Alfa (<<alpha blending>>), opcin del cdigo de colores RGBA,
que permite controlar las transparencias de los colores, por ejemplo para crear
una ventana o una mesa de vidrio.
Transformaciones de objetos, entre ellas la rotacin, la traslacin y el escalado.
9

2.3.2 La interfaz DIRECTX


Direct3D forma parte del API DirectX, propiedad de la empresa Microsoft.
Direct3D solamente se encuentra disponible para los sistemas Windows, superiores al
sistema Windows 95 y para las consolas de videojuegos XBox, tambin propiedad de
Microsoft. Direct3D se utiliza para crear grficos tridimensionales. La interfaz soporta
aceleracin de hardware, si la opcin se encuentra disponible en la tarjeta de video del
equipo. El API contienen muchos comandos para crear escenas tridimensionales, pero
contiene pocos comandos para crear y controlar escenas en dos dimensiones.
Direct3D no es multiplataforma, pero s logra esconder algunas de las diferencias
que existen entre los diferentes dispositivos de aceleracin 3D, utilizando un proceso de
emulacin de hardware.
Al igual que OpenGL, Direct3D puede operar tanto en modo inmediato como en
modo de retencin. En el modo de retencin Direct3D no utiliza listas de definicin, sino
que ofrece una interfaz de alto nivel orientada a objetos. Despus de haber cargado un
objeto, ste se puede rotar, escalar y trasladar utilizando diferentes funciones del API. En
el modo de retencin, el API ofrece funciones con las cuales se puede leer y escribir un
formato de archivo que guarda datos de objetos tridimensionales, tales como objetos
predeterminados, texturas y conjuntos de animaciones.

2.3.3 Comparacin general entre OpenGL y Direct3D1


Direct3D es un API propiedad de la corporacin Microsoft, que provee aceleracin
3D de hardware para las plataformas Windows.
OpenGL es un estndar abierto de un API que provee un nmero de funciones para
la produccin de grficos 2D y 3D. Una implementacin de estos estndares se encuentra
disponible en la mayora de los sistemas operativos modernos.

Portabilidad:
Por el momento Direct3D solo se ha implementado en sistemas operativos de la
familia Microsoft, incluyendo las versiones que se han utilizado en las consolas de
videojuegos XBox. Algunas funciones del API Direct3D han sido implementadas en el
proyecto Wine, el cual intenta trasladar APIs comnmente utilizadas en Windows a Linux,
pero el trabajo ha sido difcil debido a la dependencia entre DirectX y otros componentes
del sistema Windows.

1
Fuentes: Artculo: Comparison of Direct3D and OpenGL, http://www.wikipedia.org
Artculo: Direct3D vs. OpenGL, http://www.gamedev.net
10

OpenGL posee implementaciones disponibles para una gran variedad de sistemas


operativos incluyendo Windows de Microsoft, Linux, sistemas basados en UNIX, Mac OS
X y las consolas de videojuegos de Nintendo y Sony, por ejemplo PlayStation 3. A
excepcin de Windows, todos los sistemas operativos que permiten grficos 3D con
aceleracin de hardware han determinado OpenGL como la interfaz para programacin
grfica primaria. En trminos de portabilidad, Direct3D posee ms limitaciones que
OpenGL, sin embargo este encierro solo presenta un problema para algunas aplicaciones.

Facilidad de manejo:
Antes de la versin 8, Direct3D era conocido por ser un tanto difcil de manejar, por
ejemplo para realizar un cambio de estado se requera llevar a cabo un numero de
operaciones complicadas. Por ejemplo para habilitar la combinacin de colores conocida
como <<alpha blending>>, se tenia que crear un <<buffer>> o almacenador intermedio
llamado <<buffer>> de ejecucin, amarrarlo, llenarlo con los cdigos de operacin
correctos, junto con un encabezado estructural sealando cuntos cdigos de operacin
contena el <<buffer>> y un cdigo de operacin especial de salida, liberarlo y finalmente
enviarlo al controlador de la tarjeta de video para su ejecucin. Tal vez la queja mas famosa
fue entablada por el famoso desarrollador de videojuegos John Carmack en el archivo
.plan; l recomendaba a Microsoft abandonar Direct3D y utilizar OpenGL.
Sin embargo se produjeron muchos cambios en la versin Direct3D 8, los cuales
ayudaron a mejorar de manera notoria la imagen de Direct3D. Aun as Direct3D y OpenGL
son guiados por paradigmas distintos.
Direct3D est construido sobre el modelo de objetos COM de Microsoft, lo cual
indica que el uso de codigo C++ es un tanto inusual. Las funciones para adquirir valores no
devuelven el valor en el argumento de retorno, ya que todas las funciones COM devuelven
un HRESULT que dice si la funcin se ejecut correctamente o no. El lado positivo de usar
el modelo COM, es que se puede utilizar la misma interfaz en cualquier lenguaje con
arquitectura COM, como por ejemplo Visual Basic y Visual Basic Script, entre otros.
OpenGL es una especificacin basada en el lenguaje de programacin C. Fue
desarrollada utilizando el concepto de una mquina de estados finitos, aunque las ltimas
versiones de OpenGL lo han transformado ms en un sistema basado en objetos. Aunque la
especificacin esta construida en C, tambin se puede implementar en otros lenguajes.
En general Direct3D esta diseada para ser una interfaz de hardware 3D. Su
desarrollo depende del desarrollo del hardware y lo que el hardware puede proveer. Por
otro lado OpenGL esta diseado para ser un sistema de interpretacin 3D que puede poseer
aceleracin de hardware, como tal, su desarrollo se deriva de todo aquello que es
considerado como til por el usuario. Direct3D espera que la aplicacin maneje los
recursos del hardware, mientras que OpenGL crea la implementacin para hacerlo. Esto
facilita al usuario el hecho de escribir una aplicacin vlida, pero lo deja ms susceptible a
implementar errores. Al mismo tiempo, como OpenGL esconde los detalles del hardware,
11

incluyendo el hecho de si el hardware esta siendo utilizado o no, el usuario debe confiar en
que la implementacin esta utilizando los mejores recursos del hardware.

Desempeo:
Despus de que ambos APIs se establecieron como libreras grficas viables,
Microsoft y SGI comenzaron lo que se ha llamado la guerra de las APIs. La mayor parte de
la disputa giraba en torno a cual interfaz ofreca un mejor desempeo.
En general se ha logrado establecer que ninguna de las dos APIs es superior a la
otra en cuanto a velocidad. El desempeo de una aplicacin depende de la habilidad del
programador, la calidad de los controladores (<<drivers>>) y del hardware de grficos.

2.4 Teora de modelado tridimensional aplicada a computadoras


El modelado 3D es la representacin de objetos tridimensionales en un plano
bidimensional, por ejemplo la pantalla de una computadora. Las tcnicas de modelado
tridimensional y la creacin de motores tridimensionales se basan en axiomas matemticos
complejos. Aunque existen libreras grficas que evitan que el programador tenga que
lidiar directamente con todos los pasos algebraicos que implica crear una escena
tridimensional en un computador, es importante comprender las bases de lgebra lineal que
hay detrs de las escenas tridimensionales.

Figura 2.1 Plano 2D y espacio 3D

Un punto en el espacio se describe generalmente utilizando las coordenadas


cartesianas (x,y,z), las cuales describen la posicin del punto en un espacio tridimensional.
En la programacin de aplicaciones grficas se utilizan como base puntos y vectores para
describir las figuras geomtricas que se desea dibujar. Los vectores se pueden definir como
elementos de determinada magnitud y direccin en el espacio, pero tambin se pueden ver
como resta entre dos puntos, por ejemplo un vector se puede definir como:

V = Punto 2 Punto1 = ( x 2, y 2, y3) ( x1, y1, z1) = (a, b, c)


12

Para una computadora e incluso para el programador, las coordenadas cartesianas


son confusas, ya que no existe ningn elemento que diferencie entre un vector y un punto,
por ejemplo al leer el vector  antes definido, es imposible para la computador determinar
si los elementos (a,b,c) representan un vector o si son las coordenadas de un punto en el
espacio.

2.4.1 Las coordenadas homogneas


Las coordenadas homogneas son similares a las coordenadas cartesianas, la nica
diferencia es la existencia de un cuarto elemento en el vector coordenada, el elemento w.
Por ejemplo si P en coordenadas cartesianas est descrito por los elementos (x,y,z), en
coordenadas homogneas P est representado por los elementos (x,y,z,w), en donde w es un
cero si P es un vector y un uno si P es un punto.
Por ejemplo:
Punto1 P = (x1,y1,z1) coordenadas cartesianas.
Punto1 P = (x1,y1,z1,1) coordenadas homogneas.
Vector1 V = (x1,y1,z1) coordenadas cartesianas.
Vector1 V = (x1,y1,z1,0) coordenadas homogneas.

Generalmente se desea transformar los vrtices de los objetos que se van a dibujar,
por ejemplo trasladarlos, rotarlos con respecto a un eje e incluso escalarlos para cambiar el
tamao del objeto. Estos procesos de transformacin, conocidos como transformaciones
afines, se llevan a cabo utilizando matrices homogneas. Para poder utilizar estas matrices
de transformacin, los puntos y vectores deben estar descritos utilizando coordenadas
homogneas en lugar de coordenadas cartesianas. Las coordenadas homogneas impiden
que una transformacin acte de igual manera sobre un punto que sobre un vector, lo cual,
si llegara a pasar, sera un error que alterara de forma inesperada el objeto dibujado.
Por tales razones las coordenadas homogneas se utilizan para crear aplicaciones
grficas.

2.4.2 Los sistemas de coordenadas Cmara, Global y Objeto


En el espacio virtual de las aplicaciones tridimensionales existen varios sistemas de
coordenadas, entre ellos se encuentra el sistema de coordenadas propio de la pantalla, la
cual a partir de este punto ser llamada Cmara y el sistema de coordenadas Global o
Worldspace, que representa el sistema del mundo en el cual se encuentran todos los objetos
geomtricos que se desea dibujar, es decir es el sistema base del espacio virtual.
13

Figura 2.2 La cmara y el mundo

La posicin del punto A en la figura 2.2 est definida por las coordenadas
homogneas A(x,y,z,1), estas coordenadas son con respecto al sistema de coordenadas
globales o sistema Worldspace. Para poder graficar el punto A en la pantalla es necesario
determinar sus coordenadas respecto al sistema de coordenadas de la cmara, ya que este es
el sistema fsico en el cual se dibujar el punto.

Figura 2.3 La cmara, el mundo y el objeto

Para simplificar el proceso de crear mundos tridimensionales se utiliza un tercer


sistema de coordenadas llamado sistema de coordenadas locales o sistema Objeto. Si se
tiene un objeto que se encuentra en constante movimiento en el sistema global , se
convierte en una tarea difcil y tediosa tener que calcular a cada instante las coordenadas de
cada punto del objeto respecto al sistema global. Teniendo este nuevo sistema de
coordenadas, cuando un objeto se mueve, las coordenadas de sus puntos respecto al sistema
Objeto no varan, lo que vara es la posicin y direccin del sistema de coordenadas Objeto
respecto al sistema global y el sistema Cmara.
14

Teniendo estos tres sistemas de coordenadas en cuenta, el proceso que se debe


llevar a cabo para dibujar un objeto tridimensional en la pantalla es el siguiente:
Primero se deben pasar las coordenadas de cada punto del objeto del sistema de
coordenadas objeto al sistema de coordenadas global. Luego las coordenadas resultantes
deben trasladarse al sistema Cmara, obteniendo de esta manera las coordenadas fsicas de
cada punto del objeto en la pantalla.
Para trasladar las coordenadas de un punto de un sistema a otro se utilizan matrices
homogneas llamadas matrices de transformacin.
En el espacio virtual, los sistemas de coordenadas se pueden representar mediante
matrices de cuatro filas y cuatro columnas (matrices 4 x 4).

a a' a' ' x



b b' b' ' y
A=
c c' c' ' z

0 0 0 1

Los primeros tres vectores columna de la matriz A definen la base del sistema de
coordenadas, es decir la direccin y magnitud de los vectores x, y, z base. La cuarta
columna define el desplazamiento del sistema de coordenadas, en otras palabras, la
ubicacin del punto de origen del sistema de coordenadas. Al igual que se explic antes
para las coordenadas homogneas, el cuarto valor de cada columna define si se est
describiendo un punto o un vector. Se utiliza un cero para indicar que los valores de la
columna pertenecen a un vector y un uno para indicar que los valores pertenecen a un
punto.
Por ejemplo la base cannica estara representada por la matriz B, la cual a su vez es
la matriz identidad.
1 0 0 0

0 1 0 0
B=
0 0 1 0

0 0 0 1

En la figura 2.4 se observan tres sistemas de coordenadas definidos como Cmara,


Worldspace y Objeto. Los vectores base son los mismos para los tres sistemas, lo nico que
diferencia un sistema del otro es la ubicacin de los puntos de origen.
15

Figura 2.4 Sistemas de coordenadas Cmara, Global y Objeto.

Los sistemas Cmara, Worldspace (Global) y Objeto de la figura 2.4 estn


representados por la matrices C, W y O respectivamente.

1 0 0 3 1 0 0 0 1 0 0 3

0 1 0 4 0 1 0 0 0 1 0 4
C = W = O=
0 0 1 0 0 0 1 0 0 0 1 0

0 0 0 1 0 0 0 1 0 0 0 1

Para la figura 2.4, si se multiplica el vector de coordenadas (x,y,z,0) del punto P, las
cuales son con respecto al sistema Objeto, por la matriz O, la asociada al sistema Objeto, se
obtienen las coordenadas del punto P respecto al sistema Worldspace. Es importante
recordar que se utilizan coordenadas homogneas y no cartesianas, por lo que se le debe
agregar un uno como cuarto elemento al vector de coordenadas , para indicar que lo que
se est definiendo es un punto y no un vector . El vector P representa las coordenadas del
punto P respecto al sistema Worldspace.

1 0 0 3 2 5

0 1 0 4 4 8
P'= O P = =
0 0 1 0 0 0

0 0 0 1 1 1

16

La matriz asociada al sistema Objeto se puede denominar como T1(OW), ya que


pasa las coordenadas del sistema Objeto al sistema Worldspace. De forma anloga la matriz
asociada al sistema Cmara, es decir la matriz C, pasa las coordenadas del sistema Cmara
al sistema Worldspace, por lo que se puede denominar como T2(CW). Cuando se crea
una escena tridimensional, es necesario poseer las coordenadas de todos los objetos de la
escena respecto al sistema Cmara, para as saber en qu posicin de la pantalla se deben
dibujar. La matriz inversa de la asociada al sistema Cmara, C=C-1, pasa las coordenadas
del sistema Worldspace al sistema Cmara. La matriz C se puede denominar como
T3(WC), entonces para obtener las coordenadas del punto P respecto al sistema cmara,
se debe llevar a cabo la siguiente operacin:

P ' ' = C 'P ' = C 1 (O P )

en donde el vector  representa el vector de coordenadas del punto P respecto al sistema


Cmara.
Es importante recordar que cada vez que la cmara cambia su posicin , se debe
cambiar la matriz C. De igual manera cada vez que el objeto al cual pertenece el punto P se
mueve en el espacio virtual, se debe modificar la matriz O, para que represente de manera
adecuada la nueva posicin y rotacin del sistema de coordenadas propio al objeto.

2.4.3 Trasladar, rotar y escalar objetos


Muchas veces los objetos en una escena se deben trasladar, rotar e incluso escalar,
estas transformaciones, llamadas transformaciones afines, se logran multiplicando los
vrtices de los objetos geomtricos por matrices homogneas de transformacin. Estas
matrices se pueden concatenar una tras otra y de esta manera hacer mltiples
transformaciones a un mismo objeto geomtrico.
Las transformaciones afines estn representadas por cinco matrices genricas. Una
matriz genrica para traslaciones, tres matrices genricas para rotaciones y una matriz
genrica para escalamientos.
1 0 0 tx

0 1 0 ty
Matriz de traslacin genrica T =
0 0 1 tz

0 0 0 1

17

En la matriz genrica de traslacin, el cuarto vector columna (tx, ty, tz) representa
los valores de traslacin sobre el eje X, el eje Y y el eje Z respectivamente. Ntese que la
matriz T se puede denominar como la matriz asociada a un sistema de coordenadas con
origen en el punto (tx, ty, tz).

1 0 0 0

0 cos( ) sin( ) 0
Matriz genrica de rotacin respecto al eje X R X =
0 sin( ) cos( ) 0

0 1
0 0

cos( ) 0 sin( ) 0

0 1 0 0
Matriz genrica de rotacin respecto al eje Y RY =
sin( ) 0 cos( ) 0

0 1
0 0

cos( ) sin( ) 0 0

sin( ) cos( ) 0 0
Matriz genrica de rotacin respecto al eje Z RZ =
0 0 1 0

0 0 1
0

En las matrices genricas de rotacin, el ngulo representa el ngulo de rotacin


respecto al eje de rotacin determinado.

sX 0 0 0

0 sY 0 0
Matriz genrica de escalamiento S =
0 0 sZ 0

0 1
0 0
18

En la matriz genrica de escalamiento, los argumentos sX, sY y sZ, determinan el


factor al que se escalarn las coordenadas X, Y y Z de cada vrtice, respectivamente.
Es importante recordar que la multiplicacin de matrices no es conmutativa, es decir
para la multiplicacin de las matrices A y B se tiene que A B B A . Esto es importante,
ya que el orden de multiplicacin de las matrices afecta la posicin final del objeto en la
escena.

Figura 2.5 Rotacin y Traslacin1

En la figura 2.5 se observa cmo el resultado de rotar la maceta y luego trasladarla,


es distinto al del proceso inverso. Aun cuando las transformaciones sean las mismas, si el
orden en que stas se aplican a un objeto se cambia, el resultado final ser distinto.
Entonces por ejemplo para el primer caso de la figura 2.5, en el que primero se rota
el objeto y luego se traslada, cada vrtice del objeto se tendra que transformar de la
siguiente manera:
V f = T R Vi
en donde i y f son vectores columna que representan las coordenadas homogneas
iniciales y finales del vrtice respectivamente, mientras que R es la matriz homognea de
rotacin aplicada y T la matriz homognea de traslacin aplicada. Por otro lado para el
segundo caso, en el que primero se traslada la figura y luego se rota, la multiplicacin entre
las matrices y cada vrtice del objeto tendra el siguiente orden:
V f = R T Vi
Ntese que la direccin de concatenacin de las matrices va de derecha a izquierda,
siendo la matriz que est ms a la derecha el primer proceso de transformacin que sufre el
objeto. Otro punto que se debe tener en cuenta es que las matrices se post-multiplican, es
decir que los vrtices de cada objeto se representan como vectores columna que se
multiplican al conjunto de matrices de transformacin por la derecha.

1
Figura tomada de la gua libre de programacin OpenGL Red Book, http://www.glprogramming.com/red
19

Generalmente los programadores de aplicaciones grficas no tienen que preocuparse


por tener que estar introduciendo matrices de transformacin al cdigo, ya que al utilizar
APIs como OpenGL y Direct3D, ellas mismas se encargan de hacer todos los clculos
matriciales necesarios, mientras que el programador solo tiene que llamar la funcin
respectiva de rotacin, traslacin o escalamiento. Aun as es importante conocer cmo
funcionan los procesos de transformacin, ya que para algunos casos las funciones bsicas
de rotacin, traslacin y escalamiento provistas por las APIs no son suficientes o pueden
llegar a ser un tanto rgidas, por ejemplo cuando se desea implementar un mtodo de
deteccin de colisiones.

2.4.4 Sistemas grficos


Los sistemas grficos generalmente estn compuestos por los siguientes elementos:

Figura 2.6 Elementos tpicos de un sistema grfico

Las entradas definen todo lo que se ha calculado en la aplicacin grfica y se desea


dibujar, es decir el nuevo estado de la escena y los cambios que esto conlleva.
El procesador o CPU se encarga de la comunicacin entre los mdulos, realiza
operaciones aritmticas con ayuda de las unidades aritmticas (<<ALUs>>) y consulta la
memoria cuando sea necesario. Los sistemas especializados en grficos poseen varios
procesadores que trabajan en paralelo, por lo que pueden calcular y dibujar al mismo
tiempo, lo que mejora el rendimiento en tiempo real.
20

El <<frame buffer>> es la zona de la memoria en la cual se almacena todo lo que va


a ser dibujado. Las APIs grficas escriben en esta zona lo que se desea dibujar y luego
envan esta informacin a la pantalla.
La LUT (por sus siglas en ingls: <<Look Up Table>>), tambin conocida como
paleta, es la tabla que contiene todos los colores disponibles en el sistema.
El conversor D/A convierte la informacin del <<buffer>> de digital a analgica,
para que esta pueda ser proyectada en la pantalla.
El <<frame buffer>> est caracterizado por su resolucin y su profundidad. La
resolucin es la multiplicacin del ancho por el alto del conjunto de pxeles, es decir el
numero de filas de pxeles por el numero de columnas de pxeles. El pxel es la unidad
mnima de la pantalla. stos se encuentran aglomerados en filas y la combinacin de los
colores de cada pxel en conjunto da forma a la imagen que se ve en la pantalla.
La profundidad del <<frame buffer>> determina el numero de bits que se utiliza
para guardar la informacin de cada pxel. Este nmero depende de la cantidad de colores
que se desea mostrar en la aplicacin.

2.4.5 Arquitectura Grfica (PIPELINE)


El proceso por etapas o <<pipeline>> grfico define los pasos necesarios para editar
la escena que se desea dibujar en la pantalla, por lo tanto indica los pasos de actuacin que
debe seguir el API grfico que se est utilizando. La entrada del <<pipeline>> grfico es la
geometra u objeto geomtrico que se desea dibujar y la salida es la imagen que se obtiene
en la pantalla.

Figura 2.7 Arquitectura Grfica (pipeline)


21

A la entrada est el objeto geomtrico que se desea dibujar, el cual est compuesto
por primitivas geomtricas como puntos y lneas. Estos objetos poseen atributos
previamente establecidos, los cuales pueden ser mviles o fijos, por lo que debe existir la
posibilidad de trasladarlos, rotarlos y escalarlos si es necesario, antes de que sean dibujados
en la pantalla.
Durante el proceso de transformacin del modelo, se rotan, trasladan y escalan los
objetos geomtricos , de manera que se dibujen en la pantalla igual que se dispuso en el
mundo que se desea crear. Para lograr esto se multiplican los vrtices de los objetos por las
matrices de rotacin , traslacin y escalamiento que sean necesarias.
Una vez realizadas las transformaciones de los vrtices, se obtienen las coordenadas
de los objetos con respecto al mundo que se est creando, estas coordenadas son las
coordenadas del mundo o coordenadas globales.
El siguiente paso en el pipeline es el de iluminar los objetos para que sean visibles a
la cmara (pantalla) y determinar las coordenadas de los objetos respecto a la cmara. Este
proceso se llama transformacin del visionado. Luego de haberlo realizado se sabe cuales
son las coordenadas de todos los objetos con respecto a la cmara.
El prximo paso es recortar todo aquello que existe pero no es visible para la
cmara. Este proceso se conoce como <<clipping>>.
Durante el proceso de proyeccin se pasan las coordenadas tridimensionales del
mundo que se desea dibujar a coordenadas bidimensionales del plano de proyeccin.
Una vez proyectado el grfico se tienen las coordenadas de pantalla independientes
del dispositivo o DISC por sus siglas en ingles (<<Device Independent Screen
Coordinates>>). A estas coordenadas se les llama independientes del dispositivo, ya que
aun no se encuentran ligadas a ningn tipo de monitor, es decir todava no se sabe la
resolucin de la pantalla ni el tamao del monitor.
Finalmente se lleva acabo el proceso de rasterizacin el cual consiste en asociar
todos los puntos de la imagen proyectada a pxeles en la pantalla, obteniendo de esta
manera la imagen final en el monitor.
El pipeline grfico puede ser implementado a travs de hardware o software. La
implementacin a travs de software produce que todo el proceso sea ms lento a menos de
que se cuente con tarjetas de aceleracin grfica.
22

2.5 Introduccin a OpenGL, GLUT y GTK

2.5.1 La ventana de despliegue utilizando GLUT


Lo primero que se debe hacer a la hora de desarrollar una aplicacin grfica es crear
una ventana donde se puedan desplegar los grficos. Si se utiliza la biblioteca GLUT, la
funcin gluInit() es la primera que se debe llamar, sta se encarga de inicializar la
biblioteca GLUT y negocia una sesin con el sistema de ventanas. Si GLUT no logra ser
inicializado, el programa se cerrar y le dar un mensaje de error al usuario. Algunas causas
de error de inicializacin pueden ser fallos al conectarse con el sistema de ventanas, falta de
soporte para OpenGL por parte del sistema de ventanas y opciones invalidas en la lnea de
comandos. Los parmetros de la funcin glutInit() deben ser los mismos que aquellos de la
funcin main(), especficamente main(int argc, char**argv) y glutInit(&argc, argv).
El prximo paso es escoger el modo en el que se desplegarn los modelos de
colores en la ventana, utilizando la funcin glutDisplayMode(). Por ejemplo
glutDisplayMode(GLUT_RGBA || GLUT_DOUBLE || GLUT_DEPTH ) indica que se
utilizar el modelo de colores RGB con ndice alfa, que se utilizarn dos <<buffers>> para
desplegar los grficos y un <<buffer>> para implementar pruebas de profundidad para cada
pxel.
Lo siguiente es proporcionar las caractersticas de la ventana a crear. La funcin
glutInitWindowSize(ancho, alto) determina el tamao de la ventana a crear, en donde el
parmetro ancho es el ancho de la ventana en pxeles y alto es el alto de la ventana,
tambin en pxeles. De manera similar glutInitWindowPosition(X,Y) determina la posicin
inicial de la esquina superior izquierda de la ventana en la pantalla, donde X y Y son
coordenadas en la pantalla del monitor, medidas en pxeles.
Para crear la ventana asociada a las caractersticas anteriormente determinadas se
debe llamar la funcin glutCreateWindow(nombre), en donde la variable nombre determina
el ttulo que tendr la ventana.
La librera GLUT posee varias funciones de respuesta, en estas funciones se pueden
almacenar rutinas especificadas por el programador, que son llamadas en respuesta a algn
tipo de evento. Por ejemplo, la funcin de respuesta ms importante en cualquier programa
GLUT es la funcin glutDisplayFunc(), el argumento de esta funcin es llamado cada vez
que GLUT determina que el contenido de la ventana debe desplegarse nuevamente. Todas
la rutinas requeridas para dibujar una escena deberan estar en la funcin
glutDisplayFunc().
El argumento de la funcin glutReshapeFunc() es llamado cuando se vara el
tamao de la ventana o sta se mueve. Esto impide que se d distorsin en el dibujo al
cambiar el tamao de la ventana.
23

Existen otras funciones de respuesta, como por ejemplo las funciones


glutMouseFunc() y glutKeyboardFunc(), las cuales llaman las rutinas especificadas en sus
argumentos, cuando se da algn evento en el ratn o el teclado del computador.
La funcin de respuesta final que debe ser llamada en cualquier programa GLUT es
la funcin glutMainLoop(). Esta funcin se encarga de ensear todas la ventanas que han
sido creadas. El comando glutMainLoop() representa un lazo, del cual nunca se sale, que
se encarga de monitorear todos lo eventos, por ejemplo pulsaciones de teclas, movimientos
del ratn y en caso que sea necesario, llamar a la funcin de respuesta asociada a cada
evento.
Una vez creada la ventana para desplegar los grficos, es posible comenzar a
introducir comandos y funciones de OpenGL y as crear los objetos geomtricos deseados.

2.5.2 La ventana de despliegue utilizando GTK


GTK (por sus siglas en ingls: <<GIMP ToolKit>>), es una librera que se utiliza
para desarrollar interfaces grficas de usuario. Posee una licencia LGPL, por lo que puede
ser empleada en el desarrollo de software libre o abierto, e incluso en proyecto comerciales,
de manera gratuita.
GTK est construida sobre la biblioteca GDK (por sus siglas en ingls: <<GIMP
Drawing Kit>>), la cual es bsicamente un envoltorio alrededor de funciones de bajo nivel,
que se utilizan para acceder las funciones del sistema de ventanas. Esencialmente, GTK es
un API orientada a objetos, an cuando todo su cdigo se encuentra escrito en C. Las
funciones de biblioteca se implementan utilizando clases y punteros.
Los pasos a seguir para crear una ventana GTK son muy similares a los pasos para
crear una ventana GLUT.

/* Ejemplo: Como crear una ventana GTK */

#include <gtk/gtk.h>

int main( int argc,


char *argv[] )
{
GtkWidget *ventana;
gtk_init (&argc, &argv);
ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (venatna);
gtk_main ();
return 0;
}
24

Todos los programas que utilicen GTK deben incluir el archivo gtk.h, en el cual
se declaran las variables, funciones, estructuras, etc, que sern utilizadas por la aplicacin
GTK. La funcin gtk_init(gint *argc, gchar ***argv) es la encargada de inicializar GTK en
la aplicacin. Las interfaces grficas estn compuestas por objetos llamados <<widgets>>.
Un <<widget>>, tambin conocido como artilugio o control, es un componente grfico con
el cual el usuario interacta, como por ejemplo, una ventana, una barra de tareas, un botn
o una caja de texto. En la aplicaciones GTK los <<widgets>> son definidos como
GtkWidget, por ejemplo GtkWidget *ventana.
En la lnea ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL) del ejemplo
anterior, se define el <<widget>> ventana, como un nueva ventana GTK. El argumento
que fue pasado a la funcin indica que se desea que la ventana acepte las caractersticas de
decoracin y posicin dadas por el controlador de ventanas del sistema operativo. En vez
de crearse una ventana de tamao 0 x 0, se establece una ventana de tamao 200 x 200. Por
supuesto estas dimensiones son argumentos predeterminados que pueden ser variados
posteriormente a gusto del desarrollador.
La funcin gtk_widget_show (GtkWidget *) le indica a Gtk que ya se establecieron
todos los atributos que se deseaban para el <<widget>> y que ste ya puede ser desplegado.
Al igual que las aplicaciones GLUT, todos los programas GTK poseen una estructura de
lazo infinito, en el cual se est a la espera de que suceda algn evento. En GTK el lazo
principal es representado por la funcin gtk_main(). En el cdigo anterior no se estableci
ninguna funcin de respuesta a eventos, por lo que cualquier evento ser ignorado.
En aplicaciones GTK las funciones de respuesta se conectan a los eventos de la
siguiente manera: g_signal_connect (G_OBJECT (GtkObj), "evento", G_CALLBACK
(func_respuesta), argumento), en donde GtkObj es el objeto del tipo GTK, por ejemplo una
ventana o un botn, en el cual se di el evento, func_respuesta es la funcin que debe
llamarse como respuesta al evento y argumento representa posibles argumentos que se le
pueden pasar a la funcin de respuesta.

2.5.3 Primitivas y vrtices


Los objetos geomtricos se pueden describir por medio de conjuntos de vrtices
conectados entre s por algn tipo de primitiva geomtrica. Para determinar la posicin de
los vrtices se utiliza el comando glVertex*(), en donde el smbolo * indica que existen
variaciones para el comando base glVertex(). Algunos nombres de funciones poseen de
uno a tres caracteres al final, los cuales determinan el numero y tipo de parmetros que se
pasarn al comando. Por ejemplo la funcin glVertex3f() indica que se trata de un vector,
donde tres representa el numero de dimensiones o elementos del vector y la letra f indica
que los elementos del vector son nmeros del tipo flotante.
La posicin de los vrtices debe encontrarse entre las funciones glBegin() y glEnd(),
las cuales sealan el principio y fin de un objeto geomtrico. El argumento de la funcin
25

glBegin() indica el tipo de primitiva que se utilizar para unir los vectores. Algunos tipos
soportados por la librera OpenGL son: GL_LINES, dibuja una lnea cada dos vrtices,
GL_POINTS, dibuja un punto en cada vrtice, GL_POLYGON, dibuja un polgono. Los
polgonos deben ser convexos. La funcin glColor*(), especifica el color que OpenGL
utiliza para dibujar las figuras, el color no cambia hasta que se vuelva a llamar la funcin
glColor*().
Para el cdigo que se presenta a continuacin , dependiendo de si la variable
PRIMITIVA se sustituye por el argumento GL_POLYGON o GL_POINTS se obtendr
uno de los objetos presentados en la figura 2.8.

/* Ejemplo del uso de diferentes primitivas */

...
glBegin(PRIMITIVA); /*Determina el inicio de un conjunto de vrtices y el tipo de
primitiva que los une*/
glVertex2f(0.0, 0.0); /*Posicin del vrtice 1*/
glVertex2f(0.0, 3.0); /*Posicin del vrtice 2*/
glVertex2f(4.0, 3.0);
glVertex2f(6.0, 1.5);
glVertex2f(4.0, 0.0);
glEnd(); /*Determina el fin de un conjunto de vrtices*/
...

Figura 2.8 Polgono y puntos.

La librera GLUT posee una serie de rutinas que pueden ser utilizadas para crear
objetos tridimensionales especficos. Por ejemplo glutWireSphere() dibujar una esfera
compuesta por lneas, glutSolidCube(), dibuja un cubo, entre otros. Las dimensiones de
estos objetos se especifican en los argumentos de la funcin.

2.5.4 La matriz CTM


La librera OpenGL posee funciones que se encargan de las transformaciones de
posicin y tamao que se desean llevar a cabo en la escena. OpenGL transforma el modelo
llevando a cabo multiplicaciones matriciales. En la aplicaciones grficas como OpenGL, la
geometra se ve afectada por la CTM (por sus siglas en ingls: <<Current Transformation
Matriz>>) o matriz de transformacin actual. Aqu se guarda la informacin de todas las
26

matrices que se han ido acumulando. Los vrtices que son procesados se multiplican por
esta matriz y por lo tanto son transformados. En OpenGL la CTM est compuesta por la
multiplicacin de dos matrices, la matriz Model-View o matriz de transformacin del
modelo y la matriz de proyeccin. La primera se encarga de las transformaciones que se
llevarn a cabo y la segunda representa la proyeccin sobre el plano bidimensional, es decir
el paso del mundo 3D al mundo 2D.

2.5.5 La matriz de transformacin del modelo


Lo primero que se debe hacer para llamar matrices de transformacin es cargar la
matriz Model-View y luego reiniciarla, lo cual se logra acumulando la matriz identidad.

/* Ejemplo de como llamar la matriz de transformacin del modelo e inicializarla */


...
glMatrixMode(GL_MODELVIEW); /*Se carga la matriz Model-View*/
glLoadIndentity(); /*Se carga la matriz identidad*/
...

Despus de haber activado la matriz Model-View se pueden comenzar a acumular


matrices de transformacin para obtener el resultado deseado. Las funciones de
transformacin implementadas en OpenGL son glScale*(), glRotate*(), glTranslate*().
El comando glScalef(GLfloat sx, GLfloat sy, GLfloat sz) escala los valores de las
coordenadas X, Y y Z de la geometra, de acuerdo a los valores de sx, sy y sz. Tanto la letra
f al final del nombre de la funcin como el argumento GLfloat indican que los valores de
sx, sy y sz son del tipo flotante.
La funcin glTranslatef(GLfloat tx, GLfloat ty, GLfloat tz) traslada la geometra,
segn los factores tx, ty y tz.
La funcin glRotatef(GLfloat ngulo, GLfloat vx, GLfloat vy, GLfloat vz) rota la
geometra en un ngulo determinado. La rotacin es en sentido anti-horario, respecto al
vector definido por el conjunto de valores (vx, vy, vz).
A medida que se van introduciendo transformaciones stas se van post-
multiplicando en la matriz de transformacin, es decir que la ltima transformacin
introducida ser la primera que se le aplicar a la geometra, esto se debe a que la matriz
Model-View funciona como una pila LIFO (por sus siglas en ingls: <<Last In First
Out>>), en donde la ltima transformacin en entrar es la primera en salir. Utilizando la
funcin glPushMatrix() se puede salvar el estado actual de la pila en cualquier momento y
luego puede ser recuperado utilizando la funcin glPopMatrix(). Esto es muy til por
ejemplo en los casos que se deseen hacer transformaciones a solo algunas partes de la
geometra. Se puede salvar el estado actual de la pila, transformar solo las partes de la
27

geometra que se desean transformar y luego recuperar el estado de la pila, sin que el resto
de la geometra se vea alterada por las transformaciones que se llevaron a cabo.

/* Ejemplo que muestra como se pueden usar las funciones de la pila (Model-View) para transformar solo
algunas partes de la geometra */
...
dibujo_parte1(){...} /*se define alguna forma geomtrica*/
dibujo_parte2(){...} /*se define alguna forma geomtrica*/
...
glTranslatef... /*afecta a toda la geometra que se dibuje a partir de ahora*/
glRotatef... /*afecta a toda la geometra que se dibuje a partir de ahora*/
glPushMatrix(); /*salva el estado actual de la matriz, es decir las dos transformaciones anteriores*/
glTranslatef... /*afecta solo la geometra que se dibuje antes del prximo glPopMatrix()*/
glRotatef... /*afecta solo la geometra que se dibuje antes del prximo glPopMatrix()*/
dibujo_parte1(); /*geometra que se ve afectada por 4 transformaciones*/
glPopMatrix(); /*se recupera el estado anterior de la matriz*/
dibujo_parte2(); /*geometra que se ve afectada por solo 4 transformaciones*/
...

2.5.6 Transformacin de la visin y proyeccin de la escena.


Transformar la visin equivale a cambiar la posicin del observador. Lo primero
que se debe hacer es activar la matriz de transformacin e inicializarla, es decir cargar la
matriz identidad. Luego se determina la posicin del observador, para esto se puede utilizar
la funcin gluLookAt(px, py, px, ox, oy, oz, ax, ay, az), en donde el vector (px, py, pz)
determina la posicin del observador, el vector (ox, oy, oz) determina hacia donde ve el
observador y el vector (ax, ay, az) define el vector que apunta hacia arriba, por as decirlo,
hacia el cielo. La funcin gluLookAt() es parte de la librera GLU.
Una vez que se ha creado la escena tridimensional y se han aplicado todas las
transformaciones a los objetos y al observador, el siguiente paso es pasar la escena del
mundo tridimensional al plano de proyeccin bidimensional de la pantalla.
La matriz de proyeccin determina el tipo de proyeccin y la escogencia de los
atributos de sta, es anlogo a elegir el lente de una cmara, el cual determina el mbito de
visin y el acercamiento. La matriz de proyeccin se activa utilizando el comando
glMatrixMode(GL_PROJECTION). Una vez inicializada la matriz de proyeccin se puede
llamar la funcin glOrtho() para determinar las dimensiones del volumen de visin. El
volumen de visin determina el rango visual del observador. Utilizando los comandos
gluPerspective() o glFrustum() se define este volumen. El proceso de transformacin de la
visin y la matriz de proyeccin se puede comparar con el de tomar una fotografa, tal y
como se muestra en la figura 2.9.
28

Figura 2.9 Analoga entre cmara y computadora1

A continuacin se presenta un ejemplo de cmo configurar la visin y proyeccin de una


escena.

/* Ejemplo de configuracin de las matrices de visin y proyeccin */

void reshape (int w, int h) /*funcin que se llama cuando la ventana se crea o cambia de tamao*/
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h); /*tamao del cuadro de visin*/
glMatrixMode (GL_PROJECTION); /*activa la matriz de proyeccin*/
glLoadIdentity (); /*la reinicia*/
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0); /*determina la perspectiva*/
glMatrixMode(GL_MODELVIEW); /*activa la matriz de transformacin*/
glLoadIdentity(); /*la reinicia*/
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); /*indica la posicin del observador*/
}

1
Figura tomada de la gua libre de programacin OpenGL Red Book
29

En el ejemplo anterior, la funcin glViewport() define el rea de visin, en otras


palabras el rea de la ventana que se utiliza para dibujar la escena. En este caso se utiliz
toda la ventana. Tras haber cargado e inicializado la matriz de proyeccin, se define el
volumen de visin utilizando la funcin gluPerspective(), cuyos argumentos son: el ngulo
del campo de visin (en el ejemplo es 60.0), la razn de aspecto, la cual se define como la
divisin del ancho del rea de visin entre el alto del rea de visin, la posicin del plano
ms cercano del volumen de visin, respecto al observador (en el ejemplo es 1.0) y la
posicin del plano ms lejano del volumen de visin, respecto al observador (en el ejemplo
es 2.0). La ltima funcin del ejemplo determina la posicin del observador y el punto
hacia el cual ste se encuentra mirando.
La figura 2.10 es una representacin de un volumen de visin especificado
utilizando la funcin gluPerspective().

Figura 2.10 Volumen de visin especificado por gluPerspective()1

1
Figura tomada de la gua libre de programacin OpenGL Red Book
CAPTULO 3: La robtica

Desde un punto de vista muy bsico y tcnico, los seres humanos estn compuestos
por cinco componentes principales:
Una estructura corporal.
Un sistema muscular que mueve la estructura corporal.
Un sistema sensorial que recibe informacin del cuerpo y el ambiente que lo
rodea.
Una fuente de poder para activar los msculos y sensores.
Un cerebro que procesa la informacin sensorial y le indica a los msculos qu
hacer.
Por supuesto que los humanos tambin poseen atributos intangibles tales como la
inteligencia y la moral, entre muchos otros. Pero si se analiza desde un nivel simplemente
fsico y tcnico, los cinco atributos antes mencionados bastan para describir de manera
general el cuerpo humano. Un robot est compuesto por los mismos componentes. Los
robots tpicos poseen una estructura fsica mvil, un motor de algn tipo, un sistema
sensorial, una fuente de poder y una computadora que acta como el cerebro y que
controla todos los componentes anteriores.

3.1 Las bases de los robots


La mayora de los robots poseen ciertas cualidades comunes. En primer lugar todos
tienen un cuerpo mvil. Algunos simplemente poseen ruedas motorizadas, mientras que
otros poseen segmentos mviles con configuraciones muy complejas. Al igual que los
huesos en el cuerpo humano, los segmentos de un robot se encuentra conectados entre s
por medio de articulaciones.
Los actuadores son las unidades controladas que se encargan de mover las partes
mviles de los robots. Los actuadores hidrulicos son aquellos que utilizan lquido, los
neumticos utilizan aire comprimido para generar el movimiento, los actuadores elctricos,
los cuales estn compuestos por motores y solenoides son los ms populares.
En un robot, cada actuador se encuentra conectado a un circuito elctrico. El
circuito le brinda corriente a los motores y solenoides de forma directa, mientras que en el
caso de los actuadores hidrulicos, el circuito se encarga de activar el sistema hidrulico
por medio de la manipulacin de vlvulas elctricas. Las vlvulas determinan el camino del
lquido presurizado, a travs de la mquina.

30
31

La computadora del robot se encarga de controlar todo lo que est conectado al


circuito. Para mover el robot, la computadora enciende los motores y las vlvulas que sean
necesarias.
No todos los robots poseen sistemas sensoriales, por lo que en algunos casos es
necesario el desarrollo de programas de prediccin que trabajen de forma paralela al
sistema de control, por ejemplo programas de prediccin de choques.

3.2 El brazo robot


El trmino robot proviene de la palabra checa robota, que significa trabajo
forzado, lo cual describe muy bien las tareas que cumplen muchos robots hoy en da. La
mayora de los robots son diseados para llevar a cabo procesos industriales pesados y
repetitivos. Se encargan de tareas que pueden ser difciles, peligrosas e incluso aburridas
para el ser humano. El robot industrial ms popular es el brazo robot.
El desarrollo de brazos robot comenz en Europa hace ms de treinta aos, donde se
idearon estos brazos para la industria automotriz. Hoy en da sus aplicaciones van desde la
industria del entretenimiento hasta las ciencias de la salud.
Normalmente los brazos robot se clasifican segn su configuracin, su tipo de
actuador, el mtodo de programacin, la metodologa de control y las tareas que lleva a
acabo.
La configuracin de robot se refiera a la geometra de este, sus grados de libertad y
sus ejes de movimiento. Una de la configuraciones ms utilizadas es la de los sistemas
antropomorfos, los cuales son sistemas de brazos robot que imitan la configuracin del
brazo humano. Entre este tipo de configuracin el brazo ms comn es el de seis
articulaciones, con seis grados de libertad. El brazo humano tiene siete grados de libertad.
Los grados de libertad se refiere al numero de ngulos de giro que posee la extremidad, en
otras palabras es la suma del nmero de ejes de giro de todas las articulaciones de la
extremidad. Por ejemplo, un brazo mecnico de dos articulaciones, en el que la primera
articulacin gira respecto al eje X y la segunda respecto al eje Z, es un brazo con dos
grados de libertad, mientras que otro con dos articulaciones en el que la primera gira
respecto a X y la segunda respecto a X, Y y Z, posee cuatro grados de libertad.
Los sistemas antropomorfos poseen el equivalente a un hombro, un brazo, un codo,
un antebrazo y una mueca. El hombro normalmente est montado sobre una base giratoria,
en lugar de un cuerpo mvil.
32

Figura 3.1 Ejemplo de brazo robot con cuatro grados de libertad

Entre los mtodos de programacin de robots se encuentran, la instruccin por


direccin humana, los controles remotos y la programacin fuera de lnea.
Los sistemas de control almacenan la ubicacin del brazo en forma de puntos
discretos, adems proveen la especificacin de cmo se debe mover el brazo.
El trabajo del brazo humano es bsicamente mover la mano de un lugar a otro, de
manera similar el brazo robot tiene el trabajo de mover el mecanismo de punta, llamado
efector, de un lugar a otro.

3.2.1 El brazo robot Stubli RX90


El brazo robot Stubli RX90 L, es un brazo antropomorfo con seis grados de
libertad. Est conformado por siete partes principales, las cuales se encuentran unidas entre
s por medio de articulaciones. Los movimientos del brazo son generados por motores
elctricos. La velocidad de giro de cada motor puede variarse de manera independiente. Los
principales elementos del brazo robot Stubli son: la base (A), el hombro (B), el brazo (C),
el codo (D), el antebrazo (E), la mueca (F) y la mano (G) (ver figura 3.2).
33

Figura 3.2 Partes del brazo robot Stubli RX901

3.2.2 Geometra de brazo robot Stubli RX90


La geometra del objeto es la base de cualquier modelo tridimensional. El brazo
Stubli esta compuesto, desde un punto de vista geomtrico, por diferentes tipos de figuras,
tales como cilindros, cubos, pirmides, entre muchas otras, las cuales se junta para dar
forma al brazo. En la figura 3.3 se observan las principales medidas del brazo, las cuales
estn dadas en milmetros.

1
Figura tomada de las hojas del fabricante, http://www.staubli.com/web/robot/division.nsf
34

Figura 3.3. Medidas geomtricas del brazo robot Stubli RX901

Las articulaciones del brazo robot poseen amplitudes de giro mximas, adems de
valores mximos y nominales para las velocidades angulares, los cuales se muestran en el
cuadro 3.1. La numeracin de las articulaciones en el cuadro 3.1, est basada en la
numeracin que recibieron en la figura 3.2.

1
Figura tomada de las hojas del fabricante, http://www.staubli.com/web/robot/division.nsf
35

Cuadro 3.1 Amplitudes de giro y velocidades nominales y mximas 1

Articulacin 1 2 3 4 5 6

Amplitud () 320 275 285 540 225 540

Distribucin A B C D E F
de la amplitud 160 137.5 142.5 270 +120 270
de giro () -105

Velocidad 236 200 286 401 320 580


Nominal (/s)

Velocidad 356 356 296 409 800 1125


Mxima (/s)

En la figura 3.4 se observa la distribucin de trabajo de las amplitudes de giro, de


las diferentes articulaciones.

Figura 3.4 Distribucin de trabajo de las amplitudes de giro1

1
Datos y figuras tomados de las hojas del fabricante, http://www.staubli.com/web/robot/division.nsf
CAPTULO 4: Desarrollo de la aplicacin de simulacin

La aplicacin de simulacin presenta la siguiente estructura de funcionamiento:


Se crea la ventana donde se desplegarn todos los objetos de la escena y las
ventanas que componen la interfaz grfica de usuario. En este punto tambin
se establece la configuracin inicial de las matrices de proyeccin y del campo
visual del observador.
Se crean todos los objetos geomtricos que se utilizarn en la escena y se
inicializan los valores de posicin de los puntos de control, los objetos
geomtricos y la cmara. Adems se inicializa la velocidad de giro de cada
articulacin del brazo virtual y de la cmara.
Se da comienzo al monitoreo de eventos, el cual est compuesto por un lazo
infinito, del cual no se sale a menos que se de la orden de terminar la
aplicacin. En este lazo se vigila el estado de las ventanas y de los perifricos
como el teclado y el ratn. Si se da una orden por parte del usuario de
modificar el estado de la escena, se llama a las rutinas necesarias para llevar a
cabo el cambio.
Se ejecuta el movimiento de la cmara o del brazo robot solicitado por el
usuario. Si durante la traslacin de los elementos del brazo virtual se da una
colisin de ste consigo mismo o con el piso, se despliega un mensaje de
advertencia y se le da un valor de uno a la variable de choque. Esta variable se
utiliza para comunicarle a otras aplicaciones que se ha dado una colisin.
Se regresa al inicio del lazo de monitoreo y se espera por un nuevo evento.

36
37

Figura 4.1 Diagrama de flujo de la aplicacin de simulacin virtual


38

El desarrollo de la aplicacin de simulacin del brazo robot Stubli se dividi en


cuatro segmentos principales:
La creacin de un motor de ejecucin de un espacio virtual de tres
dimensiones.
El desarrollo de un modelo tridimensional del brazo robot, basado en las
caractersticas geomtricas dadas por el fabricante.
El desarrollo e implementacin de un mtodo de deteccin de colisiones.
El desarrollo de una interfaz grfica de usuario.

Para el desarrollo del motor de ejecucin del modelo virtual, se utilizaron las
bibliotecas OpenGL y GLU, luego se creo una interfaz grfica, dndole la posibilidad al
usuario de interactuar con los objetos y la configuracin del espacio virtual. En un principio
se emple la librera GLUT, para el desarrollo de la interfaz, pero dada la necesidad de una
interfaz ms compleja, GLUT tuvo que ser sustituida por la biblioteca GTK-2.0. En general
el programa final se puede dividir en dos secciones principales: la seccin desarrollada
utilizando OpenGL, la cual se encarga de graficar y manejar el espacio virtual y la seccin
desarrollada con GTK, en la cual se encuentra la interfaz grfica de usuario y se llevan a
cabo los procesos de comunicacin con el sistema de ventanas, que sean necesarios. Para
establecer una unin entre esta dos secciones y que fuera posible la comunicacin entre
ellas, se emple la librera GtkGLext, la cul es una extensin de GTK, que permite
desplegar y manejar aplicaciones grficas desarrolladas con OpenGL, desde interfaces
GTK. El simulador fue desarrollado en el lenguaje de programacin C, esta eleccin se
realiz con base en las caractersticas positivas propias del lenguaje y adems con el fin de
simplificar el acople entre la aplicacin aqu implementada y el programa en [4].

4.1 Simulador del brazo robot Stubli RX90 L


Normalmente, la primera fase en el proceso de creacin de grficos
tridimensionales, es el modelado de los objetos que se desean utilizar en la escena.
Generalmente los desarrolladores de aplicaciones grficas tridimensionales, no crean sus
modelos directamente desde primitivas geomtricas, como las ofrecidas en OpenGL, sino
que utilizan editores grficos tales como Lightwave 3D, 3D Studio Max, Maya, Blender,
entre otros, los cuales facilitan la creacin de las figuras tridimensionales y permiten crear
modelos ms exactos desde el punto de vista esttico. Posteriormente estos modelos son
cargados o traducidos a primitivas geomtricas que la interfaz de programacin grfica, por
ejemplo OpenGL, pueda interpretar. Esta traduccin es llevada a cabo por programas o
partes de cdigo que son capaces de leer e interpretar los formatos de archivo creados por
los programas de edicin grfica. Por ejemplo, existen muchos cdigos que fueron
39

desarrollados para interpretar y traducir a primitivas geomtricas OpenGL, la informacin


de los archivos con formato .3ds , el cual es el formato de archivos que utiliza el editor 3D
Studio Max. El problema es que la mayora de estos cdigos o programas de traduccin de
formatos no son libres. Adems la mayora solo interpretan formatos de archivos de
editores grficos propietarios, los cuales tienden a tener un costo monetario elevado. Una
de las ideas que se mantuvo al desarrollar el simulador del brazo robot, fue la tratar de
mantener el programa y el desarrollo de ste libre de programas propietarios. Por esta razn
el modelado tridimensional del brazo se desarroll utilizando directamente las primitivas
geomtricas que provee el API OpenGL.

4.1.1 El brazo robot Stubli como un modelo jerrquico


El principal aspecto que se debe tomar en cuenta al modelar un brazo robot, es que
ste es un objeto articulado, est compuesto por partes rgidas la cuales se encuentran
conectadas entre s mediante articulaciones. Esta caracterstica conlleva a la existencia de
diferentes niveles de jerarqua para cada componente de la extremidad robtica. Existen dos
diferentes niveles, el de los padres y el de los hijos. A continuacin se explican los
diferentes niveles de jerarqua utilizando el modelo de un brazo robot de tres grados de
libertad.

Figura 4.2 Modelo de brazo robot de tres grados de libertad

En la figura 4.2 se observa un modelo simple de un brazo robot con tres grados de
libertad, el cual est compuesto por tres piezas rgidas llamadas base, brazo1 y antebrazo.
La base puede girar alrededor del eje Y y su ngulo de giro es , brazo1 gira alrededor del
eje Z y su ngulo de giro es y el antebrazo gira alrededor del eje Z con un ngulo de giro
llamado . En la figura 4.2 se puede observar que cada parte del robot posee su propio
sistema de coordenadas en los cuales se encuentran definidos los ngulos de rotacin de
cada una de las partes. Adems es claro que la base est en el nivel de jerarqua ms alto. Si
la base rota, tambin rota el brazo1 y el antebrazo, en otras palabras la base es el padre del
brazo1 y el antebrazo, mientras que brazo1 y el antebrazo por su parte son hijos de la base.
Brazo1 es el padre del antebrazo, ya que si ste rota, el anterazo tambin sufre una rotacin.
40

Todas las transformaciones de traslacin o rotacin que sufren los padres, tambin se dan
en los hijos, pero las transformaciones ocurridas en los hijos no tienen porque ocurrir en los
padres necesariamente. Por ejemplo si brazo1 rota 30 grados, el antebrazo se ve obligado a
rotar 30 grados con respecto al origen de brazo1, pero si el antebrazo por su parte gira 50
grados, brazo1 no se ve obligado a sufrir ninguna rotacin. A esto se le conoce como un
modelo jerrquico. Una de las ventajas de definir un sistema de coordenadas para cada una
de las partes del robot es la siguiente, por ejemplo, si brazo1 de la figura 4.2 es rotado 20,
la posicin de antebrazo debe ser transformada para mantener la jerarqua del brazo robot,
de manera que las partes se encuentren unidas correctamente a la hora de desplegar el
modelo. Ahora bien, sera complicado tener que calcular las nuevas coordenadas que debe
tener el antebrazo en su propio sistema de coordenadas debido a la rotacin de brazo1. En
lugar lo que se hace es que se mantienen las mismas coordenadas que el antebrazo posee
con respecto a su propio sistema de coordenadas y se gira el sistema de coordenadas del
antebrazo 20 con respecto al origen del sistema de brazo1. Teniendo lo anterior en cuenta
y sabiendo que las transformaciones de rotacin y traslacin se llevan a cabo mediante la
multiplicacin de matrices, para graficar el modelo del robot de la figura 4.2 en donde la
base tiene una altura h1 y una rotacin de , brazo1 tiene una altura h2 y una rotacin de
y el antebrazo tiene una altura de h3 y una rotacin de , se llevara acabo el siguiente
proceso:

Matriz M_model = matriz_Identidad; //Se inicia la Matriz de transformacin actual


...
dibujar_robot()
{
M_model = RotarY(); /*Se multiplica a la matriz de Transf.. actual la rotacin de la base*/
base(); /*Se dibuja la base*/

/*Se multiplica a la matriz de transformacin actual la rotacin de la base, la traslacin de la altura


h1 y la rotacin del brazo1*/

M_model = RotarY()*Trasladar(0,h1,0)*RotarZ();

brazo1(); /*Se dibuja brazo1*/

/* Se multiplica a la matriz de transformacin actual la rotacin de la base, la traslacin de la altura


h1, la rotacin del brazo1, la traslacin de h2 y la rotacin del antebrazo*/

M_model = RotarY()*Trasladar(0,h1,0)*RotarZ()*Trasladar(0,h2,0)*RotarZ();

antebrazo1(); /*Se dibujar el antebrazo/


}
.
41

En el proceso anterior se nota que es poco prctico tener que estar calculando la
matriz de transformacin actual cada vez que se produce una transformacin. En lugar de
recalcular la matriz global, sta se puede actualizar concatenando matrices a su derecha de
la siguiente manera:

Matriz M_model = matriz_Identidad; /*Se inicializa la Matriz de transformacin actual*/


...
dibujar_robot()
{
M_model = RotarY(); /*Se multiplica a la matriz de transf. actual la rotacin de la base*/
base(); /*Se dibuja la base*/

/*Se concatena la traslacin de la altura h1 y la rotacin del brazo1*/


M_model *= Trasladar(0,h1,0)*RotarZ();
brazo1(); /*Se dibuja brazo1*/

/* Se concatenan la traslacin de h2 y la rotacin del antebrazo*/


M_model *= Trasladar(0,h2,0)*RotarZ();
antebrazo1(); /*Se dibujar el antebrazo/
}

Como se explico en el captulo dos, OpenGL mantiene una matriz global de estado
llamada matriz Model-View, la cual es actualizada concatenando matrices a su derecha cada
vez que se da una transformacin en el modelo. Utilizando funciones OpenGL el proceso
anterior se puede presentar de la siguiente manera:

glMatrixMode(GL_MODELVIEW) /*Se carga la Matriz de transformacin actual*/


glLoadIdentity(); /*Se inicializa la matriz de transf. actual*/
...
dibujar_robot()
{
glRotatef( theta, 0.0, 1.0, 0.0 );
base();
glTranslatef( 0.0, h1, 0.0 );
glRotatef( phi, 0.0, 0.0, 1.0 );
brazo1();
glTranslatef( 0.0, h2, 0.0 );
glRotatef( psi, 0.0, 0.0, 1.0 );
antebrazo();
}

42

4.1.2 El modelado del brazo robot Stubli RX90 L


Para el desarrollo del modelo del brazo robot se utiliz la tcnica de modelado de
geometra slida, en la cual se emplean primitivas geomtricas bsicas, tales como vrtices
y lneas para crear la figura tridimensional. La primera fase en el proceso de modelado del
brazo robot Stubli, la comprendi el estudio del nivel de jerarqua de cada uno de los
componentes del brazo. Una vez que se establecieron los diferentes niveles de cada parte,
se experiment creando modelos de brazo ms simples, con el fin de entender
adecuadamente las caractersticas de las diferentes funciones de transformacin que brinda
OpenGL.

Figura 4.3 Primer modelo creado del brazo robot.

En la figura 4.3 se muestra el primer modelo de un brazo robot, que se cre en este
proyecto. Con este modelo se lleg a comprender el funcionamiento de las figuras
tridimensionales con diferentes niveles de jerarqua y como desplegaralas y controlarlas
utilizando las funciones del API OpenGL. Este primer modelo de un brazo con tres grados
de libertad, fue la base y punto de partida para el proceso de creacin del modelo final del
brazo Stubli RX90 L.
El brazo robot Stubli RX90 L, posee seis grados de libertad y esta compuesto por
siete partes principales: la base, el hombro, el brazo (o brazo1), el codo, el antebrazo (o
brazo2), la mueca y la mano (ver captulo tres).
43

Figura 4.4 Principales componentes del brazo Stubli RX901.

Para cada uno de los componentes del brazo se estudi y determin cuales de sus
propiedades geomtricas son las ms influyentes durante los procesos de colisin del robot,
ya sea con el piso o consigo mismo. Luego se modelaron los componentes utilizando
primitivas geomtricas, tomando como gua las medidas dadas por el fabricante del brazo
robot. Se utilizaron listas de despliegue, las cuales almacenan la informacin grfica de las
diferentes partes del robot. En total se crearon siete listas de despliegue, una por cada
componente principal del brazo robot.

/* Ejemplo: creacin de la mueca del brazo robot*/


...
void crear_munieca(int slices, int stacks){

/* Se define la variables quadObj1, la cual es un puntero a un objeto cuadrtico (lib. GLU) */


GLUquadricObj *quadObj1;
quadObj1 = gluNewQuadric();

/* Se seala el inicio de la lista de despliegue MUNIECA*/


glNewList(MUNIECA, GL_COMPILE);

1
Figura (modificada) tomada de las hojas del fabricante, http://www.staubli.com/web/robot/division.nsf
44

/*Se apla el estado de la matriz actual transformacin, de manera que las


transformaciones que se den a partir de este punto, no afecten ningn objeto que haya sido
llamado(dibujado) antes de este punto*/
glPushMatrix();
glRotatef(-90, 0.0, 1.0, 0.0);
/*Se crea un cilindro con un radio de 5 unidades en ambos extremos y un largos
de 11 unidades, slices y stacks define el numero de cortes horizontales y
verticales que forman el cilindr */
gluCylinder(quadObj1, 5, 5, 11, slices, stacks);
glPushMatrix();
glRotatef(180, 1.0, 0.0, 0.0);
/*Se crea un disco con un radio de 5 unidades*/
gluDisk(quadObj1, 0, 5, slices, stacks);
glPopMatrix();
glTranslatef(0, 0, 11);
/*Se crea un disco con un radio de 5 unidades*/
gluDisk(quadObj1, 0, 5, slices, stacks);
/*Se desapila el estado anterior de la matriz de transformacin*/
glPopMatrix();
/*Se indica el fin de la lista de despliegue*/
glEndList();
}
...

En el ejemplo anterior se muestra el cdigo de la funcin que crea y define la lista


de despliegue encargada de guardar la informacin grfica referente a la mueca del brazo
robot. Se observa que los objetos que describen la forma geomtrica de la mueca se
encuentran definidos entre dos funciones, glPushMatrix() y glPopMatrix(), estas funciones
apilan (salvan) y desapilan (cargan) el estado de la matriz de transformacin actual (matriz
Model-View) respectivamente. Esto impide que las transformaciones necesarias para crear
la mueca, surtan efecto en el resto de los componentes del brazo y de la escena virtual en
general. En el cdigo tambin es posible observar, que el sistema de coordenadas es rotado
90 con respecto al eje Y antes de crear el cilindro que conforma la mueca, mediante la
funcin glRotatef(90,0.0,1.0,0.0). Esto se debe llevar a cabo, debido a que la funcin
gluCylinder() posiciona los cilindros que crea a lo largo del eje Z del sistema de
coordenadas propio del objeto y se desea que el cilindro de la mueca se encuentre
posicionado a lo largo del eje X de su sistema de coordenadas propio. El sistema de
coordenadas propio de cada disco tambin se rot por la misma razn, adems fueron
trasladados, ya que se espera que los discos se encuentren en los extremos del cilindro. Se
puede observar que con el uso correcto de las funciones glPushMatrix() y glPopMatrix() es
posible llevar a cabo transformaciones sobre una parte especifica del modelo, sin afectar al
resto de este.
Como se seal anteriormente, se crearon siete funciones encargadas de definir
siete diferentes listas de despliegue, una para cada parte principal del robot. Se estableci
un sistema de coordenadas propio para cada componente principal del brazo robot. Cada
45

sistema de coordenadas es hijo del sistema que le precede. El orden de jerarqua de los
sistemas de coordenadas propios de los objetos es el siguiente: sistema Base, sistema
Hombro, sistema Brazo1, sistema Codo, sistema Brazo2, sistema Mueca, sistema Mano,
en donde el sistema Base es quien posee el mayor nivel de jerarqua entre todos ellos, en
otras palabras, el sistema Base es padre del resto de los sistemas de coordenadas propios de
los componentes del robot. El punto de origen del sistema Base coincide con el punto de
origen del sistema de coordenadas global de la escena o espacio virtual, de hecho como la
base del brazo no sufre ninguna transformacin, es decir no gira ni se traslada, entonces
ambos sistemas sern realmente el mismo sistema de coordenadas en todo momento.
A continuacin se presenta el cdigo de la funcin dibujar(), en la cul se da el
proceso de posicionamiento y despliegue de los diferentes objetos que componen la escena
virtual. En otras palabras, aqu es donde se giran y trasladan los sistemas de coordenadas
propios de cada componente y donde son llamadas las listas de despliegue, cada vez que
alguna de las partes principales del brazo robot recibe una orden de movimiento por parte
del usuario.

/*Funcin: dibujar().Se encarga de dibujar todo lo que desea desplegar en la escena. Archivo: dibujo.c. */

gboolean dibujar(void){
GdkGLContext *glcontext = gtk_widget_get_gl_context (glarea1);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (glarea1);

/*** OpenGL INICIO ***/


if (!gdk_gl_drawable_make_current(gldrawable, glcontext)){
printf("Error al buscar area OpenGL");
return FALSE;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

if(checkmax==1){ /*limita los angulos de giro a sus amplitudes mximas*/


check_maximo();
}
if(grid==1){
/* GRID. Dibujar el piso en configuracin de rejilla */
glBegin(GL_LINES);
glColor3f(0.0, 0.1, 1.0);
int i;
for(i=-300;i<=300;i+=30) {
glVertex3f(i,altpiso,-300);
glVertex3f(i,altpiso,300);
glVertex3f(300,altpiso,i);
glVertex3f(-300,altpiso,i);
}
glEnd();
}else {
46

/*PISO. Dibujar el piso en configuracin de polgono slido */


glBegin(GL_QUADS);
glColor3f(0.9, 0.9, 0.9);
glVertex3f(-500.0f, altpiso, -500.0f);
glVertex3f(-500.0f, altpiso, 500.0f);
glVertex3f(500.0f, altpiso, 500.0f);
glVertex3f(500.0f, altpiso, -500.0f);
glEnd();
}
...

La primera etapa de la funcin dibujar(), consiste en buscar la ventana y el area de


la ventana, destinada a desplegar los grficos OpenGL, es decir el rea en donde se debe
llevar a cabo la graficacin. En la lnea que contiene la declaracin
if(!gdk_gl_drawable_make_current(gldrawable, glcontext)) es en donde se realiza esta
bsqueda. Si el rea no se encuentra, la funcin dibujar() termina, retornando el argumento
FALSE. Si el rea, por otro lado, es encontrada, se continua, primero reiniciando o
limpiando el contenido de los almacenadores intermediarios (<<buffers>>) de color y
profundidad mediante la funcin glClear(). Luego se inicializa la matriz actual de
transformacin utilizando la funcin glLoadIdentity() y se determina si se desea limitar los
angulos de giro de las articulaciones del brazo robot a sus amplitudes mximas (ver cuadro
3.1), posteriormente se dibuja el piso de la escena, ya sea en forma de rejilla o de polgono
slido.

/* Continuacin de la funcin dibujar()*/


...
/*Base externa sobre la cual se monta el brazo (opcional)*/
GLUquadricObj *quadObj1;
quadObj1 = gluNewQuadric();
glPushMatrix();
glColor3f(0.1, 0.1, 1.0);
glRotatef(90, 1.0, 0.0, 0.0);
gluCylinder(quadObj1, 12, 12, -1*altpiso, 30, 30);
glPopMatrix();

glColor3f(0.7, 0.8, 0.7);


//BASE (propia del brazo)
glPushMatrix();
glTranslatef(0.0, 0.0, 0.0);
glCallList(BASE);
glPopMatrix();

//HOMBRO
glPushMatrix();
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
47

glCallList(HOMBRO);
glTranslatef(-13.0, 0.0, 0.0);

//BRAZO1
glPushMatrix();
glRotatef(angulo2, 1.0, 0.0, 0.0);
glCallList(BRAZO1);
glTranslatef(13.0, 45.0, 0.0);

//CODO
glPushMatrix();
glRotatef(angulo3, 1.0, 0.0, 0.0);
glCallList(CODO);
glTranslatef(0.0, 10.0, 0.0);

//BRAZO2
glPushMatrix();
glRotatef(angulo4, 0.0, 1.0, 0.0);
glCallList(BRAZO2);
glTranslatef(0.0, 55.0, 0.0);

//MUNIECA
glPushMatrix();
glRotatef(angulo5, 1.0, 0.0, 0.0);
glTranslatef(5.5, 0.0, 0.0);
glCallList(MUNIECA);
glTranslatef(-5.5, 0.0, 0.0);

//MANO
glPushMatrix();
glRotatef(angulo6, 0.0, 1.0, 0.0);
glCallList(MANO);
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
...

Como se observa en el extracto de cdigo anterior, posterior a la creacin del piso


de la escena, se comienza con el posicionamiento de los sistemas de coordenadas propios
de cada componente principal del robot y se grafican los diferentes componentes. El primer
componente que se dibuja es la base externa sobre la cul va montado el brazo robot. Esta
base es opcional y su tamao puede ser variado por el usuario tal y como se explica ms
adelante. La siguiente parte del robot que se dibuja es la base propia del brazo, cuyo
48

sistema de coordenadas se encuentra en el punto de origen de la escena. En la lnea


glCallList(BASE) se llama a la lista de despliegue que contiene la informacin grfica de la
base. Se puede observar en el cdigo que para cada componente del brazo robot, primero se
llama la funcin glPushMatrix() y luego se llevan a cabo las transformaciones necesarias y
se llama la lista de despliegue propia del componente. Tal y como se explic anteriormente,
la funcin glPushMatrix() salva en una pila el estado actual de la matriz de transformacin
global, de manera que cada componente principal posee un sistema de coordenadas propio,
hijo del sistema de coordenadas del componente que le antecede. Por ejemplo, en la lnea
glRotatef(angulo1,0.0,1.0 0.0), la cual se encuentra anterior al llamado de la lista de
despliegue del hombro (glCallList(HOMBRO)), se establece una rotacin con respecto al
eje Y de magnitud igual al valor de la variable angulo1. Esta rotacin afecta a todos los
componentes que sean dibujados despus de la funcin glPushMatrix() precedente ms
cercana, es decir que afecta al hombro, brazo1, codo, brazo2, mueca y mano, pero a la
base no. Esta es la idea principal que se sigue para posicionar y dibujar los componentes
del brazo en la escena, de manera que se respete la jerarqua de cada uno de ellos. Se
observa que cada una de las partes principales del robot est ligada a una variable de giro,
excepto la base, ya que sta no rota. Estas variables definen el giro de cada uno de los
componentes, respecto a un eje determinado del sistema de coordenadas propio a cada
componente y por lo tanto ests variables son quienes, en conjunto, determinan la posicin
o configuracin final del brazo. La variable angulo1 especifica el giro del hombro, angulo2
el giro de brazo1, angulo3 el giro del codo, angulo4 el giro de brazo2, angulo5 el giro de la
mueca y angulo6 el giro de la mano.

/* Continuacin de la funcin dibujar()*/


...
if(lim==1){
dibujar_limites();
}
probar_colision(marg);
semaforo();
glFlush ();
gdk_gl_drawable_swap_buffers (gldrawable);
return TRUE;
}
...

En ultimo fragmento del cdigo de la funcin dibujar() se llevan a cabo los ltimos
pasos necesarios para desplegar la escena en la ventana. Primero se determina si se desea
dibujar los lmites geomtricos del brazo. Estos lmites fueron creados durante el modelado
del brazo para llevar a cabo pruebas sobre la geometra del modelo con respecto a la del
brazo real, son una herramienta para el programador o modelador ms que para el usuario.
En la siguiente lnea de cdigo se llama a la funcin probar_colisin(), a la cual se le pasa
el argumento marg. Esta funcin es la encargada de realizar las diferentes pruebas de
49

colisin que posee el simulador. El argumento marg determina la magnitud del margen de
precaucin con el cual se llevan a cabo las pruebas. Una vez terminadas las pruebas de
colisin se llama a la funcin glFlush (), la cul exige la ejecucin de todos los comandos
OpenGL que han sido llamados hasta este punto. La funcin
gdk_gl_drawable_swap_buffers (gldrawable) es quien se encarga de intercambiar los
almacenadores intermedios de cuadro o <<frame buffers>>, en los cuales se recolecta todo
lo que se desea dibujar en la pantalla. Esto se debe llevar a cabo en los casos que se utiliza
el mtodo de doble <<buffer>>, el cul consiste en guardar toda la informacin grfica que
se desea desplegar en la pantalla en un <<buffer>> de despliegue secundario, el cal se
intercambia con el <<buffer>> de despliegue primario, es decir se convierte en el primario,
una vez que toda la informacin necesaria haya sido recopilada, de tal manera que nunca se
manipula la informacin del <<buffer>> primario durante el despliegue, ya que esto podra
causar que la animacin se parezca cortada y poco fluida.
La iluminacin es un aspecto sumamente importante en una escena y puede llegar a
ser difcil de dominar. Sin iluminacin, no se podra distinguir entre un objeto
bidimensional y uno tridimensional. Por ejemplo en la figura 4.5 se observa la misma
esfera en dos cuadros diferentes. En el primero hay iluminacin en la escena y en el
segundo no.

Figura 4.5 Esfera con iluminacin y sin iluminacin.

A continuacin se muestra parte del cdigo de la funcin inicio() la cul se


encuentra implementada en el archivo fuente ventanagl.c. Esta funcin es la que se encarga
de crear las luces y establecer las propiedades de stas, as como las propiedades de los
materiales de los objetos en la escena.

/* Fragmentos del cdigo de la funcin inicio(). Archivo fuente: ventanagl.c */


50

gboolean inicio(void){
GLfloat ambient [] = { 0.1, 0.1, 0.1, 0.0 };
GLfloat specular []= { 1.0, 1.0, 1.0, 1.0 };
GLfloat shininess [] = { 100.0 };
GLfloat position0 [] = { 400.0, 400.0, 400.0, 1.0 };

/* Determina la propiedad de reflejo del material*/
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

/* Determina la posicin de las luces y el tipo de luz*/


glLightfv(GL_LIGHT0, GL_POSITION, position0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

En la figura 4.6 se observa el modelo final del brazo robot Stubli RX90 L, que se
desarroll en el proyecto.

Figura 4.6 Modelo del brazo robot Stubli RX90 L.

Algunas caractersticas geomtricas del brazo real, que no presentaban relevancia


para la deteccin precisa de colisiones, no fueron implementadas en el modelo.
51

4.1.3 El mtodo de deteccin de colisiones


Para la implementacin de pruebas de deteccin de colisiones en el simulador, se
establecieron nueve puntos de control sobre el brazo virtual, cada punto se encuentra ligado
a una figura de control y se localiza en el centro de sta en todo momento. Se utilizaron dos
tipos de figuras para llevar a cabo el control de colisiones, crculos y cuadros. Las figuras
estn compuestas por un nmero determinado de vrtices los cuales se encuentran unidos
entre si mediante una lnea continua. Los cuadros constan de cuatro vrtices, mientras que
los crculos estn compuestos por treinta vrtices cada uno. Las figuras de control poseen
un radio caracterstico a cada una, en el caso de los crculos el radio de control es el valor
del radio del crculo propio, mientras que en el caso de los cuadros de control, el radio es la
distancia desde el punto medio hasta el primer vrtice del cuadro (ver figura 4.7).
La figura 4.7 es una representacin esquemtica de la composicin de las figuras de
control a partir de vrtices. En la grfica tambin se observa la ubicacin del punto de
control central, as como el radio de cada figura.

Figura 4.7 Tipos de figuras de control

La figura 4.8 muestra la posicin de las diferentes figuras de control en el modelo


tridimensional del brazo robot.
52

Figura 4.8 Figuras de control en el modelo del brazo robot

La figura 4.9 es un esquema que seala la posicin de las diferentes figuras de


control en el modelo del brazo robot. Los cuatro componentes principales del brazo, mano,
mueca, brazo2 y codo, fueron graficados separados uno del otro, con el fin de comprender
mejor la ubicacin de las figuras de control. En el esquema de la figura 4.9 se tienen dos
perspectivas de visin, una frontal al brazo y una lateral.

Figura 4.9 Figuras de control (esquemtico)


53

El cuadro 4.1 enumera los diferentes puntos de control existentes y las figuras de
control que se encuentran ligadas a cada punto.

Cuadro 4.1 Puntos y figuras de control

Figura(s) de control
Punto de control ligada(s) al punto de
control
CBA (Control Brazo A) cuadBA
CBB cuadBB
CBC cuadBC, circBC
CBD circBD
CWA (Control Wrist A) circWA
CWB circWB
CWC circWC
CHA (Control Hand A) circHA
CHB circHA

En los grficos anteriores se observa que los puntos y figuras de control se


encuentran ubicados en diferentes componentes del brazo robot. Es decir que no todas las
figuras y puntos de control se ven afectados por el mismo nivel de jerarqua, en otras
palabras, no todos se encuentran dentro del mismo sistema local de coordenadas. Ntese
que por ejemplo, un movimiento de rotacin en la articulacin cuatro, es decir un cambio
en valor del ngulo angulo4, no afectara la posicin de las figuras cuadBA, cuaBB,
cuadBC, pero si afectara la posicin del resto de las figuras de control, mientras que un
cambio en el ngulo angulo3 afectara la posicin de todas las figuras de control. El nivel
de jerarqua que afecta las figuras y puntos de control es un factor sumamente importante a
la hora de trasladar los puntos de cada figura de control de sus coordenadas locales a
coordenadas globales, ya que es el nivel de jerarqua, quien determina cuales matrices de
traslacin y rotacin deben ser utilizadas para llevar a cabo el cambio de coordenadas. El
cuadro 4.2 indica el nivel de jerarqua que afecta a cada punto y figura de control.
54

Cuadro 4.2 Niveles de jerarqua de las figuras de control

Nivel de ngulos Puntos de Figuras de


jerarqua influyentes control control
3 angulo1, angulo2, CBA, CBB, cuadBA, cuadBB,
angulo3 CBC, CBD cuadBC
angulo1, angulo2, circBC, circBD,
angulo3, angulo4 circWA, circWB,
4 CWA, CWB,
circWC
CWC
angulo1, angulo2,
angulo3, angulo4,
5 CHA, CHB circHA, cirHB
angulo5

El traslado de las coordenadas de un punto de su sistema local o propio al sistema


de coordenadas Global o Worldspace, se hace mediante la multiplicacin de matrices
homogneas de traslacin y rotacin (ver captulo 2). Si rotZ(ang) representa la matriz de
rotacin homognea en el eje Z, rotY(ang) la matriz de rotacin respecto al eje Y,
rotX(ang) la matriz de rotacin respecto al eje X, ang el ngulo de rotacin especfico a
cada matriz y tras(vect) la matriz de traslacin con un vector de traslacin vect, entonces el
proceso de traslacin de las coordenadas de un punto, perteneciente al modelo del brazo
robot, desde su sistema local hasta el sistema Global estara dado por las siguientes
ecuaciones:

Nivel de jerarqua: 3
Pcoord. Global = tras(br1)*rotX(angulo2)*tras(cod)*rotX(angulo3)*Pcoord. Local

Nivel de jerarqua: 4
Pcoord. Global = tras(br1)*rotX(angulo2)*tras(cod)*rotX(angulo3)*tras(br2)
*rotY(angulo4)*Pcoord. Local

Nivel de jerarqua: 5
Pcoord. Global = tras(br1)*rotX(angulo2)*tras(cod)*rotX(angulo3)*tras(br2)
*rotY(angulo4)*tras(man)*Pcoord. Local
55

en donde br1 es un vector que representa la posicin en la que se encuentra el sistema de


coodernadas propio de brazo1 (sistema Brazo1) en el sistema Global, cod representa la
posicin del sistema de coodernadas propio del codo (sistema Codo) en el sistema Brazo1,
br2 representa la posicin del sistema de coodernadas propio de brazo2 (sistema Brazo2)
en el sistema Codo y man representa la posicin del sistema de coodernadas propio de la
mano (sistema Mano) en el sistema Brazo2. Pcoord Global es el vector de coordenadas del
punto en el sistema Global, mientras que Pcoord Local es el vector de coordenadas del punto en
el sistema Local.
El procedimiento general de las pruebas de control de colisiones es el siguiente:
Se pasan las coordenadas locales de los puntos de control a coordenadas
globales.
Si alguno de los puntos de control se encuentra dentro de alguna de las
llamadas zonas de precaucin, entonces se realiza la prueba de colisin
necesaria.
Este proceso se lleva acabo cada vez que el programa llama a la funcin dibujar().
En la aplicacin se definieron dos zonas de precaucin, una sobre el piso de la
escena virtual y otra que encierra la base del brazo robot. El volumen de ests zonas de
precaucin es variable y su valor depende del radio de la figura de control ligada al punto
de control que se encuentra en condicin de prueba.
Un punto de control se encuentra dentro de la zona de precaucin del piso cuando el
valor de su coordenada Y en el sistema Global es menor que la suma del radio de la figura
de control ligada a l y el margen de precaucin definido por el usuario, cuyo valor
predeterminado es cero.
Por otro lado, un punto de control se encuentra dentro de la zona de precaucin de
la base cuando su distancia ortogonal al eje Y es menor que la suma del radio de la base del
brazo, ms el radio de la figura de control ligada al punto y el margen de precaucin
determinado por el usuario.
La siguiente figura permite un mejor entendimiento de las zonas de precaucin y la
variacin de sus tamaos.
56

Figura 4.10 Zonas de precaucin

Por ejemplo, si se deseara saber si el punto de control CBB se encuentra dentro de


alguna de las zonas de precaucin, el procedimiento sera el siguiente:
Se pasan las coordenadas del punto de control CBB al sistema de coordenadas
Global, mediante la multiplicacin apropiada de matrices.
Se determina la altura de la zona de precaucin del piso. Como el punto de
control CBB se encuentra ligado a la figura de control cuadBB, entonces la
altura de la zona de precaucin sera la suma del radio de la figura cuadBB
(ver figura 4.7) ms el valor del margen de precaucin, cuyo valor
predeterminado es cero.
Si el valor de la coordenada Y del punto de control CBB en el sistema de
coordenadas globales es menor que la altura de la zona de precaucin del piso,
calculada anteriormente, entonces el punto se encuentra dentro de la zona de
precaucin, por lo tanto se debe llevar a cabo la prueba de colisin de la figura
cuadBB contra el piso.
Si el valor de la coordenada Y del punto de control CBB en el sistema de
coordenadas globales es menor que la altura de la base del brazo robot virtual,
entonces existe la posibilidad de que el punto de control se encuentre dentro
de la zona de precaucin de la base, por lo que se debe calcular el radio de tal
zona de precaucin para poder determinar de manera segura, si el punto se
encuentra dentro de la zona o no.
57

Como el punto de control CBB se encuentra ligado a la figura de control


cuadBB, entonces el radio de la zona de precaucin para este caso sera la
suma del radio de la base del modelo del brazo, ms el radio de la figura
cuadBB, ms el margen de precaucin.
Si la raz cuadrada de la suma de las coordenadas globales X y Z al cuadrado
del punto de control, es decir X 2 + Y 2 , es menor que el radio de la zona de
precaucin de la base, entonces el punto de control CBB se encuentra dentro
de la zona de precaucin de la base, por lo tanto existe peligro de colisin y se
debe realizar una prueba de colisin de la figura cuadBB contra la base.

Para el punto de control CBC el cual se encuentra ligado a dos figuras de control, se
utiliza la figura cuadBC para llevar a cabo estas pruebas de invasin de zona de precaucin,
ya que cuadBC posee un radio mayor que circBC, la cual es la otra figura ligada al punto.
En el simulador se implementaron tres tipos de pruebas de deteccin de colisin: la
prueba de deteccin de colisin contra el piso, la prueba de deteccin de colisin contra la
base, las cuales ya fueron mencionadas anteriormente y la prueba de deteccin de colisin
contra las orillas del hombro.
Anterior a la realizacin de cada prueba se lleva a cabo una inicializacin de sta,
fase en la que se trasladan las coordenadas de cada uno de los puntos que componen la
figura de control que va a ser examinada, de su sistema de coordenadas propio o local al
sistema de coordenadas Global.
La prueba de deteccin de colisin contra el piso consiste en comparar el valor de la
coordenada global Y de cada uno de los vrtices que componen la figura de control en
evaluacin. Si alguno de estos puntos posee un valor de Y menor o igual a la suma de la
altura del piso ms el margen de precaucin, entonces se declara que hubo un choque del
brazo robot contra el suelo.
En la prueba de deteccin de colisin contra la base se monitorea la distancia
ortogonal de cada uno de los puntos de la figura de control examinada hasta el eje Y del
sistema de coordenadas Global, es decir el valor resultante de la ecuacin X 2 + Y 2 para
cada uno de los puntos. Si las coordenadas X y Y de alguno de los puntos conlleva a un
resultado menor o igual al radio de la base del brazo virtual ms el margen de precaucin
dado por el usuario, entonces se determina que hubo un choque del brazo contra la base.
Ntese que las dos pruebas explicadas anteriormente son una derivacin de la
popular prueba de colisin de la caja limtrofe (por su nombre en ingls: <<Bounding-Box
Collision Test>>), la cual es prueba de deteccin de colisin ms utilizada en el desarrollo
de juegos de videos y simuladores virtuales. Esta consiste en encerrar un objeto en una caja
no visible y determinar si algn otro objeto a invadido la caja.
58

Para el proyecto se tuvo que desarrollar un tercer tipo de prueba de deteccin de


colisiones, de manera que se pudieran detectar todos los choque posibles. Debido a las
caractersticas geomtricas del robot Stubli RX90 L, el nico componente propio del brazo
capaz de chocar contra el hombro es el antebrazo, tambin llamado brazo2. La colisiones
del antebrazo contra el hombro suceden en las orillas del hombro, por lo que la prueba
desarrollada para detectar estos choques fue denominada como la prueba de colisin de
orillas o tambin prueba de colisin de pendientes como se explica ms adelante.

Figura 4.11 Orillas del hombro del brazo robot

Ninguna de las figuras de control especificadas en el simulador es capaz de ingresar


en el volumen definido por el componente Hombro, sin que antes ocurra una colisin entre
una de las orillas del hombro y el antebrazo, por esta razn las pruebas de deteccin de
colisiones basadas en reas limtrofes son inservibles a la hora de detectar un choque en el
hombro. Se observa en la figura 4.11 que el hombro posee cuatro orillas en las cuales se
pueden dar colisiones del brazo consigo mismo.
La prueba de colisin de orillas consiste en crear una lnea recta, llamada lnea de
control, entre el punto de la figura de control circBC ms cercano a la orilla del hombro y el
punto de la figura de control circBD anlogo, tal y como se observa en la figura 4.12.
Posteriormente se lleva a cabo una comparacin de pendientes para determinar si se ha
dado una colisin del brazo robot contra su propio hombro.
59

Figura 4.12 Prueba de colisin de orillas (1)

Ntese que si se observa el modelo del brazo robot desde una perspectiva lateral, las
cuatro orillas de colisin del hombro, definidas anteriormente, aparecen como puntos en un
plano bidimensional de coordenadas Z, Y, tal y como se observa en la figura 4.13. Esta es
la idea principal detrs de la prueba de colisin de orillas. Las cuatro orillas del hombro se
convierten en puntos de dos dimensiones y la lnea de control entre las figuras de control
circBC y circBD se transforma en una lnea recta en el plano ZY, que puede ser descrita
por la ecuacin y = m z + b , en donde m es la pendiente de la lnea y b el valor de y
cuando la lnea interseca el eje Z.

Figura 4.13 Prueba de colisin de orillas (2)


60

En la figura 4.13 es posible percibir una segunda lnea recta, entre el punto de
origen inferior de la lnea de control y la orilla superior izquierda del hombro, esta lnea se
denomina lnea al hombro. El nivel Y1 indica la altura a la cual se encuentran las orillas
inferiores del hombro, mientras que el nivel Y2 es la altura de las orillas superiores. Si se
calculan las pendientes de ambas lneas y se comparan entre s es posible determinar si se
dio una colisin entre el antebrazo y la orilla del hombro.
Ntese en la figura 4.14 que si el origen de la lnea de control y de la lnea al
hombro posee un valor de Z negativo y un valor Y menor o igual al valor Y de las orillas
superiores del hombro, entonces se puede afirmar que se da una colisin en la esquina
superior izquierda si y solo si la pendiente de la lnea de control es menor o igual que la
pendiente de la lnea al hombro. Mientras que si el origen de las lnea de control y la lnea
al hombro tiene un valor de Z positivo y un valor de Y menor o igual al valor Y de las
orillas superiores del hombro, entonces se da una colisin en la esquina superior derecha si
y solo si la pendiente de la lnea de control es mayor que la pendiente de la lnea al hombro.

Figura 4.14 Prueba de colisin de orillas (3)

Las caractersticas anteriores de la prueba de colisin de orillas son la razn por la


que tambin fue nombrada como la prueba de colisin de pendientes.
En el cuadro 4.3 se muestran las condiciones que se deben cumplir para que se lleve
a cabo una prueba de colisin de pendientes y como determinar si hubo colisin segn las
condiciones de cada prueba. En el cuadro las coordenadas que se indican se encuentra en
referencia al sistema Global (WorldSpace) y nivel Y1 y nivel Y2, son los valores de altura
de las orillas inferiores y las orillas superiores del hombro, respectivamente (ver figura
4.13). MControl es la pendiente de la lnea de control mientras que MHombro la pendiente de la
lnea al hombro.
61

Cuadro 4.3 Condiciones y resultados de la prueba de colisin de orillas

Orilla del hombro con la


cual se lleva a cabo la
Condiciones para que se lleva a cabo
prueba
la prueba de colisin de orillas
Se da un choque si :
(ver figura 4.13)

coord. Y de CBD < nivel Y1 Si coord. Z de CBD 0


&& orilla inferior izquierda
MControl MHombro
coord. Y de CBC >nivel Y1-radio circBC
&& Si coord. Z de CBD > 0
-40-margen coord. Z de CBD 40+margen orilla inferior derecha

coord. Y de CBD < nivel Y2+radio cuadBD Si coord. Z de CBC 0


&& orilla superior izquierda
coord. Y de CBC >nivel Y2
MControl MHombro
&& Si coord. Z de CBD > 0
-40-margen coord. Z de CBC 40+margen orilla superior derecha

coord. Y de CBC < nivel Y2+radio cuadBC Si coord. Z de CBD 0


&& orilla superior izquierda
coord. Y de CBD >nivel Y2
MControl MHombro
&& Si coord. Z de CBD > 0
-40-margen coord. Z de CBD 40+margen orilla superior derecha
62

A continuacin se muestra el fragmento de cdigo perteneciente a la funcin


probar_colision(), que se encarga de chequear si se estn dando las condiciones necesarias
para llevar a cabo una prueba de colisin de orillas.

/* Fragmento de cdigo. Funcin: probar_colision(flota margen). Archivo Fuente: dibujo.c.


* Este fragmento de la funcin es el encargado de verificar si se cumplen las condiciones
* para llevar a cabo las pruebas de colision de orillas. Si se cumplen las condiciones, llama la prueba .
* Nivel Y1 = 28.5 cm , y Nivel Y2 =54.5 cm. */
...
//VORTEX nivel 1 (hombro)
if((CBDreal[1]<28.5) && (CBCreal[1]>18.0) && (acbdz<=40+margen)){
dibujar_circBD();
check_vortex(circBD, circBC, circBDreal, 1);
cuidado=1;
}
//VORTEX nivel 2
if((CBDreal[1]<=65) && (CBCreal[1]>54.5) && (acbcz<=40.0+margen)){
dibujar_circBD();
check_vortex(circBD, circBC, circBDreal, 2);
cuidado=1;
}
if((CBCreal[1]<=65) && (CBDreal[1]>54.5) && (acbdz<=40+margen)){
dibujar_circBC();
check_vortex(circBC, circBD, circBCreal, 2);
cuidado=1;
}
...

Ntese que la funcin chech_vortex(arg1, arg2, arg3, 2) es la encargada de llevar a


cabo la prueba de colisin de pendientes. El argumento arg1 es la matriz de puntos con
coordenadas locales de la figura de control que se encuentra por debajo de la altura de la
orilla en prueba, arg2 es la matriz de puntos con coordenadas locales de la figura de
control que se encuentra por encima de la altura de la orilla en prueba, arg3 la matriz de
puntos con coordenadas globales de la figura de control pasada en el argumento numero
uno y arg4 es el nivel de altura de la orillas en prueba (Y1 o Y2).

Con cada llamada a la prueba de colisin de pendientes se da el siguiente proceso:


Se trasladan las coordenadas de los puntos de la figura de control sealada
en arg1, de su sistema de coordenada local al sistema de coordenadas
Global y se guardan tales coordenadas en la matriz sealada en arg3.
63

Se busca el punto de la figura de control sealada en arg1, que se


encuentra ms cercano a la orilla en prueba. Se busca el punto anlogo en
la figura de control sealada en arg2 y se pasa este punto a coordenadas
globales.
Se crea la lnea de control entre los dos puntos anteriormente
determinados.
Se compara la pendiente entre la lnea de control y la lnea al hombro.
Se determina si existe una colisin o no.

La prueba de colisin de pendientes tambin fue nombrada como prueba VORTEX


(por sus siglas en ingls: <<Virtual Object Rapid Touching Edges Examination>>) o
prueba rpida de las orillas en contacto del objeto virtual.
CAPTULO 5: La interfaz grfica de usuario de la aplicacin

Para acceder al programa de simulacin desarrollado en este proyecto, ste debe ser
ejecutado desde la lnea de comandos, dentro de un entorno grfico que tenga soporte para
OpenGL, GLU, GTK-2.0 y GtkGLext. Una vez que el programa se est corriendo, el
simulador puede ser controlado directamente desde el emulador de terminal (la lnea de
comandos) o mediante la interfaz grfica de usuario GTK. Se recomienda utilizar siempre
la interfaz grfica en lugar de la lnea de comandos, ya que sta facilita el uso de la
aplicacin.
Desde la interfaz de usuario se pueden dar rdenes de movimiento, de creacin y
ejecucin de rutinas y de configuracin al simulador. La interfaz est compuesta por tres
ventanas principales. En la figura 5.1 se observan las tres ventanas de la aplicacin, adems
de la ventana de la terminal desde la cual se encuentra corriendo el programa. Se
recomienda mantener las cuatro ventanas visibles, de manera similar a la figura 5.1. A
pesar de que algunos mensajes son desplegados en el <<textview>> de la aplicacin GTK,
muchos mensajes de importancias tambin son transmitidos a travs de la terminal.

Figura 5.1 La aplicacin grfica de usuario del simulador

En la ventana superior derecha de la figura 5.1, la cual es la ventana de despliegue


de la escena virtual, se muestra el modelo virtual del brazo robot Stubli R90X L. En el
rea superior derecha de esta ventana se puede observar una esfera. Esta esfera cambia de
lugar y de color dependiendo del riesgo que representa el movimiento actual del brazo. La

64
65

esfera de color verde indica que el movimiento es seguro y que el brazo no se encuentra
colisionado, la esfera amarilla seala que aunque no se est dando una colisin, al menos
un punto de control se localiza dentro de una de las reas de precaucin, por lo que el
choque puede estar cercano a ocurrir, finalmente la esfera roja indica que se est dando un
choque en al menos uno de los componentes del brazo.
Las ventanas grficas fueron programadas utilizando funciones de la librera gtk-
2.0. Se utilizaron objetos como botones, entradas de texto, etiquetas, etc, para formar la
interfaz de usuario la cual consta de tres ventanas, dos ventanas en donde se ubican los
botones y dems objetos para controlar el simular virtual y una tercer ventana en donde se
despliega la escena virtual, es decir el mundo virtual en el cual se encuentra el modelo de
brazo robot.
Las tres ventanas grficas son creadas en el momento en el que se inicia la
aplicacin. Las funciones encargadas de llamar y desplegar las ventanas se encuentran en el
archivo fuente de cdigo main.c.

/* Creacin y despliegue de las ventanas de interfaz grfica. Archivo fuente: main.c*/


...

gtk_init (&argc, &argv);

ventana1 = create_window1 ();


gtk_widget_show (ventana1);
ventana3 = create_window3 ();
gtk_widget_show (ventana3);
ventana2 = create_window2 ();
gtk_widget_show (ventana2);

gtk_main ();

En el segmento de cdigo mostrado anteriormente se presentan las funciones


encargadas de crear y desplegar las ventanas grficas de la aplicacin. Las funciones
create_window1(), create_window2() y create_window3() crean las ventanas especficas,
con los objetos grficos que las componen. La informacin es pasada a ventana1, ventana2
y ventana3, punteros a objetos GTK del tipo GtkWindow. Ntese como despus de la
creacin de cada ventana se llama a la funcin gtk_widget_show() y se le pasa como
argumento el puntero a la ventana que acaba de ser creada. Esta funcin produce que se
despliegue la ventana en la pantalla. La ltima funcin mostrada en el segmento de cdigo
es gtk_main(), sta seala la entrada al lazo principal Gtk. Este es un lazo infinito, en el
cul la aplicacin se encuentra en espera de algn evento.
Bsicamente las funciones encargadas de crear una ventana grfica, tienen como
tarea llamar a todos los objetos grficos que sean necesarios y colocarlos dentro de un
marco de manera que se obtenga la configuracin de la ventana, adems se debe ligar a
66

cada objeto grfico que lo requiera, las funcin de respuesta a diferentes eventos, por
ejemplo, los botones de una ventana grfica deben tener funciones de respuesta que sean
llamadas cada vez que stos son presionados.
A continuacin se muestran algunos segmentos de cdigo que componen la funcin
encargada de crear la ventana grficas superior izquierda de la figura 5.1.

/*Ejemplo: Funcin encargada de crear la ventana 1. Archivo fuente: interface.c*/

GtkWidget* create_window1 (void){


/* Se inicializan los objetos que configuran la ventana*/
GtkWidget *window1;
GtkWidget *bsimular;

/*Se crea la ventana sobre la cual se colocaran los botones y dems objetos grficos*/
window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_name (window1, "window1");
gtk_container_set_border_width (GTK_CONTAINER (window1), 3);
gtk_window_set_title (GTK_WINDOW (window1), _("Controles del Simulador"));


/* Se agregan todos los objetos que configuran la ventana. Por ejemplo, a continuacin
se despliega la funcin que agregar el botn SIMULAR */

bsimular = gtk_button_new ();


gtk_widget_set_name (bsimular, "bsimular");
gtk_widget_show (bsimular);
gtk_box_pack_start (GTK_BOX (vbox3), bsimular, FALSE, FALSE, 0);

/*Se conectan los objetos grficos y sus funciones de respuesta correspondientes*/


g_signal_connect ((gpointer) bsimular, "clicked",
G_CALLBACK (on_bsimular_clicked), NULL);

/*Se devuelve la ventana, compuesta por los objetos grficos respectivos*/
return window1;
}

Las tres funciones que crean las ventanas de la interfaz se encuentran desarrolladas
en el archivo fuente interface.c. Ntese en el cdigo anterior que la funcin
create_window1 devuelve un puntero a un objeto del tipo GTK. Dentro de la funcin se
inicializan todos los objetos grficos que componen la ventana, en el ejemplo se muestran
solo dos de los objetos de la ventana, la ventana principal window1 y el objeto del tipo
botn bsimular (botn SIMULAR de la aplicacin). En total, esta ventana se encuentra
compuesta por cincuenta y un objetos, incluyendo botones, entradas de texto, marcos,
etiquetas, etc. En el cdigo se puede verificar la existencia de diferentes funciones que
ofrece la librera Gtk, que se pueden utilizar dependiendo del objeto que se desea crear, por
67

ejemplo para crear una ventana vaca se utiliza la funcin gtk_window_new(), mientras que
para crear un botn se utiliza la funcin gtk_button_new(). Algunos objetos grficos
requieren funciones de respuesta para eventos determinados, por ejemplo en el cdigo
anterior se conecta el objeto bsimular, es decir el botn SIMULAR de la aplicacin, con la
funcin on_simular_clicked, sta funcin va a ser llamada cada vez que el botn
SIMULAR sea presionado. La funcin utilizada para ligar el proceso de respuesta al botn
fue la siguiente: g_signal_connect(arg1, arg2, arg3, arg4), a la funcin se le deben pasar
cuatro argumentos, el primero indica el objeto grfico en el que se da el evento, en el
ejemplo anterior es bsimular, el segundo argumento seala el tipo de evento para el cual se
debe llamar la funcin de respuesta, en el ejemplo el evento es del tipo clicked, es decir
cuando se presione el botn utilizando el puntero del ratn, el tercer argumento de la
funcin de conexin indica la funcin de respuesta que se desea ligar al evento y al objeto,
mientras que el cuarto argumento se utiliza para pasar informacin a la funcin de
respuesta.
Todas la funciones de respuesta se encuentran desarrolladas en el archivo fuente
callbacks.c. A continuacin se muestra parte del cdigo de la funcin on_bsimular_clicked,
la cual es llamada cada vez que el botn SIMULAR es presionado.

/*Funcin de respuesta del botn: Simular. Archivo fuente: callbacks.c*/

void on_bsimular_clicked (GtkButton *button, gpointer user_data){

/*Simula el movimiento del robot utilizando los valores de los botones 'spinner'*/
GtkSpinButton *spin1, *spin2, *spin3;
int velocporciento;

spin1=GTK_SPIN_BUTTON(spinbutton1);
spin2=GTK_SPIN_BUTTON(spinbutton2);
spin3=GTK_SPIN_BUTTON(spinbutton3);

hubochoque=0;

//Toma los valores de los botones 'spinners'


joint = gtk_spin_button_get_value_as_int(spin1);
angulodelta = gtk_spin_button_get_value_as_int(spin2);
velocporciento = gtk_spin_button_get_value_as_int(spin3);
set_velocidad(velocporciento, joint);

selec_mover_joint();
if(hubochoque==1){
printtv("\n\nCUIDADO!!!-->Se produjo un choque durante la simulacin del movimiento");
}
}

La funcin on_bsimular_clicked utiliza los valores de articulacin, ngulo y


velocidad, definidos por el usuario por medio de los botones correspondientes de la
68

aplicacin, para simular el movimiento del brazo robot. Una vez tomados los valores se
llama a la funcin selec_mover_joint(), la cual se encarga de producir el movimiento en el
modelo virtual del robot. Cada botn de la aplicacin se encuentra ligado a diferentes
funciones de respuesta, las cuales en conjunto permiten el funcionamiento correcto de la
aplicacin.

5.1 Los botones de configuracin del simulador


En la figura 5.2 se encuentran algunos botones encargados de cambiar la
configuracin del simulador.

Figura 5.2 Los botones de configuracin del simulador

El primer cuadro en la ventana contiene los botones encargados de guardar, cargar y


reiniciar las posiciones del brazo robot y de la cmara. Los botones APILAR y
DESAPILAR apilan y desapilan respectivamente, el estado del brazo virtual, en una pila
capaz de contener sesenta posiciones. Mientras que el botn Reiniciar Pila borra todas las
posiciones que hayan sido guardadas en la pila. Reiniciar Robot y Reiniciar Cmara
pueden ser presionados cuando se desea volver a la posicin inicial de estos objetos.
En el segundo cuadro de la ventana se encuentra el botn GRID, el cual produce
que el piso de la escena sea desplegado en forma de rejilla.
El tercer marco contiene los botones encargados de configurar el proceso de
simulacin en s. El seleccionar la opcin Lim. Angulos ocasiona que el simulador enve
un mensaje al usuario cada vez que alguna articulacin alcance su amplitud mxima de
giro. Si esta opcin se encuentra seleccionada y se alcanza una amplitud de giro mxima,
ya sea durante la ejecucin del comando MOVER (DRIVE), la ejecucin del comando
Simular o la ejecucin de una rutina, la rotacin de la articulacin se detendr en su
ngulo mximo. De manera similar, la seleccin de la opcin 1 Colisin ocasiona que el
brazo virtual detenga su movimiento una vez que ste detecta su primera colisin, ya sea
69

durante la ejecucin del comando MOVER (DRIVE), la ejecucin del comando


Simular o la ejecucin de una rutina. Si se da un choque y el botn 1 Colisin se
encuentra seleccionado, el modelo no se podr mover nuevamente hasta que se deshabilite
el botn indicado o se recargue en el brazo su posicin inicial o alguna en que no se
encuentre colisionado, ya sea utilizando la opcin Reiniciar Robot o DESAPILAR.
Finalmente el botn SIM ON se encarga de habilitar y deshabilitar el simulador
durante la edicin y ejecucin de rutinas o el uso del comando MOVER (DRIVE).
Existen dos cambios de configuracin del simulador que se pueden llevar a cabo por
medio de la entrada de texto del marco Lnea de comandos: agregar una base externa al
brazo virtual y definir un margen de precaucin al proceso de deteccin de colisiones.
Muchas veces los brazos mecnicos se encuentran motados sobre bases externas,
con el fin de ajustarlos mejor a la zona de trabajo en la cual deben desempaarse. El
simulador posee la opcin de agregar una base externa al brazo robot, cuyo radio es igual a
la base propia del modelo. Para aadir la base externa se introduce el comando base en la
lnea de entrada del marco Linea de comandos de la primer ventana GTK, seguido por la
altura que se desea tenga la base, en centmetros, luego se ejecuta utilizando el botn
EJECUTAR. Por ejemplo en la figura 5.3 se agreg al brazo virtual una base externa de
30 centmetros.

Figura 5.3 Introduccin de una base externa

Para definir un margen de precaucin se introduce en la entrada de texto del marco


Lnea de comandos la palabra margen seguida por la magnitud del margen de
precaucin que se desea, en centmetros, luego se presiona el botn EJECUTAR.
70

Figura 5.4 Introduccin del margen de error

En el ejemplo de la figura 5.4 se introdujo un margen de precaucin de 20


centmetros, lo cual ocasiona que el simulador indique que se dio una colisin 20
centmetros antes de que sta realmente ocurra.

5.2 Creacin, edicin y ejecucin de rutinas


Existen tres opciones para crear una rutina de movimientos para el brazo virtual. La
primera es editar de forma manual el archivo de texto que contendr la rutina, siguiendo el
formato especfico de los archivos de rutina de la aplicacin. La segunda manera es
seleccionar la ventana de despliegue de la escena virtual y presionar la tecla F5, luego se
deben seguir las rdenes desplegadas en la ventana de la terminal.

Figura 5.5 Ventana 1 de la aplicacin


71

La opcin ms recomendable para crear una rutina es la de utilizar la interfaz


grfica del programa. Lo primero que debe hacerse es asegurarse de que el simulador se
encuentre habilitado, utilizando el botn SIM ON en la ventana inferior izquierda de la
figura 5.1, luego se deben seguir los siguientes pasos:
Introducir un nombre para la nueva rutina, en la entrada de texto del cuadro
Rutinas, que se encuentra en la ventana de la figura 5.5 y presionar el botn
Crear nueva Rutina del mismo cuadro, lo cual dar comienzo a la edicin de
la nueva rutina.
Para agregar movimientos a la rutina se utiliza el botn del comando
MOVER (DRIVE) y los botones de ajuste ARTICULACIN,
ANGULO y VELOCIDAD(%). Cada movimiento agregado a la rutina
ser simulado y se indicar si el movimiento caus un choque o si se alcanz
el valor mximo de amplitud de giro para alguna articulacin, siempre y
cuando la opcin se encuentre habilitada. Si el movimiento conllev a una
colisin en la simulacin, la aplicacin preguntar al usuario si ste debe ser
agregado a la rutina o no. Nunca se recomienda agregar a la rutina
movimientos que causen choques durante la simulacin. El botn
SIMULAR, puede utilizarse como opcin al botn MOVER (DRIVE) con
la diferencia de que est simula el movimiento pero no lo guarda en el archivo
de la rutina. Antes de utilizar el botn SIMULAR, se recomienda apilar el
estado actual del brazo virtual, con ayuda del botn APILAR, en la ventana
de la figura 5.2, de manera que se pueda volver a esta posicin luego de haber
simulado el movimiento y as el brazo virtual se encuentre en la posicin
correcta cuando se vuelva a utilizar el comando MOVER (DRIVE).
Para finalizar la rutina se debe introducir el comando e por medio de la
entrada de texto y el botn EJECUTAR, ubicados en el cuadro Lnea de
Comandos, en la ventana de la figura 5.5.
Una vez finalizada la edicin de la rutina, est se encuentra cargada en la memoria,
para ejecutarla se debe presionar el botn Ejecutar Rutina del marco Rutinas. Si se
desea cargar una rutina diferente, se debe presionar el botn Cargar Rutina, el cual
despliega una ventana de seleccin de archivos, mediante la cual se puede seleccionar el
archivo de rutina que se desea cargar. El simulador guarda las rutinas en la carpeta
rutinas, ubicada dentro de la carpeta que contiene los archivos fuente de la aplicacin.
El botn de comando MOVER (DRIVE) tambin puede utilizarse para dar
ordenes de movimiento fuera de la edicin de una rutina, al igual que el botn
SIMULAR.
El proceso de cambiar, borrar o agregar movimientos a un archivo de rutina de
simulacin existente, debe realizarse de forma manual, directamente desde el archivo de
texto especfico, respetando el formato de los archivos de rutina del simulador. Todos los
archivos de rutinas de movimiento del simulador deben comenzar con la palabra inicio y
72

terminar con la palabra fin. Los movimientos se especifican utilizando el siguiente


formato de frase: M(nmero), J (nmero), A (nmero), V (nmero), , en donde el
nmero despus de la letra M seala el nmero de movimiento, el nmero posterior a J
seala la articulacin que se desea realice el movimiento, siendo (1, 2, 3, 4, 5, 6) los nicos
nmeros posibles, A indica que el numero que sigue se refiere al ngulo de giro (en
grados), mientras que el nmero siguiente a V es la velocidad porcentual de giro, la cual
debe ser mayor que cero y menor o igual que cien. Todos los nmeros deben ser enteros
excepto el ngulo de giro, el cual puede tener un dgito decimal (utilizar un punto para
ingresar el decimal). Se deben respetar la comas, las maysculas y minsculas. A
continuacin se muestra un ejemplo de un archivo de rutina.

Ejemplo: Formato de un archivo de rutina


inicio
M1, J 1, A 10.0, V 100,
M2, J 3, A 90.0, V 60,
M3, J 2, A 50.0, V 73,
M4, J 6, A 60.0, V 96,
Fin

El ejemplo revela el formato de un archivo de rutina de cuatro movimientos. La


primer lnea de texto del archivo seala el inicio de este y por lo tanto el inicio de la rutina.
La segunda lnea indica un movimiento en la primer articulacin del brazo virtual, es decir
la articulacin que une la base y el hombro. El giro es de 10 y debe realizarse a una
velocidad del 100% de la velocidad mxima de giro de tal articulacin. La siguiente lnea
de texto se refiere a un giro de 90 en la tercer articulacin (entre brazo1 y codo) a una
velocidad del 60 % de la velocidad mxima del actuador de la articulacin. De igual
manera las siguientes dos lneas indican movimientos en la segunda y sexta articulacin
respectivamente. Ntese que las palabras que indican el inicio y el fin del archivo estn
escritas en minscula.

5.3 Envo de ordenes al simulador por medio del teclado y el ratn


Es posible enviar al simulador algunas rdenes por medio del teclado y el ratn. Por
ejemplo, si se mueve el puntero del ratn dentro de la ventana de despliegue de la escena
virtual, manteniendo el botn izquierdo (botn 1) presionado, la cmara en la escena virtual
rota en direccin del movimiento, por otro lado, un desplazamiento del puntero dentro de la
misma ventana pero manteniendo el botn central (botn 2) presionado, traslada la cmara
en la direccin del movimiento, mientras que si el movimiento se hace manteniendo el
botn derecho (botn 3) presionado, varia el acercamiento (<<zoom>>) de la cmara.
73

A continuacin se muestra una listado de diferentes teclas y las rdenes ligadas a


stas. Para poder ejecutar rdenes por medio del teclado, la ventana de despliegue OpenGL,
la cual es la ventana en donde se despliega la escena virtual, debe encontrarse seleccionada.

Cuadro 5.1 Envo de ordenes por medio del teclado

Tecla(s): Funcin
r Selecciona el Robot (obj = robot)
c Selecciona la Cmara (obj = cmara)
z Modo = Rotar la cmara
x Modo = Trasladar de la cmara
if(obj = camara) if(obj = robot)
if(modo=rotar) if(modo=trasladar)
keyLeft + rotar(eje Y) - + articulacin 1
keyRight - rotar(eje Y) - - articulacin 1
keyUp + rotar(eje X) + trasladar (eje Y) + articulacin 2
keyDown - rotar(eje X) - trasladar (eje Y) - articulacin 2

PageUp Zoom Out + articulacin 3


PageDown Zoom In - articulacin 3
g - + articulacin 4
j - - articulacin 4

y - + articulacin 5
n - - articulacin 5
o - + articulacin 6
p - - articulacin 6

a + velocidad cmara + velocidad robot


d - velocidad cmara - velocidad robot
key Home - reiniciar posicin robot
key End reiniciar posicin robot -
F1 Desplegar Piso como Rejilla (ON/OFF)
F2 Limitar articulacin a su amplitud de giro mxima (ON/OFF)
F3 Detener simulacin al darse la primera colisin (ON/OFF)
F5 Abrir y Cargar Rutina (desde terminal)
F6 Crear Rutina (desde terminal)
F7 Salvar Rutina en memoria (desde terminal)
F8 Ejecutar Rutina en memoria
F9 Apilar posicin actual del robot
F10 Desapilar Posicin
F11 Limpiar Pila (borrar todas la posiciones apiladas)
F12 Desplegar los valores de los ngulos de las articulaciones
CAPITULO 6: Pruebas finales y sus resultados

Una vez finalizada la etapa de desarrollo de la aplicacin de simulacin, se llevo a


cabo un proceso de pruebas, con el fin de determinar la estabilidad y desempeo de sta.
Las pruebas fueron realizadas en un computador con procesador Pentium 4 de 1.99GHz
(<<giga hertz>>) de velocidad de procesamiento y 256 MB (<<mega bytes>>) de RAM
(<<random access memory>>).

6.1 Pruebas destructivas


Las primeras pruebas realizadas al programa fueron del tipo destructivas. En las
entradas de texto de la aplicacin se pasaron cadenas de caracteres de varios formatos y
tamaos, se crearon rutinas que nunca fueron terminadas, se dieron ordenes de abrir
archivos que no existan o cuyos formatos no concordaban con el formato de los archivos
de rutina del simulador. Por medio de ests pruebas se detect un fallo en la funcin
encargada de copiar el texto ingresado por el usuario en las entradas de texto Gtk. Algunas
veces despus de copiar la cadena, no se aada a sta el caracter de finalizacin de cadena
\0, lo que ocasionaba que se emitiera la seal de error de segmentacin, al pasar la cadena
como argumento de algunas funciones de la biblioteca estndar. Adems la funcin muchas
veces copiaba ms caracteres de los que realmente haba introducido el usuario, entonces al
tener la cadena de caracteres un tamao mayor al espacio de memoria destinado para ella,
se daban tambin errores de segmentacin. El problema fue solucionado limitando el
nmero de caracteres que copia la funcin desde la entrada de texto y concatenado al final
de todas la cadenas copiadas el carcter de terminacin \0. Despus de realizar estos
cambios, se procedi nuevamente con las pruebas. No se volvieron a presentar en ninguna
de ellas errores de segmentacin.

6.2 Pruebas de velocidad


Tambin fueron realizadas pruebas de velocidad en diferentes puntos del programa.
Algunas funciones poseen una velocidad que depende de la rapidez de reaccin del usuario,
por ejemplo, la velocidad del proceso de creacin y edicin de una rutina va a estar ms
ligada a la rapidez con la que el usuario introduzca los movimientos, que a la velocidad de
procesamiento misma del programa. Las funciones y fragmentos de cdigo que poseen
velocidades de ejecucin mayormente dependientes de la rapidez del usuario que del
programa en s, no fueron incluidos en estas pruebas. Por otro lado, el programa posee
algunos procesos o fragmentos de stos, sobre los cuales el usuario no tiene influencia. Se
realizaron pruebas de velocidad a stas segmentos de la aplicacin, midiendo el tiempo del
sistema a la entrada de cada segmento en prueba y a la salida de ste, luego se calcul la
diferencia entre ambos valores, obteniendo as el tiempo de ejecucin del proceso. Los
tiempos fueron medidos en milisegundos.

74
75

Los procesos cronometrados fueron los siguientes:


Proceso que se lleva a cabo desde que se llama al programa, hasta que este entra al
lazo de control principal infinito, en el cual estn implicados a su ves los procesos
de creacin y despliegue de las ventanas.
El proceso de extraer los valores de las entradas de texto y de los botones de ajuste
de la interfaz grfica Gtk.
El proceso de cargar de los movimientos de un archivo de rutina a los espacios de
memoria especficos.
El proceso realizado por la funcin dibujar(), la cul se encargar de graficar la
escena virtual.

Cada proceso en prueba fue cronometrado treinta veces, luego se calcul el tiempo
promedio de ejecucin de cada uno.
En promedio al programa le tom 443 ms (milisegundos) realizar todas las tareas
que implican la creacin y el despliegue de las tres ventanas de la aplicacin grfica. La
velocidad del proceso se considera buena, ya que es apenas perceptible por el usuario.
Las mediciones de velocidad de las funciones de extraccin y copia de informacin
desde los objetos de la aplicacin grfica, mostraron resultados positivos. Todas las
funciones que realizan este tipo de proceso extrajeron los valores, tanto de las entradas de
texto como de los botones de ajuste Gtk, a velocidades realmente altas. De hecho no se
pudo captar ninguna diferencia entre el tiempo de entrada y el de salida para estas
funciones, en ninguna de las pruebas, es decir que el tiempo de ejecucin siempre fue
menor a 1 milisegundo. Estos resultados muestran un gran desempeo por parte de las
funciones de extraccin de informacin desde objetos Gtk. Se puede afirmar que la
velocidad de stas es lo suficientemente alta como para que no afecten de manera negativa,
el desempeo de la aplicacin.
Al igual que para el proceso de extraccin de informacin desde los objetos Gtk, la
extraccin de informacin desde archivos de texto, durante la funcin de carga de rutinas,
tambin revel tiempos de ejecucin muy bajos. Para este caso tampoco se detectaron
tiempos de ejecucin mayores a un milisegundo, an cuando se cargaron rutinas de hasta
sesenta movimientos.
La funcin dibujar(), es la encargada de graficar la escena virtual en la pantalla.
Realmente esta funcin est compuesta por varias etapas. Lo primero que sta hace es
buscar el rea de dibujo destinada al despliegue de objetos OpenGL, luego si el rea existe
y es encontrada la funcin la selecciona como rea actual de dibujo. Como paso siguiente
se deben limpiar los almacenadores intermedios de color y de profundidad (<<color
buffer>> y <<depth buffer>>), determinar las opciones de dibujo elegidas por el usuario,
llamar a la matriz de transformacin actual, llevar a cabo las multiplicaciones de matrices
de traslacin y rotacin que sean necesarias, as como el apile y desapile de la matriz de
76

transformacin actual en los puntos que lo requieran y llamar las listas de despliegue
especficas en los puntos necesarios. Luego se debe convocar a la funcin encargada de
comparar la amplitud de giro de cada una de las articulaciones del modelo con sus
amplitudes de giro mximas y esperar a que sta termine de ser ejecutada. Posteriormente
se llama a la funcin de prueba de colisiones y se aguarda a que esta funcin emita su
resultado. Como ltimo paso se exige la ejecucin de todas las funciones OpenGL llamadas
hasta este punto y se intercambian los almacenadores intermedios grficos. Se observa que
son varios pasos los que debe realizar la funcin dibujar(), de hecho esta es la funcin cuyo
tiempo de ejecucin posee mayor influencia en el desempeo del programa, en cuanto a
velocidad de procesamiento se refiere, no solo por la cantidad de procesos que debe llevar a
cabo, sino por que es una de las ms utilizadas durante la ejecucin de la aplicacin. A
pesar de todas las tareas que realiza, dibujar() expuso un tiempo promedio de ejecucin de
apenas 29 ms, de hecho el mayor tiempo que se logr cronometrar para esta funcin fue de
32 ms, el cual se considera como aceptable, si se toma en cuenta todos los pasos que
conlleva el proceso. El tiempo es tan bajo que el usuario percibe la graficacin como
inmediata.
Las pruebas de velocidad mostraron resultados muy positivos. En su mayora los
tiempos de ejecucin de los procesos son tan bajos, que no pueden ser percibidos por el
usuario.
A continuacin se muestran algunos de los resultados obtenidos durante las pruebas
de velocidad.

/* Ejemplo: Algunos valores de tiempo obtenidos en la pruebas de velocidad */

Tiempo Main: 382 ms


Tiempo Main: 409 ms
Tiempo Main: 190 ms

Tiempo cargar movimiento a Simular: 0 ms


Tiempo cargar movimiento a Simular: 0 ms
Tiempo cargar movimiento a Simular: 0 ms

Tiempo Cargar Rutina: 0 ms. Num. movimientos: 60


Tiempo Cargar Rutina: 0 ms. Num. movimientos: 37

Tiempo extraccin valor botones de ajuste Mover (Drive): 0 ms


Tiempo extraccin valor botones de ajuste Mover (Drive): 0 ms

Tiempo extraccin valor entrada de texto: 0 ms


Tiempo extraccin valor entrada de texto: 0 ms

Tiempo de dibujar(): 27 ms
Tiempo de dibujar(): 32 ms
Tiempo de dibujar(): 28 ms
77

6.3 Pruebas de memoria


Las pruebas de memoria y bsqueda de fugas de memoria <<memory leaks>>
tambin mostraron resultados positivos. Para llevar a cabo las pruebas se llam a la
aplicacin y se examin la cantidad de memoria utilizada en diferentes puntos de la
ejecucin de sta, por ejemplo se crearon, editaron y cargaron archivos de rutinas, se dieron
ordenes de movimientos al brazo, se cambio la configuracin de ste etc, midiendo siempre
la memoria en uso antes y despus de cada proceso. Mediante las mediciones no se capt
en ninguno momento un crecimiento elevado en el uso de memoria, lo que indica que no se
produjeron fugas de sta, por el contrario la memoria de acceso aleatorio utilizada por el
programa se mantuvo prcticamente constante durante todo el tiempo que corri el
programa, para todas las ejecuciones que se llevaron a cabo. En promedio la aplicacin
present un consumo de 5 MB (mega bytes) de memoria RAM aproximadamente, el cual
es un valor aceptable considerando las tareas que lleva a cabo el programa.
A continuacin se muestra una parte de los resultados de una de las pruebas de
memoria que se llevaron a cabo.

/* Ejemplo del proceso de las pruebas de memoria */

No se ha llamado el programa:
total utilizada libre
MemRAM: 256288 247080 9208

Se corre el programa:
total utilizada libre
MemRAM: 256288 252864 3424

Se ejecuta carga una rutina de treinta movimientos:


total utilizada libre
MemRAM: 256288 252292 3996

... /*Se realizan otros procesos y se mide la memoria antes y despus de cada uno */

Se cierra el programa:
total utilizada libre
MemRAM: 256288 247432 8856

Se corre el programa nuevamente:


total utilizada libre
MemRAM: 256288 252384 3904

CAPITULO 7: Conclusiones y Recomendaciones

7.1 Conclusiones

El programa final es flexible en cuanto a las opciones de uso, se puede controlar ya


sea desde un emulador de terminal o a travs de la interfaz grfica de usuario.

La interfaz grfica de usuario creada en el proyecto, facilita el uso de la aplicacin y


la hace ms amigable.

El API OpenGL demostr ser una biblioteca de gran robustez y flexibilidad, que
permite el desarrollo de aplicaciones grficas tanto simples como complejas.

El estudio previo y entendimiento de la teora de modelado tridimensional en


computadoras, facilita el uso de los API grficos y permite al programador un mejor
desenvolvimiento durante el desarrollo de aplicaciones grficas.

Adems de ser robusto, flexible, gratuito y amigable al usuario, el API OpenGL


posee un amplio soporte por parte de los desarrolladores. Existe una gran cantidad
de material de ayuda e informacin referente a la librera, lo cual facilita e incentiva
el uso de sta.

En general existe gran cantidad de documentacin informativa y de ayuda tanto


para el sistema GNU/Linux como para las aplicaciones y libreras de esta
plataforma. El fcil acceso a esta documentacin y la adquisicin gratuita de
programas libres promueve el desarrollo de nuevas aplicaciones de software y el
mejoramiento de las ya existentes.

La aplicacin desarrollada en el proyecto posee una flexibilidad que le permite


adaptarse a diferentes configuraciones, lo que incrementa su rango de
funcionalidad.

78
79

El lenguaje de programacin C presenta las caractersticas necesarias para el


desarrollo de aplicaciones grficas complejas.

La simulacin virtual de un proceso permite al usuario obtener una idea previa del
resultado a esperar, de manera que se pueden realizar los cambios necesarios para
obtener una mayor eficiencia en el proceso, antes de que ste ocurra realmente.

La deteccin y prevencin de colisiones es un tema de suma importancia, no solo en


el rea de la robtica, sino tambin en el rea de control de otros tipos de
dispositivos electromecnicos. Poder detectar una posible colisin antes de que sta
ocurra realmente, ayuda a incrementar tanto la seguridad del dispositivo como la de
los usuarios.

Los mtodos de deteccin de colisiones utilizados en el proyecto son los


suficientemente flexibles como para ser adaptados a diferentes tipos de dispositivos
electromecnicos.

En especial la prueba de colisiones de orillas (VORTEX) o prueba de colisin de


pendientes creada en el proyecto, demostr ser no solamente efectiva y flexible,
sino que presenta una estructura sumamente simple, en comparacin con otros
mtodos de deteccin de colisiones normalmente utilizados en la industria de
desarrollo de aplicaciones grficas virtuales.

El lenguaje de programacin utilizado, la interfaz grfica de usuario y la estructura


del cdigo de la aplicacin desarrollada en el proyecto, permiten una fcil
implementacin y adicin del cdigo creado en [4].

El programa creado en este proyecto, puede ser expandido y aplicado a diferentes


reas, no solo referentes al desarrollo de escenas y mundos virtuales, sino que
tambin ligadas al control de dispositivos electromecnicos. El proyecto representa
una buena base, para futuras investigaciones ligadas al tema.
80

7.2 Recomendaciones

Es importante realizar una investigacin previa a la creacin de cualquier


aplicacin grfica, con el fin de establecer cuales libreras grficas representan la
mejor opcin tanto para el desarrollador como para el futuro usuario del programa.

Es posible aadir portabilidad a la aplicacin desarrollada en el proyecto. El lograr


que la aplicacin sea compatible con diferentes sistemas operativos, representara
un gran beneficio para el usuario, ya que no se vera limitado al sistema GNU/Linux
para poder utilizar el programa.

La realizacin de pruebas, utilizando tanto el simulador como el brazo real,


permitira, si fuera necesario, un mejor ajuste del margen de precaucin del
simulador, de manera que se obtenga el mejor desempeo posible de la aplicacin
de simulacin.

Utilizando un programa de edicin y diseo grfico profesional sera posible crear


un modelo virtual del brazo Stubli RX90L ms exacto, lo cual mejorara la
aplicacin no solo desde el punto de vista esttico, sino que podra permitir un
incremento en la precisin del proceso de deteccin previa de colisiones.

La implementacin de texturas en la escena virtual, podra conllevar a un


mejoramiento en el aspecto y realismo de sta. Esto hara la aplicacin grfica ms
agradable y mejora la experiencia del usuario.

Es posible incrementar la funcionalidad del programa desarrollado en el proyecto,


creando una funcin que permita al usuario cargar diferentes modelos virtuales de
brazos robot, de manera que se podran simular los movimientos en diferentes tipos
de brazos y comparar los resultados.

Sera de gran utilidad para el usuario, que se desarrollara un algoritmo que calcule
la combinacin de ngulos necesaria, para llevar el extremo del brazo robot a una
posicin especfica en el espacio. Tal algoritmo podra ser creado utilizando el
mtodo de cinemtica inversa.
81

BIBLIOGRAFA

[1] Giambruno, M. 3D Graphics & Animation: From Starting Up to Standing


Out, primera edicin, New Riders Publishing, E.E.U.U, 1999.

[2] Barrientos, A. Fundamentos De La Robtica, primera edicin, McGraw-


Hill, Espaa, 1997.

[3] Neider, J., Davis, T., Woo, M., The OpenGL Programming Guide The
Red Book, segunda edicin, Addison-Wesley Publishing, E.E.U.U, 1999.

[4] Montes Solano, C. Envo de video hacia un cliente remoto utilizando el


sistema video4linux y desarrollo de una aplicacin grfica GTK sobre una
plataforma GNU/Linux, para el control de brazo robot Stubli RX90,
proyecto para el grado de bachillerato en Ingeniera elctrica, Universidad de
Costa Rica, 2005.

[5] Zeledn Chaves, E. Y Zeledn Mndez, P. Creacin de una interfase


humano-maquina para el control, monitoreo y supervisin del brazo robot
Stubli RX90 va internet, proyecto para el grado de bachillerato en
Ingeniera elctrica, Universidad de Costa Rica, 2004.

[6] OpenGL, OpenGL Homepage, http://www.opengl.org/, junio, 2006.

[7] Wikipedia.<<Linux>>, Wikipedia, http://en.wikipedia.org/wiki/Linux, junio,


2006.

[8] GTK, GTK Homepage , http://www.gtk.org/, junio, 2006.

[9] Lenguaje C, C programming, http://www.cprogramming.com/, junio, 2006.

[10] Wikipedia.<<DirectX>>, Wikipedia, http://en.wikipedia.org/wiki/Directx,


junio, 2006.

[11] GL Programming, http://www.glprogramming.com/, junio, 2006.

[12] Stubli, Stubli Robots, http://www.staubli.com/web/robot/division.

[13] Video juegos, Game Development, http://www.gamedev.net/ , junio 2006


APNDICES

Archivos de cdigo fuente de la aplicacin desarrollada en el proyecto.

callbacks.c: Funciones de respuesta de la interfaz grfica de usuario


/***************************************************************************
* SimQNK
* Simulador virtual del brazo robot Stubli RX90 L
* callbacks.c: funciones de respuesta de la interfaz grfica de usuario
* Copyright(C) 2006 David Cuenca
* Email: dcuenc@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include <gdk/gdk.h>
#include <gdk/gdkgl.h>
#include <gdk/gdkkeysyms.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include "callbacks.h"
#include "interface.h"

#include "dibujo.h"
#include "ventanagl.h"
#include "rutina.h"

int simon=1; //variable de habilitacin el simulador


int edicion=0; //variable de habilitacin de la edicin de rutina
int puntrutina;
char nombrerutina[47];
const gchar *archivo_sel;
FILE *archivo1;

82
83

//Posicion del puntero del mouse


int lastx;
int lasty;

/*Funcin se encarga de Imprimir en TextView*/


void printtv(const char *texto){
int size_t;
size_t=printf(texto);
textbuffer1 = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview1));
gtk_text_buffer_get_end_iter(textbuffer1, &iter1);
gtk_text_buffer_insert(textbuffer1, &iter1, texto, size_t);
}

/*Funcion del boton: Grid*/


void on_bgrid_toggled(GtkToggleButton *togglebutton, gpointer user_data){
if (GTK_TOGGLE_BUTTON (togglebutton)->active) {
grid=1; //encender la rejilla
}else {
grid=0; //apagar la rejilla
}
dibujar();
}

/*Funcion del boton: Fondo*/


/*Cambia el color de fondo de la ventana del mundo virtual*/
void on_btexturas_toggled(GtkToggleButton *togglebutton, gpointer user_data){
if (GTK_TOGGLE_BUTTON (togglebutton)->active) {
/*Fondo de color Blanco*/
glClearColor(1.0, 1.0, 1.0, 0.0);
}else {
/*Fondo de color Negro*/
glClearColor(0.0, 0.0, 0.0, 0.0);
}
dibujar();
}

/*Funcion del boton: Apilar*/


void on_bposicion1_clicked(GtkButton *button, gpointer user_data){
//Apilar posicin actual
push_posicion();
}

/*Funcion del boton: Desapilar*/


void on_bposicion2_clicked(GtkButton *button, gpointer user_data){
//Desapilar posicin anterior
pull_posicion();
dibujar();
}

/*Funcion del boton: Reiniciar Pila*/


void on_bposicion3_clicked(GtkButton *button, gpointer user_data){
//Reiniciar Pila de posiciones
reiniciar_pila();
}

/*Funcion del boton: Reiniciar Robot*/


void on_bposicion4_clicked(GtkButton *button, gpointer user_data){
//Reiniciar los valores de posicin del Robot
valores_iniciales_robot();
dibujar();
}

/*Funcion del boton: Reiniciar Camara*/


84
void on_bposicion5_clicked (GtkButton *button, gpointer user_data){
//Reiniciar los valores de posicin de la Cmara
valores_iniciales_camara();
reshape(ventanaw, ventanah);
dibujar();
}

/*Funcion del boton: Lim. Angulos*/


void on_bcheckmax_toggled(GtkToggleButton *togglebutton, gpointer user_data){
if (GTK_TOGGLE_BUTTON (togglebutton)->active) {
checkmax=1; //habilitar prueba de angulos mximos
}else {
checkmax=0; //deshabilitar prueba de angulos mximos
}
}

/*Funcion del boton: 1 Colision*/


void on_bcolision1_toggled(GtkToggleButton *togglebutton, gpointer user_data){
if (GTK_TOGGLE_BUTTON (togglebutton)->active) {
checkcolision=1; //detener rutina al darse la primera colisin
}else {
checkcolision=0; //continuar rutina aun despues de la primera colision
}
}

/*Funcion del boton: Simulador*/


void on_bsimulador_toggled (GtkToggleButton *togglebutton, gpointer user_data){
//ENCENDER SIMULADOR
if (GTK_TOGGLE_BUTTON (togglebutton)->active) {
simon=1; //simular las ordenes
}else {
simon=0; //no simular las ordenes
}
}

/* Dialogo cuando se da una colision en la edicin de la simulacin */


gint dialogo_mensaje(void){
GtkWidget *dialog, *label;
gint result;

dialog = gtk_dialog_new_with_buttons ("Advertencia!", GTK_WINDOW(ventana1), GTK_DIALOG_MODAL,


GTK_STOCK_YES, 1, GTK_STOCK_NO, 0, NULL);

label = gtk_label_new ("CUIDADO->Se dio una colisin. \nDesea aun asi agregar el movimiento a la rutina?");
gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
gtk_widget_show_all (dialog);

/* Detiene la aplicacin hasta que se de una respuesta al dialogo*/


result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy(dialog);

return result;
}

/*Funcion del boton: MOVER (Drive)*/


void on_bdrive_clicked(GtkButton *button, gpointer user_data){
GtkSpinButton *spin1, *spin2, *spin3;
int velocporciento;
float *temp_angulo = malloc(sizeof (float) * 6);
gint guardar;

spin1=GTK_SPIN_BUTTON(spinbutton1);
spin2=GTK_SPIN_BUTTON(spinbutton2);
spin3=GTK_SPIN_BUTTON(spinbutton3);
85

hubochoque=0;

/*Toma los valores de los botones 'spinners'*/


joint=gtk_spin_button_get_value_as_int(spin1);
angulodelta=gtk_spin_button_get_value_as_int(spin2);
velocporciento=gtk_spin_button_get_value_as_int(spin3);
set_velocidad(velocporciento, joint);

/*Simula el movimiento especificado por los valores de los spinners*/


if(simon==1 && edicion==0){
selec_mover_joint();
if(hubochoque==1){
printtv("\nSe produjo una colision-->La seal NO ser enviada al robot\n");
}else if(hubochoque==0){
printtv("\nEnviando seal al robot\n");
/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/
}
}else if(simon==1 && edicion==1){
/*edicin de una rutina*/
/*guardar el movimiento en la matriz de rutinas*/
puntrutina+=1;
rutina[puntrutina][0]=joint;
rutina[puntrutina][1]=angulodelta;
rutina[puntrutina][2]=velocporciento;
rutina[0][0]+=1;

/*Guarda los angulos actuales del robot en una memoria temporal, antes de moverlo*/
temp_angulo[0]=angulo1; temp_angulo[1]=angulo2; temp_angulo[2]=angulo3;
temp_angulo[3]=angulo4; temp_angulo[4]=angulo5; temp_angulo[5]=angulo6;

/*simular el movimiento del robot*/


selec_mover_joint();

/*Si no hubo choque guarda el movimient. en la rutina y envia la seal al robot*/


if(hubochoque!=1){
//guardar el movimiento en la matriz de rutinas
fprintf(archivo1,"M%i, J %d, A %3.1f, V
%d,\n",puntrutina,(int)rutina[puntrutina][0],rutina[puntrutina][1],(int)rutina[puntrutina][2]);

/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/

}
/*Si hubo choque pregunta si se debe guardar el movimiento.*/
if(hubochoque==1){
printtv("\n\n!!CUIDADO!!-->se produjo una colision durante la simulacin del movimiento");
printtv("\nSe recomienda eliminar el ultimo movimiento de la rutina");
guardar=dialogo_mensaje();
if(guardar==1){
/*guardar el movimiento en la matriz de rutinas y enviar seal*/
printtv("\nSe guardo el movimiento en la rutina");
fprintf(archivo1,"M%i, J %d, A %3.1f, V
%d,\n",puntrutina,(int)rutina[puntrutina][0],rutina[puntrutina][1],(int)rutina[puntrutina][2]);

/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/

}else {
/*Se devuelve el brazo y el puntero de rutina a la posicin anterior*/
printtv("\nNo se guardo el movimiento en la rutina");
puntrutina-=1;
angulo1=temp_angulo[0]; angulo2=temp_angulo[1]; angulo3=temp_angulo[2];
angulo4=temp_angulo[3]; angulo5=temp_angulo[4]; angulo6=temp_angulo[5];
dibujar();
/*No se le enva ninguna seal al robot*/
86
}
}
/*Si se alcanzan los 60 movimientos-> Se termina la edicin de rutina del simulador*/
if(puntrutina==60){
printtv("Movimiento #60 --> Mximo que puede guardar la rutina del simulador");
fprintf(archivo1,"fin");
fclose(archivo1);
edicion=0;
printtv("\n\nFin de la edicin de la rutina");
printf("\nFin de la edicin de la rutina: %s", nombrerutina);
}
}else if(simon==0){
printtv("\nSimulador Apagado. Enviando la seal directamente al robot");
/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/
}
free(temp_angulo);
fflush(stdout);
}

/*Funcion del boton: Simular*/


void on_bsimular_clicked (GtkButton *button, gpointer user_data){
/*Simula el movimiento del robot utilizando los valores de los botones 'spinner'*/
GtkSpinButton *spin1, *spin2, *spin3;
int velocporciento;

spin1=GTK_SPIN_BUTTON(spinbutton1);
spin2=GTK_SPIN_BUTTON(spinbutton2);
spin3=GTK_SPIN_BUTTON(spinbutton3);

hubochoque=0;

//Toma los valores de los botones 'spinners'


joint = gtk_spin_button_get_value_as_int(spin1);
angulodelta = gtk_spin_button_get_value_as_int(spin2);
velocporciento = gtk_spin_button_get_value_as_int(spin3);
set_velocidad(velocporciento, joint);

selec_mover_joint();
if(hubochoque==1){
printtv("\n\nCUIDADO!!!-->Se produjo un choque durante la simulacin del movimiento");
}
}

/*Funcion del boton: Ejecutar*/


void on_bejecutar_clicked (GtkButton *button, gpointer user_data){
/*Ejecutar comando introducido el linea de comandos*/
char entrada[30];
char *comandos[7];
char base_fija[20];
char margen_p[20];
int comp[7];
int pc;
char letra_c;

/*lista de comandos */
comandos[0]="e\0"; comandos[1]="edit "; comandos[2]="ex ";
comandos[3]="drive "; comandos[4]="base"; comandos[5]="margen";

/*extrae la cadena de caracteres de la entrade de texto entrycomando*/


strncpy(entrada, gtk_entry_get_text(GTK_ENTRY(entrycomando)), sizeof(entrada));
entrada[sizeof(entrada)-1]='\0';

/*compara el comando recibido con la lista de comandos de arriba*/


comp[0] = strncmp(entrada, comandos[0], 2);
87
comp[1] = strncmp(entrada, comandos[1], 5);
comp[2] = strncmp(entrada, comandos[2], 3);
comp[3] = strncmp(entrada, comandos[3], 6);
comp[4] = strncmp(entrada, comandos[4], 4);
comp[5] = strncmp(entrada, comandos[5], 5);

/*dependiendo del resultado de la comparacin realiza alguna de las sigueintes acciones*/


if(comp[0] == 0 && edicion==1){
fprintf(archivo1,"fin");
fclose(archivo1);
/*fin de la edicin de la rutina*/
edicion=0;
printtv("\n\nFin de la edicin de la rutina");
printf("\nFin de la edicin de la rutina: %s", nombrerutina);
/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/

}else if((comp[1] ==0 || comp[2] ==0) && (simon==1)){


printtv("\n\nSi desea utilizar el simulador, los comandos de las Rutinas se deben dar utilizando los botones de la
rutina");
printtv("\nNo se ejecut la orden. Solucion: Utilizar botnes de Rutina o deshabilitar el simulador");

}else if(comp[3] == 0 && simon==1){


printtv("\n\nSi desea utilizar el simulador, los comandos DRIVE se deben dar utilizando el botn DRIVE");
printtv("\nNo se ejecut la orden. Solucion: Utilizar botn DRIVE o deshabilitar el simulador");

}else if(comp[4] == 0){


/*Se recibio el comando de adaptar una base externa*/
printtv("\n\nAdaptar base\0");
pc=4;
letra_c='e';
while(letra_c != '\0'){
letra_c=entrada[pc];
base_fija[pc-4]=entrada[pc];
pc++;
}
altpiso=-1*(atof(base_fija));
printf(" de: %.1f centmetros de alto", -1*altpiso);
dibujar();

}else if(comp[5] == 0){


/*se recibio el comando de estblecer un margen de precaucin*/
printtv("\n\nEstablecer margen de precaucion");
pc=6;
letra_c='n';
while(letra_c != '\0'){
letra_c=entrada[pc];
margen_p[pc-6]=entrada[pc];
pc++;
}
marg=atof(margen_p);
init_vortexfijos(marg);
printf(" de: %.1f centmetros", marg);

}else{
printtv("\nEnviando seal al robot");
/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/
}
gtk_entry_set_text(GTK_ENTRY(entrycomando),"");
fflush(stdout);
/* previene que el handler predeterminado corra */
gtk_signal_emit_stop_by_name(GTK_OBJECT(button),"clicked");
}

/*Funcion del boton: Crear Rutina*/


88
void on_brutina1_clicked (GtkButton *button, gpointer user_data){
/*Establecer el nombre de edicin de una nueva rutina y el inicio de la edicin de esta misma*/
edicion=1; //se habilita la edicin de la rutina
puntrutina=0; //se inicializa el puntero de la matriz de rutinas
rutina[0][0]=0; //se inicializa el numero de movimientos en la matriz de rutinas

strcpy(nombrerutina, "./rutinas/\0");
strncat(nombrerutina, gtk_entry_get_text(GTK_ENTRY(entryrutina)),(sizeof(nombrerutina)-sizeof("./rutinas/\0")-3));
nombrerutina[sizeof(nombrerutina)-1]='\0';
printtv("\n\nInicio de la edicin de la rutina");
printf("\nInicio de la edicin de la rutina: %s", nombrerutina);
fflush(stdout);
archivo1=fopen(nombrerutina,"w");
fprintf(archivo1,"inicio\n");
}

/* Guarda el nombre del archivo seleccionado */


void guardar_nombre (GtkWidget *widget, gpointer user_data) {
GtkWidget *file_selector = GTK_WIDGET (user_data);
archivo_sel = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector));
printtv("\n\nCargar Archivo seleccionado");
printf("\nCargar Archivo: %s\n", archivo_sel);
}

/* Crea la ventana de seleccion de archivos */


void crear_selector (void) {
GtkWidget *file_selector;
file_selector = gtk_file_selection_new ("Selector de Archivos");

g_signal_connect (GTK_FILE_SELECTION (file_selector)->ok_button,


"clicked", G_CALLBACK (guardar_nombre), file_selector);

g_signal_connect_swapped (GTK_FILE_SELECTION (file_selector)->ok_button,


"clicked", G_CALLBACK (gtk_widget_destroy), file_selector);

g_signal_connect_swapped (GTK_FILE_SELECTION (file_selector)->cancel_button,


"clicked", G_CALLBACK (gtk_widget_destroy), file_selector);
gtk_widget_show (file_selector);

gtk_dialog_run(GTK_DIALOG(file_selector));

/*Funcion del boton: Cargar Rutina*/


void on_brutina2clicked (GtkButton *button, gpointer user_data){

FILE *archivo2;
char letra_ui;
char articult_ui[3];
char angt_ui[7];
char veloct_ui[7];
char linea_ui[15];
int p1, p2, p3; //punteros

/*llama a la ventana de seleccion de archivos*/


crear_selector();

/*abre el archivo seleccionado*/


archivo2=fopen(archivo_sel,"r");

if (!archivo2){
printtv("\n\n-ERROR-->No se pudo abrir el archivo");
printf("\n-ERROR-->No se pudo abrir el archivo %s", archivo_sel);
} else {
89
/*comienza a extraer la informacin del archivo*/
p1=0;
rutina[0][0]=0;
do{
/*se trata de un nuevo movimiento*/
letra_ui=fgetc(archivo2);
if(letra_ui=='M'){
if(p1<60){
p1++;
rutina[0][0]++;
}
}else if(letra_ui=='A'){
/*se trata de un angulo*/
p2=0;
while(letra_ui!=','){
letra_ui=fgetc(archivo2);
angt_ui[p2]=letra_ui;
p2++;
}
rutina[p1][1]=atof(angt_ui);
}else if(letra_ui=='J'){
/*se trata de una articulacin (joint)*/
p2=0;
while(letra_ui!=','){
letra_ui=fgetc(archivo2);
articult_ui[p2]=letra_ui;
p2++;
}
rutina[p1][0]=atof(articult_ui);
}else if(letra_ui=='V'){
/*se trata de la velocidad del movimiento*/
p2=0;
while(letra_ui!=','){
letra_ui=fgetc(archivo2);
veloct_ui[p2]=letra_ui;
p2++;
}
rutina[p1][2]=atof(veloct_ui);
}
}while (letra_ui!='f');
/*se cierra el archivo*/
fclose(archivo2);
}

/*Funcion del boton: Ejecutar Rutina*/


void on_brutina3_clicked(GtkButton *button, gpointer user_data){
//Ejecutar Rutina
hubochoque=0;
if(simon==1){
/*Se simula la rutina*/
ejecutar_rutina();
if(hubochoque==1){
/*se dio una colision*/
printtv("\nSe produjo una colision-->La seal de ejecutar rutina NO ser enviada al robot\n");
}else if(hubochoque==0){
/*no se dio ninguna colision*/
printtv("\nRutina Segura. Enviando seal de ejecutar rutina al robot\n");
/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/
}
}else{
/*Simulador apagado->No se simula la rutina*/
/*La seal se enva de una vez al robot. Sin simular*/
90
printtv("\nSimulador Apagado. Enviando seal de ejecutar rutina al robot\n");
/*Aqui se debe introducir el codigo para enviar la seal respectiva al brazo robot*/
}
}

/***********VENTANA OPENGL************************/
/*Movimiento del Mouse genera movimiento de la camara,
*si se mantiene alguno de los botones presionados*/
gboolean on_glarea_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data){
int x;
int y;
int difx;
int dify;
GdkModifierType state;

if (event->is_hint) {
gdk_window_get_pointer(event->window, &x, &y, &state);
}
/*calcula la diferencia entre las coordenadas actuales del ratn y las pasadas*/
difx=event->x - lastx;
dify=event->y - lasty;
lastx=event->x;
lasty=event->y;

/*hace un acercamiento de la camara*/


if (event->state & GDK_BUTTON3_MASK) {
zoom_z -= (float) 0.1f * difx;

}else if (event->state & GDK_BUTTON1_MASK) {


/*rota la camara*/
angulo_xr += (float) 0.5f * dify;
angulo_yr += (float) 0.5f * difx;

}else if (event->state & GDK_BUTTON2_MASK) {


/*traslada la camara*/
ancho_x += (float) 0.1f * difx;
altura_y -= (float) 0.1f * dify;
}
reshape(ventanaw, ventanah);
dibujar();
return TRUE;
}
//Boton del Mouse presionado
gboolean on_glarea_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data){
/*se guarda la posicion del mouse*/
lastx= event->x;
lasty= event->y;
return TRUE;
}

//Tecla presionada
/*Se llama una funcin por cada tecla presionada dentro de la ventana OpenGL*/
gboolean on_glarea_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data){

event->keyval;

if(event->keyval==GDK_x){
printtv("\nDesplazar-->CAMARA");
mov_cam=1;
}else if(event->keyval==GDK_z){
printtv("\nRotar-->CAMARA");
mov_cam=2;
}else if(event->keyval==GDK_c){
91
printtv("\nObjeto Seleccionado-->CAMARA");
mover_obj=2;
}else if(event->keyval==GDK_r){
printtv("\nObjeto Seleccionado-->ROBOT");
mover_obj=1;
}else if(event->keyval==GDK_l){
if(lim==0){
lim=1;
}else {
lim=0;
}
}else if(mover_obj == 1){ /*se mueve el modelo del robot*/
if(event->keyval==GDK_y){
angulo5-=aument;
}else if(event->keyval==GDK_n){
angulo5+=aument;
}else if(event->keyval==GDK_j){
angulo4-=aument;
}else if(event->keyval==GDK_g){
angulo4+=aument;
}else if(event->keyval==GDK_o){
angulo6+=aument;
}else if(event->keyval==GDK_p){
angulo6-=aument;
}else if(event->keyval==GDK_a){
printtv("\nAUMENTAR VELOCIDAD ROBOT");
aument+=1;
if (aument > 45){
aument = 45;
}
}else if(event->keyval==GDK_d){
printtv("\nDISMINUIR VELOCIDAD ROBOT");
aument-=1;
if (aument < 1){
aument = 1;
}
}
}else if(mover_obj==2){ //*se mueve la camara en la escena*/
if(event->keyval==GDK_a){
printtv("\nAUMENTAR VELOCIDAD CAMARA");
aument_cam+=1;
if (aument_cam > 45){
aument_cam = 45;
}
}else if(event->keyval==GDK_d){
printtv("\nDISMINUIR VELOCIDAD CAMARA");
aument_cam-=1;
if (aument_cam < 1){
aument_cam = 1;
}
}
}
if(event->keyval==GDK_F1){
if(grid==0){
/*se activa la rejilla del piso*/
grid=1;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bgrid), TRUE);
}else {
/*se desactiva la rejilla*/
grid=0;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bgrid), FALSE);
}
}else if(event->keyval==GDK_F2){
if(checkmax==0){
92
/*se activa la opcin de limite de angulos mximos*/
checkmax=1;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bcheckmax), TRUE);
}else {
checkmax=0;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bcheckmax), FALSE);
}
}else if(event->keyval==GDK_F3){
if(checkcolision==0){
/* se activa la opcin de detencin de la sim. en el primer choque*/
checkcolision=1;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bcolision1), TRUE);
}else {
checkcolision=0;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bcolision1), FALSE);
}
}else if(event->keyval==GDK_F5){
printf("\nCREAR RUTINA");
crear_rutina();
}else if(event->keyval==GDK_F6){
printf("\nABRIR Y CARGAR RUTINA");
abrir_rutina();
}else if(event->keyval==GDK_F7){
printf("\nSALVAR RUTINA");
salvar_rutina();
}else if(event->keyval==GDK_F8){
printtv("\nEJECUTAR RUTINA");
ejecutar_rutina();
}else if(event->keyval==GDK_F9){
printtv("\nAPILAR POSICION");
push_posicion();
dibujar();
}else if(event->keyval==GDK_F10){
printtv("\nDESAPILAR POSICION");
pull_posicion();
dibujar();
}else if(event->keyval==GDK_F11){
printtv("\nREINICIAR PILA");
reiniciar_pila();
}else if(event->keyval==GDK_F12){
printf("\nInformacin:");
printf("\nAngulos: A1 %.0f, A2 %.0f, A3 %.0f, A4 %.0f, A5 %.0f, A6 %.0f\n", angulo1,-1*angulo2,-
1*angulo3,angulo4,-1*angulo5,angulo6);
}
if(mover_obj == 1){/*se mueve el robot*/
if(event->keyval==GDK_Up){
angulo2-=aument;
}else if(event->keyval==GDK_Down){
angulo2+=aument;
}else if(event->keyval==GDK_Right){
angulo1-=aument;
}else if(event->keyval==GDK_Left){
angulo1+=aument;
}else if(event->keyval==GDK_Page_Up){
angulo3-=aument;
}else if(event->keyval==GDK_Page_Down){
angulo3+=aument;
}
}else if(mover_obj== 2){/*se mueve la camara*/
if(event->keyval==GDK_Page_Up){
zoom_z-=1;
}else if(event->keyval==GDK_Page_Down){
zoom_z+=1;
}else if(mov_cam==1){
93
if(event->keyval==GDK_Up){
altura_y+=aument_cam;
}else if(event->keyval==GDK_Down){
altura_y-=aument_cam;
}
}else if(mov_cam==2){
if(event->keyval==GDK_Up){
angulo_xr+=aument_cam;
}else if(event->keyval==GDK_Down){
angulo_xr-=aument_cam;
}else if(event->keyval==GDK_Right){
angulo_yr+=aument_cam;
}else if(event->keyval==GDK_Left){
angulo_yr-=aument_cam;
}
}
reshape(ventanaw, ventanah);
}
if(event->keyval==GDK_Home){
printtv("\nREINICIANDO ROBOT");
mover_obj = 1;
valores_iniciales_robot();//REINICIAR POSICION ROBOT

}else if(event->keyval==GDK_End){
printtv("\nREINICIANDO CAMARA");
valores_iniciales_camara();//REINICIAR POSICION CAMARA
reshape(ventanaw, ventanah);
}
dibujar();
return TRUE;
}

gboolean on_glarea_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data){


/*se da un evento de exposicin , la escena se dibuja de nuevo*/
dibujar();
return TRUE;
}

gboolean on_glarea_configure_event (GtkWidget* widget, GdkEventConfigure* event) {


/*se cambio el tamao de la ventana, se llama a la funcin de ajuste de ventana: reshape*/
ventanaw = widget->allocation.width;
ventanah = widget->allocation.height;
reshape(ventanaw, ventanah);
return TRUE;
}

gboolean glarea_init (GtkWidget* widget) {


/*la ventana esta lista para ser iniciada: se llama a la funcin inicio()*/
inicio();
return TRUE;
}

void on_bsim_clicked(GtkButton *button, gpointer user_data){


/*Simula el movimiento del robot utilizando los valores de los botones 'spinner'*/
GtkSpinButton *spin1, *spin2, *spin3;
int velocporciento;

spin1=GTK_SPIN_BUTTON(spinbutton1);
spin2=GTK_SPIN_BUTTON(spinbutton2);
spin3=GTK_SPIN_BUTTON(spinbutton3);

hubochoque=0;

/*Toma los valores de los botones 'spinners'*/


94
joint = gtk_spin_button_get_value_as_int(spin1);
angulodelta = gtk_spin_button_get_value_as_int(spin2);
velocporciento=gtk_spin_button_get_value_as_int(spin3);
set_velocidad(velocporciento, joint);

/*simula el movimiento*/
selec_mover_joint();
if(hubochoque==1){
printtv("\n\nCUIDADO!!!-->Se produjo un choque durante la simulacin del movimiento");
}

}
/* Informacin del Programa*/
void on_bacerca_clicked(GtkButton *button, gpointer user_data){
GtkWidget *mensaje;

mensaje = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,


GTK_BUTTONS_CLOSE,
"Programa (Program): SimQNK \nSimulador del brazo Robot Stubli RX90L (Robotic Arm Simulator)\nAutor
(developer): David Cuenca Alpzar\nJunio 2006 (June 2006)\n(C) Copyright 2006\nE-mail: dcuenc@gmail.com",
NULL);
gtk_widget_show(mensaje);
/* Destruir Ventana de mensaje al presionar el botn */
g_signal_connect_swapped (mensaje, "response",
G_CALLBACK (gtk_widget_destroy),
mensaje);
}

/*************************************************************************************************************/

dibujo.c: Funciones de despliegue de la escena virtual y de pruebas de colisin

/***************************************************************************
* SimQNK
* Simulador virtual del brazo robot Stubli RX90 L
* dibujo.c: funciones de dibujo y pruebas de colision del modelo 3D
* Copyright(C) 2006 David Cuenca
* Email: dcuenc@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "dibujo.h"

#define BASE 1
#define BRAZO1 2
#define BRAZO2 4
#define CODO 3
#define MUNIECA 5
95
#define MANO 6
#define ESFERA 7
#define CUBO 8
#define HOMBRO 9
#define EMPO 10

//Vectores para prueba de colision


float menorz [4];
float menory [4];
float menorz2 [5];
float menory2 [5];
float vortexm [4];
/*Vectores de las orillas de choque del hombro*/
float vortexfijo1 [3] = {0, 28.5, 13.1};
float vortexfijo2 [3] = {0, 54.5, 13.1};

//Constantes para prueba de colision


float nively1=28.5;
float nively2=54.5;
float zhombro=13.1;
float numpuntos=30;
int choquep; //control de choque contra el piso
int choqueb; //control de choque contra la base
int choqueh; //control de choque contra el hombro
int choquev; //control de choque contra los vortices del hombro
float radbase=12;
int npuntos=30;
//Punteros de control de colision
int i;
int j;
int n;
int cuidado;

//Vectores para multiplicar matrices


float vtemp [4];
float vectr[4];

//Figuras de control
float circHB [31][4];
float circHA [31][4];
float circWA [31][4];
float circWB [31][4];
float circWC [31][4];
float circBD [31][4];
float circBC [31][4];
float cuadBA [5][4]={0,0,0,0, 6.6,-15,-5.7,1, -5.7,-15,-5.7,1, -5.7,-15,5.7,1, 6.6,-15,5.7,1};
float cuadBB [5][4]={0,0,0,0, 12,-10,-11.1,1, -10.2,-10,-11.1,1, -10.2,-10,11.1,1, 12,-10,11.1,1};
float cuadBC [5][4]={0,0,0,0, 12,10,-11.1,1, -10.2,10,-11.1,1, -10.2,10,11.1,1, 12,10,11.1,1};
float circHBreal [31][4];
float circHAreal [31][4];
float circWAreal [31][4];
float circWBreal [31][4];
float circWCreal [31][4];
float circBDreal [31][4];
float circBCreal [31][4];
float cuadBAreal [5][4];
float cuadBBreal [5][4];
float cuadBCreal [5][4];

//Puntos de control
float CHB [5]={0.0, 8.5, 0.0, 1, 5};
float CHA [5]={0.0, 5.6, 0.0, 1, 5};
float CWA [5]={-5.5, 55.0, 0.0, 1, 4};
float CWB [5]={0.0, 55.0, 0.0, 1, 4};
96
float CWC [5]={5.5, 55.0, 0.0, 1, 4};
float CBA [5]={0.0, -15, 0.0, 1, 3};
float CBB [5]={0.0, -10, 0.0, 1, 3};
float CBC [5]={0.0, 10, 0.0, 1, 3};
float CBD [5]={0.0, 58, 0.0, 1, 3};
float CHBreal [3];
float CHAreal [3];
float CWAreal [3];
float CWBreal [3];
float CWCreal [3];
float CBAreal [3];
float CBBreal [3];
float CBCreal [3];
float CBDreal [3];

//Matrices de rotacion y traslacion


float rotx2 [4][4] = {1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1};//rotacion en x angulo2
float rotx3 [4][4] = {1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1};//rotacion en x angulo3
float rotx5 [4][4] = {1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1};//rotacion en x angulo5
float roty4 [4][4] = {0,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,1};//rotacion en y angulo4
float tras1 [4][4] = {1,0,0,0, 0,1,0,42, 0,0,1,0, 0,0,0,1};//traslacion
float tras2 [4][4] = {1,0,0,0, 0,1,0,45, 0,0,1,0, 0,0,0,1};
float tras3 [4][4] = {1,0,0,0, 0,1,0,10, 0,0,1,0, 0,0,0,1};//traslacion
float tras4 [4][4] = {1,0,0,0, 0,1,0,55, 0,0,1,0, 0,0,0,1};

/*Valores de posicion inicial del robot*/


void valores_iniciales_robot(void){
printf("\nObjeto Seleccionado--> ROBOT");
angulo1 = 0;
angulo2 = 0;
angulo3 = 0;
angulo4 = 0;
angulo5 = 0;
angulo6 = 0;
aument = 1;
}

/*Llenar Matrices de rotacion*/


void llenar_matrices_rot(void){

rotx2[1][1]=cos(angulo2*M_PI/180);
rotx2[1][2]=(-1)*sin(angulo2*M_PI/180);
rotx2[2][1]=sin(angulo2*M_PI/180);
rotx2[2][2]=cos(angulo2*M_PI/180);

rotx3[1][1]=cos(angulo3*M_PI/180);
rotx3[1][2]=(-1)*sin(angulo3*M_PI/180);
rotx3[2][1]=sin(angulo3*M_PI/180);
rotx3[2][2]=cos(angulo3*M_PI/180);

rotx5[1][1]=cos(angulo5*M_PI/180);
rotx5[1][2]=(-1)*sin(angulo5*M_PI/180);
rotx5[2][1]=sin(angulo5*M_PI/180);
rotx5[2][2]=cos(angulo5*M_PI/180);

roty4[0][0]=cos(angulo4*M_PI/180);
roty4[0][2]=sin(angulo4*M_PI/180);
roty4[2][0]=(-1)*sin(angulo4*M_PI/180);
roty4[2][2]=cos(angulo4*M_PI/180);

}
/*Llenar los vectores de posicin de la orillas del hombro fijos*/
void init_vortexfijos(float margen){
97
vortexfijo1[1]=28.5-(margen/2);
vortexfijo1[2]=13.1+(margen/2);
vortexfijo2[1]=54.5+(margen/2);
vortexfijo2[2]=13.1+(margen/2);
}

/*DIBUJAR Linea de control de la prueba de colision de orillas*/


void dibujarvortex(float numero1[], float numero2[]){
glPushMatrix();
glRotatef(angulo1, 0, 1, 0);
glBegin(GL_LINES);
glVertex3f(numero1[0], numero1[1], numero1[2]);
glVertex3f(numero2[0], numero2[1], numero2[2]);
glEnd();
glPopMatrix();
}

/*Multiplicacion Matriz(4x4) x Vector(4)*/


void mult_mat_vect(float mat[4][4],float vect[5]){
for(i=0; i<4; i++){
vectr[i]=mat[i][0]*vect[0]+mat[i][1]*vect[1]+mat[i][2]*vect[2]+mat[i][3]*vect[3];
}
}

/*Pasar a Vtemp. Vetor temporal*/


void llenar_vtemp(void){
for(i=0;i<4;i++){
vtemp[i]=vectr[i];
}
}

/*Pasar punto de coordenadas locales a coordenas globales*/


void coord_globales_pta(float numero[5], float numreal[3]){
int s;
s=numero[4];//Nivel de jeraqua del sistema de coordenadas

llenar_matrices_rot();
/*Concatenacin de matrices para nivel de jerarquia 5*/
if(s==5){
mult_mat_vect(rotx5, numero);
llenar_vtemp();
mult_mat_vect(tras4, vtemp);
llenar_vtemp();
mult_mat_vect(roty4, vtemp);
llenar_vtemp();
mult_mat_vect(tras3, vtemp);
llenar_vtemp();
mult_mat_vect(rotx3, vtemp);
llenar_vtemp();
mult_mat_vect(tras2, vtemp);
llenar_vtemp();
mult_mat_vect(rotx2, vtemp);
llenar_vtemp();
mult_mat_vect(tras1, vtemp);
for(j=0;j<4;j++){
numreal[j]=vectr[j];
}
}
/*Concatenacin de matrices para nivel de jerarquia 4*/
if(s==4){
mult_mat_vect(roty4, numero);
llenar_vtemp();
mult_mat_vect(tras3, vtemp);
llenar_vtemp();
98
mult_mat_vect(rotx3, vtemp);
llenar_vtemp();
mult_mat_vect(tras2, vtemp);
llenar_vtemp();
mult_mat_vect(rotx2, vtemp);
llenar_vtemp();
mult_mat_vect(tras1, vtemp);
for(j=0;j<4;j++){
numreal[j]=vectr[j];
}
}
/*Concatenacin de matrices para nivel de jerarquia 3*/
if(s==3){
mult_mat_vect(rotx3, numero);
llenar_vtemp();
mult_mat_vect(tras2, vtemp);
llenar_vtemp();
mult_mat_vect(rotx2, vtemp);
llenar_vtemp();
mult_mat_vect(tras1, vtemp);
for(j=0;j<4;j++){
numreal[j]=vectr[j];
}
}
}

/*Comparar pendientes de la prueba de colision de orillas (VORTEX)*/


void vortex_test(float numero1[4], float numero2[4], float numero3[3], int mayor){

if((numero1[2]!=numero2[2]) && (numero1[2]!=numero3[2])){


/*Calcular la pendiente de la liena de control*/
float pendiente1 = (numero2[1]-numero1[1])/(numero2[2]-numero1[2]);
float pendiente2;

/*Prueba sobre las orillas inferiores*/


if(mayor==1){
if((pendiente1>0) && (numero1[2]>0)){
/*Calcular la pendiente de la linea al hombro (rango z positivo:orilla derecha)*/
pendiente2 = (numero3[1]-numero1[1])/(numero3[2]-numero1[2]);
if((pendiente1 >= pendiente2) && (pendiente2 > 0)){
choquev=1;
}
}
if((pendiente1<0) && (numero1[2]<0)){
/*Calcular la pendiente de la linea al hombro (rango z negativo:orilla izquierda)*/
pendiente2 = (numero3[1]-numero1[1])/((-1)*numero3[2]-numero1[2]);
if((pendiente1 <= pendiente2) && (pendiente2 < 0)){
choquev=1;
}
}
}
/*Prueba sobre las orillas inferiores*/
else if(mayor==2){
if((pendiente1>0) && (numero1[2]<0)){
/*Calcular la pendiente de la linea al hombro (rango z negativo:orilla izquierda)*/
pendiente2 = (numero3[1]-numero1[1])/((-1)*numero3[2]-numero1[2]);
if((pendiente1 <= pendiente2) && (pendiente2 > 0)){
choquev=1;
}
}
if((pendiente1<0) && (numero1[2]>0)){
/*Calcular la pendiente de la linea al hombro (rango z positivo:orilla derecha)*/
pendiente2 = (numero3[1]-numero1[1])/(numero3[2]-numero1[2]);
if((pendiente1 >= pendiente2) && (pendiente2 < 0)){
99
choquev=1;
}
}
if(pendiente1==0){
if(numero1[1] <= numero3[1]){
choquev=1;
}
}
}
}
}

/*Buscar el mismo punto en otra figura de control*/


void mismo_pt_a2(float numero[4], float array[][4], float numsalida[5]){
int n;
n=numero[3],
numsalida[0]=array[n][0];
numsalida[1]=array[n][1];
numsalida[2]=array[n][2];
numsalida[3]=array[n][3];
numsalida[4]=array[0][0];
}

//Buscar el punto con el menor valor de Z


void pila_menorz(float array[][4]){
menorz[0]=0; //valor x
menorz[1]=0; //valor y
menorz[2]=40; //valor z
menorz[3]=0; //# del numero en el array

numpuntos=array[0][1];

for(i=1; i<=numpuntos; i++){

if(fabs(array[i][2])<=fabs(menorz[2])){
menorz[0]=array[i][0];
menorz[1]=array[i][1];
menorz[2]=array[i][2];
menorz[3]=i;
}
}
}

//Buscar el punto con el menor valor de Y


void pila_menory(float array[][4]){
menory[0]=0; //valor x
menory[1]=300; //valor y
menory[2]=0; //valor z
menory[3]=0; //# del numero en el array

numpuntos=array[0][1];

for(i=1; i<=numpuntos; i++){


if(array[i][1]<=menory[1]){
menory[0]=array[i][0];
menory[1]=array[i][1];
menory[2]=array[i][2];
menory[3]=i;
}
}
}

//Prueba de choque contra la base


void lim_radiobase(float array[][4],float radiobase, float margen){
100
float radio;
numpuntos=array[0][1];
for(i=1; (i<=numpuntos)&&(choqueb!=1); i++){
radio=sqrt(pow(array[i][0],2)+pow(array[i][2],2));
if(radio <= radiobase+margen){
choqueb=1;
}
}
}

//Pruebar choque contra el piso


void lim_piso(float array[][4], float margen){
numpuntos=array[0][1];
for(i=1; (i<=numpuntos)&&(choquep!=1); i++){
if(array[i][1] <=(altpiso+margen)){
choquep=1;
}
}
}

//Prueba choque contra el hombro


void lim_box_yz(float array[][4], float margen, float y1, float y2, float z){
numpuntos=array[0][1];
for(i=1; (i<=numpuntos)&&(choqueh!=1); i++){
if((array[i][1]>=y1-margen) && (array[i][1]<=y2+margen) && (abs(array[i][2])<=z+margen)){
choqueh=1;
}
}
}

//Pasar todos puntos del array a coordenadas globales y guardarlo en arrayreal


void coord_globales(float array[][4], float arrayreal[][4]){
int s=array[0][0]; //Nivel de jerarqua de los puntos
numpuntos=array[0][1];
llenar_matrices_rot();

arrayreal[0][0]=array[0][0];
arrayreal[0][1]=array[0][1];
/*Concatenacin de matrices para nivel de jerarqua 5*/
if(s==5){
for(n=1; n<=numpuntos; n++){
mult_mat_vect(rotx5, array[n]);
llenar_vtemp();
mult_mat_vect(tras4, vtemp);
llenar_vtemp();
mult_mat_vect(roty4, vtemp);
llenar_vtemp();
mult_mat_vect(tras3, vtemp);
llenar_vtemp();
mult_mat_vect(rotx3, vtemp);
llenar_vtemp();
mult_mat_vect(tras2, vtemp);
llenar_vtemp();
mult_mat_vect(rotx2, vtemp);
llenar_vtemp();
mult_mat_vect(tras1, vtemp);
for(j=0;j<4;j++){
arrayreal[n][j]=vectr[j];
}
}
}
/*Concatenacin de matrices para nivel de jerarqua 4*/
if(s==4){
for(n=1; n<=numpuntos; n++){
101
mult_mat_vect(roty4, array[n]);
llenar_vtemp();
mult_mat_vect(tras3, vtemp);
llenar_vtemp();
mult_mat_vect(rotx3, vtemp);
llenar_vtemp();
mult_mat_vect(tras2, vtemp);
llenar_vtemp();
mult_mat_vect(rotx2, vtemp);
llenar_vtemp();
mult_mat_vect(tras1, vtemp);
for(j=0;j<4;j++){
arrayreal[n][j]=vectr[j];
}
}
}
/*Concatenacin de matrices para nivel de jerarqua 4*/
if(s==3){
for(n=1; n<=numpuntos; n++){
mult_mat_vect(rotx3, array[n]);
llenar_vtemp();
mult_mat_vect(tras2, vtemp);
llenar_vtemp();
mult_mat_vect(rotx2, vtemp);
llenar_vtemp();
mult_mat_vect(tras1, vtemp);
for(j=0;j<4;j++){
arrayreal[n][j]=vectr[j];
}
}
}
}

//Preparar prueba de choque contra el hombro


void check_boundingH(float array[][4], float arrayreal[][4]){
choqueh=0;
coord_globales(array, arrayreal);
lim_box_yz(arrayreal, marg, nively1, nively2, zhombro);
if(choqueh==1){
printf("\nCHOQUE HOMBRO");
}
}

//Preparar prueba de choque contra el vortice


void check_vortex(float array1[][4], float array2[][4], float arrayreal1[][4], int nivel){
choquev=0;
coord_globales(array1,arrayreal1);

if(nivel==1){
pila_menorz(arrayreal1);
mismo_pt_a2(menorz, array2, menorz2);
coord_globales_pta(menorz2, vortexm);
dibujarvortex(menorz,vortexm);
vortex_test(menorz, vortexm, vortexfijo1, 1);
if(choquev==1){
printf("\nCHOQUE Orilla INFERIOR del HOMBRO");
}
}
if(nivel==2){
pila_menory(arrayreal1);
mismo_pt_a2(menory, array2, menory2);
coord_globales_pta(menory2, vortexm);
dibujarvortex(menory,vortexm);
vortex_test(menory, vortexm, vortexfijo2, 2);
102
if(choquev==1){
printf("\nCHOQUE Orilla SUPERIOR del HOMBRO");
}
}
}

//Preparar prueba de choque contra la base


void check_base(float array[][4], float arrayreal[][4]){
choqueb=0;
coord_globales(array, arrayreal);
lim_radiobase(arrayreal, radbase, marg);
if(choqueb==1){
printf("\nCHOQUE BASE");
}
}

//Preparar prueba de choque contra el piso


void check_piso(float array[][4], float arrayreal[][4]){
choquep=0;
coord_globales(array, arrayreal);
lim_piso(arrayreal, marg);
if(choquep==1){
printf("\nCHOQUE PISO");
}
}

//Crear las figuras de control


void crear_controles(void){
//Crear circulos, cuadrados y puntos de control
float dif=2*M_PI/npuntos;
float alpha;
alpha=0;

circHA[0][0]=5;//Nivel del sistema de coordenadas de cada figura de control


circHB[0][0]=5;
circWA[0][0]=4;
circWB[0][0]=4;
circWC[0][0]=4;
circBD[0][0]=4;
circBC[0][0]=4;
cuadBA[0][0]=3;
cuadBB[0][0]=3;
cuadBC[0][0]=3;

circHA[0][1]=npuntos;//Numero de puntos de cada figura de control


circHB[0][1]=npuntos;
circWA[0][1]=npuntos;
circWB[0][1]=npuntos;
circWC[0][1]=npuntos;
circBD[0][1]=npuntos;
circBC[0][1]=npuntos;
cuadBA[0][1]=4;
cuadBB[0][1]=4;
cuadBC[0][1]=4;

//CIRULOS
for(i=1; i<=npuntos; i++){
circHA[i][0]=(3*sin(alpha));//coord. x del punto 1 (local)
circHA[i][1]=5.6;//coord. y del punto 1 (local)
circHA[i][2]=(3*cos(alpha));//coord. z del punto 1 (local)
circHA[i][3]=1;//indica que es un punto

circHB[i][0]=(3*sin(alpha));
circHB[i][1]=8.5;
103
circHB[i][2]=(3*cos(alpha));
circHB[i][3]=1;

circWA[i][0]=-5.5;
circWA[i][1]=(55+5*sin(alpha));
circWA[i][2]=(5*cos(alpha));
circWA[i][3]=1;

circWB[i][0]=0;
circWB[i][1]=(55+5*sin(alpha));
circWB[i][2]=(5*cos(alpha));
circWB[i][3]=1;

circWC[i][0]=5.5;
circWC[i][1]=(55+5*sin(alpha));
circWC[i][2]=(5*cos(alpha));
circWC[i][3]=1;

circBD[i][0]=(8.3*sin(alpha));
circBD[i][1]=48;
circBD[i][2]=(0.7+8.3*cos(alpha));
circBD[i][3]=1;

circBC[i][0]=(9*sin(alpha));
circBC[i][1]=0;
circBC[i][2]=(0.7+9*cos(alpha));
circBC[i][3]=1;

alpha+=dif;
}
}

//Dibujar las figuras de control


void dibujar_circHA(void){
numpuntos=circHA[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glTranslatef(0.0, 55.0, 0.0);
glRotatef(angulo5, 1.0, 0.0, 0.0);
glBegin( GL_LINE_LOOP );
for(i=1; i<=numpuntos; i++){
glVertex3f(circHA[i][0],circHA[i][1],circHA[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_circHB(void){
numpuntos=circHB[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
104
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glTranslatef(0.0, 55.0, 0.0);
glRotatef(angulo5, 1.0, 0.0, 0.0);
glBegin( GL_LINE_LOOP );
for(i=1; i<=numpuntos; i++){
glVertex3f(circHB[i][0],circHB[i][1],circHB[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_circWA(void){
numpuntos=circWA[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(circWA[i][0],circWA[i][1],circWA[i][2]);
}
glEnd();
glPopMatrix();

void dibujar_circWB(void){
numpuntos=circWB[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(circWB[i][0],circWB[i][1],circWB[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_circWC(void){
numpuntos=circWC[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
105
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(circWC[i][0],circWC[i][1],circWC[i][2]);
}
glEnd();
glPopMatrix();

}
void dibujar_circBC(void){
numpuntos=circBC[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(circBC[i][0],circBC[i][1],circBC[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_circBD(void){
numpuntos=circBD[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glTranslatef(0.0, 10.0, 0.0);
glRotatef(angulo4, 0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(circBD[i][0],circBD[i][1],circBD[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_cuadBA(void){
numpuntos=cuadBA[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
106
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(cuadBA[i][0],cuadBA[i][1],cuadBA[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_cuadBB(void){
numpuntos=cuadBB[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(cuadBB[i][0],cuadBB[i][1],cuadBB[i][2]);
}
glEnd();
glPopMatrix();
}

void dibujar_cuadBC(void){
numpuntos=cuadBC[0][1];

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glRotatef(angulo2, 1.0, 0.0, 0.0);
glTranslatef(0.0, 45.0, 0.0);
glRotatef(angulo3, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
for(i=1; i<=numpuntos; i++){
glVertex3f(cuadBC[i][0],cuadBC[i][1],cuadBC[i][2]);
}
glEnd();
glPopMatrix();
}

//Pasar los puntos de control a coordenadas globales


void coord_globales_pts_control(void){
/* coordenas globales de solo los puntos de control
* CHB, CHA, CWA, CWC, CWB, CBA, CBB, CBC, CBD, CBE*/
coord_globales_pta(CHB, CHBreal);
coord_globales_pta(CHA, CHAreal);
coord_globales_pta(CWA, CWAreal);
coord_globales_pta(CWB, CWBreal);
coord_globales_pta(CWC, CWCreal);
coord_globales_pta(CBA, CBAreal);
coord_globales_pta(CBB, CBBreal);
coord_globales_pta(CBC, CBCreal);
coord_globales_pta(CBD, CBDreal);
107
}
/*Verificar si se cumplen las condiciones para realizar alguna de las pruebas de colision*/
void probar_colision(float margen){

coord_globales_pts_control(); /*pasar los puntos de control a coord globales*/

float radchb;
float acwaz;
float acwbz;
float acwcz;
float acbez;
float acbdz;
float acbcz;
float acbbz;
float acbaz;
float achbz;
float achaz;

choque=choquep=choqueb=choqueh=choquev=0;
cuidado=0;
/*distancia del punto de control CHB al eje Y*/
radchb=sqrt(pow(CHBreal[2],2)+pow(CHBreal[0],2));
/*Valor absoluto de la coordena Z de los putnos de control*/
acwaz=fabs(CWAreal[2]);
acwbz=fabs(CWBreal[2]);
acwcz=fabs(CWCreal[2]);
acbdz=fabs(CBDreal[2]);
acbcz=fabs(CBCreal[2]);
acbbz=fabs(CBBreal[2]);
acbaz=fabs(CBAreal[2]);
achbz=fabs(CHBreal[2]);
achaz=fabs(CHAreal[2]);

//PISO
/*Verificar algun punto de control entro al area de precaucin del piso*/
if(CBAreal[1] <= (6+margen)){
dibujar_cuadBA();
check_piso(cuadBA, cuadBAreal);
cuidado=1;
}
if((CBBreal[1] <= (11.5+margen)) && (CBBreal[1] <= CBCreal[1])){
dibujar_cuadBB();
check_piso(cuadBB, cuadBBreal);
cuidado=1;
}
if((CBCreal[1] <= (11.5+margen)) && (CBCreal[1] < CBBreal[1])){
dibujar_cuadBC();
check_piso(cuadBC, cuadBCreal);
cuidado=1;
}
if((CWAreal[1] <= (5.5+margen)) && (CWAreal[1] <= CWCreal[1])){
dibujar_circWA();
check_piso(circWA, circWAreal);
cuidado=1;
}
if((CWCreal[1] <= (5.5+margen)) && (CWCreal[1] < CWAreal[1])){
dibujar_circWC();
check_piso(circWC, circWCreal);
cuidado=1;
}
if(CHBreal[1] <= (3.5+margen)){
dibujar_circHB();
check_piso(circHB, circHBreal);
108
cuidado=1;
}

//BASE
/*Verificar algun punto de control entro al area de precaucin de la base*/
if((CHBreal[1]<25.5) && (radchb<=15.5+margen)){
dibujar_circHB();
check_base(circHB, circHBreal);
cuidado=1;
}
if((CWAreal[1]<23.5) && (acwaz<=17.5+margen)){
dibujar_circWA();
check_base(circWA, circWAreal);
cuidado=1;
}
if((CWBreal[1]<23.5) && (acwbz<=17.5+margen)){
dibujar_circWB();
check_base(circWB, circWBreal);
cuidado=1;
}
if((CWCreal[1]<23.5) && (acwcz<=17.5+margen)){
dibujar_circWC();
check_base(circWC, circWCreal);
cuidado=1;
}
if((CBDreal[1]<28.5) && (acbdz<=21+margen)){
dibujar_circBD();
check_base(circBD, circBDreal);
cuidado=1;
}
if((CBAreal[1]<28.5) && (acbaz<=25+margen)){
dibujar_cuadBA();
cuidado=1;
choqueh=0;
coord_globales(cuadBA, cuadBAreal);
lim_box_yz(cuadBAreal, marg, altpiso, nively1, radbase);
if(choqueh==1){
printf("CHOQUE BASE\n");
}
}
if((CBBreal[1]<28.5) && (acbbz<=25+margen)){
dibujar_cuadBB();
cuidado=1;
choqueh=0;
coord_globales(cuadBB, cuadBBreal);
lim_box_yz(cuadBBreal, marg, altpiso, nively1, radbase);
if(choqueh==1){
printf("CHOQUE BASE\n");
}
}

//HOMBRO

//VORTEX nivel 1 (hombro)


/*Verificar si se cumplen las condiciones para que este cerca una colision en las orillas inferiores*/
if((CBDreal[1]<28.5) && (CBCreal[1]>18.0) && (acbdz<=40+margen)){
dibujar_circBD();
check_vortex(circBD, circBC, circBDreal, 1);
cuidado=1;
}
//VORTEX nivel 2
/*Verificar si se cumplen las condiciones para que se de una posible colision en las orillas superiores*/
if((CBDreal[1]<=65) && (CBCreal[1]>54.5) && (acbcz<=40.0+margen)){
dibujar_circBD();
109
check_vortex(circBD, circBC, circBDreal, 2);
cuidado=1;
}
if((CBCreal[1]<=65) && (CBDreal[1]>54.5) && (acbdz<=40+margen)){
dibujar_circBC();
check_vortex(circBC, circBD, circBCreal, 2);
cuidado=1;
}

//ALGUN CHOQUE?
/*Si se dio algun choque se llena la variable de hubochoque y la de choque*/
if((choquep==1) || (choqueb==1) || (choqueh==1) || (choquev==1)){
choque=1;
hubochoque=1;
}
}

//Verificar angulo mximo de las articulacines


void check_maximo(void){
int numart;
angmax=0;

if(angulo1<(-160)){
numart=1;
angmax=1;
angulo1=-160;
}else if(angulo1>160){
numart=1;
angmax=1;
angulo1=160;
}
if(angulo2<(-137.5)){
numart=2;
angmax=1;
angulo2=-137.5;
}else if(angulo2>137.5){
numart=2;
angmax=1;
angulo2=137.5;
}
if(angulo3<(-142.5)){
numart=3;
angmax=1;
angulo3=-142.5;
}else if(angulo3>142.5){
numart=3;
angmax=1;
angulo3=142.5;
}
if(angulo4<(-270)){
numart=4;
angmax=1;
angulo4=-270;
}else if(angulo4>270){
numart=4;
angmax=1;
angulo4=270;
}
if(angulo5<(-120)){
numart=5;
angmax=1;
angulo5=-120;
}else if(angulo5>105){
numart=5;
110
angmax=1;
angulo5=105;
}
if(angulo6<(-270)){
numart=6;
angmax=1;
angulo6=-270;
}else if(angulo6>270){
numart=6;
angmax=1;
angulo6=270;
}
if(angmax==1){
printf("\nArticulacin %d alcanzo su mxima amplitud de giro",numart);
}
}
//Limites geomtricos del modelo
/*Herramienta para el desarrollador o modelador*/
void dibujar_limites(void){
//Verticales
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(-26.8, 0, 0);
glVertex3f(-26.8, 180, 0);
glVertex3f(-12.7, 0, 0);
glVertex3f(-12.7, 180, 0);
glVertex3f(15, 0, 0);
glVertex3f(15, 180, 0);
glVertex3f(11.9, 0, 0);
glVertex3f(11.9, 180, 0);
glVertex3f(0, 0, 0);
glVertex3f(0, 200, 0);
glVertex3f(-5.4, 132, 0);
glVertex3f(-5.4, 150, 0);
glVertex3f(5.4, 132, 0);
glVertex3f(5.4, 150, 0);
glVertex3f(0, 0, 13);
glVertex3f(0, 180, 13);
glVertex3f(0, 0, -13);
glVertex3f(0, 180, -13);
glVertex3f(0, 54, 11);
glVertex3f(0, 180, 11);
glVertex3f(0, 54, -11);
glVertex3f(0, 180, -11);
glEnd();
glPopMatrix();

//HORIZONTALES
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(-20, 42.0, 0);
glVertex3f(20, 42.0, 0);
glVertex3f(-20, 54.5, 0);
glVertex3f(20, 54.5, 0);
glVertex3f(-20, 71.7, 0);
glVertex3f(20, 71.7, 0);
glVertex3f(-20, 87, 0);
glVertex3f(20, 87, 0);
glVertex3f(-20, 96.7, 0);
glVertex3f(20, 96.7, 0);
glVertex3f(-20, 111, 0);
glVertex3f(20, 111, 0);
111
glVertex3f(-20, 152, 0);
glVertex3f(20, 152, 0);
glEnd();
glPopMatrix();
}

//SEAL DE PRECAUCION
/*Esferas de colores que indican el riesgo del movimiento actual*/
void semaforo(void){
GLUquadricObj *quadObj1;
float semaf_x;
float semaf_y;
float color[3];

semaf_x=140*ventanaw/ventanah;

quadObj1 = gluNewQuadric();

if(choque==1){
color[0]=1.0; color[1]=0.0; color[2]=0.0;
semaf_y=150;
}else if(cuidado==1){
color[0]=1.0; color[1]=0.9; color[2]=0.0;
semaf_y=140;
}else{
color[0]=0.0; color[1]=1.0; color[2]=0.5;
semaf_y=130;
}
glPushMatrix();
glColor3fv(color);
glRotatef(-1*angulo_yr, 0.0, 1.0, 0.0);
glTranslatef(-1*ancho_x, -1*altura_y, 0.0);
glRotatef(-1*angulo_xr, 1.0, 0.0, 0.0);
glTranslatef(semaf_x*zoom_z/160, semaf_y*zoom_z/160, 600.0);
gluSphere(quadObj1, 7*zoom_z/160, 30, 30);
glPopMatrix();
}

//----------------------DIBUJAR ESCENA----------------------------------------
gboolean dibujar(void){

/*Buscar area OpenGL*/


GdkGLContext *glcontext = gtk_widget_get_gl_context (glarea1);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (glarea1);

/*** OpenGL INICIO ***/


if (!gdk_gl_drawable_make_current(gldrawable, glcontext)){
printf("\nError al buscar area OpenGL. Se crea la ventana nuevamente");

/* Error al buscar el area GL. Se crea la ventana 2 nuevamente y se vuelve a intentar*/


ventana2 = create_window2 ();
gtk_widget_show (ventana2);
printf("\nCreando area de nuevo");
glcontext = gtk_widget_get_gl_context (glarea1);
gldrawable = gtk_widget_get_gl_drawable (glarea1);

/* Si el error se da nuevamente, se retorna el valor FALSE*/


if (!gdk_gl_drawable_make_current(gldrawable, glcontext)){
printf("\nError al buscar area OpenGL. Segundo Intento");
return FALSE;
}
}
/*Limpiar los buffers de profundidad y color*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
112
glLoadIdentity();

if(checkmax==1){
/*limita los angulos de giro a sus amplitudes mximas*/
check_maximo();
}

/*Dibujar piso en forma de rejilla*/


if(grid==1){
// GRID
glBegin(GL_LINES);
glColor3f(0.0, 0.1, 1.0);
glNormal3f(0.0, 1.0, 0.0);
int i;
for(i=-300;i<=300;i+=30) {
glVertex3f(i,altpiso,-300);
glVertex3f(i,altpiso,300);
glVertex3f(300,altpiso,i);
glVertex3f(-300,altpiso,i);
}
glEnd();
}else {
//PISO
/*Dibujar piso en forma poligono solido*/
glBegin(GL_QUADS);
glColor3f(0.9, 0.9, 0.9);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-500.0f, altpiso, -500.0f);
glVertex3f(-500.0f, altpiso, 500.0f);
glVertex3f(500.0f, altpiso, 500.0f);
glVertex3f(500.0f, altpiso, -500.0f);
glEnd();
}
/*Base externa sobre la cual se monta el brazo (opcional)*/
GLUquadricObj *quadObj1;
quadObj1 = gluNewQuadric();
glPushMatrix();
glColor3f(0.1, 0.1, 1.0);
glRotatef(90, 1.0, 0.0, 0.0);
gluCylinder(quadObj1, 12, 12, -1*altpiso, 30, 30);
glPopMatrix();

/*Posicionar y dibujar los componentes del brazo en la escena*/


glColor3f(0.7, 0.8, 0.7);
//BASE
glPushMatrix();
glTranslatef(0.0, 0.0, 0.0);
glCallList(BASE);
glPopMatrix();

//HOMBRO
glPushMatrix();
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 42.0, 0.0);
glRotatef(angulo1, 0.0, 1.0, 0.0);
glCallList(HOMBRO);
glTranslatef(-13.0, 0.0, 0.0);

//BRAZO1
glPushMatrix();
glRotatef(angulo2, 1.0, 0.0, 0.0);
glCallList(BRAZO1);
glTranslatef(13.0, 45.0, 0.0);
113
//CODO
glPushMatrix();
glRotatef(angulo3, 1.0, 0.0, 0.0);
glCallList(CODO);
glTranslatef(0.0, 10.0, 0.0);

//BRAZO2
glPushMatrix();
glRotatef(angulo4, 0.0, 1.0, 0.0);
glCallList(BRAZO2);
glTranslatef(0.0, 55.0, 0.0);

//MUNIECA
glPushMatrix();
glRotatef(angulo5, 1.0, 0.0, 0.0);
glTranslatef(5.5, 0.0, 0.0);
glCallList(MUNIECA);
glTranslatef(-5.5, 0.0, 0.0);

//MANO
glPushMatrix();
glRotatef(angulo6, 0.0, 1.0, 0.0);
glCallList(MANO);
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();

if(lim==1){
dibujar_limites();
}

/*Realizar las pruebas de colisiones necesarias*/


probar_colision(marg);
/*Actualizar el semaforo de precaucin*/
semaforo();
/*Exigir la ejecucuin de todos los comandos OpenGL llamados hasta ahora*/
glFlush ();
/*Intercambiar los frame buffers. Tecnica de double buffering*/
gdk_gl_drawable_swap_buffers (gldrawable);
return TRUE;
}

/*Funciones que crean las listas de despliegue de los componentes principales del robot*/

//BASE del Robot


void crear_base(int slices, int stacks){
GLUquadricObj *quadObj1;

quadObj1 = gluNewQuadric();

glNewList(BASE, GL_COMPILE);
glPushMatrix();
glRotatef(-90, 1.0, 0.0, 0.0);
gluCylinder(quadObj1, 12, 12, 30, slices, stacks);
glPopMatrix();
glEndList();
}

//HOMBRO del Robot


void crear_hombro(){
GLUquadricObj *quadObj1;
114

quadObj1 = gluNewQuadric();

glNewList(HOMBRO, GL_COMPILE);
glPushMatrix();
glRotatef(-90, 1.0, 0.0, 0.0);
glRotatef(45, 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.0, -13.5);
gluCylinder(quadObj1, 18.4, 18.4, 26, 4, 16);
gluDisk(quadObj1, 0, 18.4, 4, 16);
glTranslatef(0.0, 0.0, 26);
gluDisk(quadObj1, 0, 18.4, 4, 16);
glPopMatrix();
glPushMatrix();
glRotatef(90, 0.0, 1.0, 0.0);
glTranslatef(0.0, -0.5, 13.0);
glPushMatrix();
glRotatef(45, 0.0, 0.0, 1.0);
gluCylinder(quadObj1, 18.4, 7.0, 2, 4, 16);
glTranslatef(0.0, 0.0, 2.0);
gluDisk(quadObj1, 0, 7, 4, 16);
glPopMatrix();
glPopMatrix();
glEndList();
}

//BRAZO del Robot


void crear_brazo1(int slices, int stacks){
GLUquadricObj *quadObj1;

quadObj1 = gluNewQuadric();

glNewList(BRAZO1, GL_COMPILE);
glPushMatrix();
glRotatef(-90, 0.0, 1.0, 0.0);//ROTAR
gluCylinder(quadObj1, 12, 13, 7, slices, stacks);
glTranslatef(0.0, 0.0, 7.0);
gluCylinder(quadObj1, 13, 13, 7, slices, stacks);
glTranslatef(0.0, 0.0, 7.0);
gluPartialDisk(quadObj1, 0, 13, slices, stacks, 90, 180);
glTranslatef(0.0, 0.0, -3.5);

glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0); //Izquierda
glVertex3f(-11.0, 45.0, 3.5);
glVertex3f(-13.0, 0.0, 3.5);
glVertex3f(13.0, 0.0, 3.5);
glVertex3f(11.0, 45.0, 3.5);

glNormal3f(0.0, 0.0, -1.0); //Derecha


glVertex3f(-11.0, 45.0, -3.5);
glVertex3f(-13.0, 0.0, -3.5);
glVertex3f(13.0, 0.0, -3.5);
glVertex3f(11.0, 45.0, -3.5);

glNormal3f(0.999, 0.044, 0.0); //Frontal


glVertex3f(11.0, 45.0, 3.5);
glVertex3f(13.0, 0.0, 3.5);
glVertex3f(13.0, 0.0, -3.5);
glVertex3f(11.0, 45.0, -3.5);

glNormal3f(-0.999, 0.044, 0.0); //Trasero


glVertex3f(-11.0, 45.0, 3.5);
115
glVertex3f(-13.0, 0.0, 3.5);
glVertex3f(-13.0, 0.0, -3.5);
glVertex3f(-11.0, 45.0, -3.5);
glEnd();

glTranslatef(0.0, 0.0, -3.5);


glBegin(GL_QUADS);
glColor3f(0.1, 0.1, 1.0);
glNormal3f(0.0, 0.0, -1.0); //Derecha COBERTO
glVertex3f(-8.0, 40.0, -3.5);
glVertex3f(8.0, 40.0, -3.5);
glVertex3f(8.0, 7.0, -3.5);
glVertex3f(-8.0, 7.0, -3.5);
glNormal3f(1.0, 0.0, 0.0); //Frontal COBERTOR
glVertex3f(8.0, 40.0, 3.5);
glVertex3f(8.0, 7.0, 3.5);
glVertex3f(8.0, 7.0, -3.5);
glVertex3f(8.0, 40.0, -3.5);
glNormal3f(-1.0, 0.0, 0.0); //Trasero COBERTOR
glVertex3f(-8.0, 40.0, 3.5);
glVertex3f(-8.0, 7.0, 3.5);
glVertex3f(-8.0, 7.0, -3.5);
glVertex3f(-8.0, 40.0, -3.5);
glEnd();

glColor3f(0.7, 0.8, 0.7);


glTranslatef(0.0, 45.0, -7.0);
gluCylinder(quadObj1, 11, 11, 14, slices, stacks);
gluDisk(quadObj1, 0, 11, slices, stacks);
glTranslatef(0.0, 0.0, 14.0);
gluPartialDisk(quadObj1, 0, 11, slices, stacks, 270, 180);
glPopMatrix();
glEndList();
}

//CODO del Robot


void crear_codo(void){
GLUquadricObj *quadObj1;

quadObj1 = gluNewQuadric();

glNewList(CODO, GL_COMPILE);
glPushMatrix();
glPushMatrix();
glRotatef(-90, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, 10.1);
gluCylinder(quadObj1, 9.8, 9.8, 3, 12, 16);
glPopMatrix();
glRotatef(-90, 1.0, 0.0, 0.0);
glRotatef(45, 0.0, 0.0, 1.0);
glTranslatef(0.45, -0.45, -10.0);
gluCylinder(quadObj1, 15.556, 15.556, 20, 4, 16);
glTranslatef(0.0, 0.0, -5.0);
gluCylinder(quadObj1, 4.0, 15.556, 5, 4, 16);
glPushMatrix();
glRotatef(180, 1.0, 0.0, 0.0);
gluDisk(quadObj1, 0, 4.0, 4, 16);
glPopMatrix();
glTranslatef(0.0, 0.0, 25.0);
gluDisk(quadObj1, 0, 15.556, 4, 16);
glPopMatrix();
glEndList();
}
116
//ANTERBRAZO del Robot
void crear_brazo2(int slices, int stacks){
GLUquadricObj *quadObj1;

quadObj1 = gluNewQuadric();

glNewList(BRAZO2, GL_COMPILE);
glPushMatrix();
glPushMatrix();
glRotatef(-90, 1.0, 0.0, 0.0);
gluCylinder(quadObj1, 9.0, 9.0, 14, slices, stacks);
glTranslatef(0.0, 0.0, 14.0);
gluDisk(quadObj1, 0, 9.0, slices, stacks);
glPopMatrix();
glTranslatef(0.0, 0.0, 0.7);
glPushMatrix();
glRotatef(-90, 1.0, 0.0, 0.0);
glRotatef(45, 0.0, 0.0, 1.0);
gluCylinder(quadObj1, 9.0, 8.3, 48, slices, stacks);
glTranslatef(0.0, 0.0, 48);
gluDisk(quadObj1, 0, 8.3, slices, stacks);
gluCylinder(quadObj1, 8.3, 4.0, 7, 4, 16);
glTranslatef(0.0, 0.0, 7.0);
gluDisk(quadObj1, 0, 4.0, 4, stacks);
glPopMatrix();
glPopMatrix();
glEndList();
}

//MUECA del Robot


void crear_munieca(int slices, int stacks){
GLUquadricObj *quadObj1;

quadObj1 = gluNewQuadric();

glNewList(MUNIECA, GL_COMPILE);
glPushMatrix();
glRotatef(-90, 0.0, 1.0, 0.0);
gluCylinder(quadObj1, 5, 5, 11, slices, stacks);
glPushMatrix();
glRotatef(180, 1.0, 0.0, 0.0);
gluDisk(quadObj1, 0, 5, slices, stacks);
glPopMatrix();
glTranslatef(0, 0, 11);
gluDisk(quadObj1, 0, 5, slices, stacks);
glPopMatrix();
glEndList();
}

//MANO del Robot


void crear_mano(int slices, int stacks){
GLUquadricObj *quadObj1;

quadObj1 = gluNewQuadric();

glNewList(MANO, GL_COMPILE);
glPushMatrix();
glColor3f(0.1, 0.1, 1.0);
glRotatef(-90, 1.0, 0.0, 0.0);
gluCylinder(quadObj1, 3, 3, 8.5, slices, stacks);
glTranslatef(0, 0, 8);
gluDisk(quadObj1, 0, 3, slices, stacks);
glPopMatrix();
glEndList();
117
}

/*************************************************************************************************************/

interface.c: Interfaz grfica de usuario

/***************************************************************************
* SimQNK
* Simulador virtual del brazo robot Stubli RX90 L
* interface.c: interfaz grfica de usuario
* Copyright(C) 2006 David Cuenca
* Email: dcuenc@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifdef ENABLE_NLS
# include <libintl.h>
# undef _
# define _(String) dgettext (PACKAGE, String)
# define Q_(String) g_strip_context ((String), gettext (String))
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define Q_(String) g_strip_context ((String), (String))
# define N_(String) (String)
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#include <gdk/gdkkeysyms.h>
118
#include <gdk/gdk.h>
#include <gdk/gdkgl.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>

#include "callbacks.h"
#include "interface.h"

#define GLADE_HOOKUP_OBJECT(component,widget,name) \
g_object_set_data_full (G_OBJECT (component), name, \
gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)

#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
g_object_set_data (G_OBJECT (component), name, widget)

/*Funcin de creacin de la ventana 1*/


GtkWidget*
create_window1 (void)
{
/*Objetos de la ventana 1*/
GtkWidget *window1;
GtkWidget *vbox1;
GtkWidget *hbox1;
GtkWidget *frame1;
GtkWidget *scrolledwindow1;
GtkWidget *label1;
GtkWidget *hbox2;
GtkWidget *frame3;
GtkWidget *alignment3;
GtkWidget *vbox2;
GtkWidget *label6;
GtkObject *spinbutton1_adj;
GtkWidget *label7;
GtkObject *spinbutton2_adj;
GtkWidget *label8;
GtkObject *spinbutton3_adj;
GtkWidget *bdrive;
GtkWidget *label3;
GtkWidget *frame4;
GtkWidget *alignment4;
GtkWidget *vbox3;
GtkWidget *bsimular;
GtkWidget *alignment6;
GtkWidget *hbox3;
GtkWidget *image1;
GtkWidget *label9;
GtkWidget *bejecutar;
GtkWidget *alignment7;
GtkWidget *hbox4;
GtkWidget *image2;
GtkWidget *label10;
GtkWidget *label4;
GtkWidget *frame5;
GtkWidget *alignment5;
GtkWidget *vbox4;
GtkWidget *brutina1;
GtkWidget *alignment15;
GtkWidget *hbox11;
GtkWidget *image8;
GtkWidget *label18;
GtkWidget *brutina2;
GtkWidget *alignment16;
GtkWidget *hbox12;
119
GtkWidget *image9;
GtkWidget *label19;
GtkWidget *brutina3;
GtkWidget *alignment17;
GtkWidget *hbox13;
GtkWidget *image10;
GtkWidget *label20;
GtkWidget *label5;

/*Creacin y agrupamiento de los objetos de la ventana*/


window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_name (window1, "window1");
gtk_container_set_border_width (GTK_CONTAINER (window1), 3);
gtk_window_set_title (GTK_WINDOW (window1), _("Controles del Simulador (Controles Rutinas)"));

vbox1 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox1, "vbox1");
gtk_widget_show (vbox1);
gtk_container_add (GTK_CONTAINER (window1), vbox1);

hbox1 = gtk_hbox_new (FALSE, 0);


gtk_widget_set_name (hbox1, "hbox1");
gtk_widget_show (hbox1);
gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);

frame1 = gtk_frame_new (NULL);


gtk_widget_set_name (frame1, "frame1");
gtk_widget_show (frame1);
gtk_box_pack_start (GTK_BOX (hbox1), frame1, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame1), 3);
gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_NONE);

scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);


gtk_widget_set_name (scrolledwindow1, "scrolledwindow1");
gtk_widget_show (scrolledwindow1);
gtk_container_add (GTK_CONTAINER (frame1), scrolledwindow1);

textview1 = gtk_text_view_new ();


gtk_widget_set_name (textview1, "textview1");
gtk_widget_show (textview1);
gtk_container_add (GTK_CONTAINER (scrolledwindow1), textview1);
gtk_widget_set_size_request (textview1, 250, 100);

label1 = gtk_label_new (_("<b>MENSAJES</b>"));


gtk_widget_set_name (label1, "label1");
gtk_widget_show (label1);
gtk_frame_set_label_widget (GTK_FRAME (frame1), label1);
gtk_label_set_use_markup (GTK_LABEL (label1), TRUE);

hbox2 = gtk_hbox_new (FALSE, 0);


gtk_widget_set_name (hbox2, "hbox2");
gtk_widget_show (hbox2);
gtk_box_pack_start (GTK_BOX (vbox1), hbox2, TRUE, TRUE, 0);

frame3 = gtk_frame_new (NULL);


gtk_widget_set_name (frame3, "frame3");
gtk_widget_show (frame3);
gtk_box_pack_start (GTK_BOX (hbox2), frame3, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame3), 3);
gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_OUT);

alignment3 = gtk_alignment_new (0.5, 0.5, 1, 1);


gtk_widget_set_name (alignment3, "alignment3");
gtk_widget_show (alignment3);
120
gtk_container_add (GTK_CONTAINER (frame3), alignment3);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment3), 0, 0, 12, 0);

vbox2 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox2, "vbox2");
gtk_widget_show (vbox2);
gtk_container_add (GTK_CONTAINER (alignment3), vbox2);

label6 = gtk_label_new (_("ARTICULACION"));


gtk_widget_set_name (label6, "label6");
gtk_widget_show (label6);
gtk_box_pack_start (GTK_BOX (vbox2), label6, TRUE, TRUE, 0);
gtk_label_set_justify (GTK_LABEL (label6), GTK_JUSTIFY_CENTER);

spinbutton1_adj = gtk_adjustment_new (1, 1, 6, 1, 10, 10);


spinbutton1 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton1_adj), 1, 0);
gtk_widget_set_name (spinbutton1, "spinbutton1");
gtk_widget_show (spinbutton1);
gtk_box_pack_start (GTK_BOX (vbox2), spinbutton1, TRUE, TRUE, 0);

label7 = gtk_label_new (_("ANGULO"));


gtk_widget_set_name (label7, "label7");
gtk_widget_show (label7);
gtk_box_pack_start (GTK_BOX (vbox2), label7, TRUE, TRUE, 0);

spinbutton2_adj = gtk_adjustment_new (0, -360, 360, 1, 10, 10);


spinbutton2 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton2_adj), 1, 0);
gtk_widget_set_name (spinbutton2, "spinbutton2");
gtk_widget_show (spinbutton2);
gtk_box_pack_start (GTK_BOX (vbox2), spinbutton2, TRUE, TRUE, 0);

label8 = gtk_label_new (_("VELOCIDAD (%)"));


gtk_widget_set_name (label8, "label8");
gtk_widget_show (label8);
gtk_box_pack_start (GTK_BOX (vbox2), label8, TRUE, TRUE, 0);

spinbutton3_adj = gtk_adjustment_new (100, 1, 100, 1, 10, 10);


spinbutton3 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton3_adj), 1, 0);
gtk_widget_set_name (spinbutton3, "spinbutton3");
gtk_widget_show (spinbutton3);
gtk_box_pack_start (GTK_BOX (vbox2), spinbutton3, TRUE, TRUE, 0);

bdrive = gtk_button_new_with_mnemonic (_("DRIVE"));


gtk_widget_set_name (bdrive, "bdrive");
gtk_widget_show (bdrive);
gtk_box_pack_start (GTK_BOX (vbox2), bdrive, TRUE, TRUE, 0);

label3 = gtk_label_new (_("<b>Comando Drive</b>"));


gtk_widget_set_name (label3, "label3");
gtk_widget_show (label3);
gtk_frame_set_label_widget (GTK_FRAME (frame3), label3);
gtk_label_set_use_markup (GTK_LABEL (label3), TRUE);

frame4 = gtk_frame_new (NULL);


gtk_widget_set_name (frame4, "frame4");
gtk_widget_show (frame4);
gtk_box_pack_start (GTK_BOX (hbox2), frame4, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame4), 3);
gtk_frame_set_shadow_type (GTK_FRAME (frame4), GTK_SHADOW_OUT);

alignment4 = gtk_alignment_new (0.5, 0.5, 1, 1);


gtk_widget_set_name (alignment4, "alignment4");
gtk_widget_show (alignment4);
gtk_container_add (GTK_CONTAINER (frame4), alignment4);
121
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment4), 0, 0, 12, 0);

vbox3 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox3, "vbox3");
gtk_widget_show (vbox3);
gtk_container_add (GTK_CONTAINER (alignment4), vbox3);

entrycomando = gtk_entry_new ();


gtk_widget_set_name (entrycomando, "entrycomando");
gtk_widget_show (entrycomando);
gtk_box_pack_start (GTK_BOX (vbox3), entrycomando, TRUE, TRUE, 48);
gtk_entry_set_text (GTK_ENTRY (entrycomando), _("Comando"));
gtk_entry_set_width_chars (GTK_ENTRY (entrycomando), 0);

bsimular = gtk_button_new ();


gtk_widget_set_name (bsimular, "bsimular");
gtk_widget_show (bsimular);
gtk_box_pack_start (GTK_BOX (vbox3), bsimular, FALSE, FALSE, 0);

alignment6 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment6, "alignment6");
gtk_widget_show (alignment6);
gtk_container_add (GTK_CONTAINER (bsimular), alignment6);

hbox3 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox3, "hbox3");
gtk_widget_show (hbox3);
gtk_container_add (GTK_CONTAINER (alignment6), hbox3);

image1 = gtk_image_new_from_stock ("gtk-network", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image1, "image1");
gtk_widget_show (image1);
gtk_box_pack_start (GTK_BOX (hbox3), image1, FALSE, FALSE, 0);

label9 = gtk_label_new_with_mnemonic (_("SIMULAR"));


gtk_widget_set_name (label9, "label9");
gtk_widget_show (label9);
gtk_box_pack_start (GTK_BOX (hbox3), label9, FALSE, FALSE, 0);

bejecutar = gtk_button_new ();


gtk_widget_set_name (bejecutar, "bejecutar");
gtk_widget_show (bejecutar);
gtk_box_pack_start (GTK_BOX (vbox3), bejecutar, TRUE, FALSE, 0);

alignment7 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment7, "alignment7");
gtk_widget_show (alignment7);
gtk_container_add (GTK_CONTAINER (bejecutar), alignment7);

hbox4 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox4, "hbox4");
gtk_widget_show (hbox4);
gtk_container_add (GTK_CONTAINER (alignment7), hbox4);

image2 = gtk_image_new_from_stock ("gtk-yes", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image2, "image2");
gtk_widget_show (image2);
gtk_box_pack_start (GTK_BOX (hbox4), image2, FALSE, FALSE, 0);

label10 = gtk_label_new_with_mnemonic (_("EJECUTAR"));


gtk_widget_set_name (label10, "label10");
gtk_widget_show (label10);
gtk_box_pack_start (GTK_BOX (hbox4), label10, FALSE, FALSE, 0);
122
label4 = gtk_label_new (_("<b>Linea de Comandos</b>"));
gtk_widget_set_name (label4, "label4");
gtk_widget_show (label4);
gtk_frame_set_label_widget (GTK_FRAME (frame4), label4);
gtk_label_set_use_markup (GTK_LABEL (label4), TRUE);

frame5 = gtk_frame_new (NULL);


gtk_widget_set_name (frame5, "frame5");
gtk_widget_show (frame5);
gtk_box_pack_start (GTK_BOX (hbox2), frame5, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame5), 3);
gtk_frame_set_shadow_type (GTK_FRAME (frame5), GTK_SHADOW_OUT);

alignment5 = gtk_alignment_new (0.5, 0.5, 1, 1);


gtk_widget_set_name (alignment5, "alignment5");
gtk_widget_show (alignment5);
gtk_container_add (GTK_CONTAINER (frame5), alignment5);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment5), 0, 0, 12, 0);

vbox4 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox4, "vbox4");
gtk_widget_show (vbox4);
gtk_container_add (GTK_CONTAINER (alignment5), vbox4);

entryrutina = gtk_entry_new ();


gtk_widget_set_name (entryrutina, "entryrutina");
gtk_entry_set_max_length(GTK_ENTRY (entryrutina), 20);
gtk_widget_show (entryrutina);
gtk_box_pack_start (GTK_BOX (vbox4), entryrutina, TRUE, FALSE, 0);
gtk_entry_set_text (GTK_ENTRY (entryrutina), _("Nombre Rutina"));

brutina1 = gtk_button_new ();


gtk_widget_set_name (brutina1, "brutina1");
gtk_widget_show (brutina1);
gtk_box_pack_start (GTK_BOX (vbox4), brutina1, TRUE, FALSE, 0);

alignment15 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment15, "alignment15");
gtk_widget_show (alignment15);
gtk_container_add (GTK_CONTAINER (brutina1), alignment15);

hbox11 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox11, "hbox11");
gtk_widget_show (hbox11);
gtk_container_add (GTK_CONTAINER (alignment15), hbox11);

image8 = gtk_image_new_from_stock ("gtk-save-as", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image8, "image8");
gtk_widget_show (image8);
gtk_box_pack_start (GTK_BOX (hbox11), image8, FALSE, FALSE, 0);

label18 = gtk_label_new_with_mnemonic (_("Crear Rutina"));


gtk_widget_set_name (label18, "label18");
gtk_widget_show (label18);
gtk_box_pack_start (GTK_BOX (hbox11), label18, FALSE, FALSE, 0);

brutina2 = gtk_button_new ();


gtk_widget_set_name (brutina2, "brutina2");
gtk_widget_show (brutina2);
gtk_box_pack_start (GTK_BOX (vbox4), brutina2, TRUE, FALSE, 0);

alignment16 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment16, "alignment16");
gtk_widget_show (alignment16);
123
gtk_container_add (GTK_CONTAINER (brutina2), alignment16);

hbox12 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox12, "hbox12");
gtk_widget_show (hbox12);
gtk_container_add (GTK_CONTAINER (alignment16), hbox12);

image9 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image9, "image9");
gtk_widget_show (image9);
gtk_box_pack_start (GTK_BOX (hbox12), image9, FALSE, FALSE, 0);

label19 = gtk_label_new_with_mnemonic (_("Cargar Rutina"));


gtk_widget_set_name (label19, "label19");
gtk_widget_show (label19);
gtk_box_pack_start (GTK_BOX (hbox12), label19, FALSE, FALSE, 0);

brutina3 = gtk_button_new ();


gtk_widget_set_name (brutina3, "brutina3");
gtk_widget_show (brutina3);
gtk_box_pack_start (GTK_BOX (vbox4), brutina3, TRUE, FALSE, 0);

alignment17 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment17, "alignment17");
gtk_widget_show (alignment17);
gtk_container_add (GTK_CONTAINER (brutina3), alignment17);

hbox13 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox13, "hbox13");
gtk_widget_show (hbox13);
gtk_container_add (GTK_CONTAINER (alignment17), hbox13);

image10 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image10, "image10");
gtk_widget_show (image10);
gtk_box_pack_start (GTK_BOX (hbox13), image10, FALSE, FALSE, 0);

label20 = gtk_label_new_with_mnemonic (_("Ejecutar Rutina"));


gtk_widget_set_name (label20, "label20");
gtk_widget_show (label20);
gtk_box_pack_start (GTK_BOX (hbox13), label20, FALSE, FALSE, 0);

label5 = gtk_label_new (_("<b>Rutinas</b>"));


gtk_widget_set_name (label5, "label5");
gtk_widget_show (label5);
gtk_frame_set_label_widget (GTK_FRAME (frame5), label5);
gtk_label_set_use_markup (GTK_LABEL (label5), TRUE);

/*Ligar las funciones de respuesta especficas a cada boton de la ventana*/


g_signal_connect ((gpointer) bdrive, "clicked",
G_CALLBACK (on_bdrive_clicked),
NULL);
g_signal_connect ((gpointer) bsimular, "clicked",
G_CALLBACK (on_bsimular_clicked),
NULL);
g_signal_connect ((gpointer) bejecutar, "clicked",
G_CALLBACK (on_bejecutar_clicked),
NULL);
g_signal_connect ((gpointer) bejecutar, "clicked",
G_CALLBACK (on_bejecutar_clicked),
NULL);
g_signal_connect ((gpointer) brutina1, "clicked",
G_CALLBACK (on_brutina1_clicked),
NULL);
124
g_signal_connect ((gpointer) brutina2, "clicked",
G_CALLBACK (on_brutina2clicked),
NULL);
g_signal_connect ((gpointer) brutina3, "clicked",
G_CALLBACK (on_brutina3_clicked),
NULL);

/* destroy - Se desea destruir la ventana, aqui es donde se


* debe llevar a cabo la limpieza necesaria */
g_signal_connect((gpointer) window1, "destroy",
G_CALLBACK(gtk_widget_destroy), GTK_OBJECT (window1));

return window1;
}

/*Funcin de creacin de ventana 2*/


GtkWidget*
create_window2 (void)
{
/*Objetos de la ventana 2*/
GtkWidget *window2;
GtkWidget *frame6;
GtkWidget *alignment18;
GtkWidget *vbox8;
GtkWidget *hbox14;
GtkWidget *bsim;
GtkWidget *alignment19;
GtkWidget *hbox15;
GtkWidget *image11;
GtkWidget *label24;
GtkWidget *bquit;
GtkWidget *alignment20;
GtkWidget *hbox16;
GtkWidget *image12;
GtkWidget *label25;
GtkWidget *label23;
GtkWidget *bacerca;
GtkWidget *alignment21;
GtkWidget *hbox17;
GtkWidget *image13;
GtkWidget *label26;

/* Atributos del area GTKGL */


GdkGLConfig *glconfig;

glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH |
GDK_GL_MODE_DOUBLE);

window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);


gtk_widget_set_name (window2, "window2");
gtk_window_set_title (GTK_WINDOW (window2), _("Mundo Virtual"));

frame6 = gtk_frame_new (NULL);


gtk_widget_set_name (frame6, "frame6");
gtk_widget_show (frame6);
gtk_container_add (GTK_CONTAINER (window2), frame6);
gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_NONE);

alignment18 = gtk_alignment_new (0.5, 0.5, 1, 1);


gtk_widget_set_name (alignment18, "alignment18");
gtk_widget_show (alignment18);
gtk_container_add (GTK_CONTAINER (frame6), alignment18);
125
vbox8 = gtk_vbox_new (FALSE, 2);
gtk_widget_set_name (vbox8, "vbox8");
gtk_widget_show (vbox8);
gtk_container_add (GTK_CONTAINER (alignment18), vbox8);
gtk_container_set_border_width (GTK_CONTAINER (vbox8), 2);

/*Creacin del area de despliegue OpenGL*/


glarea1 = gtk_drawing_area_new();
gtk_widget_set_gl_capability(GTK_WIDGET (glarea1),
glconfig,
NULL,
TRUE,
GDK_GL_RGBA_TYPE);
gtk_widget_set_name (glarea1, "glarea1");
/*Eventos habilitados en el area OpenGL*/
gtk_widget_set_events(glarea1,
GDK_EXPOSURE_MASK|
GDK_BUTTON_PRESS_MASK|
GDK_KEY_PRESS_MASK|
GDK_POINTER_MOTION_MASK|
GDK_POINTER_MOTION_HINT_MASK);
gtk_widget_show (glarea1);
gtk_box_pack_start (GTK_BOX (vbox8), glarea1, TRUE, TRUE, 0);
gtk_widget_set_size_request (glarea1, 350, 350);

hbox14 = gtk_hbox_new (FALSE, 0);


gtk_widget_set_name (hbox14, "hbox14");
gtk_widget_show (hbox14);
gtk_box_pack_start (GTK_BOX (vbox8), hbox14, TRUE, TRUE, 0);

bsim = gtk_button_new ();


gtk_widget_set_name (bsim, "bsim");
gtk_widget_show (bsim);
gtk_box_pack_start (GTK_BOX (hbox14), bsim, TRUE, TRUE, 0);

alignment19 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment19, "alignment19");
gtk_widget_show (alignment19);
gtk_container_add (GTK_CONTAINER (bsim), alignment19);

hbox15 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox15, "hbox15");
gtk_widget_show (hbox15);
gtk_container_add (GTK_CONTAINER (alignment19), hbox15);

image11 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image11, "image11");
gtk_widget_show (image11);
gtk_box_pack_start (GTK_BOX (hbox15), image11, FALSE, FALSE, 0);

label24 = gtk_label_new_with_mnemonic (_("SIMULAR"));


gtk_widget_set_name (label24, "label24");
gtk_widget_show (label24);
gtk_box_pack_start (GTK_BOX (hbox15), label24, FALSE, FALSE, 0);
gtk_label_set_justify (GTK_LABEL (label24), GTK_JUSTIFY_CENTER);

bquit = gtk_button_new ();


gtk_widget_set_name (bquit, "bquit");
gtk_widget_show (bquit);
gtk_box_pack_start (GTK_BOX (hbox14), bquit, FALSE, FALSE, 0);
gtk_widget_set_size_request (bquit, 133, -1);

alignment20 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment20, "alignment20");
126
gtk_widget_show (alignment20);
gtk_container_add (GTK_CONTAINER (bquit), alignment20);

hbox16 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox16, "hbox16");
gtk_widget_show (hbox16);
gtk_container_add (GTK_CONTAINER (alignment20), hbox16);

image12 = gtk_image_new_from_stock ("gtk-cancel", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image12, "image12");
gtk_widget_show (image12);
gtk_box_pack_start (GTK_BOX (hbox16), image12, FALSE, FALSE, 0);

label25 = gtk_label_new_with_mnemonic (_("QUIT"));


gtk_widget_set_name (label25, "label25");
gtk_widget_show (label25);
gtk_box_pack_start (GTK_BOX (hbox16), label25, FALSE, FALSE, 0);

bacerca = gtk_button_new ();


gtk_widget_set_name (bquit, "bacerca");
gtk_widget_show (bacerca);
gtk_box_pack_start (GTK_BOX (hbox14), bacerca, FALSE, FALSE, 0);

alignment21 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment20, "alignment21");
gtk_widget_show (alignment21);
gtk_container_add (GTK_CONTAINER (bacerca), alignment21);

hbox17 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox16, "hbox17");
gtk_widget_show (hbox17);
gtk_container_add (GTK_CONTAINER (alignment21), hbox17);

image13 = gtk_image_new_from_stock ("gtk-edit", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image13, "image13");
gtk_widget_show (image13);
gtk_box_pack_start (GTK_BOX (hbox17), image13, FALSE, FALSE, 0);

label26 = gtk_label_new_with_mnemonic (_("Acerca de (about)"));


gtk_widget_set_name (label26, "label26");
gtk_widget_show (label26);
gtk_box_pack_start (GTK_BOX (hbox17), label26, FALSE, FALSE, 0);

label23 = gtk_label_new (_("<b>Simulador</b>"));


gtk_widget_set_name (label23, "label23");
gtk_widget_show (label23);
gtk_frame_set_label_widget (GTK_FRAME (frame6), label23);
gtk_label_set_use_markup (GTK_LABEL (label23), TRUE);

g_signal_connect ((gpointer) bsim, "clicked",


G_CALLBACK (on_bsim_clicked), NULL);

g_signal_connect((gpointer) bquit, "clicked",


G_CALLBACK(gtk_main_quit), NULL);

/* Esta funcin se encarga de monitorear cuando se presiona un botn dentro del


* area GTKGL.*/
g_signal_connect ((gpointer) glarea1, "button_press_event",
G_CALLBACK(on_glarea_button_press_event), NULL);

g_signal_connect((gpointer) bacerca, "clicked",


G_CALLBACK(on_bacerca_clicked), NULL);

/* Esta funcin se encarga de monitorear cuando se presiona una tecla


127
* y la ventana OpenGL est en frente*/
g_signal_connect_swapped (G_OBJECT (window2), "key_press_event",
G_CALLBACK (on_glarea_key_press_event), glarea1);

/* motion_notify_event - El ratn se esta moviendo dentro de la ventana */


g_signal_connect ((gpointer) glarea1, "motion_notify_event",
G_CALLBACK(on_glarea_motion_notify_event), NULL);

/* expose_event - La ventana se ha expuesto y el contenido debe de ser redibujado */


g_signal_connect ((gpointer) glarea1, "expose_event",
G_CALLBACK(on_glarea_expose_event), NULL);

/* configure_event - Se ha cambiado el tamao de la ventana.*/


g_signal_connect ((gpointer) glarea1, "configure_event",
G_CALLBACK(on_glarea_configure_event), NULL);

/* realize - Se ha creado la ventana, aqui se introducen las */


/* rutinas de inicializacin. */
g_signal_connect ((gpointer) glarea1, "realize",
G_CALLBACK(glarea_init), NULL);

/* destroy - Se desea destruir la ventana, aqui es donde se


* debe llevar a cabo la limpieza necesaria */
g_signal_connect((gpointer) glarea1, "destroy",
G_CALLBACK(gtk_widget_destroy), GTK_OBJECT (window2));

return window2;
}

/*Funcin de creacin de la ventana 3*/


GtkWidget*
create_window3 (void)
{
/*Objetos de la ventana 3*/
GtkWidget *window3;
GtkWidget *hbox16;
GtkWidget *frame2;
GtkWidget *alignment2;
GtkWidget *hbox5;
GtkWidget *vbox5;
GtkWidget *label12;
GtkWidget *bposicion1;
GtkWidget *alignment10;
GtkWidget *hbox6;
GtkWidget *image3;
GtkWidget *label13;
GtkWidget *bposicion2;
GtkWidget *alignment11;
GtkWidget *hbox7;
GtkWidget *image4;
GtkWidget *label14;
GtkWidget *bposicion3;
GtkWidget *alignment12;
GtkWidget *hbox8;
GtkWidget *image5;
GtkWidget *label15;
GtkWidget *bposicion4;
GtkWidget *alignment14;
GtkWidget *hbox10;
GtkWidget *image7;
GtkWidget *label17;
GtkWidget *bposicion5;
GtkWidget *alignment13;
128
GtkWidget *hbox9;
GtkWidget *image6;
GtkWidget *label16;
GtkWidget *vseparator2;
GtkWidget *vbox6;
GtkWidget *label21;
GtkWidget *vseparator1;
GtkWidget *vbox7;
GtkWidget *label22;
GtkWidget *bsimulador;
GtkWidget *label2;
GtkWidget *hbox2;

window3= gtk_window_new (GTK_WINDOW_TOPLEVEL);


gtk_widget_set_name (window3, "window3");
gtk_container_set_border_width (GTK_CONTAINER (window3), 3);
gtk_window_set_title (GTK_WINDOW (window3), _("Controles del Simulador (Controles de Configuracin)"));

hbox16 = gtk_hbox_new (FALSE, 0);


gtk_widget_set_name (hbox16, "hbox16");
gtk_widget_show (hbox16);
gtk_container_add (GTK_CONTAINER (window3), hbox16);

frame2 = gtk_frame_new (NULL);


gtk_widget_set_name (frame2, "frame2");
gtk_widget_show (frame2);
gtk_box_pack_start (GTK_BOX (hbox16), frame2, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame2), 3);
gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_OUT);

alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1);


gtk_widget_set_name (alignment2, "alignment2");
gtk_widget_show (alignment2);
gtk_container_add (GTK_CONTAINER (frame2), alignment2);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 0, 0, 12, 0);

hbox5 = gtk_hbox_new (FALSE, 0);


gtk_widget_set_name (hbox5, "hbox5");
gtk_widget_show (hbox5);
gtk_container_add (GTK_CONTAINER (alignment2), hbox5);

vbox5 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox5, "vbox5");
gtk_widget_show (vbox5);
gtk_box_pack_start (GTK_BOX (hbox5), vbox5, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox5), 13);

label12 = gtk_label_new (_("POSICION"));


gtk_widget_set_name (label12, "label12");
gtk_widget_show (label12);
gtk_box_pack_start (GTK_BOX (vbox5), label12, TRUE, FALSE, 0);

bposicion1 = gtk_button_new ();


gtk_widget_set_name (bposicion1, "bposicion1");
gtk_widget_show (bposicion1);
gtk_box_pack_start (GTK_BOX (vbox5), bposicion1, TRUE, FALSE, 0);

alignment10 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment10, "alignment10");
gtk_widget_show (alignment10);
gtk_container_add (GTK_CONTAINER (bposicion1), alignment10);

hbox6 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox6, "hbox6");
129
gtk_widget_show (hbox6);
gtk_container_add (GTK_CONTAINER (alignment10), hbox6);

image3 = gtk_image_new_from_stock ("gtk-redo", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image3, "image3");
gtk_widget_show (image3);
gtk_box_pack_start (GTK_BOX (hbox6), image3, FALSE, FALSE, 0);

label13 = gtk_label_new_with_mnemonic (_("APILAR"));


gtk_widget_set_name (label13, "label13");
gtk_widget_show (label13);
gtk_box_pack_start (GTK_BOX (hbox6), label13, FALSE, FALSE, 0);

bposicion2 = gtk_button_new ();


gtk_widget_set_name (bposicion2, "bposicion2");
gtk_widget_show (bposicion2);
gtk_box_pack_start (GTK_BOX (vbox5), bposicion2, TRUE, FALSE, 0);

alignment11 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment11, "alignment11");
gtk_widget_show (alignment11);
gtk_container_add (GTK_CONTAINER (bposicion2), alignment11);

hbox7 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox7, "hbox7");
gtk_widget_show (hbox7);
gtk_container_add (GTK_CONTAINER (alignment11), hbox7);

image4 = gtk_image_new_from_stock ("gtk-undo", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image4, "image4");
gtk_widget_show (image4);
gtk_box_pack_start (GTK_BOX (hbox7), image4, FALSE, FALSE, 0);

label14 = gtk_label_new_with_mnemonic (_("DESAPILAR"));


gtk_widget_set_name (label14, "label14");
gtk_widget_show (label14);
gtk_box_pack_start (GTK_BOX (hbox7), label14, FALSE, FALSE, 0);

bposicion3 = gtk_button_new ();


gtk_widget_set_name (bposicion3, "bposicion3");
gtk_widget_show (bposicion3);
gtk_box_pack_start (GTK_BOX (vbox5), bposicion3, TRUE, FALSE, 0);

alignment12 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment12, "alignment12");
gtk_widget_show (alignment12);
gtk_container_add (GTK_CONTAINER (bposicion3), alignment12);

hbox8 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox8, "hbox8");
gtk_widget_show (hbox8);
gtk_container_add (GTK_CONTAINER (alignment12), hbox8);

image5 = gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image5, "image5");
gtk_widget_show (image5);
gtk_box_pack_start (GTK_BOX (hbox8), image5, FALSE, FALSE, 0);

label15 = gtk_label_new_with_mnemonic (_("Reiniciar Pila"));


gtk_widget_set_name (label15, "label15");
gtk_widget_show (label15);
gtk_box_pack_start (GTK_BOX (hbox8), label15, FALSE, FALSE, 0);

bposicion4 = gtk_button_new ();


130
gtk_widget_set_name (bposicion4, "bposicion4");
gtk_widget_show (bposicion4);
gtk_box_pack_start (GTK_BOX (vbox5), bposicion4, TRUE, FALSE, 0);

alignment14 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment14, "alignment14");
gtk_widget_show (alignment14);
gtk_container_add (GTK_CONTAINER (bposicion4), alignment14);

hbox10 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox10, "hbox10");
gtk_widget_show (hbox10);
gtk_container_add (GTK_CONTAINER (alignment14), hbox10);

image7 = gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image7, "image7");
gtk_widget_show (image7);
gtk_box_pack_start (GTK_BOX (hbox10), image7, FALSE, FALSE, 0);

label17 = gtk_label_new_with_mnemonic (_("Reiniciar Robot"));


gtk_widget_set_name (label17, "label17");
gtk_widget_show (label17);
gtk_box_pack_start (GTK_BOX (hbox10), label17, FALSE, FALSE, 0);

bposicion5 = gtk_button_new ();


gtk_widget_set_name (bposicion5, "bposicion5");
gtk_widget_show (bposicion5);
gtk_box_pack_start (GTK_BOX (vbox5), bposicion5, TRUE, FALSE, 0);

alignment13 = gtk_alignment_new (0.5, 0.5, 0, 0);


gtk_widget_set_name (alignment13, "alignment13");
gtk_widget_show (alignment13);
gtk_container_add (GTK_CONTAINER (bposicion5), alignment13);

hbox9 = gtk_hbox_new (FALSE, 2);


gtk_widget_set_name (hbox9, "hbox9");
gtk_widget_show (hbox9);
gtk_container_add (GTK_CONTAINER (alignment13), hbox9);

image6 = gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_BUTTON);


gtk_widget_set_name (image6, "image6");
gtk_widget_show (image6);
gtk_box_pack_start (GTK_BOX (hbox9), image6, FALSE, FALSE, 0);

label16 = gtk_label_new_with_mnemonic (_("Reiniciar C\303\241mara"));


gtk_widget_set_name (label16, "label16");
gtk_widget_show (label16);
gtk_box_pack_start (GTK_BOX (hbox9), label16, FALSE, FALSE, 0);

vseparator2 = gtk_vseparator_new ();


gtk_widget_set_name (vseparator2, "vseparator2");
gtk_widget_show (vseparator2);
gtk_box_pack_start (GTK_BOX (hbox5), vseparator2, TRUE, TRUE, 0);

vbox6 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox6, "vbox6");
gtk_widget_show (vbox6);
gtk_box_pack_start (GTK_BOX (hbox5), vbox6, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox6), 3);

label21 = gtk_label_new (_("VISTA"));


gtk_widget_set_name (label21, "label21");
gtk_widget_show (label21);
gtk_box_pack_start (GTK_BOX (vbox6), label21, FALSE, FALSE, 18);
131

bgrid = gtk_toggle_button_new_with_mnemonic (_("GRID"));


gtk_widget_set_name (bgrid, "bgrid");
gtk_widget_show (bgrid);
gtk_box_pack_start (GTK_BOX (vbox6), bgrid, TRUE, FALSE, 0);

btexturas = gtk_toggle_button_new_with_mnemonic (_("Fondo Blanco"));


gtk_widget_set_name (btexturas, "btexturas");
gtk_widget_show (btexturas);
gtk_box_pack_start (GTK_BOX (vbox6), btexturas, TRUE, FALSE, 0);

vseparator1 = gtk_vseparator_new ();


gtk_widget_set_name (vseparator1, "vseparator1");
gtk_widget_show (vseparator1);
gtk_box_pack_start (GTK_BOX (hbox5), vseparator1, TRUE, TRUE, 0);

vbox7 = gtk_vbox_new (FALSE, 0);


gtk_widget_set_name (vbox7, "vbox7");
gtk_widget_show (vbox7);
gtk_box_pack_start (GTK_BOX (hbox5), vbox7, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox7), 3);

label22 = gtk_label_new (_("SIMULACION"));


gtk_widget_set_name (label22, "label22");
gtk_widget_show (label22);
gtk_box_pack_start (GTK_BOX (vbox7), label22, TRUE, FALSE, 0);

bcheckmax = gtk_toggle_button_new_with_mnemonic (_("Lim. Angulos"));


gtk_widget_set_name (bcheckmax, "bcheckmax");
gtk_widget_show (bcheckmax);
gtk_box_pack_start (GTK_BOX (vbox7), bcheckmax, TRUE, FALSE, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bcheckmax), TRUE);

bcolision1 = gtk_toggle_button_new_with_mnemonic (_("1\302\260 Colisi\303\263n"));


gtk_widget_set_name (bcolision1, "bcolision1");
gtk_widget_show (bcolision1);
gtk_box_pack_start (GTK_BOX (vbox7), bcolision1, TRUE, FALSE, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bcolision1), TRUE);

bsimulador = gtk_toggle_button_new_with_mnemonic (_("SIM ON"));


gtk_widget_set_name (bsimulador, "bsimulador");
gtk_widget_show (bsimulador);
gtk_box_pack_start (GTK_BOX (vbox7), bsimulador, TRUE, FALSE, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (bsimulador), TRUE);

label2 = gtk_label_new (_("<b>OPCIONES DEL SIMULADOR</b>"));


gtk_widget_set_name (label2, "label2");
gtk_widget_show (label2);
gtk_frame_set_label_widget (GTK_FRAME (frame2), label2);
gtk_label_set_use_markup (GTK_LABEL (label2), TRUE);
gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_CENTER);

/*Coneccin de la funciones de respuestas a los botones la ventana 3*/


g_signal_connect ((gpointer) bposicion1, "clicked",
G_CALLBACK (on_bposicion1_clicked),
NULL);
g_signal_connect ((gpointer) bposicion2, "clicked",
G_CALLBACK (on_bposicion2_clicked),
NULL);
g_signal_connect ((gpointer) bposicion3, "clicked",
G_CALLBACK (on_bposicion3_clicked),
NULL);
g_signal_connect ((gpointer) bposicion4, "clicked",
G_CALLBACK (on_bposicion4_clicked),
132
NULL);
g_signal_connect ((gpointer) bposicion5, "clicked",
G_CALLBACK (on_bposicion5_clicked),
NULL);
g_signal_connect ((gpointer) bposicion5, "clicked",
G_CALLBACK (on_bposicion5_clicked),
NULL);
g_signal_connect ((gpointer) bgrid, "toggled",
G_CALLBACK (on_bgrid_toggled),
NULL);
g_signal_connect ((gpointer) btexturas, "toggled",
G_CALLBACK (on_btexturas_toggled),
NULL);
g_signal_connect ((gpointer) bcheckmax, "toggled",
G_CALLBACK (on_bcheckmax_toggled),
NULL);
g_signal_connect ((gpointer) bcolision1, "toggled",
G_CALLBACK (on_bcolision1_toggled),
NULL);
g_signal_connect ((gpointer) bsimulador, "toggled",
G_CALLBACK (on_bsimulador_toggled),
NULL);

/* destroy - Se desea destruir la ventana, aqui es donde se


* debe llevar a cabo la limpieza necesaria */
g_signal_connect((gpointer) window3, "destroy",
G_CALLBACK(gtk_widget_destroy), GTK_OBJECT (window3));

return window3;
}

/*************************************************************************************************************/

rutina.c: Funciones de creacin, edicin y ejecucin de rutinas desde linea de comandos


/***************************************************************************
* SimQNK
* Simulador virtual del brazo robot Stubli RX90 L
* rutina.c: funciones de creacin, edicin, carga y ejecucin de rutinas desde la linea de comandos
* Copyright(C) 2006 David Cuenca
* Email: dcuenc@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "rutina.h"

int puntpos=0;
133

/*MATRIZ DE PILA POSICIONES*/


/*Espacio de memoria en el que se apilan las posiciones*/
float pilaposiciones[60][6];

/*Velocidades Maximas de giro de cada articulacin*/


int velocmaximas[6]={356, 356, 296, 409,800, 1125};

//.............APILAR/DESAPILAR POSICION ACTUAL...................//


void push_posicion(void){
pilaposiciones[puntpos][0]=angulo1;
pilaposiciones[puntpos][1]=angulo2;
pilaposiciones[puntpos][2]=angulo3;
pilaposiciones[puntpos][3]=angulo4;
pilaposiciones[puntpos][4]=angulo5;
pilaposiciones[puntpos][5]=angulo6;
if(puntpos < 60){
puntpos++; //aumenta el puntero de la pila
}
}
void pull_posicion(void){
if(puntpos > 0){ puntpos--;}
angulo1=pilaposiciones[puntpos][0];
angulo2=pilaposiciones[puntpos][1];
angulo3=pilaposiciones[puntpos][2];
angulo4=pilaposiciones[puntpos][3];
angulo5=pilaposiciones[puntpos][4];
angulo6=pilaposiciones[puntpos][5];
}

/*Reiniciar la pila*/
void reiniciar_pila(void){
puntpos=0;
}

//.............VELOCIDADES DE CADA ARTICULACION.........//


/*Se establece la velocidad del movimientos, dependiedo del
* porcentaje pasado y de la velocidad mxima de la articulacin*/
void set_velocidad(int porciento, int numart){
velocidad=(velocmaximas[numart-1])*porciento/100;
if(velocidad==0){
velocidad=10;
}
}

//.............CREACION DE UNA RUTINA...................//


/* Utilizando la terminal (linea de comandos)*/
void crear_rutina(void){
int nru;
char basura[10];

/*Se pide el nombre la rutina a crear*/


printf("\n\n----CREACIN DE UNA RUTINA (Presione ENTER)---");
fflush(stdin);
scanf("%c",&basura);
printf("\nNumero de movimientos:_");
scanf("%f", &rutina[0][0]);
if(rutina[0][0] > 60){
rutina[0][0]=60;
}
for(nru=1; nru<=rutina[0][0];nru++){
/*Se pide caracterizar los movimientos de la rutina*/
printf("Movimiento #%i ->JOINT:_", nru);
scanf("%f", &rutina[nru][0]);
134
printf("Movimiento #%i ->ANGULO:_", nru);
scanf("%f", &rutina[nru][1]);
printf("Movimiento #%i ->VELOCIDAD:_", nru);
scanf("%f", &rutina[nru][2]);
}
printf("\nUtiliza la tecla >> F8 << para ejecutar la rutina");
fflush(stdout);
}

/*.............CRONOMETRO DE ESPERA.......................*/
/*Regula la velocidad de dibujo de los cuadro de la escena (frames)*/
void esperar(float segundos)
{
clock_t tiempoespera;
tiempoespera = clock () + segundos * CLK_TCK ;
while (clock() < tiempoespera) {}
}

//.............MOVER CADA ARTICULACIN.........//


/*mueva cada articulacin hasta alcanzar el agnulo deseado*/
void mover_joint(float* ang, float delta, float vel){
float angfinal;
float veldelta=velocidad/50;
int finwhile;
int ya;
ya=0;
finwhile=0;
choque=0;
angmax=0;

push_posicion(); //apila la posicin actual;


angfinal= (*ang) + delta;

if(delta > 0){


/*realizar giro positivo*/
while((*ang) < angfinal && finwhile<1){
dibujar();
(*ang)+=veldelta;
if(checkcolision==1 ){
if(choque==1){
/*si se da choque y esta habilitada la opcin de terminar al
* primer choque, se manda seal de terminar*/
finwhile=1;
(*ang)-=veldelta;
ya=1;
}
}
if(checkmax==1 ){
if(angmax==1 && ya!=1){
/*si se llega a angulo maximo y esta habilitada la opcin de limitar
angulos de giro,
* se manda seal de terminar*/
finwhile=1;
(*ang)-=veldelta;
}
}
//esperar(1);
}
if(finwhile!=1){
(*ang)=angfinal;
}
/*dibujar el modelo en la nueva posicin*/
dibujar();
}else if(delta < 0){
135
/*realizar giro negativo*/
while((*ang) > angfinal && finwhile<1){
dibujar();
(*ang)-=veldelta;
if(checkcolision==1 ){
if(choque==1){
finwhile=1;
(*ang)+=veldelta;
ya=1;
}
}
if(checkmax==1 ){
if(angmax==1 && ya!=1){
finwhile=1;
(*ang)+=veldelta;
}
}
//esperar(1);
}
if(finwhile!=1){
(*ang)=angfinal;
}
/*dibujar el modelo en la nueva posicin*/
dibujar();
}
}

void selec_mover_joint(void){
/*Seleccionar cual articulacin es la que se debe mover, segun la orden del usuario*/
float* puntang;
if(joint==1){
puntang = &angulo1;
mover_joint(puntang, angulodelta, velocidad);

}else if(joint==2){
puntang = &angulo2;
mover_joint(puntang, -1*angulodelta, velocidad);

}else if(joint==3){
puntang = &angulo3;
mover_joint(puntang, -1*angulodelta, velocidad);

}else if(joint==4){
puntang = &angulo4;
mover_joint(puntang, angulodelta, velocidad);

}else if(joint==5){
puntang = &angulo5;
mover_joint(puntang, -1*angulodelta, velocidad);

}else if(joint==6){
puntang = &angulo6;
mover_joint(puntang, angulodelta, velocidad);

}
}

//.............EJECUTAR RUTINA..............//
/*Ejecutar la rutina cargada en memoria*/
void ejecutar_rutina(void){
int nm;
if(rutina[0][0]!=0){
for(nm=1; nm<=rutina[0][0]; nm++){
joint=rutina[nm][0];
136
angulodelta=rutina[nm][1];
set_velocidad((int)rutina[nm][2], (int)joint);
selec_mover_joint();
}
}
}

//..............ABRIR y LEER ARCHIVO DE RUTINA................//


int abrir_rutina(void){
FILE *archivo1;
char nombrefile[15];
char letra;
char articult[3];
char angt[7];
char veloct[7];
char linea[15];
char basura[10];
int p1, p2, p3; //punteros

/*Pide nombre de archivo que se desea cargar*/


printf("\nLEER ARCHIVO DE RUTINA (Presione ENTER)\n");
fflush(stdin);
scanf("%c", &basura);
printf("\nEscriba el nombre del archivo que desea abrir:_");
scanf("%s", &nombrefile);

/*abre el archivo y lee la informacin*/


archivo1=fopen(nombrefile,"r");
if (!archivo1){
printf("\n-ERROR-->No se pudo abrir el archivo %s", nombrefile);
fflush(stdout);
return 1;
}
p1=0;
rutina[0][0]=0;
do{
letra=fgetc(archivo1);
if(letra=='M'){
if(p1<60){
p1++;
rutina[0][0]++;
}
}else if(letra=='A'){
p2=0;
while(letra!=','){
letra=fgetc(archivo1);
angt[p2]=letra;
p2++;
}
rutina[p1][1]=atof(angt);
}else if(letra=='J'){
p2=0;
while(letra!=','){
letra=fgetc(archivo1);
articult[p2]=letra;
p2++;
}
rutina[p1][0]=atof(articult);
}else if(letra=='V'){
p2=0;
while(letra!=','){
letra=fgetc(archivo1);
veloct[p2]=letra;
137
p2++;
}
rutina[p1][2]=atof(veloct);
}
}while (letra!='f');

fclose(archivo1);
}

//................SALVAR RUTINA A ARCHIVO...............................//


int salvar_rutina(void){
FILE *archivo1;
char nombrefile[15];
char basura[10];
int p1; //punteros

/*Pide nombre de archivo en que se desea guardar la rutina*/


printf("\nSALVAR RUTINA (Presione ENTER)\n");
fflush(stdin);
scanf("%c", &basura);
printf("\nEscriba el nombre del archivo que desea crear:_");
scanf("%s", &nombrefile);

archivo1=fopen(nombrefile,"w");
if (!archivo1){
printf("\n-ERROR-->No se pudo abrir el archivo %s", nombrefile);
return 1;
}
p1=0;
fprintf(archivo1,"inicio\n");
for(p1=1;p1<=rutina[0][0];p1++){
/*imprime cada movimiento de la rutina de la memoria, en una linea nueva del archivo de texto*/
fprintf(archivo1,"M%i, J %d, A %3.1f, V %d,\n",p1,(int)rutina[p1][0],rutina[p1][1],(int)rutina[p1][2]);
}
fprintf(archivo1,"fin");
fclose(archivo1);
}
/*************************************************************************************************************/

ventanagl.c: Funciones de configuracin de la ventana OpenGL


/***************************************************************************
* SimQNK
* Simulador virtual del brazo robot Stubli RX90 L
* ventanagl.c: funciones de configuracin de la ventana de despliegue OpenGL
* Copyright(C) 2006 David Cuenca
* Email: dcuenc@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
138

#include "ventanagl.h"

#define SLICES 30
#define STACKS 30

/*Posicin de las luces*/


GLfloat position0 [] = { 0.0, 0.0, 600.0, 1.0 };

/*Funcin reinicia los valores de posicin y velocidad de la camara*/


void valores_iniciales_camara(void){
printf("\nObjeto Seleccionado--> CAMARA");
camara_x = 0;
camara_y = 0;
camara_z = 300;
ancho_x=0;
altura_y =0;
angulo_yr=0;
angulo_xr=0;
zoom_z = 160;
aument_cam = 1;
mov_cam = 1;
}

/* Inicio de la ventana OpenGL --> (luces, materiales, buffers)*/


gboolean inicio(void){

GdkGLContext *glcontext = gtk_widget_get_gl_context (glarea1);


GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (glarea1);

/*** OpenGL BEGIN ***/


if (!gdk_gl_drawable_make_current(gldrawable, glcontext)){
printf("\nError al buscar area OpenGL");
return FALSE;
}
/*Vectores que definen el tipo de material*/
GLfloat ambient [] = { 0.1, 0.1, 0.1, 0.0 };
GLfloat specular []= { 1.0, 1.0, 1.0, 1.0 };
GLfloat shininess [] = { 100.0 };

glClearColor(0.0, 0.0, 0.0, 0.0);


glShadeModel(GL_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_DEPTH_TEST);

/*Definicin del tipo de material de los objetos a dibujar*/


glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

/*Posicin de las luces*/


glLightfv(GL_LIGHT0, GL_POSITION, position0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

/*Se habilitan las luces*/


glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

/*Crear las diferentes partes del robot compilando las listas de despliegue*/
crear_base(SLICES, STACKS);
crear_hombro();
crear_brazo1(SLICES, STACKS);
139
crear_codo();
crear_brazo2(SLICES, STACKS);
crear_munieca(SLICES, STACKS);
crear_mano(SLICES, STACKS);

return TRUE;
}

/* Reajustar el tamao de la ventana OpenGL*/


gboolean reshape(int w, int h){
/*Buscar area OpenGL*/
GdkGLContext *glcontext = gtk_widget_get_gl_context (glarea1);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (glarea1);
/*** OpenGL INICIO ***/
if (!gdk_gl_drawable_make_current(gldrawable, glcontext)){
printf("\nError al buscar area OpenGL");
return FALSE;
}
/*Prevenir la divisin por cero*/
if(h==0){h=1;};
/*Define el area de dibujo de la ventana*/
glViewport(0, 0, (GLint)w, (GLint)h);
/*Se carga la Matriz de proyeccin*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/*Volumen de visin de la camara*/
glOrtho(-1*zoom_z*w/h, zoom_z*w/h, -1*zoom_z, zoom_z, -1200, 1200);
/*Posicin de la camara en la escena*/
gluLookAt(camara_x, camara_y, camara_z, 0, 0, 0, 0, 1, 0);

/*Se mueva la camara */


glRotatef(angulo_xr, 1.0, 0.0, 0.0);
glTranslatef(ancho_x, altura_y, 0.0);
glRotatef(angulo_yr, 0.0, 1.0, 0.0);

glMatrixMode(GL_MODELVIEW);

/*Mover la luces. Luces siguen a la camara*/


glPushMatrix();
glRotatef(-1*angulo_yr, 0.0, 1.0, 0.0);
glTranslatef(-1*ancho_x, -1*altura_y, 0.0);
glRotatef(-1*angulo_xr, 1.0, 0.0, 0.0);
glLightfv(GL_LIGHT0, GL_POSITION, position0);
glPopMatrix();
return TRUE;
}

/*************************************************************************************************************/

main.c: Funcin principal de la aplicacin


/***************************************************************************
* SimQNK
* Simulador virtual del brazo robot Stubli RX90 L
* main.c: funcin principal del programa
* Copyright(C) 2006 David Cuenca
* Email: dcuenc@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
140
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <gtk/gtk.h>

#include "ventanagl.h"
#include "dibujo.h"
#include "rutina.h"
#include "interface.h"
#include "callbacks.h"

int main (int argc, char *argv[])


{
/* Se establecen los parametros de configuracin inicial del simulador*/
checkmax=1; //Se verifican los ang. mximos
checkcolision=1; //Se detiene en el primer choque
mover_obj = 1; //El objeto seleccionado es el robot
lim=0;
grid=0; //Piso solido
altpiso=0.0; //Sin base externa
marg=0.0; //margen de precaucin=0

/*Incializar GTK*/
gtk_set_locale ();
gtk_init (&argc, &argv);

/*Creary desplegar las ventanas de la aplicacin*/


ventana1 = create_window1 ();
gtk_widget_show (ventana1);
ventana3 = create_window3 ();
gtk_widget_show (ventana3);
ventana2 = create_window2 ();
gtk_widget_show (ventana2);

/*Inicializar los valores de posicin de la camara y el robot*/


inicio();
valores_iniciales_camara();
valores_iniciales_robot();
init_vortexfijos(marg);

/*Crear los puntos de control de colisin*/


crear_controles();

/*Lazo infinito del que nunca se sale*/


gtk_main ();
return 0;
}

/*************************************************************************************************************/
141

You might also like