User Tools

Site Tools


Writing /var/lib/dokuwiki/data/meta/teaching/ie0117/proyectos/2015/i/proyecto_2/aplicacion_carro_movil.meta failed
teaching:ie0117:proyectos:2015:i:proyecto_2:aplicacion_carro_movil

This is an old revision of the document!


Marco Antonio Montero Chavarría

Carné: A94000

Aplicación móvil para el carro omni

Objetivo General:

Implementación y creación de una interfaz gráfica para un aplicación móvil que controle los movimientos del carro omnidireccional del arcos lab.

Objetivos específicos:

1. Investigación sobre tecnologías existentes, aplicaciones móviles, código, plataformas utilizadas, ya sea raspberry pi o algún otro micro controlador.

2. Instalación Eclipse Java y JDK.java devoleper tools, para creación de aplicaciones android.

3. Creación interfaz gráfica de la aplicación.

4. Creación de un servidor que escuche una entrada y envié información a un puerto yarp.

5. Conexión de la aplicación al servidor y conexión del servidor con yarp.

6. Puesta en prueba de la aplicación

Justificación

Los medios para la realización de una investigación como esta, presentan una fuente bastante importante de aprendizaje, ya que para el presente trabajo se deben trabajar con distintos lenguajes de programación y más aún entender sobre protocolos de comunicaciones, como por ejemplo tcp/ip. Esto hace de un trabajo como este una fuente integral de conocimiento para futuros trabajos o investigaciones que vayan de la mano con proyectos de programación en plataformas móviles, es decir sentará cierta base teórica y obligará a un esfuerzo extra para la compresión del mismo, que será valiosa a futuro. Además a la larga un sistema simple de movimiento mediante una aplicación móvil permite el acceso a un robot o una plataforma con movimiento en 2D. Permitiría un acceso remoto que puede ayudar a agilizar procesos ya que no se necesitaría un acción directa presencial de un operario sobre el sistema.

===== Parte Proyecto 1 =====

Parte1

La idea principal de esta primera parte yacía en encontrar una plataforma o ambiente de programación, en el cual se pudiera desarrollar una aplicación móvil. Una vez encontrada la misma, estudiar el lenguaje de programación utilizado en la plataforma y crear poco a

poco una aplicación simple que cumpliera con 4 necesidades básicas; crear 4 flechas que apuntaran en las direcciones cardinales: norte, sur, este y oeste. Se decidió por programar la aplicación en el sistema operativo android por encima de IOS. Android es un sistema operativo desarrollado por google con kernel Linux y existen muchos más ejemplos y mucho más documentación que se pueden utilizar de referencia para aprender sobre el mismo, en comparación con IOS. Para el IOS de la empresa Apple la creación de una aplicación móvil es un poco más laboriosa ya que tienen ciertos estándares rigurosos que se deben cumplir y aparte solo pueden ser utilizadas por teléfonos iphone. Android es un sistema más libre y muchos más celulares lo utilizan. Ahora bien, se comenzó por la plataforma android studio de la compañía google, que es la más moderna en la actualidad y la que se puede utilizar por excelencia para la creación de una aplicación android. Para desarroladores principiantes existe una guía en la página oficial de google:

https://developer.android.com/sdk/index.html

En ella se detalla paso a paso como instalar la aplicación y los paquetes necesarios para que la misma funcione debidamente, entre ellos los más importantes son los paquetes del javaSDK que se encarga de las simulaciones y de preparar los emuladores de celulares para el android studio. En si el programa una vez instalado tiene todo para comenzar a programar una aplicación y aparte en la misma página existe un tutorial pequeño que explica cómo hacer un “hello world” y obtenerlo en pantalla.

Es simplemente abrir una serie de archivos “sample” y seguir las instrucciones paso a paso. Desafortunadamente el emulador no puede ser usado para una computadora de 32bits ya que el paquete actualizado HAX. del javaSDK que se encarga de las simulaciones solo sirve en sistemas operativos de 64bits y la versión de 32bits desactualizada no funciona con el android studio nuevo. Debido a esto se debió buscar una solución alterna, y se encontró eclipse java que es una plataforma de programación en java equivalente a dr java, pero más profesional. Esta misma puede ser adjuntada al javaSDK versión de 32bits que tiene lo necesario para hacer simulaciones y creaciones de aplicaciones. Además cabe destacar que para crear una aplicación móvil android se requieren dos cosas, conocimiento básico de lenguaje android nativo y conocimiento quizás basto de java, ya que es mediante a lenguaje de programación java que se crean los métodos necesarios para el funcionamiento de la aplicación. Por su parte el lenguaje android nativo se utiliza para asignación de posición de botones, menus, imágenes, barras de tareas en la aplicación. Primero se debía buscar algún tutorial o apoyo que diera instrucciones para instalación y ejecución de eclipse en conjunto con java SDK. Para efecto se encontró una lección online impartida por la universidad autónoma de Madrid, mediante el sitio virtual Edx. La siguiente página, brinda lo necesario para aprender a usar el ambiente de programación, además aprender a instalar los paquetes de SDK para desarrollo de aplicaciones android:

https://www.edx.org/course/jugando-con-android-aprende-programar-tu-uamx-android301x#!

Las lecciones son impartidas por profesores, se requiere crear un usuario y contraseña e inscribirse en el curso, luego se puede seguir en orden o en desorden el curso de acuerdo a lo que se desee.

Parte 2

Creación aplicación

Se tiene el código Main_activity.java y el activity_main.xml

El archivo .java posee los métodos y variables en lenguaje java, mientras que el .xml posee los parámetros de acomodo de los botones en el layout de la aplicación.

Se buscó crear 4 flechas en la interfaz celular simulada y esto se realizó por el comando image button que existe en el grid layout del programa.

Creando cuatro archivos .png se creó las 4 flechas, luego por medio del comando image button en “images and media” se pueden colocar las imagenes como botones en el layout emulado. Además se crea el código android en el activity_main.

<ImageButton android:id=”@+id/imageButton4” 
android:layout_width=“wrap_content”   
android:layout_height=“wrap_content” 
android:layout_alignLeft=”@+id/imageButton1” 
android:layout_alignStart=”@+id/imageButton1” 
android:layout_centerVertical=“true” 
android:contentDescription=”@string/desc” 
android:src=”@drawable/felchaizquierda” />

Cada botón generó un código similar a este de 6-7 lineas. Este código define los parámetros necesarios de posicionamiento del mismo dentro del gridlayout

Luego se debió poner un actionListener, en este caso conocido como “onclickListener”, al butón para que cuando este sea presionado, suceda algo: se envie un mensaje en pantalla o en consola, enceder, mover, etc. Para este caso se le puso que envié un mensaje “mover hacia x” a consola.

Esto se debe realizar en la parte de java del proyecto, llamado Main Activity.java. Se crea un método privado void setupBotonIzquierda() y así para cada botón, luego se le añade un parámetro que une la imagen a un objeto Button “botónIzquierda” y luego se le añade la capacidad de “escuchar clicks” al butón. Una vez hecho esto se obtiene una pantalla con 4 flechas que al ser clickeadas presentan el mensaje en pantalla “mover hacia (una dirección cardinal)”

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
setupBotonDerecha(); 
setupBotonIzquierda(); 
setupBotonAdelante(); 
setupBotonAtras(); } 
private void setupBotonDerecha(){ 
Button botonderecha = (Button) findViewById(R.id.imageButton3); 
botonderecha.setOnClickListener(newView.OnClickListener() { 
@Override 
public void onClick(View v) {TODO Auto-generated method stub 
Log.i(“Omni”, “Mover derecha”); 
} 
}); 
}''

Y el mismo se repite para cada una de las flechas necesarias

==== Parte Proyecto 2 ====

Parte 1

Modificación código aplicación

Para esta segunda parte se debe hacer cambios en la aplicación android para que la misma pueda enviar datos a un puerto. Utilizando librerías que permitan el uso de sockets y creación de conexiones 1 a 1.

Por lo tanto la aplicación debe crear un cliente socket y enviar información a través del mismo, para que un servidor que este escuchando esta salida pueda tomar los datos enviados.

Se eligió los comandos direccionales de las flechas como la palabra a enviar, “Mover a la derecha” para la flecha derecha y así respectivamente para cada una.

Para la aplicación por lo tanto se tiene el siguiente código en el archivo Main_activity.java que es el que posee, las invocaciones a métodos y variables necesarias de la aplicación.

Se tiene entonces el siguiente código final para la aplicación:

//Main_activity.java inicio 
package com.example.carroomni2; 
import java.io.IOException; 
import java.io.PrintWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import android.annotation.SuppressLint; 
import android.os.Bundle;
import android.view.View; 
import android.widget.Button; 
import android.support.v7.app.ActionBarActivity; 
import android.view.Menu; 
import android.view.MenuItem;
@SuppressLint("WrongViewCast") 
@SuppressWarnings("deprecation") 
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
setupBotonDerecha(); 
setupBotonIzquierda(); 
setupBotonAdelante(); 
setupBotonAtras();
}
private void setupBotonDerecha(){
Button botonderecha = (Button) findViewById(R.id.imageButton3); 
botonderecha.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String message = "Mover a la derecha";
try {
Socket client = new Socket("127.0.0.1", 7000); //conectese al servidor
PrintWriter printwriter = new
PrintWriter(client.getOutputStream(),true);
printwriter.write(message); //escriba el mensaje en la salida
printwriter.flush(); printwriter.close();
client.close(); //termine la conexión
} 
catch (UnknownHostException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace();
}
}
});
};
private void setupBotonIzquierda(){
Button botonIzquierda = (Button) findViewById(R.id.imageButton4); 
botonIzquierda.setOnClickListener(new  View.OnClickListener() {
@Override
public void onClick(View v) {
String message = "Mover a la izquierda";
try {
Socket client = new Socket("127.0.0.1", 7000); //conectese al servidor
PrintWriter printwriter = new
PrintWriter(client.getOutputStream(),true);
printwriter.write(message); //escriba el mensaje en la salida
printwriter.flush();
printwriter.close();
client.close(); //termine la conexión
} catch (UnknownHostException e) {
 e.printStackTrace(); 
} 
catch (IOException e) {
e.printStackTrace();
}
}
});
};
private void setupBotonAdelante(){
Button botonAdelante = (Button) findViewById(R.id.imageButton1); 
botonAdelante.setOnClickListener(new View.OnClickListener() 
{
@Override
public void onClick(View v) {
String message = "Mover hacia Adelante";
try {
Socket client = new Socket("127.0.0.1", 7000); //conectese al servidor
PrintWriter printwriter = new
PrintWriter(client.getOutputStream(),true);
printwriter.write(message); //escriba el mensaje en la salida
printwriter.flush(); printwriter.close();
client.close(); //termine la conexión
}catch (UnknownHostException e) { 
e.printStackTrace(); 
} catch (IOException e) { 
e.printStackTrace();
}
}
});
};
private void setupBotonAtras(){
Button botonAtras = (Button) findViewById(R.id.imageButton2); 
botonAtras.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { 
String message = "Mover hacia Atrás";
try {
Socket client = new Socket("127.0.0.1", 7000); //conectese al servidor
PrintWriter printwriter = new PrintWriter(client.getOutputStream(),true);
printwriter.write(message); //escriba el mensaje en la salida
printwriter.flush(); printwriter.close();
client.close(); //termine la conexión
} catch (UnknownHostException e) {
e.printStackTrace(); 
} catch (IOException e) { 
e.printStackTrace();
}
}
});
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in 
//AndroidManifest.xml.
int id = item.getItemId(); 
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
//Fin

La nueva adición está en los métodos para las flechas, a los mismos se les añade la creación de una conexión por medio de un socket y poniendo un “outputstream” en ese puerto mediante el método “printwriter”. Una vez enviada la información cierra la comunicación para que otros métodos la puedan usar.

Básicamente los métodos escuchan a los “botones imágenes”, una vez que se clickean se envía un mensaje respectivo de ese botón a un puerto. Ese puerto más adelante se verá que se conectado a un servidor.

A esto se le añade el codigo .xml que define los parametros de la descripcion del layout, que se definio en la primera parte.

Luego se debe crear un emulador por medio del sdk manager, correrlo e instalar la aplicacion al mismo para tenerla disponible en el emulador.

Parte 2

Servidor python

La última parte del proyecto consiste en crear un medio de comunicación entre la aplicación y el programa yarp para robótica. Según la página del programa, yarp tiene bindings para python y java, pero por razones de simplicidad y ya que python con bindings de yarp se utilizó en las prácticas del curso, se decidió crear el servidor en lenguaje python.

Básicamente el servidor crea un socket con la ip del host y un puerto. Luego escucha el socket, una vez que hay una conexión entrante se conecta al socket y guarda la información entrante en una variable que luego envía por medio de bindings de yarp a un puerto yarp.

Del otro lado se tiene la información disponible para qué yarp la utilicé en lo que sea necesario.

Código para el servidor python:

//server.py
import sys 
import yarp 
from yarp import BufferedPortBottle as buffport
yarp.Network.init() 
output_port= buffport()
output_port.open("/out")
# Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port server_address = ("127.0.0.1", 7000) 
print >>sys.stderr, 'starting up on %s port %s' % server_address sock.bind(server_address)
# Listen for incoming connections sock.listen(1)
while True: 
# Wait for a connection 
print >>sys.stderr, 'waiting for a connection' connection,client_address = sock.accept() 
try:
print >>sys.stderr, 'connection from', client_address
# recibe datosen tramos y los envia 
while True:
data = connection.recv(32) 
if data:
bottle=output_port.prepare() 
bottle.clear() 
bottle.addString(data) 
output_port.write()
finally:
# Clean up the connection 
connection.close()
//Fin

Con bindings de yarp se crea un puerto /out al que una vez que el servidor reciba una conexión entrante se manda la variable data. Data va a contener 32 caracteres concatenados provenientes del socket.

Por último para observar la salida si se requiere hacer pruebas se debe seguir los pasos de la práctica de laboratorio con yarp server.

1. Correr yarpserver en consola

2. Crear una puerto /read

3. Conectar el puerto /out con /read

4. Poner en función el servidor python para que escuche

5. Enviar un mensaje al socket que está escuchando el servidor.

Conclusiones

El proyecto presentó un reto de aprendizaje basto, debido al desconocimiento del ambiente de programación que se usó, pero a su vez llevo a la adquisición de bastantes horas programación tanto en java, android nativo y python, que serán útiles durante el resto de la carrera y como conocimiento general.

Finalmente se logran cumplir la mayoría de objetivos que se pensaron al inicio del trabajo y el proyecto terminará dejando una base teórica útil para cualquier estudiante, que a futuro necesite un punto de partida para iniciar con un proyecto propio similar o mejorar este mismo en cierto grado.

Referencias

Códigos de prueba útiles

Servidor en java sin bindings de yarp:

//inicio
package servidorjava; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.ServerSocket; 
import java.net.Socket;
public class servidor {
private static ServerSocket serverSocket; 
private static Socket clientSocket; 
private static InputStreamReader inputStreamReader; 
private static BufferedReader bufferedReader; 
private static String message;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(7000); //Socket del Server
} catch (IOException e) {
System.out.println("No se puede oir el puerto 7000");
}
System.out.println("Servidor comenzo a escuchar el puerto 7000");
while (true) { 
try {
clientSocket = serverSocket.accept(); //acceptar conexión del cliente
inputStreamReader = new
InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
//obtener mensaje del cliente message = bufferedReader.readLine();
System.out.println(message); inputStreamReader.close(); clientSocket.close();
} catch (IOException ex) {
System.out.println("Problema al leer el mensaje");
}
}
}
}//fin.

Si se quiere realizar pruebas en el ambiente eclipse sin tener que abrir una interfaz para python. O si se quiere realizar a futuro un servidor java con bindings yarp este es un buen punto de inicio.

Cliente de pruebas para el servidor python:

Para hacer pruebas al servidor python se utilizó el siguiente código para un cliente que envía un mensaje al server.py:

//inicio 
#!/usr/bin/python 
import socket import sys # Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening 
server_address = ("127.0.0.1", 7000) 
print>>sys.stderr, 'connecting to %s port %s' %server_address 
sock.connect(server_address) 
try:
# Send data message = 'Mueva hacia Adelante' 
print >>sys.stderr, 'sending "%s"' % message   
sock.sendall(message)
finally: 
print >>sys.stderr,'closing socket' 
sock.close() 
//fin   

Plataformas 2015/07/17 11:17Marco Antonio Montero Chavarria ====

teaching/ie0117/proyectos/2015/i/proyecto_2/aplicacion_carro_movil.1457364269.txt.gz · Last modified: 2022/09/20 00:08 (external edit)