Informe - Escuela de Ingeniería Eléctrica

Transcripción

Informe - Escuela de Ingeniería Eléctrica
Universidad de Costa Rica
Facultad de Ingeniería
Escuela de Ingeniería Eléctrica
IE-502 Proyecto Eléctrico
Diseño de una aplicación para el iPhone® para el
control del Stäubli® RX90 L
Por:
Gabriel Valverde Zúñiga
Ciudad Universitaria Rodrigo Facio
Diciembre del 2011
Diseño de una aplicación para el iPhone® para el
control del Stäubli® RX90 L
Por:
Gabriel Valverde Zúñiga
Sometido a la Escuela de Ingeniería Eléctrica
de la Facultad de Ingeniería
de la Universidad de Costa Rica
Como requisito parcial para optar por el grado de:
BACHILLER EN INGENIERÍA ELÉCTRICA
Aprobado por el Tribunal:
______________________________
Ing. Mauricio Espinoza Bolaños
Profesor Guía
____________________________
____________________________
Ing. Marco Villalta Fallas
Ing. Jaime Cascante, Ph.D.
Profesor lector
Profesor lector
ii
DEDICATORIA
Dios.
A mi madre por ser ese soporte, apoyo
incondicional y siempre pero siempre creer
en mí, aun en los momentos más oscuros de
todo el proceso que me hizo llegar hasta
aquí. A mi abuela, sin ella nada de esto
hubiera sido posible. A Don Gabriel Zúñiga a
quien por su apoyo, confianza y consejos le
dedico mi proyecto final. Los amo.
Gracias.
iii
RECONOCIMIENTOS
Un agradecimiento a Mauricio Espinoza por apoyar mi idea y ayudarme a llevarla
hasta el final. Gracias por su comprensión, confianza y entender mi forma de trabajar.
A mis tutores Dr. Jaime Cascante y Ing. Marco Villalta por el apoyo y sugerencias.
A la Escuela de Ingeniería Eléctrica de la Universidad de Costa Rica, por abrirme
las puertas, darme varias lecciones y guiarme hasta acá. Sus conocimientos dados se
honraran.
iv
ÍNDICE GENERAL
ÍNDICE DE FIGURAS .................................................................................................... VII
ÍNDICE DE TABLAS ..................................................................................................... VIII
NOMENCLATURA ........................................................................................................... IX
RESUMEN ........................................................................................................................... X
CAPÍTULO 1: INTRODUCCIÓN ................................................................................. 11
1.1.1 Objetivo general ................................................................................................. 11
1.1.2 Objetivos específicos .......................................................................................... 12
1.2 METODOLOGÍA .............................................................................................................. 13
CAPÍTULO 2: DESARROLLO TEÓRICO ................................................................. 14
2.1 INTRODUCCIÓN .............................................................................................................. 14
2.2 OBJECTIVE-C ................................................................................................................. 14
2.2.1 Objetos ................................................................................................................ 15
2.2.2 Uso de Instancias ................................................................................................ 15
2.2.3 Clases .................................................................................................................. 15
2.2.4 Interface & Implementation Clases .................................................................... 15
2.3 XCODE ........................................................................................................................... 17
2.3.1 Introducción ........................................................................................................ 17
2.3.2 Frameworks ........................................................................................................ 18
2.4 COCOA ........................................................................................................................... 18
2.4.1 Model View Controller ....................................................................................... 20
2.5 NETWORKING................................................................................................................. 20
2.5.1 Descripción General de los Protocolos TCP/IP .................................................. 21
2.5.2 Sockets ................................................................................................................ 21
CAPÍTULO 3: DISEÑO DE LA APLICACIÓN Y EL MOTOR DE
COMUNICACIÓN ..................................................................................................... 23
3.1 DISEÑO DE LA APLICACIÓN ............................................................................................ 23
3.1.1 Conexión al Robot .............................................................................................. 24
3.1.2 Inicialización ...................................................................................................... 27
3.1.3 Configuración ..................................................................................................... 27
3.1.4 Instrucciones ....................................................................................................... 29
3.1.5 Rutina.................................................................................................................. 31
3.2 DISEÑO DE LA COMUNICACIÓN....................................................................................... 34
3.2.1 Programa en LabVIEW ...................................................................................... 35
3.2.2 Programa en el iPhone ........................................................................................ 37
CAPÍTULO 4: VALIDACIÓN ....................................................................................... 41
CAPÍTULO 5: CONCLUSIONES Y RECOMENDACIONES .................................. 42
5.1 CONCLUSIONES .............................................................................................................. 42
5.2 RECOMENDACIONES....................................................................................................... 42
v
BIBLIOGRAFÍA ................................................................................................................ 43
APÉNDICES ....................................................................................................................... 46
A. CÓDIGO DE LA APLICACIÓN PARA EL IPHONE ................................................................. 46
A.1 Conexión a Robot ............................................................................................... 46
A.2 Inicializacion ...................................................................................................... 59
A.3 Configuracion ..................................................................................................... 61
A.4 Instrucciones ....................................................................................................... 66
A.5 Drive ................................................................................................................... 73
A.6 Rutina.................................................................................................................. 92
vi
ÍNDICE DE FIGURAS
Figura 2.2-1 Concepto básico de un objeto .......................................................................... 14
Figura 2.2-3 Interface & Implementación [2] ...................................................................... 16
Figura 2.3-1 Workspace de Xcode ....................................................................................... 17
Figura 2.3-2 Simulador del iOS............................................................................................ 18
Figura 2.4-1 Las capas que forman parte del iOS [4] ........................................................... 19
Figura 2.4-2 Model View Controller [19] ............................................................................ 20
Figura 3.1-1 Diagrama del entorno grafico de la aplicación ................................................ 24
Figura 3.1-2 Pantalla Principal de la Aplicación .................................................................. 25
Figura 3.1-3 Pantalla del MenuViewController ................................................................... 26
Figura 3.1-4 Organización del menú dentro de la aplicación. .............................................. 26
Figura 3.1-5 Junturas del robot Stäubli® RX90 L [31] ........................................................ 28
Figura 3.1-6 Ventana de Configuración ............................................................................... 29
Figura 3.1-7 Ventana de Instrucciones ................................................................................. 30
Figura 3.1-8 Ventana para mover articulación ..................................................................... 30
Figura 3.1-9 Ventana de Rutina............................................................................................ 32
Figura 3.1-10 Alerta para introducir nombre del Programa ................................................. 33
Figura 3.1-11 Ventana para crear rutina ............................................................................... 33
Figura 3.1-12 Registro de instrucciones ............................................................................... 34
Figura 3.2-1 Modelo de comunicación utilizado .................................................................. 34
Figura 3.2-2 Bloques para cerrar el puerto serial ................................................................. 35
Figura 3.2-3 Bloque TCP para abrir la conexión ................................................................. 36
Figura 3.2-4 Bloque de Lectura por TCP ............................................................................. 36
Figura 3.2-5 Estructura de funcionamiento en LabVIEW .................................................... 37
Figura 3.2-6 Código para establecer la conexión ................................................................. 38
Figura 3.2-7 Envió de datos y desconexion.......................................................................... 39
Figura 3.2-8 Envió del comando do Ready .......................................................................... 40
vii
ÍNDICE DE TABLAS
Tabla 3.2-1 Configuración del Bloque VISA ....................................................................... 35
Tabla 3.2-2 Parámetros del bloque de lectura de LabVIEW ................................................ 36
viii
NOMENCLATURA
API: interfaz de programación de aplicaciones
SDK: “Software Development Kit”
Bundle: estructura que contiene el código ejecutable y los recursos utilizados.
IB: “Interface Builder”
IDE: entorno de desarrollo integrado
iDevice: dispositivo electrónico de Apple
iOS: sistema operativo del iPhone
O.O.: orientado a objetos
UI: “User Interface”
V+: Lenguaje de Programación de alto nivel utilizado para el control del Stäubli® RX90 L
LabVIEW: “Laboratory Virtual Instrumentation Engineering Workbench”
TCP/IP: “Transmission Control Protocol / Internet Protocol”
VISA: “Virtual Instrument Software Architecture”
ix
RESUMEN
Este proyecto consistió en desarrollar una aplicación para el iPhone® capaz de
controlar el robot Stäubli® RX90 L. El desarrollo de aplicaciones para dispositivos móviles
es un tema poco común en la Universidad de Costa Rica, por lo que el proyecto pretende
ser un motivador para un futuro desarrollo e implementación de diversas funciones en
plataformas móviles tanto para control de dispositivos como para complemento de los
estudios.
Ya que se debía manipular información vía inalámbrica así como enviar comandos a
través del puerto serial se utilizó el software LabVIEWTM, un programa para pruebas,
control y diseño mediante un entorno de programación gráfica, como motor de
comunicación entre el robot y la aplicación.
El resultado final del proyecto fue la creación de una interfaz que le permite al
usuario navegar con facilidad dentro de la aplicación, la misma integra a su vez un medio
de comunicación capaz de conectarse al programa de comunicación de LabVIEW TM. Esto
último permitió el control del robot mediante el envío de comandos del lenguaje requerido
por el robot, V+.
Finalmente entre los puntos que se recomienda implementar están: el procesamiento
de video, la creación de un modelo gráfico del robot que permita emular el mismo para ver
su funcionamiento antes de enviar el programa o instrucción al robot, además del aspecto
de encriptación para que la aplicación sea más segura, ya que este último factor no se tomó
en cuenta para la elaboración de la aplicación.
x
11
Capítulo 1: Introducción
La revolución de los teléfonos inteligentes en los últimos años ha sido sorprendente,
cada vez estos dispositivos son más comunes, más accesibles, más rápidos, e integran más
funciones con el objetivo de facilitar la vida del usuario.
Desde la aparición del iPhone en el 2007 nace un mercado que crece cada vez a un
paso más acelerado, como lo son las tiendas de aplicaciones, donde cualquier persona
puede crear su aplicación y distribuirla ya sea de forma gratuita o pagada, en este último
caso las compañías cobran una comisión que varía entre el 25% al 30% de las ventas totales
de la misma.
Para el caso de este proyecto se ve que el App Store, tienda de aplicaciones de
Apple, para finales del 2011, tuvo ingresos totales de aproximadamente 3900 millones de
dólares, donde el 70% fue distribuido entre los programadores de las 500 mil aplicaciones
que posee esta tienda. [37]
No solo es un aspecto económico, sino que poco a poco estos dispositivos integran
funciones que anteriormente solo poseían las computadoras, por lo que hace posible el
manejo de muchas funciones en la marcha; ya sea correo electrónico, finanzas, redes
sociales, así como, lectura de archivos, control remoto de dispositivos e inclusive el hogar.
En este proyecto se adoptó el modelo llamado Modal-View-Controller, el cual
permite un mejor mantenimiento y sostenibilidad a la aplicación, de manera tal que se le
permita al programador agregar funciones e instrucciones más adelante.
Además se complementa la programación del robot a través de un lenguaje llamado
V+ con una aplicación para el iPhone, el propósito del proyecto fue crear una aplicación
sencilla capaz de simplificar y optimizar las tareas que se deba realizar el operario con el
brazo de manera que no sea necesario tener conocimiento en lenguaje V+.
1.1.1 Objetivo general

Elaborar una aplicación para dispositivos iPhone®, utilizando el SDK de Apple®,
mediante comunicación inalámbrica de modo que esta sea un medio de control para
el Robot RX90L.
12
1.1.2 Objetivos específicos

Crear una aplicación para el iPhone® con una interfaz gráfica capaz de facilitar al
usuario el posicionamiento, la programación y configuración del robot Stäubli®
RX90 L.

Modificar un módulo de comunicación, utilizando el lenguaje de programación
LabVIEW™, que permita la interacción entre el robot Stäubli® RX90 L y la
aplicación para el iPhone®.

Utilizar una red inalámbrica como medio de comunicación, manipulando el
protocolo TCP/IP para el control del robot RX90 L.

Crear un manual de usuario donde se muestren los pasos necesarios para la
utilización la aplicación realizada.
13
1.2 Metodología
El proyecto se divide en 2 etapas:

Diseño de una aplicación para el iPhone.

Integración de la comunicación serial en un programa de LabVIEW ya existente, el
cual originalmente está diseñado para comunicarse vía inalámbrica por medio del
protocolo TCP. Este programa es el motor encargado de la comunicación entre el
robot Stäubli® RX90 L y la aplicación para el iPhone.
La primera etapa tuvo un periodo de investigación, ya que esta fase requirió
aprender el lenguaje Objective C y su uso en el paquete de desarrollo de software de Apple,
Xcode. Una vez recopilada la información se elaboró la interfaz gráfica de la aplicación
para el iPhone.
En una segunda etapa, se realizó una investigación acerca de la manipulación de
información por vía inalámbrica, ya que este es el método utilizado para manipular el robot.
También se tuvo que integrar los comandos del lenguaje de programación V+, lenguaje de
programación utilizado por el robot Stäubli® RX90 L.
Finalmente se redactó un manual que describe cómo utilizar la aplicación, de
manera tal que le permita al usuario controlar el robot para realizar las tareas necesarias.
14
Capítulo 2: Desarrollo teórico
2.1 Introducción
La aplicación consta de una parte visual, el código que habilita la funcionabilidad y
la integración del manejo de los comandos del robot por vía inalámbrica para que los
mismos sean procesados por el programa en LabVIEW.
Debido a que el núcleo del proyecto radica en la creación de la aplicación, la nota
teórica aborda los conceptos básicos de la programación por objetos, se analiza el entorno
de programación para el iPhone y finalmente se describe los protocolos de comunicación
TCP/IP, debido a que este fue el medio utilizado para la transmisión de datos.
2.2 Objective-C
Objective-C es un lenguaje de programación que se crea en la década de 1980 y es
una extensión del lenguaje C.
Las clases en Objective C son las mismas que las de otros lenguajes de
programación orientado a objetos. Una clase encapsula las propiedades, métodos y forma
un programa construyendo bloques. Este funciona enviando mensajes entre sí. En un
lenguaje de programación orientado a objetos, los objetos son los elementos básicos del
diseño, en el caso de la figura 2.2-1, se aprecia como Vehículo es el objeto principal, hay
dos tipos de Vehículos, marinos y terrestres, estos a su vez tienen varios tipos. Estos tipos
son objetos también.
Figura 2.2-1 Concepto básico de un objeto
15
2.2.1 Objetos
Objective C utiliza una estructura para crear una clase. Por ejemplo: se crea una
clase denominada Automóvil, por lo que se le solicita a esta clase crear un Automóvil, lo
que este devuelve es un objeto. El objeto realmente es un espacio de memoria, por lo que el
objeto Automóvil es una instancia de la clase Automóvil.
En Objective-C una clase tiene métodos. Un método es similar a una función, ya
que tiene un nombre, un tipo de retorno y espera una lista de parámetros. Si desea que un
objeto ejecute el código en uno de sus métodos, se envía un mensaje a ese objeto.
2.2.2 Uso de Instancias
Una instancia de una clase u objeto tiene un ciclo de vida: se crea, manda mensajes
y se elimina una vez que ya no se utiliza. Para crear un objeto se crea un puntero y se le
asigna un espacio de memoria. En el ejemplo 2.2-1 se crea un objeto denominado
myString, a este se le asigna un espacio de memoria con el método alloc e inicializa con el
método init.
Ejemplo 2.2-1
NSString* myString = [[NSString alloc] init];
2.2.3 Clases
Una clase es una construcción que se utiliza como un modelo para crear objetos de
ese tipo. El modelo describe el estado y el comportamiento que todos los objetos de la clase
comparten.
2.2.4 Interface & Implementation Clases
Objective-C requiere que la interfaz e implementación de una clase estén en bloques
de código separados. El archivo de interfaz, normalmente posee el sufijo .h, se utiliza para
definir una lista de todos los métodos y propiedades que la clase va a utilizar. Esto es útil
para otras piezas de código, incluyendo Interface Builder1. El archivo de implementación,
posee el sufijo .m, contiene el código de los métodos en una clase. En esta sección se
encuentra todos los algoritmos de los métodos que se declararon en la interface. Desde un
1 El interface builder es la sección gráfica del Xcode donde que asocia las entradas y salidas con los métodos
16
punto de vista gráfico la figura 2.2-4 muestra como la interface es la parte externa del
programa e implementación es lo que le da la funcionabilidad al programa. [1]
Figura 2.2-2 Interface & Implementación [2]
Sección de interface:
El formato general de esta sección se muestra en el ejemplo 2.2-2, donde se declara
el nombre de la clase, dentro de los paréntesis se incluyen todos los objetos que se van a
utilizar y fuera de estos se especifican las propiedades de los mismos así como los métodos
a utilizar en la sección de implementación
Ejemplo 2.2-2
@interface NewClassName: ParentClassName {
memberDeclarations;}
methodDeclarations;
@end
Sección de implementación:
Como se explicó anteriormente en esta sección se incluye el código necesario para
desarrollar el programa, como se muestra en el ejemplo 2.2-3.
Ejemplo 2.2-3
@implementation NewClassName
methodDefinitions;
@end
17
2.3 Xcode
2.3.1 Introducción
Xcode es el IDE, entorno de desarrollo integrado, en el cual se programa el sistema
operativo del iPhone, iOS. La interfaz de Xcode se aprecia en la figura 2.3-1, es un
programa que posee varias herramientas muy útiles entre ellas están: diferentes formas de
compilación y programación utilizando una interfaz gráfica, Interface Builder. [4]
Xcode tiene integrado los frameworks Cocoa y Cocoa Touch, este último es la base
para la programación del iPhone.
En la figura 2.3-2, se aprecia el iOS Simulator, el cual permite ejecutar la aplicación
como si fuera en un verdadero dispositivo de marca Apple. Su utilidad es verificar el
correcto funcionamiento de la aplicación, de manera tal que le sea más sencillo al usuario
depurar la aplicación antes de cargarla en el dispositivo real. El iOS Simulator cuenta con
varias limitaciones, ya que su funcionamiento depende de los frameworks que se carguen.
Por lo que es una herramienta útil, mas no reemplaza el factor de probar la aplicación en el
dispositivo. [4]
Figura 2.3-1 Workspace de Xcode
18
Figura 2.3-2 Simulador del iOS
2.3.2 Frameworks
Los Frameworks son librerías que incluyen el código necesario para manipulación
de video, red, gráficos, entre otros. Estas librerías permiten que el código escrito funcione.
La mayoría de estos frameworks, son incorporados por Apple. Pero estos no forman parte
de la aplicación una vez que es instalada en el iDevice, ya que el dispositivo cuenta con los
frameworks incorporados por defecto.
2.4 Cocoa
Cuando se programa para el iOS, se cuenta con la ventaja de un conjunto de
frameworks los cuales son proporcionados por Apple. Estos frameworks, en conjunto
constituyen Cocoa, existe una variación de Cocoa para el iPhone, Cocoa Touch, el cual es
el API, interfaz de programación de aplicaciones para el iOS. Por lo tanto Cocoa juega un
papel fundamental en el rol de la programación del iOS; el código escrito, en su totalidad
tendrá comunicación con los frameworks de Cocoa, con el fin de hacer una aplicación que
hace lo que quiere que haga. Los frameworks son de gran ayuda ya que se le proporciona al
programador funcionalidad subyacente de que cualquier aplicación iOS tiene que tener.
19
Por ejemplo una aplicación puede poner una ventana, mostrar una interfaz que
contenga un botón y este botón pude ser utilizado por el usuario para responder a una
acción. [4]
Apple describe las tecnologías implementadas dentro del iOS como una serie de
capas, en cada capa existen diferentes frameworks que pueden ser aprovechados en la
aplicación. Por lo que Cocoa Touch se encuentra en la capa superior como se muestra en la
figura 2.4-1. [17]
Figura 2.4-1 Las capas que forman parte del iOS [4]
Como se mencionó anteriormente cada capa posee funciones específicas,
dependiendo de la complejidad de la aplicación y las funciones que se requieran, así serán
los frameworks que se deben de incluir.

Cocoa Touch: La capa de Cocoa Touch se compone de varios frameworks que
proporcionará la base funcionalidad para sus aplicaciones.

Media Layer: El iPhone puede crear complejos gráficos, audio y vídeo, e incluso
generar gráficos en tiempo real en 3D.

Core Services: La capa de Core Services se utiliza para el acceso de bajo nivel de
servicios del sistema operativo, tales como el acceso a archivos, redes y muchos
tipos comunes de objetos de datos

Core OS: El Core OS layer, se compone de los servicios de más bajo nivel en el
iOS. Estas características incluyen temas como: cálculos matemáticos complejos,
accesorios de hardware, y la criptografía. En muy raras circunstancias se debe de
acceder a estos frameworks. [17]
20
2.4.1 Model View Controller
Model View Controller (MVC, por sus siglas en inglés) define una clara separación
entre componentes de las aplicaciones, consta de tres partes como se aprecia en la figura
2.4-2: [19]

Model: En esta sección es donde se lleva a cabo toda la lógica del programa.

View: es lo que el usuario ve e interactúa con él.

Controller: El medio entre el model y el view.
Figura 2.4-2 Model View Controller [19]
2.5 Networking
TCP/IP es una serie de protocolos desarrollados para permitir a los dispositivos
conectados en una red compartir recursos.
El nombre exacto para el conjunto de protocolos es el "Internet Protocol Suite".
Debido a que TCP e IP son los más conocidos de los protocolos, es común el uso del
término TCP/IP. Algunos de estos protocolos ofrecen funciones de "bajo nivel" necesarias
para muchas aplicaciones. Entre estas se incluyen IP, TCP y UDP. Los servicios TCP/IP
más importantes son:

Transferencia de archivos.

Inicio de sesión remoto

PC-mail
En un modelo de servicios de red "cliente / servidor", un servidor es un sistema que
proporciona un servicio específico para el resto de la red. Un cliente es otro sistema que
utiliza ese servicio. [30]
21
2.5.1 Descripción General de los Protocolos TCP/IP
Nivel TCP
La información se transfiere como una secuencia de "datagramas". Un datagrama es
un conjunto de datos que se envían como un solo mensaje. Cada uno de estos datagramas se
envía a través de la red de forma individual. Existen ciertas disposiciones para abrir las
conexiones y mantener la comunicación. Sin embargo, en algún nivel, la información de
dichas conexiones se divide en datagramas y estos son tratados de forma independiente por
la red.
TCP es responsable de asegurarse de que los comandos llegan hasta el otro extremo.
Se realiza un seguimiento de lo que se envía y retransmite todo lo que no pasó. Si algún
mensaje es demasiado grande para un datagrama, por ejemplo: el texto del mail, TCP lo
divide en varios datagramas y se asegura de que todos ellos hayan llegado correctamente.
Se podría por lo tanto decir que TCP forma una librería de rutinas, que las
aplicaciones pueden usar cuando requieren una comunicación confiable, a través de la red,
con otra computadora. Al igual que TCP, IP se puede decir que es una librería de rutinas
que TCP llama, pero a su vez está disponible para aplicaciones que no usan TCP.
Nivel IP
TCP envía cada uno de estos datagramas a IP. Por lo que le tiene que decir al
protocolo IP la dirección de Internet del equipo en el otro extremo, esto es prácticamente lo
único que le incumbe al protocolo IP. No importa lo que está en el datagrama, o incluso en
la cabecera de TCP. El trabajo de IP es encontrar una ruta para el datagrama y llevarlo al
otro extremo.
2.5.2 Sockets
Los sockets son un mecanismo que permite a los programas comunicarse, ya sea en
la misma máquina o en una red. Una computadora es un host2 con una serie de sockets. Un
socket es un extremo de la conexión de red y en el otro extremo existe otro socket. Desde
un punto de vista, cualquier socket es un socket local y el socket en el otro extremo de la
conexión es un socket remoto.
2
Computadoras conectadas a una red, que proveen y utilizan servicios de ella
22
Para establecer una conexión, ambos sockets deben de comunicarse entre sí, cada
socket tiene una dirección, que consta de dos partes: la dirección del host y el número de
puerto. La dirección del host es la dirección IP de la computadora, y el número de puerto
identifica de forma única cada socket alojado en el equipo. Una vez que se han conectado
ambos sockets, estos podrán intercambiar información.
23
Capítulo 3: Diseño de la aplicación y el motor de comunicación
El proyecto consta de un período de aprendizaje del lenguaje Objective-C. Una vez
que se familiariza con el lenguaje de programación se procede con las dos etapas definidas
en la metodología:

La creación de una aplicación para el iPhone que sea amigable al usuario, que le
permita navegar a través de ella con comodidad, enviar comandos, crear programas
y ejecutar los mismos para controlar el robot Stäubli® RX90 L.

El uso de un motor de comunicación, de manera tal que no solo le permita al iPhone
comunicarse con el programa LabVIEW, sino enviar comandos en el lenguaje V+ y
recibir la respuesta de la misma manera.
El desarrollo se organizará de la siguiente manera, en la primera parte se explicará
el diseño de la aplicación, algoritmo utilizado para cada view y subview, así como los
comandos que serán enviados.
En una segunda parte se detalla acerca del diseño del motor de comunicación, que
protocolo se utilizó, el diseño del Cliente-Servidor, el detalle de los bloques utilizados en
LabVIEW y finalmente se especifica cómo se logró la comunicación con el iPhone.
3.1 Diseño de la aplicación
La aplicación se construyó con una plantilla proporcionada por Xcode llamada
Navigation-Based Application. Esta plantilla se utilizó porque ya tiene configurada una UI,
con un navigation controller, el cual permite el despliegue de un listado de ítems.
Si bien es cierto en la aplicación no se utiliza el listado, la configuración del
navigation controller, a diferencia de las otras plantillas permite un manejo más sencillo de
varios subviews. Además, como está previamente configurada, el código para la inserción
de nuevos elementos como botones, la configuración del título de la barra, entre otros, está
incluido de una vez.
El diseño de la aplicación consta de cuatro subviews, estos a su vez poseen un
subview cada uno, como se puede apreciar en la Figura 3.1-1.
El IDE para el SDK del iPhone, tiene la posibilidad de organizar el programa por
grupos, cada grupo corresponde a cada uno de los elementos de la figura 3.1-1.
24
Figura 3.1-1 Diagrama del entorno grafico de la aplicación
3.1.1 Conexión al Robot
Este grupo se compone de las siguientes clases:

RobotControlAppDelegate

RootViewController

MenuViewController
Donde los más importantes son RootViewController y el MenuViewController
RootViewController
Las funciones de este view son las siguientes:

Establecer la comunicación con el programa LabVIEW3.

Pasar a la “ventana” del MenuViewController.
En la figura 3.1-2 se muestra la pantalla correspondiente al RootViewController
3
En la sección de Diseño de Comunicación se define como se establece la comunicación con LabVIEW
25
Figura 3.1-2 Pantalla Principal de la Aplicación
La función del botón Conectar es iniciar o terminar la comunicación por vía
inalámbrica a través del socket, este botón tiene dos estados, si se presiona una vez abre el
puerto por el cual se va a efectuar la comunicación, si se presiona nuevamente cierra el
puerto, inhabilitando la comunicación.
El textView opera como un notificador, de manera tal que si se establece la
comunicación correctamente, mostrara el siguiente mensaje:
“Ha sido aceptado el Cliente: host:port”
Donde el host indica la dirección IP del cliente y el puerto por el cual se conectó.
En caso de desconexión se muestra el siguiente mensaje:
“Se ha desconectado el Cliente: host:port”
MenuViewController
Este controlador es el motor encargado de la navegación dentro de la aplicación. En
esta clase se define cual botón activa cierto view. Es importante recalcar que el manejo de
los views de Inicializacion, Configuracion, Instrucciones y Rutina se hace a través de un
Tab Bar, tal y como se puede apreciar en el recuadro azul de la Figura 3.1-3.
26
Figura 3.1-3 Pantalla del MenuViewController
Es también en esta sección donde se crean los botones respectivos del navigation
bar. Estos botones se crean de forma programática, como se verá más adelante.
En la Figura 3.1-4 se muestra la organización del MenuViewController dentro de la
aplicación. Esta será la pantalla que se desplegará una vez que se presionó el botón GO en
el RootViewController.
Figura 3.1-4 Organización del menú dentro de la aplicación.
27
3.1.2 Inicialización
En la clase de Inicializacion se ejecutan cuatro acciones:

Encender el robot Stäubli® RX90 L.

Apagar el robot

Enviar el comando de V+, do Ready, el cual pone en posición inicial el robot.

Pasar al view de Messages
Se declaran dos métodos los cuales serán los encargados de ejecutar la acción al
presionar el botón o el switch. El código para cada una de las acciones se aprecia en el
archivo Implementation en la sección de anexos.

viewDidLoad: le pone título al navigation bar.

btnPower: envía los comandos del lenguaje V+, dis Po, para apagar el robot o en Po
para encenderlo.

doReady: envía el comando do Ready del lenguaje V+, para posicionar el robot en
su posición inicial.
3.1.3 Configuración
En esta clase se ejecutan cinco acciones:

Enviar el comando V+: LEFTY

Enviar el comando V+: RIGHTY

Definir la velocidad general de los movimientos de las junturas

Definir el porcentaje de carga máxima del robot

Pasar al view de Messages
De acuerdo con las especificaciones del fabricante4, la carga máxima que puede
soportar el robot a velocidad nominal es de 3.6kg. A velocidad reducida la carga máxima
que puede soportar es de 9kg. Estas capacidades a su vez están directamente relacionadas
con la inercia de las junturas 5 y 6, estas junturas se pueden observar en el recuadro azul de
la figura 3.1-5. El fabricante define velocidad reducida como el 60% de la velocidad
nominal. Esta última no se tomó en cuenta a la hora de elaborar el programa, por lo que se
define la carga de 3.6kg como el 100% de la carga máxima.
4
Para mayor información acerca de las especificaciones del robot ver [31].
28
Figura 3.1-5 Junturas del robot Stäubli® RX90 L [31]
En el caso de la velocidad, se considera como la velocidad máxima el parámetro
dado por la hoja del fabricante, el cual corresponde a 12.6 m/s. Por lo que se define como el
100% de la velocidad. La figura 3.1-6 corresponde a la pantalla que resume todos los
parámetros mencionados anteriormente. [31]
29
Figura 3.1-6 Ventana de Configuración
3.1.4 Instrucciones
En esta clase se ejecutan las siguientes acciones:

Ir a posición

Acercar a alguna posición

Alejar de la posición

Mover

Una opción para ejecutar el movimiento en línea recta
La ventana correspondiente a Instrucciones se puede observar en la figura 3.1-7. La
opción de ir a posición utiliza el comando de V+ move x y en caso de querer que el robot se
mueva a la posición en línea recta se envía el comando moves x. Donde x se refiere al
nombre de la posición. Para el caso de querer que el robot se acerque a cierta posición se
envía el comando apro o si se habilita la opción de línea recta el comando que se estará
enviando será apros. De manera similar aplica para la opción alejar, donde se utiliza el
comando depart o si se habilita la opción que se aleje en línea recta el comando departs será
el que se envía. Dado que se desea que la instrucción se realice de manera inmediata, se
escribe el comando do antes de esta.
30
Figura 3.1-7 Ventana de Instrucciones
El botón mover despliega la pantalla mostrada en la figura 3.1-8.
Figura 3.1-8 Ventana para mover articulación
31
El algoritmo en esta parte del programa toma las siguientes consideraciones:

El robot se encuentra en la posición de inicio Ready, por lo que cada vez que se
ingresa a esta pantalla el robot envía la instrucción do Ready antes de poder realizar
cualquier movimiento.

Los ángulos máximos de cada juntura se definieron de acorde con las
especificaciones del fabricante, se tomó en consideración especial el rango de
movimiento de la juntura 2, ya que al introducir el ángulo máximo negativo
colisionaba con el conector del robot, lo que ocasionó que el mismo se desconectara
y su restablecimiento dificultoso.

Se introdujo un contador de grados que le indica al usuario cuantos grados tanto
positivos como negativos quedan disponibles.

La opción send solo se puede utilizar cuando el comando drive este completo, esto
significa que: el text field debe de poseer el siguiente formato: drive a, b, c, donde a
es la juntura (1 a 6), b es la ángulo (depende de la juntura) y la velocidad c la cual
varia de 1 a 100. Si alguno de estos valores no se introduce la instrucción no se
enviará5.

En caso de que el usuario exceda el valor del rango de movimiento se muestra una
alarma indicando que al ángulo introducido excede los valores definidos por el
fabricante.

El nombre de la posición debe de tener algún valor de lo contrario la posición no se
memorizará y se despliega una alerta indicando que no se ha introducido ningún
valor.

Finalmente, cada vez que se envía el comando do drive o here, este se almacena en
un arreglo, que se definió como una variable global para poderlo desplegar en el
textView de la pantalla de PosicionViewController.
3.1.5 Rutina
En esta clase se ejecutan las siguientes acciones:
5

Cargar el programa

Crear Programa
El comando drive va acompañado de do, para que ejecute la instrucción de manera inmediata.
32
Cargar el programa
Para cargar un programa este se lleva a cabo mediante la función de V+, ex x,
donde x es el nombre del programa, tal y como se muestra en la figura 3.1-9. Al igual que
las instrucciones anteriores si esta opción se encuentra vacía no enviará ninguna
instrucción.
Figura 3.1-9 Ventana de Rutina
Para entrar a la pestaña de crear programa, se le pregunta al usuario primero el
nombre del programa. Por lo que cuando se introduce el nombre del programa, se envía el
comando, ed x, donde x nuevamente se refiere al nombre del programa tal y como se
muestra en la figura 3.1-10.
CrearRutinaViewController
Al igual que el controlador RutinaViewController, la misma posee las opciones
existentes en esa ventana, mover, acercar, alejar en línea recta o no. Asi como la opción de
posición de inicio, Ready. También se incluye la instrucción delay, lo cual provoca que el
robot espere el tiempo determinado antes de continuar con el programa.
También se habilita la opción para que el usuario que tenga conocimiento del
lenguaje V+, introduzca la instrucción deseada.
33
Figura 3.1-10 Alerta para introducir nombre del Programa
La ventana para crear el programa se muestra en la figura 3.1-11.
Figura 3.1-11 Ventana para crear rutina
El movimiento de articulación se incluye también en esta sección, ya que en muchas
ocasiones el usuario debe de introducir un nuevo movimiento. El botón de instrucciones
lleva un registro de todas las instrucciones que van formando parte del programa.
Una vez que el usuario ha terminado la rutina y presiona el botón Back, se envía el
comando e, el cual indica que la creación de la rutina ha finalizado.
34
Con la opción Instrucciones se habilita la pantalla de la figura 3.1-11, esta pantalla
tiene como función llevar un registro de todas las instrucciones que se van introduciendo en
la rutina, el botón Leer actualiza el textView, el cual despliega todas las instrucciones tal y
como se puede observar en la figura 3.1-12.
Figura 3.1-12 Registro de instrucciones
3.2 Diseño de la comunicación
Para establecer la comunicación se planteó un modelo de capas como se muestra en
la figura 3.2-1. Donde las capas inferiores implementan el establecimiento y el manejo de la
sesión cliente/servidor, para la comunicación vía inalámbrica se utiliza el protocolo TCP
mediante el uso de sockets. La serializacion de los objetos a transmitir se lleva a cabo
mediante la Transmisión del Mensaje y como última capa se encuentra la aplicación móvil.
Mobile App
Transmisión del Mensaje
Sesión cliente/servidor
Comunicación Vía Inalámbrica
Figura 3.2-1 Modelo de comunicación utilizado
35
Para lograr lo anterior la sección de comunicación se divide en dos:

Programa en LabVIEW, el cual fue el cliente.

Comunicación por TCP/IP en el iPhone, servidor.
3.2.1 Programa en LabVIEW
Este programa consta de dos secciones:

Protocolo de Comunicación Serial

Protocolo de Comunicación TCP
Comunicación Serial
Para establecer la comunicación entre la computadora la cual contiene el vi y el
brazo robótico a través del puerto serial se utilizó el bloque VISA6.
La configuración del puerto se muestra en la tabla 3.2-1.
Tabla 3.2-1 Configuración del Bloque VISA
Timeout
10000s
VISA resource name
Interface
Baud rate
9600
Data bits
8
Parity
0: none
Stop Bits
1
Flow Control
0: none
En el programa se utiliza tanto el bloque VISA de lectura como el de escritura, para
finalizar se utiliza la configuración mostrada en la figura 3.2-3.
Figura 3.2-2 Bloques para cerrar el puerto serial
La cual cierra el puerto de manera tal que si otro dispositivo desea utilizar el puerto
este quede disponible.
6
Para mayor información acerca de la comunicación serial, consultar la sección de ayuda de LabVIEW
36
Comunicación TCP/IP
La comunicación utilizando el protocolo TCP/IP es sencilla en LabVIEW ya que
elimina el uso de código el cual se tendría que elaborar en C++ o Java o cualquier otro
lenguaje de programación ya que básicamente se requiere de los siguientes bloques:
El bloque de abrir conexión
Figura 3.2-3 Bloque TCP para abrir la conexión
Lo significativo de los bloques de la figura 3.2-3 es que únicamente se requiere de
la dirección IP y el puerto para establecer la conexión con otro dispositivo7. El número de
puerto es un entero sin signo de 16 bits, que va desde 0 hasta 65535. [28]
El bloque de lectura
Figura 3.2-4 Bloque de Lectura por TCP
El bloque de la figura 3.2-4 lee un número de bytes de una conexión de red TCP,
devolviendo los resultados de los datos de salida.
La configuración utilizada requiere de los parámetros mostrados en la tabla 3.2-2.
Tabla 3.2-2 Parámetros del bloque de lectura de LabVIEW
Conexión ID
Es una conexión de red la cual identifica la conexión IP
Bytes to read
Es el número de bytes que se leerán
Timeout ms
Especifica el tiempo, en milisegundos, que el modo de espera antes de
informar de un error de tiempo de espera.
data out
Contiene los datos que fueron leídos por la conexión TCP
error out
Contiene la información del error
Basado en la información anterior, el funcionamiento es el siguiente: se establece la
conexión por el puerto y la dirección IP indicada por el usuario, luego se utiliza una
7
Para mayor información acerca de la comunicación inalámbrica, consultar la sección de ayuda de LabVIEW
37
estructura flat, la cual consiste en una serie de cuadros que se ejecutan secuencialmente,
donde primero el bloque de TCP de lectura escribe en el indicador la instrucción enviada
por el iPhone, esta información a la vez pasa al bloque de VISA de escritura y envía la
información en forma de texto al controlador del robot. Para evitar la latencia en la
siguiente parte de la estructura flat se lee los bytes en el puerto. El funcionamiento se puede
observar en la figura 3.2-6.
Figura 3.2-5 Estructura de funcionamiento en LabVIEW
3.2.2 Programa en el iPhone
Para la lograr una comunicación entre el iPhone u otros dispositivos mediante una
red inalámbrica, se consideraron las siguientes opciones:

Bonjour para la detección de dispositivos

Utilizar directamente los sockets BSD

Utilizar Asynsockets
El uso de Bonjour es útil ya que no hubiera sido necesario incluir la dirección IP y
el puerto en el programa de LabVIEW ya que Bonjour lo hace de forma automática.
Lamentablemente su integración en LabVIEW era laboriosa por lo que se concentró en la
comunicación entre el programa de LabVIEW y el iPhone.
El uso de Asynsockets presenta grandes ventajas, las cuales se discutieron en el
capítulo 2. La conexión se establece en la clase denominada RootViewController. Donde
primero se crean dos objetos uno denominado listenSocket el cual pertenece a la clase
AsyncSocket que es el responsable de realizar la conexión. Y otro objeto denominado
connectedSockets, un arreglo por el cual se envía y se reciben los datos.
El código de la figura 3.2-6 muestra cómo se inicia conexión con algún dispositivo
u programa, haciendo uso del protocolo TCP/IP primero se verifica si la conexión ya está
establecida mediante el booleano denominado isRunning, luego utiliza el puerto 34445, el
38
cual se eligió de forma aleatoria. La definición del puerto se encuentra en la cabecera del
archivo de RootViewController.m.
Después verifica si existe algún error o un puerto indebido, si lo anterior es
verdadero una alarma se mostrará indicando que ha ocurrido un error a la hora de establecer
la conexión. Si no hay error se establece la conexión utilizando el objeto listenSocket el
cual indica el puerto que se utilizará. En caso de que no se requiera la conexión se envía el
mensaje de desconexión.
Código para establecer la conexión
- (IBAction)startStop:(id)sender
{
if(!isRunning)
{
int port = PORTNUM;
NSError *error = nil;
if(![listenSocket acceptOnPort:port error:&error])
{
[self conectMessage:FORMAT(@"Error starting server: %@", error)];
return;
}
[self conectMessage:FORMAT(@"WIFI Server started on port %hu",
[listenSocket localPort])];
isRunning = YES;
[startStopButton setTitle:@"Stop" forState:UIControlStateNormal];
[startStopButton setTag:1];
}else{
[listenSocket disconnect];
int i;
for(i = 0; i < [connectedSockets count]; i++)
{
[[connectedSockets objectAtIndex:i] disconnect];
}
[self conectMessage:@"Stopped WIFI Server"];
isRunning = false;
[startStopButton setTitle:@"Start" forState:UIControlStateNormal];
[startStopButton setTag:2];
}
}
Figura 3.2-6 Código para establecer la conexión
En la figura 3.2-7 se muestra el código para el envío de datos y desconexión del programa
de LabVIEW.
39
“Handshake”, Envió de datos y desconexión
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket
*)newSocket
{
[connectedSockets addObject:newSocket];
}
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host
port:(UInt16)port
{
[self conectMessage:FORMAT(@"Ha sido aceptado el Cliente: %@:%hu\n",
host, port)];
NSString *welcomeMsg = @"Acaba de Conectarse al iPhone\r\n";
NSData *welcomeData = [welcomeMsg
dataUsingEncoding:NSUTF8StringEncoding];
[sock writeData:welcomeData withTimeout:-1 tag:WELCOME_MSG];
}
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0];
}
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data
withTag:(long)tag
{
NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length] 1)];
NSString *storeData=[[NSString alloc] initWithData:strData
encoding:NSUTF8StringEncoding];
[sock writeData:storeData withTimeout:-1 tag:ECHO_MSG];
}
Figura 3.2-7 Envió de datos y desconexion
El código para enviar comandos de V+ a través del socket se muestra en la figura
3.2-8. El comando do Ready se envía como un string, el cual es codificado y enviado a
través del socket por el arreglo connectedSockets.
Todos los comandos poseen el mismo formato, algunas instrucciones poseen
básicamente el mismo contenido, mas presentan ciertas variaciones, como se puede
apreciar en la sección de anexos.
40
Envío del comando do Ready a través del socket
NSString *doReadyMsg = @"do Ready\n";
NSData *doReadyData=[doReadyMsg dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:doReadyData withTimeout:-1 tag:0];
}
Figura 3.2-8 Envió del comando do Ready
41
Capítulo 4: Validación
El diseño de la aplicación logró enviar las instrucciones de manera exitosa, además
fue fácil para el usuario con una leve explicación desarrollar un programa así como a la
hora de marcar los puntos donde se quería que llegara el robot.
Se realizaron varias pruebas con distintas personas sin conocimiento del
funcionamiento del robot, para observar que tan sencillo era el manejo del mismo
utilizando la aplicación. En su mayoría con una simple explicación entendían el
funcionamiento de la aplicación. Todos los usuarios fueron capaces de operar el brazo con
facilidad ya que coincidieron que el programa era muy intuitivo.
Durante el periodo de pruebas aparecieron las siguientes limitaciones:

La latencia entre LabVIEW y el iPhone se solucionó con una estructura flat para
que primero leyera los bytes en el puerto y luego los escribiera, de manera tal que la
latencia fuera únicamente el tiempo de espera de 300ms, tiempo suficiente para que
el robot escribiera en el bloque VISA.

En la pantalla de mensajes se debía de escribir la respuesta del robot, se intentó de
varias maneras con diversas configuraciones, pero cuando se leía la respuesta del
robot, el programa se saturaba ya que al unir el bloque VISA de lectura con el
bloque TCP de escritura la cantidad de datos enviada al iPhone sobrepasaba lo que
podía leer.

Se separaron las instrucciones en views así como la creación de rutinas y el manejo
de las junturas de manera que es más sencillo la operación y creación de programas.
Capítulo 5: Conclusiones y recomendaciones
5.1 Conclusiones
1. Se elaboró una aplicación para dispositivos iPhone®, utilizando el SDK de Apple®,
que es un medio de control para el robot RX90L.
2. Se implementó un contador de grados en el código que permite al usuario nunca
salirse del rango específico del robot.
3. Se modificó un programa en LabVIEW que funciona como motor de comunicación
entre el robot y el iPhone®.
5.2 Recomendaciones
Son varias las recomendaciones que se dejan para el desarrollo de la aplicación entre ellas
están:

Realizar una aplicación universal para que pueda correr en dispositivos iPads.

Mejorar el manejo de lectura por TCP de la respuesta del robot, ya que por falta de
tiempo la lectura no es eficaz, si se implementa un algoritmo que permita mantener
la respuesta en el indicador hasta que el iPhone lo lea y este mande un mensaje de
que lo leyó de manera adecuada podría solucionar el problema.

Integrar una mayor cantidad de comandos de V+, tanto para el manejo de las
entradas y salidas analógicas del robot así como ciclos while, for e if entre otros.

Incluir una parte de transmisión de video para monitorear los movimientos del robot
en tiempo real.

Incluir un modelo del robot en 3D en el iPhone, que contenga el mismo algoritmo
de movimiento del robot para poder utilizar el modelo y programar el movimiento
antes de siquiera mover el robot, con lo que se podría tener un manejo más
adecuado del mismo.
42
Bibliografía
Libros
[1] Brannan J., “iPhone™ SDK Programming: A Beginner’s Guide”, McGraw-Hill,
Estados Unidos, 2010.
[2] Apple Inc., “The Objective-C 2.0 Programming Language Cocoa: Objective-C
Language”, Estados Unidos, 2009.
[3] Kochan, S., “Programming in Objective-C 2.0”, Pearson Education, Inc., Estados
Unidos, 2009.
[4] Nueburg M., “Programming iOS 4”, O’Reilly, Estados Unidos, 2011.
[5] Hillegas, A., “Cocoa® programming for Mac® OS X”, Pearson Education, Inc.,
Estados Unidos, 2008.
[6] Lee W., “Beginning iPhone® SDK Programming with Objective-C®”, Wiley
Publishing, Inc., Estados Unidos, 2010.
[7] Apple Inc., “Cocoa Fundamentals Guide: General”, Estados Unidos, 2010.
[8] Tejkowski, E., “Cocoa® programming for Mac® OS X for Dummies”, Wiley
Publishing, Inc., Estados Unidos, 2009.
[9] Hillegas, A. Conway J., “iPhone Programming: The big nerd ranch guide”, Big
Nerd Ranch, Inc., Estados Unidos, 2010.
[10] Apple Inc., “Your First iOS Application: General”, Estados Unidos, 2010.
[11] Zdziarski, J., “iPhone SDK Application Development”, Primera Edición, O'Reilly
Media, Inc., Estados Unidos, 2009
[12] Knaster, S. Dalrymple M., “Learn Objective-C on the Mac”, Apress, Estados
Unidos, 2009.
[13] Apple Inc., “Object-Oriented Programming with Objective-C”, Estados Unidos,
2010.
[14] Allan A., “Learning iPhone Programming”, O'Reilly Media, Inc., Estados
Unidos, 2010.
[15] Alessi
P.,
“Professional
iPhone®
and
iPad™
Database
Programing”, Wiley Publishing, Inc., Estados Unidos, 2011.
43
Application
44
[16] Wagner R., “Professional iPhone™ and iPod® touch Programming”, Wiley
Publishing, Inc., Estados Unidos, 2008.
[17] Ray J., “Sams Teach Yourself iPhone Application Development in 24 Hours”,
Segunda Edición, Pearson Education, Inc., Estados Unidos, 2011.
[18] Sadun E., “The iPhone™ Developer’s Cookbook”, Pearson Education, Inc.,
Estados Unidos, 2009.
[19] Anderson F., “Xcode 3 Unleashed”, Pearson Education, Inc., Estados Unidos,
2009.
[20] Dudney B., Adamson C., “iPhone SDK Development: Building iPhone
Applications”, The Pragmatic Bookshelf, Estados Unidos, 2009.
[21] Apple Inc., “Stream Programming Guide Networking & Internet: Protocol
Streams”, Estados Unidos, 2009.
[22] Apple Inc., “CFNetwork Programming Guide Networking & Internet”, Estados
Unidos, 2011.
[23] Mark D., LaMarche J., “Beginning iPhone 3 Development: Exploring the iPhone
SDK”, Apress, Estados Unidos, 2009.
[24] Pilone D., Pilone T., “Head First iPhone and iPad Development”, O’Reilly
Media, Inc., Estados Unidos, 2011.
[25] Clemmens A., “Introduction to Cocoa Programming for Mac OS X”, Holanda,
2008
[26] Mark D., LaMarche J., “More iPhone 3 Development: Tackling iPhone SDK 3”,
Apress, Estados Unidos, 2009.
[27] Hockenberry C., “iPhone App Development: The Missing Manual”, O’Reilly
Media, Inc., Estados Unidos, 2010.
[28] Comer D., “Internetworking with TCP/IP Vol I: Principles, Protocols, and
Architecture”, Cuarta Edicion, Prentice Hall, Estados Unidos, 2000.
[29] Dix A., “Unix Network Programming with TCP/IP iPhone SDK Development:
Building iPhone Applications”, Short Course Notes, 1996.
[30] Leiden C., Wilensky M., “TCP/IP for Dummies”, Sexta Edicion, Wiley
Publishing, Inc., 2009.
45
[31] Staübli Faverges. “Staübli RX Series 90 Family General Description”. Adept
Technology Inc. Noviembre del 2004
Páginas Web
[32] “Xcode” Consultado en Agosto, 26, 2011 en:
http://developer.apple.com/library/mac/#featuredarticles/XcodeConcepts/ConceptProjects.html#//apple_ref/doc/uid/TP40009328-CH5-SW1
[33] “Xcode”, Consultado en Agosto, 26, 2011 en:
http://developer.apple.com/library/mac/#documentation/ToolsLanguages/Conceptua
l/Xcode4UserGuide/Introduction/Introduction.html
[34] “Xcode”, Consultado en Agosto, 26, 2011 en:
http://developer.apple.com/technologies/tools/
[35] “CS 193P iPhone Application Development”, Consultado en Setiembre, 2, 2011 en:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-fall
[36] “Asyncsocket” Consultado en Setiembre, 20, 2011 en:
http://code.google.com/p/cocoaasyncsocket/
[37] “UIViewController” Consultado en Noviembre, 2, 2011 en:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewContr
oller_Class/Reference/Reference.html
[38] “App
Store:
Consultado
en
Noviembre,
5,
2012
http://9to5mac.com/2011/07/07/apple-issues-app-store-stats-15b-downloads425000-apps-nearly-3-6b-revenue/
en:
46
Apéndices
A. Código de la aplicación para el iPhone
A continuación se presenta el código utilizado en cada una de las partes de la aplicación.
Cada sección consta de un archivo interface, sufijo .h y un archivo de implementación,
sufijo .m.
A.1

Conexión a Robot
RootViewController
// RootViewController.h
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
#import "MenuViewController.h"
@class AsyncSocket;
NSMutableArray *connectedSockets;
NSMutableArray *readFromRobot;
@interface RootViewController : UIViewController {
AsyncSocket *listenSocket;
UIAlertView *alertMessage;
UIAlertView *alertMessage1;
BOOL isRunning;
IBOutlet UITextView *logView;
IBOutlet UITextView *hideView;
IBOutlet UIButton *startStopButton;
IBOutlet MenuViewController *menuViewController;
}
@property(nonatomic,retain) MenuViewController *menuViewController;
@property (retain, nonatomic) UITextView *logView;
47
@property (retain, nonatomic) UITextView *hideView;
@property (retain, nonatomic) UIButton *startStopButton;
- (IBAction)startStop:(id)sender;
- (IBAction)toMenu;
@end
// RootViewController.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import "RootViewController.h"
#import "AsyncSocket.h"
#define WELCOME_MSG 0
#define ECHO_MSG
1
#define PORTNUM 34445
#define FORMAT(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]
@interface RootViewController (PrivateAPI)
- (void)conectMessage:(NSMutableString *)msg;
@end
@implementation RootViewController
@synthesize menuViewController;
@synthesize logView;
@synthesize startStopButton;
@synthesize hideView;
48
(IBAction)toMenu {
if(!isRunning) {
alertMessage = [[UIAlertView alloc]
initWithTitle:@"No se ha conectado a ningun Cliente"
message:@"Presione conectar"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertMessage show];
}else {
[self.navigationController pushViewController:menuViewController animated:YES];
}
}
#pragma mark #pragma mark View lifecycle
- (void)viewDidLoad {
self.title = @"Conectar al Robot";
NSLog(@"Ready");
listenSocket = [[AsyncSocket alloc] initWithDelegate:self];
connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
readFromRobot = [[NSMutableArray alloc] initWithCapacity:1];
NSLog(@"listenSocket");
isRunning = NO;
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] action:nil];
[self.navigationItem setBackBarButtonItem: backButton];
[backButton release];
}
- (void)conectMessage:(NSMutableString *)msg
{
NSMutableString *message = [NSMutableString stringWithFormat:@"%@\n", msg];
[logView setText:message];
}
49
/******************CONEXION**********************/
#pragma mark NETWORKING
- (IBAction)startStop:(id)sender
{
if(!isRunning)
{
int port = PORTNUM;
NSError *error = nil;
if(![listenSocket acceptOnPort:port error:&error])
{
[self conectMessage:FORMAT(@"Error starting server: %@", error)];
return;
}
[self conectMessage:FORMAT(@"Servidor WIFI iniciado por el puerto %hu",
[listenSocket localPort])];
isRunning = YES;
[startStopButton setTitle:@"Desconectar" forState:UIControlStateNormal];
[startStopButton setTag:1];
}
else
{
// Stop accepting connections
[listenSocket disconnect];
// Stop any client connections
int i;
for(i = 0; i < [connectedSockets count]; i++)
{
// Call disconnect on the socket,
[[connectedSockets objectAtIndex:i] disconnect];
}
50
[self conectMessage:@"Servidor WIFI Detenido"];
isRunning = false;
[startStopButton setTitle:@"Conectar" forState:UIControlStateNormal];
//[disconnect setTitle:@"Connect" forState:UIControlStateNormal];
[startStopButton setTag:2];
}
}
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
[connectedSockets addObject:newSocket];
}
-
(void)onSocket:(AsyncSocket
*)sock
didConnectToHost:(NSString
*)host
port:(UInt16)port
{
[self conectMessage:FORMAT(@"Ha sido aceptado el Cliente: %@:%hu\n", host,
port)];
NSString *welcomeMsg = @"Acaba de Conectarse al iPhone\r\n";
NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding];
[sock writeData:welcomeData withTimeout:-1 tag:WELCOME_MSG];
}
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0];
}
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
[self conectMessage:FORMAT(@"Se ha desconectado el Cliente: %@:%hu", [sock
connectedHost], [sock connectedPort])];
alertMessage1 = [[UIAlertView alloc]
initWithTitle:@"Error por Desconexion"
51
message:@"Volver a Conectar"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertMessage1 show];
}
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
{
[connectedSockets removeObject:sock];
}
- (void)dealloc {
[logView release];
[hideView release];
[alertMessage release];
[alertMessage1 release];
[menuViewController release];
[connectedSockets release];
[super dealloc];
}
@end

RobotControlAppDelegate
// RobotControlAppDelegate.h
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
@interface RobotControlAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
}
52
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@end
// RobotControlAppDelegate.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import "RobotControlAppDelegate.h"
#import "RootViewController.h"
@implementation RobotControlAppDelegate
@synthesize window;
@synthesize navigationController;
#pragma mark #pragma mark Application lifecycle
(BOOL)application:(UIApplication
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[navigationController release];
[window release];
[super dealloc];
}
@end
*)application
53

MenuViewController
// MenuViewController.h
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
#import "DRIVEViewController.h"
#import "MessagesViewController.h"
#import "CrearRutinaViewController.h"
@class AsyncSocket;
@interface MenuViewController : UIViewController {
IBOutlet UITabBar *menuTabBar;
UITextField *userInput;
IBOutlet UIViewController *Inicializacion;
IBOutlet UIViewController *Configuracion;
IBOutlet UIViewController *Instrucciones;
IBOutlet UIViewController *Rutina;
}
@property (nonatomic, retain) UITextField *userInput;
@property (nonatomic, retain) UITabBar *menuTabBar;
@property (nonatomic, retain) UIViewController *Inicializacion;
@property (nonatomic, retain) UIViewController *Configuracion;
@property (nonatomic, retain) UIViewController *Instrucciones;
@property (nonatomic, retain) UIViewController *Rutina;
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
54
// MenuViewController.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import "MenuViewController.h"
#import "AsyncSocket.h"
extern NSMutableArray *connectedSockets;
@implementation MenuViewController
@synthesize menuTabBar;
@synthesize Inicializacion;
@synthesize Configuracion;
@synthesize Instrucciones;
@synthesize Rutina;
@synthesize userInput;
-(void) clearView {
if (Inicializacion.view.superview) {
[Inicializacion.view removeFromSuperview];
}else if (Configuracion.view.superview){
[Configuracion.view removeFromSuperview];
}else if ((Instrucciones.view.superview)) {
[Instrucciones.view removeFromSuperview];
}else {
[Rutina.view removeFromSuperview];
}
}
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
UIBarButtonItem *messagesViewButton = [[UIBarButtonItem alloc]
55
initWithTitle:@"Messages"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(messagesViewAction)];
self.navigationItem.rightBarButtonItem = messagesViewButton;
int index = [tabBar.items indexOfObject:item];
switch (index) {
case 0:
[self clearView];
[self.view insertSubview:Inicializacion.view atIndex:0];
self.title = @"Inicializacion";
self.navigationItem.rightBarButtonItem = messagesViewButton;
break;
case 1:
[self clearView];
[self.view insertSubview:Configuracion.view atIndex:0];
self.title = @"Configuracion";
self.navigationItem.rightBarButtonItem = messagesViewButton;
break;
case 2:
[self clearView];
[self.view insertSubview:Instrucciones.view atIndex:0];
self.title = @"Instrucciones";
UIBarButtonItem *modalViewButton = [[UIBarButtonItem alloc]
initWithTitle:@"Mover"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(modalViewAction)];
self.navigationItem.rightBarButtonItem = modalViewButton;
break;
case 3:
56
[self clearView];
[self.view insertSubview:Rutina.view atIndex:0];
self.title = @"Rutina";
UIBarButtonItem *crearRutinaViewButton = [[UIBarButtonItem alloc]
initWithTitle:@"Crear"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(crearRutinaViewAction)];
self.navigationItem.rightBarButtonItem = crearRutinaViewButton;
break;
default:
break;
}
}
- (void)modalViewAction
{
NSString *doReadyMsg = @"do Ready\n";
NSData
*doReadyData
=
[doReadyMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:doReadyData withTimeout:-1 tag:0];
}
DRIVEViewController *temp = [[DRIVEViewController alloc]
initWithNibName:@"DRIVEViewController" bundle:nil];
[self.navigationController presentModalViewController:temp animated:YES];
[temp release];
}
57
- (void)crearRutinaViewAction
{
UIAlertView *alertDialog;
alertDialog = [[UIAlertView alloc]
initWithTitle: @"Introduzca el nombre del Programa"
delegate: self
cancelButtonTitle: @"Ok"
otherButtonTitles: nil];
userInput=[[UITextField alloc] initWithFrame:
CGRectMake(12.0, 70.0, 260.0, 25.0)];
[userInput setBackgroundColor:[UIColor whiteColor]];
[alertDialog addSubview:userInput];
[alertDialog show];
[alertDialog release];
}
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString
*sendPayloadMsg
=
[[NSString
alloc]
initWithFormat:@"ed
%@\n",userInput.text];
if ([alertView.title
isEqualToString: @"Introduzca el nombre del Programa!"]) {
if ([userInput.text length] != 0) {
sleep(3);
NSData
*sendPayloadData
=
[sendPayloadMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:sendPayloadData withTimeout:-1
tag:0];
58
}
CrearRutinaViewController *temp = [[CrearRutinaViewController alloc]
initWithNibName:@"CrearRutinaViewController" bundle:nil];
temp.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:temp animated:YES];
[temp release];
}
}
[sendPayloadMsg release];
}
- (void)messagesViewAction
{
MessagesViewController *temp = [[MessagesViewController alloc]
initWithNibName:@"MessagesViewController" bundle:nil];
[self.navigationController pushViewController:temp animated:YES];
[temp release];
}
- (void)viewDidLoad
{
[self clearView];
[self.view insertSubview:Inicializacion.view atIndex:0];
self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
self.title = @"Inicializacion";
UIBarButtonItem *messagesViewButton = [[UIBarButtonItem alloc]
initWithTitle:@"Messages"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(messagesViewAction)];
self.navigationItem.rightBarButtonItem = messagesViewButton;
[super viewDidLoad];
}
59
- (void)dealloc {
[userInput release];
[menuTabBar release];
[Inicializacion release];
[Configuracion release];
[Instrucciones release];
[Rutina release];
[super dealloc];
}
@end
A.2
Inicializacion
// InicializacionViewController.h
// RobotControl
//
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
@class AsyncSocket;
@interface InicializacionViewController : UIViewController {
IBOutlet UISwitch *powerSwitch;
IBOutlet UILabel *powerMessage;
}
@property (nonatomic, retain) UISwitch *powerSwitch;
@property (nonatomic, retain) UILabel *powerMessage;
-(IBAction)btnPower:(id)sender;
-(IBAction)doReady:(id)sender;
@end
60
// InicializacionViewController.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "InicializacionViewController.h"
#import "AsyncSocket.h"
extern NSMutableArray *connectedSockets;
@implementation InicializacionViewController
@synthesize powerSwitch;
@synthesize powerMessage;
- (void)viewDidLoad {
self.navigationItem.title = @"Inicializacion";
powerMessage.text=@"dis Po\n";
[super viewDidLoad];
}
-(IBAction)btnPower:(id)sender{
if ([powerSwitch isOn]) {
[powerSwitch setOn:YES animated:YES];
powerMessage.text = @"en Po\n";
NSData *disPower = [powerMessage.text dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:disPower withTimeout:-1 tag:0];
}
}else {
61
[powerSwitch setOn:NO animated:YES];
powerMessage.text = @"dis Po\n";
NSData *enPower = [powerMessage.text dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:enPower withTimeout:-1 tag:0];
}
}
}
-(IBAction)doReady:(id)sender{
NSString *doReadyMsg = @"do Ready\n";
NSData *doReadyData = [doReadyMsg dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:doReadyData withTimeout:-1 tag:0];
}
}
- (void)dealloc {
[powerSwitch release];
[powerMessage release];
[super dealloc];
}
@end
A.3
Configuracion
// ConfiguracionViewController.h
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
62
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
@class AsyncSocket;
@interface ConfiguracionViewController : UIViewController {
IBOutlet UISlider *velJoints;
IBOutlet UILabel *velJointsSpeed;
IBOutlet UISlider *payloadJoints;
IBOutlet UILabel *velJointspayload;
UIAlertView *alertMessage1;
UIAlertView *alertMessage;
}
@property (nonatomic, retain) UISlider *velJoints;
@property (nonatomic, retain) UILabel *velJointsSpeed;
@property (nonatomic, retain) UISlider *payloadJoints;
@property (nonatomic, retain) UILabel *velJointspayload;
- (IBAction)rightyConfig:(id)sender;
- (IBAction)leftyConfig:(id)sender;
- (IBAction) setJointSpeed:(id)sender;
- (IBAction) sendSpeed:(id)sender;
- (IBAction) setJointPayload:(id)sender;
- (IBAction) sendPayload:(id)sender;
@end
// ConfiguracionViewController.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
63
#import "ConfiguracionViewController.h"
#import "AsyncSocket.h"
extern NSMutableArray *connectedSockets;
@implementation ConfiguracionViewController
@synthesize velJoints;
@synthesize velJointsSpeed;
@synthesize payloadJoints;
@synthesize velJointspayload;
/****************** RIGHTY & LEFTY *************************/
-
(IBAction)rightyConfig:(id)sender{
NSString *rightyConfigMsg = @"RIGHTY\n";
NSData *rightyConfigData = [rightyConfigMsg dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:rightyConfigData withTimeout:-1
tag:0];
}
}
-
(IBAction)leftyConfig:(id)sender{
NSString *leftyConfigMsg = @"LEFTY\n";
NSData
*leftyConfigData
=
[leftyConfigMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:leftyConfigData withTimeout:-1 tag:0];
64
}
}
/****************** SPEED OF JOINTS ***********************/
-
(IBAction) setJointSpeed:(id)sender
{
velJointsSpeed.text = [[NSString alloc] initWithFormat:@"%1.0f ",velJoints.value];
}
-
(IBAction) sendSpeed:(id)sender{
alertMessage1 = [[UIAlertView alloc]
initWithTitle:@"Problema al enviar el comando"
message:@"no se introdujo ningun valor de velocidad"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
NSString
*sendSpeedMsg
=
[[NSString
alloc]
initWithFormat:@"speed
%@\n",velJointsSpeed.text];
NSLog(@"El valor de joint speed es: %@",velJointsSpeed.text);
if ([velJointsSpeed.text intValue] == 0) {
[alertMessage1 show];
}else {
NSData
*sendSpeedData
=
[sendSpeedMsg
writeData:sendSpeedData
withTimeout:-1
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
tag:0];
}
objectAtIndex:y]
65
}
[sendSpeedMsg release];
}
/****************** PAYLOAD OF JOINTS ***********************/
-
(IBAction) setJointPayload:(id)sender
{
velJointspayload.text
=
[[NSString
alloc]
initWithFormat:@"%1.0f
",
payloadJoints.value];
}
-
(IBAction) sendPayload:(id)sender{
alertMessage = [[UIAlertView alloc]
initWithTitle:@"Problema al enviar el comando"
message:@"no se introdujo ningun valor de carga"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
NSString
*sendPayloadMsg
=
[[NSString
alloc]
initWithFormat:@"payload
%@\n",velJointspayload.text];
if ([velJointspayload.text length] == 0) {
[alertMessage show];
}else {
NSData
*sendPayloadData
=
[sendPayloadMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:sendPayloadData withTimeout:-1
tag:0];
}
66
}
[sendPayloadMsg release];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)dealloc {
[payloadJoints release];
[alertMessage1 release];
[alertMessage release];
[velJointspayload release];
[velJoints release];
[velJointsSpeed release];
[super dealloc];
}
@end
A.4
Instrucciones
// InstruccionesViewController.h
// RobotControl
//
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
@class AsyncSocket;
@interface InstruccionesViewController : UIViewController {
IBOutlet UISwitch *lineaRecta1;
IBOutlet UITextField *bufGoToPosition;
67
NSString *sendGoToPositionMsg;
IBOutlet UITextField *bufDoApprosPosition;
IBOutlet UITextField *bufDoApprosDistance;
NSString *sendDoApprosMsg;
IBOutlet UITextField *bufDoDepartsPosition;
NSString *sendDoDepartsMsg;
UIAlertView *alertMessageEmptyValue;
}
@property (nonatomic, retain) UISwitch *lineaRecta1;
@property (nonatomic, retain) UITextField *bufGoToPosition;
@property (nonatomic, retain) UITextField *bufDoApprosPosition;
@property (nonatomic, retain) UITextField *bufDoApprosDistance;
@property (nonatomic, retain) UITextField *bufDoDepartsPosition;
- (IBAction)hideKeyboard:(id)sender;
- (IBAction)sendGoToPosition:(id)sender;
- (IBAction)sendDoApprosRecto:(id)sender;
- (IBAction)sendDoDepartsRecto:(id)sender;
@end
// InstruccionesViewController.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
68
#import "InstruccionesViewController.h"
#import "AsyncSocket.h"
extern NSMutableArray *connectedSockets;
@implementation InstruccionesViewController
@synthesize lineaRecta1;
@synthesize bufGoToPosition;
@synthesize bufDoApprosPosition;
@synthesize bufDoApprosDistance;
@synthesize bufDoDepartsPosition;
/************** IR EN LINEA RECTA & DESPLAZAR POSICION **************/
- (IBAction)sendGoToPosition:(id)sender
{
if ([bufGoToPosition isEditing]) {
} else {
if ([lineaRecta1 isOn]) {
[lineaRecta1 setOn:YES animated:YES];
sendGoToPositionMsg
=
[[NSString
alloc]
initWithFormat:@"do
moves
%@\n",bufGoToPosition.text];
if ([bufGoToPosition.text length] == 0) {
[alertMessageEmptyValue show];
}else {
NSData
*sendGoToPositionData
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
=
[sendGoToPositionMsg
69
[[connectedSockets
objectAtIndex:y]
writeData:sendGoToPositionData
withTimeout:-1 tag:0];
}
}
}else {
[lineaRecta1 setOn:NO animated:YES];
sendGoToPositionMsg
=
[[NSString
alloc]
initWithFormat:@"do
move
%@\n",bufGoToPosition.text];
if ([bufGoToPosition.text length] == 0) {
[alertMessageEmptyValue show];
}else {
NSData
*sendGoToPositionData
=
[sendGoToPositionMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
objectAtIndex:y]
writeData:sendGoToPositionData
withTimeout:-1 tag:0];
}
}
}
}
}
/************** IR EN LINEA RECTA & APROXIMAR POSICION **************/
- (IBAction)sendDoApprosRecto:(id)sender
{
if ([lineaRecta1 isOn]) {
[lineaRecta1 setOn:YES animated:YES];
sendDoApprosMsg
=
[[NSString
alloc]
initWithFormat:@"do
%@,%@\n",bufDoApprosPosition.text,bufDoApprosDistance.text];
appros
70
if ([bufDoApprosPosition.text length] == 0 || [bufDoApprosDistance.text length] == 0
){
[alertMessageEmptyValue show];
}
NSData
*sendDoApprosRectoData
=
[sendDoApprosMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
objectAtIndex:y]
writeData:sendDoApprosRectoData
withTimeout:-1 tag:0];
}
} else {
[lineaRecta1 setOn:NO animated:YES];
sendDoApprosMsg
=
[[NSString
alloc]
initWithFormat:@"do
appro
%@,%@\n",bufDoApprosPosition.text,bufDoApprosDistance.text];
if ([bufDoApprosPosition.text length] == 0 || [bufDoApprosDistance.text length] == 0
){
[alertMessageEmptyValue show];
}
NSData
*sendDoApprosRectoData
=
[sendDoApprosMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
withTimeout:-1 tag:0];
}
}
}
objectAtIndex:y]
writeData:sendDoApprosRectoData
71
/************** IR EN LINEA RECTA & ALEJAR POSICION **************/
- (IBAction)sendDoDepartsRecto:(id)sender
{
if ([lineaRecta1 isOn]) {
[lineaRecta1 setOn:YES animated:YES];
sendDoApprosMsg
=
[[NSString
alloc]
initWithFormat:@"do
departs
%@\n",bufDoDepartsPosition.text];
if ([bufDoDepartsPosition.text length] == 0) {
[alertMessageEmptyValue show];
}else {
NSData
*sendDoDepartsRectoData
=
[sendDoApprosMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
objectAtIndex:y]
writeData:sendDoDepartsRectoData
withTimeout:-1 tag:0];
}
}
}else {
[lineaRecta1 setOn:NO animated:YES];
sendDoApprosMsg = [[NSString alloc] initWithFormat:@"do depart %@\n",bufDoDepartsPosition.text
if ([bufDoDepartsPosition.text length] == 0) {
[alertMessageEmptyValue show];
}else {
NSData
*sendDoDepartsRectoData
=
[sendDoApprosMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
objectAtIndex:y]
writeData:sendDoDepartsRectoData
72
withTimeout:-1 tag:0];
}
}
}
}
- (IBAction)hideKeyboard:(id)sender
{
[bufDoDepartsPosition resignFirstResponder];
[bufDoApprosPosition resignFirstResponder];
[bufDoApprosDistance resignFirstResponder];
[bufGoToPosition resignFirstResponder];
}
- (void)viewDidLoad {
alertMessageEmptyValue = [[UIAlertView alloc]
initWithTitle:@"Problema al enviar el comando"
message:@"no se introdujo ningun valor"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[super viewDidLoad];
}
- (void)dealloc {
[lineaRecta1 release];
[bufDoDepartsPosition release];
[bufDoApprosPosition release];
[bufDoApprosDistance release];
[bufGoToPosition release];
[alertMessageEmptyValue release];
[super dealloc];
}
@end
73
A.5

Drive
DriveViewController
// DRIVEViewController.h
// DRIVE
//
// Created by Gabriel Valverde on 9/16/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
#import "PosicionViewController.h"
@class AsyncSocket;
NSMutableArray *results;
@interface DRIVEViewController : UIViewController <UIPickerViewDelegate> {
IBOutlet PosicionViewController *posicionViewController;
IBOutlet UITextView *hiddenView;
NSMutableArray *jointArray;
UIPickerView *toPickerView;
UIButton *doneButton;
UIButton *button1;
UITextField *toTextButton;
IBOutlet UITextField *AngleOfJoint;
IBOutlet UISegmentedControl *angleSign;
IBOutlet UILabel *segmentedLabel;
IBOutlet UISlider *setSpeedOfJoint;
IBOutlet UILabel *SpeedOfJoint;
IBOutlet UITextField *instCompleta;
NSString *compareJoint;
NSString *AngleRateString;
NSString *SpeedRateString;
NSString *actionMessage;
NSString *instMessage;
IBOutlet UITextField *bufMemo;
74
NSString *sendMemoMsg;
/*********Parametros de seguridad**********/
/************* JOINT 1 ********************/
NSNumber *angleNumber;
int n;
int n1;
//ANGLE RANGE
int y;
int z;
NSString *prueba2;
NSString *prueba3;
/************* JOINT 2 ********************/
int a;
int a1;
//ANGLE RANGE
int b;
int c;
NSString *prueba4;
NSString *prueba5;
/************* JOINT 3 ********************/
int d;
int d1;
//ANGLE RANGE
int e;
int f;
NSString *prueba6;
NSString *prueba7;
75
/************* JOINT 4 ********************/
int g;
int g1;
//ANGLE RANGE
int h;
int i;
NSString *prueba8;
NSString *prueba9;
/************* JOINT 5 ********************/
int j;
int j1;
//ANGLE RANGE
int k;
int l;
NSString *prueba10;
NSString *prueba11;
/************* JOINT 6 ********************/
int m;
int m1;
//ANGLE RANGE
int o;
int p;
NSString *prueba12;
NSString *prueba13;
/****maximo valor Positivo & Negativo*****/
IBOutlet UILabel *anguloMaximo;
IBOutlet UILabel *anguloMinimo;
76
UIAlertView *alertMessage1;
UIAlertView *alertMessage2;
UIAlertView *alertMessageEmptyValue;
/*********empty values*******************/
NSString *emptyValue15;
}
@property(nonatomic,retain) UITextView *hiddenView;
@property(nonatomic,retain) IBOutlet UITextField *toTextButton;
@property(nonatomic,retain) IBOutlet UIButton *button1;
@property(nonatomic,retain) UIButton *doneButton;
@property (retain,nonatomic) UITextField *AngleOfJoint;
@property (retain,nonatomic) UISegmentedControl *angleSign;
@property (retain,nonatomic) UILabel *segmentedLabel;
@property (retain,nonatomic) UISlider *setSpeedOfJoint;
@property (retain,nonatomic) UILabel *SpeedOfJoint;
@property (nonatomic, retain) UITextField *bufMemo;
@property (nonatomic, retain) UILabel *anguloMaximo;
@property (nonatomic, retain) UILabel *anguloMinimo;
(IBAction) segmentedControlIndexChanged;
(IBAction)ToButton:(id)sender;
(IBAction)setSpeed:(id)sender;
(IBAction)hideKeyboard:(id)sender;
(IBAction)goBack;
(IBAction)moverPosicion;
(IBAction)sendinstCompleta:(id)sender;
(IBAction)sendinstCompleta1;
(IBAction)sendMemo:(id)sender;
(void)writeInView;
@end
// DRIVEViewController.m
77
// DRIVE
// Created by Gabriel Valverde on 9/16/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import "DRIVEViewController.h"
#import "AsyncSocket.h"
#import "AudioToolbox/AudioToolbox.h"
extern NSMutableArray *connectedSockets;
@implementation DRIVEViewController
@synthesize button1,toTextButton;
@synthesize hiddenView;
@synthesize doneButton;
@synthesize AngleOfJoint;
@synthesize angleSign;
@synthesize setSpeedOfJoint;
@synthesize SpeedOfJoint;
@synthesize segmentedLabel;
@synthesize bufMemo;
@synthesize anguloMaximo;
@synthesize anguloMinimo;
(IBAction)goBack{
[self dismissModalViewControllerAnimated:YES];
}
(IBAction)moverPosicion {
PosicionViewController *temp = [[PosicionViewController alloc]
initWithNibName:@"PosicionViewController" bundle:nil];
temp.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:temp animated:YES];
[temp release];
}
78
/************** MEMORIZAR & ACEPTAR POSICION **************/
(IBAction)sendMemo:(id)sender {
emptyValue15 = [[NSString alloc] initWithFormat:@""];
alertMessageEmptyValue = [[UIAlertView alloc]
initWithTitle:@"Problema al enviar el comando"
message:@"no se introdujo ningun valor"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
sendMemoMsg = [[NSString alloc] initWithFormat:@"here %@",bufMemo.text];
emptyValue15 = bufMemo.text;
if ([emptyValue15 length] == 0) {
[alertMessageEmptyValue show];
}else {
self.hiddenView.text
=
[NSString
stringWithFormat:@"%@%@\n",self.hiddenView.text, sendMemoMsg];
[results addObject:self.hiddenView.text];
//[alertMessageEmptyValue release];
NSData
*sendMemoData
=
[sendMemoMsg
writeData:sendMemoData
withTimeout:-1
dataUsingEncoding:NSUTF8StringEncoding];
int r;
for(r = 0; r < [connectedSockets count]; r++)
{
[[connectedSockets
objectAtIndex:r]
tag:0];
}
}
//[alertMessageEmptyValue release];
}
#pragma mark - Drive Parameters
79
-(IBAction) segmentedControlIndexChanged{
NSString
*segmentedSign=[[NSString
alloc]initWithFormat:@"%@",segmentedLabel.text];
switch (angleSign.selectedSegmentIndex) {
case 0:
self.segmentedLabel.text=@"";
NSLog(@"El signo es %@",segmentedSign);
break;
case 1:
self.segmentedLabel.text=@"-";
NSLog(@"El signo es %@",segmentedSign);
break;
default:
break;
}
[segmentedSign release];
}
// define la velocidad del joint
-(IBAction) setSpeed:(id)sender {
SpeedRateString=[[NSString
initWithFormat:@"%1.0f",setSpeedOfJoint.value];
SpeedOfJoint.text=SpeedRateString;
}
alloc]
80
(IBAction)sendinstCompleta:(id)sender
{
AngleRateString
=[[NSString
alloc]
initWithFormat:@"%@%@",segmentedLabel.text,AngleOfJoint.text];
angleNumber = [NSNumber numberWithInt:[AngleRateString intValue]];
NSLog(@"El signo es %@",AngleRateString);
NSLog(@"El signo es %@",SpeedRateString);
instMessage
=
[[NSString
alloc]
initWithFormat:@"drive
%@,
%@,
%@",compareJoint, AngleRateString,SpeedRateString];
//Store instrucciones //
//NSString
*sendAngleTrial=
[[NSString
alloc]
initWithFormat:@"%@",instMessage];
if ([compareJoint isEqualToString:@"1"]) {
if ([AngleRateString intValue] == 0 || [SpeedRateString intValue] == 0) {
[alertMessage1 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}else {
n = n + [angleNumber intValue];
n1 = n1 - [angleNumber intValue];
y = 160 + n1;
z = -160 - n;
NSNumber *bla3 = [NSNumber numberWithInteger:y];
NSNumber *bla4 = [NSNumber numberWithInteger:z];
if ([bla3 intValue] <= 0 || [bla3 intValue] > 320 || [bla4 intValue] >= 0 || [bla4
intValue] < -320 ) {
[alertMessage2 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
81
n = n - [angleNumber intValue];
y = 160 - n1;
n1 = n1 + [angleNumber intValue];
z = -160 + n;
}else {
prueba2 = [[NSString alloc] initWithFormat:@"%@",bla3];
prueba3 = [[NSString alloc] initWithFormat:@"%@",bla4];
anguloMaximo.text = prueba2;
anguloMinimo.text = prueba3;
instCompleta.text = instMessage;
[self writeInView];
[self sendinstCompleta1];
}
}
} else if ([compareJoint isEqualToString:@"2"]) {
if ([AngleRateString intValue] == 0 || [SpeedRateString intValue] == 0) {
[alertMessage1 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
} else {
a = a + [angleNumber intValue];
a1 = a1 - [angleNumber intValue];
b = 137.5 + a1;
c = -125 - a;
NSNumber *bla5 = [NSNumber numberWithInteger:b];
NSNumber *bla6 = [NSNumber numberWithInteger:c];
if ([bla5 intValue] <= 0 || [bla5 intValue] > 275 || [bla6 intValue] >= 0 || [bla6
intValue] < -275 ) {
[alertMessage2 show];
82
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
a = a - [angleNumber intValue];
b = 137.5 - a1;
a1 = a1 + [angleNumber intValue];
c = -125 + a;
}else {
prueba4 = [[NSString alloc] initWithFormat:@"%@",bla5];
prueba5 = [[NSString alloc] initWithFormat:@"%@",bla6];
anguloMaximo.text = prueba4;
anguloMinimo.text = prueba5;
instCompleta.text = instMessage;
[self writeInView];
[self sendinstCompleta1];
}
}
} else if ([compareJoint isEqualToString:@"3"]) {
if ([AngleRateString intValue] == 0 || [SpeedRateString intValue] == 0) {
[alertMessage1 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}else {
d = d + [angleNumber intValue];
d1 = d1 - [angleNumber intValue];
e = 142.5 + d1;
f = -142.5 - d;
NSNumber *bla7 = [NSNumber numberWithInteger:e];
NSNumber *bla8 = [NSNumber numberWithInteger:f];
if ([bla7 intValue] <= 0 || [bla7 intValue] > 285 || [bla8 intValue] >= 0 || [bla8
intValue] < -285 ) {
[alertMessage2 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
d = d - [angleNumber intValue];
83
e = 142.5 - d1;
d1 = d1 + [angleNumber intValue];
f = -142.5 + d;
}else {
prueba6 = [[NSString alloc] initWithFormat:@"%@",bla7];
prueba7 = [[NSString alloc] initWithFormat:@"%@",bla8];
anguloMaximo.text = prueba6;
anguloMinimo.text = prueba7;
instCompleta.text = instMessage;
[self writeInView];
[self sendinstCompleta1];
}
}
} else if ([compareJoint isEqualToString:@"4"]) {
if ([AngleRateString intValue] == 0 || [SpeedRateString intValue] == 0) {
[alertMessage1 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}else {
g = g + [angleNumber intValue];
g1 = g1 - [angleNumber intValue];
h = 270 + g1;
i = -270 - g;
NSNumber *bla9 = [NSNumber numberWithInteger:h];
NSNumber *bla10 = [NSNumber numberWithInteger:i];
if ([bla9 intValue] <= 0 || [bla9 intValue] > 540 || [bla10 intValue] >= 0 || [bla10
intValue] < -540 ) {
[alertMessage2 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
g = g - [angleNumber intValue];
h = 270 - g1;
g1 = g1 + [angleNumber intValue];
84
i = -270 + g;
}else {
prueba8 = [[NSString alloc] initWithFormat:@"%@",bla9];
prueba9 = [[NSString alloc] initWithFormat:@"%@",bla10];
anguloMaximo.text = prueba8;
anguloMinimo.text = prueba9;
instCompleta.text = instMessage;
[self writeInView];
[self sendinstCompleta1];
}
}
} else if ([compareJoint isEqualToString:@"5"]) {
if ([AngleRateString intValue] == 0 || [SpeedRateString intValue] == 0) {
[alertMessage1 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}else {
j = j + [angleNumber intValue];
j1 = j1 - [angleNumber intValue];
k = 120 + j1;
l = -105 - j;
NSNumber *bla11 = [NSNumber numberWithInteger:k];
NSNumber *bla12 = [NSNumber numberWithInteger:l];
if ([bla11 intValue] <= 0 || [bla11 intValue] > 225 || [bla12 intValue] >= 0 || [bla12
intValue] < -225 ) {
[alertMessage2 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
j = j - [angleNumber intValue];
k = 120 - j1;
j1 = j1 + [angleNumber intValue];
l = -105 + j;
85
}else {
prueba10 = [[NSString alloc] initWithFormat:@"%@",bla11];
prueba11 = [[NSString alloc] initWithFormat:@"%@",bla12];
anguloMaximo.text = prueba10;
anguloMinimo.text = prueba11;
instCompleta.text = instMessage;
[self writeInView];
[self sendinstCompleta1];
}
}
} else if ([compareJoint isEqualToString:@"6"]) {
if ([AngleRateString intValue] == 0 || [SpeedRateString intValue] == 0) {
[alertMessage1 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}else {
m = m + [angleNumber intValue];
m1 = m1 - [angleNumber intValue];
= 270 + m1;
p = -270 - m;
NSNumber *bla13 = [NSNumber numberWithInteger:o];
NSNumber *bla14 = [NSNumber numberWithInteger:p];
if ([bla13 intValue] <= 0 || [bla13 intValue] > 540 || [bla14 intValue] >= 0 || [bla14
intValue] < -540 ) {
[alertMessage2 show];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
m = m - [angleNumber intValue];
= 270 - m1;
m1 = m1 + [angleNumber intValue];
p = -270 + m;
}else {
86
prueba12 = [[NSString alloc] initWithFormat:@"%@",bla13];
prueba13 = [[NSString alloc] initWithFormat:@"%@",bla14];
anguloMaximo.text = prueba12;
anguloMinimo.text = prueba13;
instCompleta.text = instMessage;
[self writeInView];
[self sendinstCompleta1];
}
}
} else {
return;
}
}
// define el boton done del picker view
-(IBAction)ToButton:(id)sender
{
toPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 250, 320,
100)];
[self.view addSubview:toPickerView];
toPickerView.delegate = self;
toPickerView.showsSelectionIndicator = YES;
doneButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[doneButton addTarget:self
action:@selector(ToPickerViewRemove:)
forControlEvents:UIControlEventTouchDown];
doneButton.frame = CGRectMake(265.0,252, 52.0, 30.0);
UIImage *img = [UIImage imageNamed:@"done.png"];
[doneButton setImage:img forState:UIControlStateNormal];
87
//[img release];
[self.view addSubview:doneButton];
}
// Oculta el number keyboard
-(IBAction)hideKeyboard:(id)sender;
{
[AngleOfJoint resignFirstResponder];
[toTextButton resignFirstResponder];
[bufMemo resignFirstResponder];
}
/************** Mover Juntura **************/
(IBAction)sendinstCompleta1 {
NSString
*sendinstCompletaMsg
=
[[NSString
alloc]
initWithFormat:@"do
%@\n",instCompleta.text];
NSData
*sendinstCompletaData
=
[sendinstCompletaMsg
dataUsingEncoding:NSUTF8StringEncoding];
int q;
for(q = 0; q < [connectedSockets count]; q++)
{
[[connectedSockets objectAtIndex:q] writeData:sendinstCompletaData withTimeout:1 tag:0];
}
[sendinstCompletaMsg release];
}
(void)writeInView {
self.hiddenView.text
=
stringWithFormat:@"%@%@\n",self.hiddenView.text, instMessage];
[results addObject:self.hiddenView.text];
}
[NSString
88
// oculta el picker view y el boton de done
-(IBAction)ToPickerViewRemove:(id)sender
{
[toPickerView removeFromSuperview];
[doneButton removeFromSuperview];
}
(void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
(void)viewDidLoad {
results = [[NSMutableArray alloc] initWithCapacity:1];
compareJoint=[[NSString alloc] initWithFormat:@"1"];
self.toTextButton.text = @"1";
//([ intValue] == 0 || [SpeedRateString intValue] == 0)
AngleRateString = @"1";
SpeedRateString = @"50";
self.AngleOfJoint.text = @"1";
SpeedOfJoint.text = @"50";
self.anguloMaximo.text = @"160";
self.anguloMinimo.text = @"-160";
jointArray=[[NSMutableArray alloc]initWithObjects:
@"1",@"2",@"3"
,@"4",@"5",@"6" ,nil];
alertMessage1 = [[UIAlertView alloc]
initWithTitle:@"No se han introducido datos"
message:@"Favor introducir velocidad y/o angulo de juntura"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
89
alertMessage2 = [[UIAlertView alloc]
initWithTitle:@"Angulo del Joint"
message:@"Fuera del rango"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
}
(void)dealloc {
[emptyValue15 release];
[hiddenView release];
[button1 release];
[doneButton release];
[toTextButton release];
[AngleOfJoint release];
[angleSign release];
[segmentedLabel release];
[anguloMaximo release];
[anguloMinimo release];
[setSpeedOfJoint release];
[SpeedOfJoint release];
[alertMessage1 release];
[alertMessage2 release];
[alertMessageEmptyValue release];
[super dealloc];
}
#pragma mark - Picker View datasource
(NSInteger)pickerView:(UIPickerView
numberOfRowsInComponent:(NSInteger)component {
return [jointArray count];
}
*)pickerView
90
(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
(void)pickerView:(UIPickerView
*)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
[toTextButton
setText:[NSString
stringWithFormat:@"%@",[jointArray
objectAtIndex:[pickerView selectedRowInComponent:0]]]];
/************Mensage del Rango de los angulos*****************/
compareJoint=[[NSString
alloc]
initWithFormat:@"%@",[jointArray
objectAtIndex:[pickerView selectedRowInComponent:0]]];
NSLog(@"La juntura es %@",compareJoint);
if ([compareJoint isEqualToString:@"1"]) {
if ([prueba2 intValue]==0 || [prueba3 intValue]==0) {
anguloMaximo.text = @"160";
anguloMinimo.text = @"-160";
}else {
anguloMinimo.text = prueba3;
anguloMaximo.text = prueba2;
}
} else if ([compareJoint isEqualToString:@"2"]){
if ([prueba4 intValue]==0 || [prueba5 intValue]==0) {
anguloMaximo.text = @"137.5";
anguloMinimo.text = @"-125";
}else {
anguloMinimo.text = prueba5;
anguloMaximo.text = prueba4;
91
}
} else if ([compareJoint isEqualToString:@"3"]){
if ([prueba6 intValue]==0 || [prueba7 intValue]==0) {
anguloMaximo.text = @"142.5";
anguloMinimo.text = @"-142.5";
}else {
anguloMinimo.text = prueba7;
anguloMaximo.text = prueba6;
}
} else if ([compareJoint isEqualToString:@"4"]){
if ([prueba8 intValue]==0 || [prueba9 intValue]==0) {
anguloMaximo.text = @"270";
anguloMinimo.text = @"-270";
}else {
anguloMinimo.text = prueba9;
anguloMaximo.text = prueba8;
}
} else if ([compareJoint isEqualToString:@"5"]){
if ([prueba10 intValue]==0 || [prueba11 intValue]==0) {
anguloMaximo.text = @"120";
anguloMinimo.text = @"-105";
}else {
anguloMinimo.text = prueba11;
anguloMaximo.text = prueba10;
}
} else if ([compareJoint isEqualToString:@"6"]){
if ([prueba12 intValue]==0 || [prueba13 intValue]==0) {
anguloMaximo.text = @"270";
anguloMinimo.text = @"-270";
}else {
anguloMinimo.text = prueba13;
92
anguloMaximo.text = prueba12;
}
}
}
// este le pone el nombre a las rows
(NSString
*)pickerView:(UIPickerView
*)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
return [jointArray objectAtIndex:row];
}
// tell the picker the width of each row for a given component
(CGFloat)pickerView:(UIPickerView
widthForComponent:(NSInteger)component {
CGFloat componentWidth =100.0;
//componentWidth = 50.0;// second column is narrower to show numbers
return componentWidth;
}
@end
A.6
Rutina
// RutinaViewController.h
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import <UIKit/UIKit.h>
@class AsyncSocket;
@class RootViewController;
@interface RutinaViewController : UIViewController {
IBOutlet UITextField *bufCargarPrograma;
IBOutlet UITextField *prog;
*)pickerView
93
IBOutlet UITextView *whereText;
UIAlertView *alertMessage;
}
@property (nonatomic, retain) UITextView *whereText;
@property (nonatomic, retain) UITextField *prog;
@property (nonatomic, retain,getter=isEditing) UITextField *bufCargarPrograma;
- (IBAction)sendCargarPrograma:(id)sender;
- (IBAction)doWhere:(id)sender;
- (IBAction)hideKeyboard:(id)sender;
@end
// RutinaViewController.m
// RobotControl
// Created by Gabriel Valverde on 11/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
#import "RutinaViewController.h"
#import "RootViewController.h"
#import "AsyncSocket.h"
extern NSMutableArray *connectedSockets;
extern NSMutableArray *readFromRobot;
@implementation RutinaViewController
@synthesize bufCargarPrograma;
@synthesize whereText;
@synthesize prog;
/************** CARGAR PROGRAMA **************/
- (IBAction)sendCargarPrograma:(id)sender {
NSString *sendCargarProgramaMsg = [[NSString alloc] initWithFormat:@"ex
%@",bufCargarPrograma.text];
if ([bufCargarPrograma.text length] == 0) {
94
[alertMessage show];
}else {
NSData
*sendCargarProgramaData
=
[sendCargarProgramaMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets
objectAtIndex:y]
writeData:sendCargarProgramaData
withTimeout:-1 tag:0];
}
}
[sendCargarProgramaMsg release];
}
/************** UBICAR ROBOT **************/
- (IBAction)doWhere:(id)sender{
NSString *doWhereMsg = @"where";
NSData
*doWhereData
=
[doWhereMsg
dataUsingEncoding:NSUTF8StringEncoding];
int y;
for(y = 0; y < [connectedSockets count]; y++)
{
[[connectedSockets objectAtIndex:y] writeData:doWhereData withTimeout:-1 tag:0];
}
}
- (IBAction)hideKeyboard:(id)sender
{
[bufCargarPrograma resignFirstResponder];
}
- (void)viewDidLoad {
alertMessage = [[UIAlertView alloc]
95
initWithTitle:@"Problema al enviar el comando"
message:@"no se introdujo ningun nombre de programa"
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[super viewDidLoad];
}
- (void)dealloc {
[alertMessage release];
[whereText release];
[bufCargarPrograma release];
[prog release];
[super dealloc];
}
@end

Documentos relacionados