Table of Contents
Carrito Omnidireccional
Rodríguez Mariana B45842
Fallas Pizarro Ariel B42481
Blanco Arias Sebastián B41005
Hernández Chacón Leonardo B43262
Sotela Gólcher Sebastián B16455
Fonseca Becker Moacir B12581
Zuñiga Calvo Ericka B47835
Descripción del Proyecto:
Se trabajará de manera íntegra el carrito omnidireccional, en donde se abarcará el diseño del hardware, mejoras en la odometría, y además que logre autonomía y pueda evadir obstáculos.
Objetivo general:
Desarrollar de manera integral el carrito omnidireccional.
Objetivos específicos:
A) Odometría del carrito omnidireccional.
Estimar la posición relativa al punto inicial del carrito omnidireccional durante su navegación por medio de odometría.
Habilitar los encoders para leer los datos recibidos del sensor. Medir las velocidades máximas y mínimas del omni y definir mecanismos de transmisión de las mismas para el control. de o Estimado de odometría de la posición x y y , a su vez la orientación a partir de la odometría independiente de cada rueda. Crear la interfaz de la odometría anterior a ROS/Yarp.
B) Diseño e integración del hardware.
Diseñar el circuito PCB, del circuito preexistente mediante el sistema de software KiCad.
Circuito de manejo de motor y circuito de odometría Construcción de PCB Diseñar y construir una estructura funcional al carro omni-direccional, capaz de transportar una laptop, además de cargar otras posibles estructuras robóticas como un brazo robótico. Posicionado adecuado de todos los sensores actuadores y unidades de cálculo. C) Sistema de evasión de obstáculos.
Diseñar un sistema de evasión de obstáculos mediante la utilización del sensor Kinect.
ROS
Poner ROS en funcionamiento Simular un robot móvil
SLAM
Poner en funcionamiento de mapeo en el simulador Crear de mapa con el robot verdadero Localizar utilizando el mapa de arriba en el robot verdadero
Evasión
Explicar los algoritmos existentes para el problema de evasión de obstáculos. Identificar y modificar los módulos en ROS y en Player Project, para reutilizarlos en el proyecto. Poner en funcionamiento utilizando un simulador Adaptar al SLAM y al kinect. Adaptar al sistema completo.
Desarrollo del proyecto e información importante.
Como objetivo principal del proyecto se quiere desarrollar de manera integral el carrito omnidireccional, para esto fue necesario que el mismo volviera a funcionar.
Se hizo una revisión exhaustiva de errores en la protoboard logrando encontrar que un cable que va a la fuente estaba mal colocado. Los cables de tensión son de color azul y los blancos son de tierra (Así se eliminan fuentes de error humanas).
Luego de varias pruebas el carrito funcionó bien. No obstante, cuando se volvió a trabajar en él y se probó este no encendió. Se tuvo que buscar nuevamente un error encontrando que un puente H ( permite a un motor eléctrico DC girar en ambos sentidos, avance y retroceso, además pueden convertir la potencia y disipa el calor) estaba corrido un pin en la protoboard.
Se procedió a arreglar el circuito y verificar que los puentes H estuvieran en buen estado. Para esto se hizo un circuito de prueba para puente H. se puede acceder por medio del siguiente link: http://www.instructables.com/id/Dual-H-Bridge-L298-Breakout-Board-Homemade/
Luego se tuvo que probar continuidad en los elementos del circuito. Además se conectó un generador de señales que entrega 10 V y 3 V a las diferentes partes del circuito. Luego con el osciloscopio digital se midieron los valores de los voltajes para corroborar que el generador estuviera entregando los 5 V respectivos al stm. El stm tiene que entregar 3 V. Por lo que se colocó el osciloscopio en esta parte también.
Con base a la odometría se inició con la parte teórica de la materia y para esto se tienen que hacer diversas suposiciones:
- Movimiento en un plano horizontal
- Rodamiento puro
- No hay deslizamiento en ninguna dirección
- Ejes de rotación ortogonales al plano de la superficie
- El chasis es rígido y las llantas no se deforman
Se partió de los modelos matemáticos encontrados en el libro Autonomous Mobile Robots, del MIT press. Se utilizaron los modelos matemáticos para una rueda sueca, elaborados bajo las suposiciones anteriores. Los parámetros que se debieron medir del robot para poder elaborar el modelo fueron: distancias de largo y ancho, distancias entre el centro másico del robot y cada rueda. Y el diámetro de las ruedas. La ecuación matricial que describe el comportamiento del robot en el plano inercial, con base a parámetros de velocidad medidos desde el plano del robot es:
Donde R(theta) es la matriz ortogonal de rotación que se encuentra en función del ángulo theta (ángulo entre ejes de los dos marcos de referencia, que es positivo anti-horario), que permite “cambiarnos” o transformar los valores de velocidades y posiciones de un marco de referencia al otro. Y donde J1 y C1 son matrices de proyecciones que transforman las velocidades medidas en el marco de referencia de las llantas al marco de referencia en el plano del robot. Estas matrices están en función de los ángulos: α (alfa), β (beta) y γ (gamma), y también en función de la distancia L, parámetros que se midieron para el omni específicamente.
- Largo = 26cm
- Ancho = 24.5 cm
- Diámetro de ruedas = 6 cm
- Gamma = 0.7853 rads (45 grados)
- Alfa 1 = 0.88617 rads
- Alfa 2 = 2.2555 rads.
- Alfa 3 = -0.88617 rads.
- Alfa 4 = -2.2555 rads.
- Beta 1,2,3,4 = 0.6846 rads.
- Distancia entre centro y ruedas = 17.86 cm
Al computar los valores para las matrices necesarias, se obtuvo los resultados siguientes:
La última matriz, es la matriz de velocidades angulares de cada rueda, ésta información se obtiene a partir de los encoders, que son los parámetros de entrada necesarios para el cálculo final de posición del robot.
Circuito PCB
Se logró la esquematización del circuito del carro omnidireccional. Es importante destacar que para esto se debieron de comparar el esquemático pre-existente con el del carro pues no eran exactamente iguales. Por otro lado nos topamos con el problema del funcionamiento del carrito pues en determinado momento dejó de funcionar por lo que no sabíamos si el circuito se encontraba correcto. También se logró hacer un prediseño de la posible estructura del carro en freeCad. Se nos presentaron dificultades como la falta de conocimiento de la herramienta por lo que tuvimos que instruirnos tanto en software de freeCad como KiCad, además de los ya mencionados. Para el diseño de dicha estructura se realizó una búsqueda de modelos de vehículos que cumplieran con ciertas características necesarias para brindar soporte a la computadora que controla el funcionamiento del carro OMNI. Para ello se procedió con la búsqueda de diseños en distintos foros de CAD que ya estuvieran avanzados, para tener que empezar el diseño desde cero y poder hacerle larPas modificaciones necesarias para poder emplearlo en el carro OMNI. La característica requerida consistía en que la carrocería contase con poca aerodinámica, para darle mayor soporte a la computadora. Debido a las complicaciones que podría acarrear el modelo que inicialmente se propuso para la carrocería final, se optó por un diseño más simple realizado en AutoCAD, que consiste en dos pisos, uno de madera, que soporta el circuito y uno de acrílico que soporta la computadora.
La construcción de la PCB requería 3 pasos fundamentales, para la construcción de esta utilizamos el tutorial dispuesto en la página del ARCOSLAB en el siguiente link “wiki.arcoslab.eie.ucr.ac.cr/doku.php/ie0117_proyectos_i_2014:proyecto_1:diseno_de_circuito_impreso_con_kicad_y_cortadora_laser?s[]=caravaca”. El primer paso consistía en la esquematización del circuito, para ello se tuvo que comparar el circuito esquemático ya existente con el que se observaba en el carrito. Este paso es esencial y hay que procurar que todo este correcto. Debido a que de lo contrario el error se seguirá arrastrando y para arreglarlo tendríamos que devolvernos a este paso. Este es la esquematización del circuito.
En el paso siguiente se hizo la lista de componentes necesarios en la construcción y se tomaron sus características de la página de “mouser”, con el fin de poder generar la lista en kicad para comenzar el diseño de la PCB. Una vez elegidos los componentes a utilizar y mandados a comprar, Ahora se le presenta cada asignación correspondiente.
Aquí es de suma importancia conocer las medidas de cada componente que se va a soldar para poder hacer esta lista. Finalmente se realizó el diseño de la tarjeta. Esta fue la parte más dificil de los 3 pasos debido a que se debieron de rediseñar una y otra vez para que los cables pudieran estar bien. A pesar de los múltiples intentos no se logró hacer todas las conexiones en una sola capa, por lo que a la hora de la construcción se deberán de tirar algunos cables que vayan de un pin a otro. Esto debido a que la cortadora que se encuentra a disposición únicamente corta una capa. Se adjunta el diseño final de la PCB, los cables verdes corresponderían a los cables que habría que tirar por encima de la PCB.
Lastimosamente, la construcción del circuito no se pudo llevar a cabo pues la cortadora Láser del ARCOSLAB se descompuso, por lo que no se pudo continuar con la aplicación del químico para remover el cobre necesario y el soldar los componentes electrónicos de la PCB.
Robots Operating System
ROS es un marco de trabajo para el desarrollo de software para robots. Incluye herramientas, librererías y convenciones para facilitar la creación de complejos comportamientos robóticos en diferentes plataformas. Este proyecto de software libre tiene una excelente documentación que incluye tutoriales detallados y buenos foros. La página para iniciar con la instalación es http://wiki.ros.org/indigo/Installation/Ubuntu . Es importante seguir todos los pasos al pie de la letra debido a que cualquier omisión de algún detalle puede provocar la falla del sistema o un paquete de este.
El primer paso es configurar los repositorios de ubuntu para permitir el uso de “universe”, “restricted” y “multiverse”. Como se menciono anteriormente debe asegurarse de configurar las fuentes de software exactamente como dice el tutorial. A la hora de hacer esta documentación se descubrió el error que propició la falla de la mayoría de los paquetes de ROS. Hay una ventanilla que dice “Download from”, y en un principio no se utilizó la opcion “Main Server”.
Luego se debe configurar la computadora para que acepte software de packages.ros.org editando el archivo sources.list . Se debe configurar las llaves, actualizar el índice de paquetes e instalar ros-indigo-desktop-full. Despues se inicializa el manejador de dependencias rosdep y se configura la terminal para que añada las variables de entorno necesitadas por ROS cada vez que se abre una nueva. Además se instala rosinstall para facilitar instalaciones de otros paquetes.
Despues de crear el ambiente se crea el “catkin Workspace” para comenzar a utilizar ROS. Cada paso de como realizar estas cosas se encuentra con detalle en la página, es cuestión de ir en orden. Los archivos de sistema de ROS presentan comandos de consola especializados para facilitar la navegación en este sistema como rospack, roscd y rosls.
Algunos conceptos importantes en el uso general de ROS son los nodos, mensajes, temas y el núcleo. El núcleo o roscore estácompuesto por un proovedor de servicio de nombres (master), salida y error estándar (rosout) y un servidor de parámetros. Roscore debe ser lo primero que se corra al utilizar ROS. Además del núcleo estan los nodos, estos son ejecutables que utilizan el sistema operativo para comunicarse con otros nodos mediante mensajes. El tema se refiere como al canal ya que los nodos publican mensajes a un tema o se suscriben a un tema para recibir mensajes.
Existen diferentes comandos para desplegar información de cada “estructura”, por ejemplo rostopic rosmsg y rosnode combinados con algún argumento. También está el comando rosrun para ejecutar nodos.
Al principio ningún simulador servía, ni siquiera las herramientas como rqt_graph. Se desinstaló e instaló varias veces el sistema operativo y sus paquetes se examinó los tutoriales de forma exhaustiva y no se encontró el error hasta la elaboración de esta documentación. Incluso después de desinstalar e instalar varias veces se introdujó un nuevo error. En una de estas se no se desintaló correctamente ROS, por lo que a la hora de instalarlo no aparecía el archivo setup.bash para añadir las variables de entorno. Se recomienda usar el siguiente comando a la hora de desinstalar ROS:
$ sudo apt-get purge ros-*
Sin embargo después de esto había un par de librerías que quedaron desactualizadas y al actualizarlas se creó un problema de “unmet dependencies”. Los sigueientes comandos fueron necesarios para solucionarlo.
$ sudo apt-get clean
$ sudo apt-get autoclean
$ sudo apt-get -f install
$ sudo dpkg –configure -a
$ sudo apt-get -f install
$ sudo apt-get autoremove
Introducción a la evasión de obstáculos
Para dar una solución eficiente al problema de la evasión de obstáculos,llevamos a cabo una revisión de las diferentes técnicas y algoritmos existentes para su resolución del problema, buscando el que mejor se ajustase a las necesidades y especificaciones determinadas, para posteriormente adaptarlo para que llevara a cabo la tarea, de la manera deseada. Cabe destacar que se planteó reutilizar algoritmos de ROS y posteriormente, utilizando un paquete de simulación bidimensional de esta misma plataforma, para de esta forma visualizar los resultados, y poder especular sobre la implementación física y dar una idea del alcance del proyecto.
El movimiento del robot va a depender de la lectura de los sensores y de su posición inicial. Inicialmente tienen diferentes técnicas para la evasión de obstáculos, entre ellas se tienen:
Bug 2: Rodea Obstáculos, no toma en cuenta cinemática. Campos potenciales repulsivos: Obstáculos repulsivos y atracción hacia una meta. Histograma de campo vectorial: Mapeo mediante un histograma polar. Enfoque Ventana Dinámica: Derivado de la dinámica del robot.
Para utilizar el kinect son necesarios ciertos paquetes de audio, imagen y data en general, entonces se procedió a instalar los paquetes siguientes (con los que aun no se contaba):
libspeex-dev (Audio) libbluetooth-dev (General Data) libdc1394-22-dev libaw1394-dev libraw1394-tools libraw1394-doc (Suggested)
De manera análoga se instalaron algunas dependencias:
sudo apt-get install git-core cmake freeglut3-dev pkg-config build-essential libxmu-dev libxi-dev libusb-1.0- 0-dev doxygen graphviz mono-complete
Ahora para mantener el orden se creó un directorio en home llamado kinect para la descarga y la instalación. Se procedio a instalar los drivers más recientes de Nvidia como sigue:
sudo add-apt-repository ppa:xorg-edgers/ppa sudo apt-get update
Ahora se procedió a clonar desde Github las versiones más recientes de OpenNI, NITE y AVIN2 (Con sus respectivos driver):
git clone git://github.com/avin2/SensorKinect.git git clone https://github.com/OpenNI/OpenNI.git
Ahora para instalar el AVIN2:
cd ~/kinect/SensorKinect/Platform/Linux/CreateRedist/ chmod a+x RedistMaker sudo ./RedistMaker cd ../Redist/Sensor-Bin-Linux-x64-v5.1.0.25 sudo chmod a+x install.sh sudo ./install.sh
Y de manera analoga para instalar el OpenNI y el NITE, como sigue(respectivamente):
cd OpenNI/Platform/Linux/CreateRedist/ chmod +x RedistMaker ./RedistMaker cd ../Redist/OpenNI-Bin-Dev-Linux-x64-v1.5.7.19/ sudo ./install.sh cd ~/kinect/nite/ chmod a+x install.sh sudo ./install.sh
Y para probarlo simplemente:
cd ~/kinect/openni/Samples/Bin/x64-Release/ ./Sample-NiSimpleSkeleton
Sin embargo el sitio para el Nite no funciono.
Simulación:
Para realizar la simulación se planteó el uso del paquete Stage dentro de ROS. Este simulador bidimensional provee un mundo virtual poblado por robots, sensores y objetos.
Posteriormente se necesita transformar la nube de puntos tridimensionales generados por el sensor Kinect, y plasmarlos como puntos en un plano, de manera que sea manejable con nuestros recursos en dos dimensiones; se planteó el uso del paquete de ROS openni launch, este se encarga de encontrar el dispositivo OpenNi y obtener la nube de puntos del mismo. Con esto ya hecho, se escogió el paquete de ROS Depthimage to laser scan que básicamente toma las imágenes de profundidad y genera un escaneo láser en 2D.
Introducción a SLAM
SLAM es un algoritmo utilizado para ubicación y mapeo simultáneo en robótica. Tiene varias etapas y el corazón del algoritmo es la técnica matemática “Extended Kalman Filter” para la estimación no lineal de estados. Utiliza una serie de mediciones a lo largo de un periódo de tiempo con ruido para la estimación de variables desconocidas que es mejor que una simple medición.
Cuando el robot se mueve, este actualiza la odometría. Al mismo tiempo se realiza un escaneo laser (en este caso kinect) para extraer referencias del entorno. Luego se asocian estas referencias con las que ya han sido vistas y se actualiza la posición estimada. Las referencias re observadas adquieren mayor peso y las nuevas son agregadas. Luego se repite el ciclo.
Actualización de odometría
La odometría en general es mala pero sirve como un buen punto de partida de la ubicación del robot. Por medio de SLAM se mejora la estimación de la posición, sin embargo esta no es la real pues siempre hay un error asociado a los instrumentos de medición por ejemplo. La extracción de datos de la odometría es sencilla pues se obtienen de los controles del robot. La parte difícil de la odometría es que esté coordinada con la extracción de datos con el láser.
Extracción de referencias
El ambiente en el que se moviliza el robot debe tener suficientes referencias distinguibles unas de otras para evitar que el robot se pierda y que el algoritmo funcione. Además las referencias deben ser fácilmente re-observables y estacionarias. Una referencia que se mueva puede introducir graves errores en el algoritmo.
La forma en que se extraen las referencias depende del sensor que se use y del tipo de referencias que se quieran “observar”. Un método que funciona para ambientes muy heterogéneos o discontinuos es el “spike landmark”. Como su nombre lo dice, su fuerte es encontrar puntas o cambios abruptos en el ambiente. El escaner toma 3 puntos y si uno difiere de los otros dos en un valor por encima de un umbral, existe un borde.
Otra forma de extraer referencias es con el método RANSAC (Random Sampling Consensus). Este método es robusto ante personas estorbando en el camino del robot, y sirve principalmente para extraer líneas rectas (paredes). Primero realiza un escaneo láser, luego toma unas cuantas muestras aleatorias contenidas en un determinado arco. Con esas muestras calcula una recta de mejor ajuste. Después trata de asociar los datos restantes con la recta determinada. Si se logran asociar un número de datos igual a un consenso, la recta encontrada se considera una referencia.
Asociación de datos
La asociación de datos consiste en usar una base de datos para las referencias ya observadas, y conforme se encuentran referencias verificar si son una ya vista o una nueva. El mayor problema en este paso es observar una referencia asociarla incorrectamente a una previamente observada. El algoritmo puede ser asociar un referencia extraída con la referencia re-observada n veces guardada en la base de datos más cercana. Pasarla por un proceso de validación en el que si acierta la referencia extraída debe ser la misma referencia de la base de datos por lo que se aumenta el número de veces que ha sido re-observada. Si no acierta, se considera una nueva referencia y el número de veces que ha sido vista es 1.
Carrito Omnidireccional
STM32F4DISCOVERY
El STM32 son circuitos integrados de 32 bits con núcleos Cortex-M3, Cortex-M0 y RISC ARM Cortex-M4F de STMicroelectronics y el procesador ARM IP de ARM Holdings.
La STM32F4 es la que se utilizó, esta pertenece al primer grupo de las STM32 basada en ARM Cortex-M4F. El F4 es también la primera serie STM32 en tener DSP y las instrucciones de coma flotante. La F4 es pin a pin compatible con el F2 de la serie STM32 y añade una mayor velocidad de reloj, 64K CCM RAM estática, full duplex I ² S, mejorado en tiempo real, y ADCs más rápido.
Es necesario añadir la arquitectura i386
dpkg --add-architecture i386
Es necesario hacer un:
apt-get update
Y obtener las dependencias:
apt-get install libncurses5 apt-get install libncurses5:i386
Se debe descargar el tarball de las Herramientas de GNU, luego se debe descomprimir.
cd ~/local/src wget https://launchpad.net/gcc-arm-embedded/4.7/4.7-2013-q1-update/+download/gcc-arm-none-eabi-4_7-2013q1-20130313-linux.tar.bz2 tar -xjf gcc-arm-none-eabi-4_7-2013q1-20130313-linux.tar.bz2
Luego se debe poner a disposición las herramientas de GNU a los usuarios, para esto se debe agregar el directorio bin a la PATH variable:
echo 'export PATH=$PATH:/home/****user****/local/src/gcc-arm-none-eabi-4_7-2013q1/bin/' >> /home/****user****/.bashrc
Regargue el archivo.
- Cerrando sesión.
- . .bashrc
Es necesario instalar opencd
sudo apt-get install openocd
Para continuar es necesario tener Phyton-Yalm ya instalado.
sudo apt-get install python-yaml
Y se crea la librería
cd ~/local/src/ git clone https://github.com/libopencm3/libopencm3-examples cd libopencm3-examples git submodule init git submodule update cd libopencm3 make
STLINK
Es necesario instalar el paquete libusb-1.0
sudo apt-get install libusb-1.0
Se ingresa a la carpeta src que se encuentra en el local.
cd ~/local/src/
Y se descarga desde el GITHUB. (Una nube en la que hay información reelevante)
git clone https://github.com/texane/stlink
Se ingresa a la carpeta de stlink y se ejecuta el programa para tener el paquete pkg-config
./autogen.sh ./configure --prefix=/home/**user**/local/DIR/stlink
Copiar y Compilar
make make install cd cd local/DIR xstow stlink
Es necesario copiar las siguientes reglas dentro de la ubicación /local/src/stlink),
sudo cp 49-stlinkv1.rules /etc/udev/rules.d/ sudo cp 49-stlinkv2.rules /etc/udev/rules.d/ sudo /etc/init.d/udev restart
Ahora antes de Flashear la STM se edita el archivo Makefile.includ dentro de la dirección local/src/libopencm3-examples/examples/stm32/f4
ifeq ($(BMP_PORT),) ifeq ($(OOCD_SERIAL),) %.flash: %.hex @printf " FLASH $<\n" @# IMPORTANT: Don't use "resume", only "reset" will work correctly! $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ -f board/$(OOCD_BOARD).cfg \ -c "init" -c "reset init" \ **-c "stm32x mass_erase 0" \** -c "flash write_image $(*).hex" \ -c "reset" \ -c "shutdown" $(NULL) else
Se deben de agregar las siguientes líneas a todos los archivos del Makefile al cual se le deben agregar las siguientes lineas antes de la ultima linea de código
OOCD_INTERFACE=stlink-v2 OOCD_BOARD=stm32f4discovery
Se borra TODO lo de la STM
st-flash erase
Para flashear los ejemplos prosiga con:
make make flash
O para ver en consola lo que sucede hacemos
make V=1 flash
PWM
Para generar el PWM (pulse-width modulation) que se enviará a los puentes H, se utiliza como base un ejemplo llamado src1 que se encuentra en el GITHUB
https://github.com/arcoslab/open-coroco
Este repositorio se debe de descargar
cd /local/src git clone https://github.com/arcoslab/open-coroco
En el siguiente código podemos observar los ajustes de los pines.
void tim1_init(void) {
/* Enable TIM1 clock. and Port E clock (for outputs) */ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_TIM1EN); rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPEEN); //Set TIM1 channel (and complementary) output to alternate function push-pull'. gpio_mode_setup(GPIOE, GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO9 | GPIO11 | GPIO13); gpio_set_af(GPIOE, GPIO_AF1, GPIO9 | GPIO11 | GPIO13); gpio_mode_setup(GPIOE, GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO8 | GPIO10 | GPIO12); gpio_set_af(GPIOE, GPIO_AF1, GPIO8 | GPIO10 | GPIO12);
Aquí se inicializan los pines correspondientes al reloj del TIM1, en este caso se activan los 3 canales y su respectiva negación. Aquí se designa la función alternativa que se quiere que realicen los pines seleccionados, que en este caso es la de timers.
/* Disable outputs. */
timer_disable_oc_output(TIM1, TIM_OC1); timer_disable_oc_output(TIM1, TIM_OC1N); timer_disable_oc_output(TIM1, TIM_OC2); timer_disable_oc_output(TIM1, TIM_OC2N); timer_disable_oc_output(TIM1, TIM_OC3); timer_disable_oc_output(TIM1, TIM_OC3N); /* -- OC1 and OC1N configuration -- */ /* Configure global mode of line 1. */ timer_enable_oc_preload(TIM1, TIM_OC1); timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); /* Configure OC1. */ timer_set_oc_polarity_high(TIM1, TIM_OC1); timer_set_oc_idle_state_unset(TIM1, TIM_OC1); //When idle (braked) put 0 on output /* Configure OC1N. */ timer_set_oc_polarity_high(TIM1, TIM_OC1N); timer_set_oc_idle_state_unset(TIM1, TIM_OC1N); /* Set the capture compare value for OC1. */ timer_set_oc_value(TIM1, TIM_OC1, INIT_DUTY*PWM_PERIOD_ARR);//initial_duty_cycle*pwm_period_ARR); /* -- OC2 and OC2N configuration -- */ /* Configure global mode of line 2. */ timer_enable_oc_preload(TIM1, TIM_OC2); timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1); /* Configure OC2. */ timer_set_oc_polarity_high(TIM1, TIM_OC2); timer_set_oc_idle_state_unset(TIM1, TIM_OC2); /* Configure OC2N. */ timer_set_oc_polarity_high(TIM1, TIM_OC2N); timer_set_oc_idle_state_unset(TIM1, TIM_OC2N); /* Set the capture compare value for OC2. */ timer_set_oc_value(TIM1, TIM_OC2, INIT_DUTY*PWM_PERIOD_ARR);//initial_duty_cycle*pwm_period_ARR); /* -- OC3 and OC3N configuration -- */ /* Configure global mode of line 3. */ timer_enable_oc_preload(TIM1, TIM_OC3); timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1); /* Configure OC3. */ timer_set_oc_polarity_high(TIM1, TIM_OC3); timer_set_oc_idle_state_unset(TIM1, TIM_OC3); /* Configure OC3N. */ timer_set_oc_polarity_high(TIM1, TIM_OC3N); timer_set_oc_idle_state_unset(TIM1, TIM_OC3N); /* Set the capture compare value for OC3. */ timer_set_oc_value(TIM1, TIM_OC3,INIT_DUTY*PWM_PERIOD_ARR);//initial_duty_cycle*pwm_period_ARR);//100); /* Reenable outputs. */ timer_enable_oc_output(TIM1, TIM_OC1); timer_enable_oc_output(TIM1, TIM_OC1N); timer_enable_oc_output(TIM1, TIM_OC2); timer_enable_oc_output(TIM1, TIM_OC2N); timer_enable_oc_output(TIM1, TIM_OC3); timer_enable_oc_output(TIM1, TIM_OC3N);
Esta sección de código configura las salidas de los canales del TIM1 y sus salidas negadas las cuales son llamadas como OC1 ó OC1N según corresponda el canal. Cabe destacar que para el funcionamiento del TIM8 lo que cambia son los pines y la función de realiza las interrupciones. A continuación se mostrará la diferencia
void tim1_up_tim10_isr(void) { // Clear the update interrupt flag timer_clear_flag(TIM1, TIM_SR_UIF); gen_pwm(); } void tim8_up_tim13_isr(void) { // Clear the update interrupt flag timer_clear_flag(TIM8, TIM_SR_UIF); gen_pwm1(); }
El siguiente código genera el PWM
void gen_pwm(void) { duty_a=ref_freqA/10.0f; duty_b=ref_freqB/10.0f; duty_c=ref_freqC/10.0f; if (duty_a < 0.0f) { timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); timer_disable_oc_output(TIM1,TIM_OC1); timer_enable_oc_output (TIM1, TIM_OC1N); duty_a=-duty_a; } else { timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); timer_enable_oc_output(TIM1, TIM_OC1 ); timer_disable_oc_output (TIM1, TIM_OC1N); }
Aquí se puede ver que si la entrada de una de las llantas de duty_a es menor que cero lo que hace es que activa la salida negada del canal correspondiente, lo que hace que el motor gire en reversa. Esto se realiza para cada una de los canales utilizados.
Al Make hay que realizarle un cambio importante; lo que se hace es que se abre el documento y se ve algo como esto
BINARY = "nombre de su archivo .c" OBJS := LDSCRIPT = ../libopencm3-plus/lib/libopencm3_plus_stm32f4discovery.ld OOCD_INTERFACE = stlink-v2 OOCD_BOARD = stm32f4discovery include Makefile.include
Y lo que hacemos es que donde dice “BINARY=” colocamos el nombre de nuestro archivo.c
Si salen “warnings” de que las funciones no se encuentran definidas entonces se debe poner:
void tim8_init(void); void tim1_init(void); void gen_pwm(void);
Y se flashea nuevamente.
La salidas son eviadas al Puente H. Se utilizó el L298n se puede ver en la hoja del fabricante que se puede encontrar en el siguiente link.
https://www.sparkfun.com/datasheets/Robotics/L298_H_Bridge.pdf
Lectura de los datos del Joystick
Las llantas omnidireccionales basan su movimiento en las siguientes ecuaciones
- V1 = Vd*sen(Ø+π/4)+Vø
- V2 = Vd*sen(Ø+π/4)-Vø
- V3 = Vd*sen(Ø+π/4)-Vø
- V4 = Vd*sen(Ø+π/4)+Vø
A continuación vamos a ver que significa cada una de ellas
- Vd = magnitud de la velocidad de las llantas
- Ø = ángulo que da la dirección
- Vø = magnitud de la velocidad de giro
Cada uno de los datos los vamos a leer de los Joysticks, estos rigen sus movimientos dentro de un círculo unitario, estos datos las vamos a obtener mediante coordenadas polares, tomando en cuenta que los joysticks lo que nos da es una lectura de “x” y “y”, hacemos
* Vd = sqtr(x²+y²) * Ø = atan2(x+y)
Sabiendo esto lo que ahora necesitamos es es leer los datos del joystick, esto lo hacemos mediante Pygame, para lo que necesitamos instalar lo siguiente
sudo apt-get install python sudo apt-get install python-pygame
Con esto instalado y el siguiente código obtendremos los datos deseados
#!/usr/bin/env python import pygame import math # Define some colors BLACK = ( 0, 0, 0) WHITE = ( 255, 255, 255) # This is a simple class that will help us print to the screen # It has nothing to do with the joysticks, just outputing the # information. class TextPrint: def __init__(self): self.reset() self.font = pygame.font.Font(None, 20) def printd (self, screen, textString): textBitmap = self.font.render(textString, True, BLACK) screen.blit(textBitmap, [self.x, self.y]) self.y += self.line_height def reset(self): self.x = 10 self.y = 10 self.line_height = 15 def indent(self): self.x += 10 def unindent(self): self.x -= 10 pygame.init() #Loop until the user clicks the close button. done = False # Used to manage how fast the screen updates clock = pygame.time.Clock() # Initialize the joysticks pygame.joystick.init() # Get ready to print textPrint = TextPrint() # -------- Main Program Loop ----------- while done==False: # EVENT PROCESSING STEP for event in pygame.event.get(): # User did something if event.type == pygame.QUIT: # If user clicked close done=True # Flag that we are done so we exit this loop # Possible joystick actions: JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION if event.type == pygame.JOYBUTTONDOWN: print("Joystick button pressed.") if event.type == pygame.JOYBUTTONUP: print("Joystick button released.") # Get count of joysticks joystick_count = pygame.joystick.get_count() # For each joystick: for i in range(joystick_count): joystick = pygame.joystick.Joystick(i) joystick.init() #Usually axis run in pairs, up/down for one, and left/right for the other axes = joystick.get_numaxes() for i in range( axes ): axis = joystick.get_axis( i ) y=joystick.get_axis(3); x=joystick.get_axis(2); velocidad= math.sqrt(x**2+y**2); direccion=math.atan2(y,x); v1=-(velocidad*math.sin(direccion+(math.pi/4))); v2=velocidad*math.cos(direccion+(math.pi/4)); v3=velocidad*math.cos(direccion+(math.pi/4)); v4=-(velocidad*math.sin(direccion+(math.pi/4))); print v1 print v2 print v3 print v4 # Limit to 20 frames per second clock.tick(20) pygame.quit ()
Ya con esto vamos a obtener los datos y de una vez la velocidades necesitadas para el funcionamiento de las llantas omnidireccionales
XSTOW
Esto se hará siguiendo la siguiente guía
http://arcoslab.eie.ucr.ac.cr/dokuwiki/doku.php?id=using_xstow_for_local_installations
YARP
Esto se hará siguiendo la siguiente guía
http://arcoslab.eie.ucr.ac.cr/dokuwiki/doku.php?id=installing_yarp_in_debian
Con esto instalado, se enviarán los datos de las velocidades mediante un bottle
´Para poner a funcionar el carrito es necesario aterrizar a tierra todo el circuito, luego conectar el transformador (1), el hub (3), y a este último conectarle el caple a la coputadora, y el transformador (este debe ir en la entrada de 12 V, transforma el voltaje a uno de 5V) y el cable a la STM (2)
Inkscape
Se usa inkscape para generar un archivo .pdf que se utilizará en la cortadora laser. Ya sea para imprimir la PCB o el diseño del carrito.
Para instalar Inkscape:
$sudo apt-get install inkscape
Abrir el archivo SVG con Inkscape. Seleccionar todo el objeto y tomar nota de las dimensiones. Seleccionar: File/ Export Bitmap (SHIT-CTRL-E).
Clic en la pestaña “Selection”, y en la parte de ancho de bitmap poner 4000.00 dpi y clic en “Export”.
Seleccionar: File → Import (CTRL-I). Importar la imagen .png, se abrirá una ventana donde hay que seleccionar “Link or embed Image”: Seleccionar siempre “embed”.
Seleccionar: Path → TraceBitmap (SHIFT-ALT-B) y poner las siguientes configuraciones.
Seleccionar la imagen vectorizada y presionar F2 solo para comprobar un trazo correcto. Luego presionar F1 para volver al modo normal.
Seleccionar la imagen vectorizada y hacer CTR+SHIFT+K. r a Object → Fill and stroke: Poner las siguientes configuraciones y cerrar la ventana. Si no se ve nada en la imagen, es porque hay que aumentar el zoom.
Hecho esto, ahora hacer: CTRL-K
Seleccionar la imagen y poner las dimensiones de la imagen original. Eliminar la imagen NO vectorizada y la imagen original.
Por último guardar como pdf.
Si se genera el diseño en PDF se puede exportar a un .eps y luego de esto abrirlo en Inkscape.
Cortadora laser.
Para usar la cortadora láser se usa el software “RetinaEngrave”. Es necesario contar con Windows ya que el software solo funciona con Windows.
Lo primero que debemos hacer es abrir el archivo .pdf seleccionar la opción de imprimir. Escoger la impresora “Full Spectrum Engineering Driver”. Presentación “Horizontal”. Color “Blanco y negro” Tamaño del papel “FSL Hobby series Gen5 20×12”. Si no sale este tipo de papel seleccionar cualquier otro que se entre en las dimensiones del módelo. Calidad de impresión “1200×1200”. Clic en Aceptar, y se abrirá el archivo en el software de la impresora.
Para poner a funcionar la cortadora es necesario seguir de manera estricta los siguientes pasos:
Encender la bomba de agua e inclinar la cortadora, al mismo tiempo, para eliminar las burbujas de aire que puedan quedar por usos anteriores. No continuar hasta eliminar la mayoría de las burbujas.
Luego encender el extractor de aire caja metálica cuadrada.
Luego encender la bomba de aire a 30 psi(diferente al extractor de aire), esta es para controlar la llama del laser.
Por último encender la cortadora láser. Girar el botón grande rojo.
Estos pasos son ESTRICTOS. Cuando se apaga es necesario hacerlo en el orden inverso.
Al encender la cortadora apuntar el IP que esta tiene, esta IP puede cambiar cada vez que se encienda la misma.
Ahora volvemos al RetinaEngrave donde tenemos nuestro diseño. Le damos click a Hobby (esquina superior izquierda) para conectar el software con la cortadora, y ponemos el IP de la cortadora y clic en conectar, en la esquina inferior izquierda debe aparecer como conectado y el IP correcto.
Recuerde configurar la potencia y velocidad.
Para el caso de la PCB la configuración que se utiliza es la siguiente:
Velocidad = 100% Potencia = 15%
Para el caso del diseño en madera la configuración que se va a utilizar es la siguiente:
Velocidad = 30% Potencia = 100%
En la siguiente tabla podemos observar la potencia y velocidad específica para distintos materiales.
Cuando se ubica el objeto que se desea cortar es importante darle click al boton del perímetro para corroborar que lo que se quiere cortar esta dentro del área de cortadura.
Y se le da RUN. La cortadora termina ella solita. Es importante recordar el orden de apagado.
Inroducción al Kinect y simulación de robot móvil
Objetivos
Extraer datos del kinect en una dimensión para el posterior uso en la extracción de referencias en SLAM
Simular un robot móvil Gazebo o Rviz
Gazebo es un simulador 3-D para varios robots con complejos escenarios. Modela muy bien la física involucrada, tiene altas cualidades gráficas y es software libre. Rviz es una herramienta de ROS para la visualización de 3-D. Al trabajar con sensores que perciben por ejemplo nubes de puntos con coordenadas es difícil despulgar viendo tantos números por separado. Esta herramienta permite que se vea lo que está viendo el robot para así poder probar corregir y mejorar algoritmos.
Se tuvieron bastantes problemas en la puesta en funcionamiento de estos 2, pues constantemente aparece el error bus error(core dumped). Al escribir este ocumento gazebo empezó a funcionar sin haberle hecho ningun cambio.
Kinect
El kinect es un dispositivo que fue creado por microsoft para jugar juegos sin control tradicional. Incluye una camara RGB con reconocimiento facial, sensores de profundidad, motor y micrófonos. Los micrófonos poseen un software capaz de reconocimiento yaislamiento de voz excelente. El motor sirve para mover el aparato y poder seguir a las personas por ejemplo. Los sensores de profundidad usan tecnología CMOS y son un emisor infrarojo y un receptor separados a una distancia de casi 7 cm. Lo que hace al kinect famoso es el software que tiene para identificar y seguir los movimientos de las personas, más que todo con los sensores de profundidad.
Para poder utilizar el kinect desde la computadora siga los siguientes pasos:
Instale opencv de git
git clone https://github.com/Itseez/opencv.git
Instalar las siguientes dependencias:
sudo apt-get install git-core cmake freeglut3-dev pkg-config build-essential libxmu-dev libxi-dev libusb-1.0-0-dev
Luego clone el siguiente repositorio con el código fuente de la librería
git clone git://github.com/OpenKinect/libfreenect.git
Instale la librería usando los siguientes comandos:
cd libfreenect mkdir build cd build cmake -L .. make sudo make install sudo ldconfig /usr/local/lib64/
Agregue permisos al usuario de usar el kinect:
sudo adduser $USER video sudo adduser $USER plugdev
Cree un archivo con reglas para el manejador de dispositivos de Linux
sudo nano /etc/udev/rules.d/51-kinect.rules
Pegue esto dentro del archivo
# ATTR{product}=="Xbox NUI Motor" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02b0", MODE="0666" # ATTR{product}=="Xbox NUI Audio" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02ad", MODE="0666" # ATTR{product}=="Xbox NUI Camera" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02ae", MODE="0666" # ATTR{product}=="Xbox NUI Motor" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02c2", MODE="0666" # ATTR{product}=="Xbox NUI Motor" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02be", MODE="0666" # ATTR{product}=="Xbox NUI Motor" SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02bf", MODE="0666"
Conecte el kinect y pruebe que funciona usando la siguiente aplicación
freenect-glview'
Instale las siguientes dependencias antes de instalar los wrappers de python para manejar el kinect con opencv y python:
sudo apt-get install cython sudo apt-get install python-dev sudo apt-get install python-numpy
Corra el siguiente comando en la carpeta …/libfreenect/
sudo python setup.py install
Se utilizó un programa de demostración bajado de la página https://github.com/amiller/libfreenect-goodies para manipular y calibrar el kinect. La idea era empezar por la extracción de datos del sensor de profundidad. Como el kinect debe ser usado a la hora de hacer SLAM en un carro omnidireccional, se extrajó una línea de datos (1 dimensión) del centro de la cámara. Lo ideal es extraer referencias como las paredes.
El programa extrae los datos de la cámara RGB y de la de profundidad en matrices 480×640 que es la resolución de la cámara. Las coordenadas de la imagen empiezan en la esquina superior izquierda (0,0). En el caso de los sensores de profundidad, esta está expresada en 11 bits desde 0 hasta 2047. 2047 significa un error y 0 significa que el objeto está infinitamente largo. Luego se realizan conversiones al sistema de coordenadas cartesianas utilizando matrices de calibración, donde Z es el eje de la profundidad y apunta hacia el lente de la cámara. Si se aleja de la cámara los valores son negativos. El eje Y apunta hacia arriba y el eje X apunta hacia la derecha. por ejemplo en el que el punto (0,0,0) es el centro de la cámara a una distancia que está no produzca errores. Los objetos muy cercanos a la cámara tienden a generar errores debido a la forma en que se calcula la profundidad.
El programa extrae los datos con éxito. Sin embargo a la hora de continuar se querían usar librerías como opencv y matplotlib y a la hora de importarlas se introduce un error al correr el programa: bus error(core dumped). Al igual que en la primera parte se intent'de todo para resolverlo se cree que es el hardware de la computador a usada que ha estado fallando últimamente. La computadora pasa notificando internal errors y apagándose cuando se mueve un poco el hardware.
Bibliografía:
Aguado, B. F., Castaño, J. A., Casanova, E. Z., & García-Bermejo, J. G. (2004). Diseño y Simulación de un Filtro Kalman para un Robot Móvil. XXV Jornadas de Automática, Ciudad Real.
Introducción a los Robots móviles Autónomos. Obtenido el 30 de abril de: http://www.robotee.com/EBooks/Introduction_to_Autonomous_Mobile_Robots.pdf.
Ohtsuki, T., & Ono, Y. (1989). Potential range dependence of mixing of edge states in quantum hall effect. Journal of the Physical Society of Japan,58(10), 3863-3864. Berlekamp, E. (1982). Bit-serial reed-solomon encoders. Information Theory, IEEE Transactions on, 28(6), 869-874.
Mojtahedzadeh, R. (2011). Robot obstacle detection using the Kinect . Master Thesis of Royal Institute and Technology School of Computer Science and Communication.
Prasad, L. (2014) Obstacle - Avoiding Robot : A possible introduction project for engineering students. Bachelor Thesis.
Dreszer, D., Gnacik, K., Kaleta, P., Szymanska, O. (2013) Autonomization of two-wheeled inverted pendulum-Kinect-Based Obstacle Detection and Avoidance System. .rodinámica, para darle mayor soporte a la computadora.
Riisgaard, S. and Rufus M. (NA). SLAM for Dummies. Extraído de: ocw.mit.edu/courses/…/1aslam_blas_repo.pdf
ROS. (2015). Ubuntu install of ROS Indigo. http://wiki.ros.org/indigo/Installation/Ubuntu
Implementación de una base móvil con evasión de obstáculos utilizando Navegation de ROS Por: Carolina Arauz Villegas.
Ribeiro, M. I. (2005). Navigation/collision avoidance 1:1 introduction obstacle avoidance
Khatib, O. (1995). Real-time oerbstacle avoidance for manipulators and mobile robots. International Journal of Robotics Research, 5(1):90–98.
Fox, D., Burgard, W., y Thrun, S. (1997). The dynamic window approach to collision avoidance. IEEE Robotics and Automation, 4(1).
Boeing, A. (2012). Dynamic window algorithm motion planning. http://adrianboeing.blogspot.com/2012/05/ dynamic-window-algorithm-motion.html
Crawford, S. How Microsoft Kinect Works. Extraído de: http://electronics.howstuffworks.com/microsoft-kinect2.htm
Experimenting with Kinect using opencv, python and open kinect (libfreenect). https://naman5.wordpress.com/2014/06/24/experimenting-with-kinect-using-opencv-python-and-open-kinect-libfreenect/