====== Instalación y configuración de ROS (26 dic) ====== Cada versión de ROS soporta un máximo de tres versiones de ubuntu, por lo que conviene tener claro qué versión vamos a instalar. Para Ubuntu 12.10 debemos instalar ROS groovy. ==== Ubuntu 12.10 ==== == Instalación de ROS Groovy == Añadir los repositorios de ros-groovy para ubuntu 12.10 (a 12 dic 2012) sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu quantal main" > /etc/apt/sources.list.d/ros-latest.list' wget http://packages.ros.org/ros.key -O - | sudo apt-key add - sudo apt-get update sudo apt-get upgrade Instalar con apt-get (todas las dependencias se instalan automáticamente). sudo apt-get install ros-groovy-desktop-full Instalar también otras herramientas que facilitan el trabajo con ROS. sudo apt-get install python-rosinstall python-rosdep == Configuración de ROS Groovy == Configuración inicial: sudo rosdep init rosdep update source /opt/ros/groovy/setup.bash Creamos nuestro espacio de trabajo (se recomienda para no ensuciar la instalación base) cd /opt/ros mkdir rosws sudo chmod -R 775 /opt/ros/rosws sudo chown user:user /opt/ros/rosws rosws init /opt/ros/rosws /opt/ros/groovy Añadimos el script de configuración al bashrc echo "source /opt/ros/rosws/setup.bash" >> ~/.bashrc . ~/.bashrc == Instalación de stacks desde repositorios == Para instalar cualquier stack desde repositorios: roscd roslocate info STACKNAME | rosws merge - source setup.sh rosws update STACKNAME rosmake STACKNAME Un ejemplo de instalación del stack ROSARIA. Este stack es un wrapper de [[http://robots.mobilerobots.com/wiki/ARIA|ARIA]] para ROS que nos permite acceder al sonar y odometría de todos los robots de MobileRobots/ActivMedia. roscd roslocate info ROSARIA | rosws merge - source setup.sh rosws update ROSARIA rosmake ROSARIA ====== Tutoriales de ROS ====== [[http://www.ros.org/doc/api/rosinstall/html/rosws_tutorial.html|Tutorial de la herramienta rosws]] ====== Crear un paquete ROS ====== En este tutorial mostraremos cómo crear un paquete de software para ROS. A modo de ejemplo, crearemos un paquete ficticio con un único nodo ROS, que se encargará de las siguientes tareas: - Abrir un sensor ficticio. - Leer los datos que proporciona el sensor de forma periódica. - Publicar los datos a través del sistema de intercambio de mensajes ROS. El programa que se encargue de esto recibirá el nombre de //publisher//. Nuestro sensor ficticio proporcionará la posición 3D de un objeto y la marca temporal asociada a cada dato: timestamp x y z Antes de comenzar el tutorial, debemos descargarnos los fuentes que utilizaremos en el paquete {{:inv:sensorfakesources.zip|}} * SensorFake.cpp y SensorFake.h: librería de interacción con el sensor. * SensorFake_Publisher.cpp: //publisher//. ==== Diseño del paquete ROS ==== Al tratarse de un paquete sencillo, proponemos un diseño que no complique en exceso ni la implementación ni el mantenimiento del mismo. Nuestro paquete constará de los siguientes archivos: - Librería para el manejo del sensor. Proporcionará las funciones típicas: conexión, lectura, desconexión, etc. Debería ser totalmente independiente de ROS. - Nodo ROS encargado de comunicarse con el sensor (a través de su librería) y transmitir los datos a través del sistema de mensajes ROS. Para paquetes más complejos, se recomienda encarecidamente utilizar un [[http://www.sharprobotica.com/2010/04/developing-well-designed-packages-for-robot-operating-system-ros-part-i/|diseño más adecuado]]. ==== Creación del paquete ==== Nos situamos en la carpeta donde queramos crear nuestro paquete. Por ejemplo: ${HOME}/ros Creamos el paquete. El nombre del paquete será //sensor_fake// y dependerá de //roscpp//. roscreate-pkg sensor_fake roscpp La salida del comando debería ser algo como: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING: current working directory is not on ROS_PACKAGE_PATH! Please update your ROS_PACKAGE_PATH environment variable. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Created package directory /home/citius_robot/ros_pruebas/sensor_fake Created include directory /home/citius_robot/ros_pruebas/sensor_fake/include/sensor_fake Created cpp source directory /home/citius_robot/ros_pruebas/sensor_fake/src Created package file /home/citius_robot/ros_pruebas/sensor_fake/Makefile Created package file /home/citius_robot/ros_pruebas/sensor_fake/manifest.xml Created package file /home/citius_robot/ros_pruebas/sensor_fake/CMakeLists.txt Created package file /home/citius_robot/ros_pruebas/sensor_fake/mainpage.dox Please edit sensor_fake/manifest.xml and mainpage.dox to finish creating your package Esto nos indica: 1) que el paquete creado no está en la variable de entorno //ROS_PACKAGE_PATH// (solución en la siguiente sección), 2) que se ha creado correctamente la estructura de directorios y ficheros de configuración del paquete. Si nos desplazamos a la carpeta correspondiente (//${HOME}/ros_pruebas/sensor_fake//), observamos la estructura del paquete: * include: directorio para ficheros ".h". * * sensor_fake: directorio para ficheros ".h" de la librería que se encarga de la interacción con el sensor. * src: directorio para ficheros ".cpp" * mainpage.dox: fichero para generacion de documentación con Doxygen. * CMakeLists.txt: configuración de la compilación con CMake [[http://www.ros.org/wiki/rosbuild/CMakeLists|(enlace)]]. * manifest.xml: información sobre el paquete [[http://ros.org/wiki/Manifest|(enlace)]]. ==== Añadiendo el paquete al workspace ==== **Desde ${HOME}/ros**, añadimos el paquete al workspace de ROS. rosws set sensor_fake Alternativamente, podemos ejecutar: rosstack profile && rospack profile Cerramos el terminal y lo abrimos de nuevo, para que se recarguen las variables de entorno correspondientes. A continuación, ejecutamos: rospack profile En este punto, ROS debería ser capaz de encontrar nuestro paquete. Lo comprobamos mediante: rospack find sensor_fake Comprobamos que todo funciona correctamente ejecutando una compilación de prueba: rosmake sensor_fake Cuya salida debería ser algo como: [ rosmake ] rosmake starting... [ rosmake ] Packages requested are: ['sensor_fake'] [ rosmake ] Logging to directory /home/david/.ros/rosmake/rosmake_output-20121115-180018 [ rosmake ] Expanded args ['sensor_fake'] to: ['sensor_fake'] [rosmake-0] Starting >>> roslang [ make ] [rosmake-0] Finished <<< roslang No Makefile in package roslang [rosmake-0] Starting >>> roscpp [ make ] [rosmake-0] Finished <<< roscpp No Makefile in package roscpp [rosmake-0] Starting >>> sensor_fake [ make ] [rosmake-0] Finished <<< sensor_fake [PASS] [ 5.56 seconds ] [ rosmake ] Results: [ rosmake ] Built 3 packages with 0 failures. [ rosmake ] Summary output to directory [ rosmake ] /home/david/.ros/rosmake/rosmake_output-20121115-180018 ==== Importación a Eclipse ==== Si queremos importar este paquete a un proyecto Eclipse, podemos seguir las instrucciones que se encuentran en: [[http://www.ros.org/wiki/IDEs#Eclipse]] ==== Compilación de la librería para interacción con sensor_fake ==== En primer lugar, copiamos el archivo //SensorFake.cpp// en //${HOME}/ros/sensor_fake/src// y el archivo //SensorFake.h// en //${HOME}/ros/sensor_fake/include/sensor_fake// (fuentes: {{:inv:sensorfakesources.zip|}}). A continuación, modificamos el //CMakeLists.txt// para que los compile como una librería dinámica. #common commands for building c++ executables and libraries -> Añadimos el comando debajo de este comentario rosbuild_add_library(${PROJECT_NAME} src/SensorFake.cpp) #Esto indica que queremos compilar SensorFake.cpp como una librería dinámica. Esta librería tendrá el mismo nombre que el proyecto # (sensor_fake) Compilamos: rosmake sensor_fake **Nota importante**: SensorFake.cpp asume que el SensorFake.h está en //include/sensor_fake//, al hacer: #include "sensor_fake/SensorFake.h" De no se así (por ejemplo, si le hemos dado otro nombre al paquete), debemos modificar este //include//. Si la compilación es satisfactoria, //rosmake// nos habrá creado una nueva carpeta //${HOME}/ros/sensor_fake/lib//, que contendrá la librería compilada //libsensor_fake.so//. ==== Definición de los mensajes ROS ==== Ahora debemos definir los mensajes que nuestro paquete va a utilizar para comunicarse con ROS. Para ello, creamos la carpeta //${HOME}/ros/sensor_fake/msg// y copiamos en ella el archivo de definición del mensaje (//XYZ.msg//). A continuación, modificamos el archivo //CMakeLists.txt// para que compile la definición del mensaje. #uncomment if you have defined messages rosbuild_genmsg() #---> Descomentamos esta línea Compilamos: rosmake sensor_fake Si la compilación es correcta, //rosmake// habrá creado dos nuevas carpetas: 1) //${HOME}/ros/sensor_fake/msg_gen// y 2) //${HOME}/ros/sensor_fake/src/sensor_fake///. Estas carpetas contienen las clases necesarias para el manejo del mensaje generado. ==== Compilación del //publisher// ==== Ahora estamos en disposición de escribir un programa que lea los datos de nuestro //sensor_fake// y los publique en ROS (utilizando el tipo de mensaje generado en el apartado anterior). En primer lugar, copiamos el archivo //SensorFake_Publisher.cpp// en //${HOME}/ros/sensor_fake/src// (fuentes: {{:inv:sensorfakesources.zip|}}). A continuación, modificamos el //CMakeLists.txt// para enlazar la librería //{HOME}/ros/sensor_fake/lib/libsensor_fake.so// y compilar el //publisher// como ejecutable. #common commands for building c++ executables and libraries ## -> Ya estaba! rosbuild_add_library(${PROJECT_NAME} src/SensorFake.cpp) ## -> Ya estaba! rosbuild_add_executable(SensorFake_Publisher src/SensorFake_Publisher.cpp) target_link_libraries(SensorFake_Publisher ${PROJECT_NAME}) Si la compilación es satisfactoria, //rosmake// habrá creado el ejecutable //${HOME}/ros/sensor_fake/bin/SensorFake_Publisher//. ==== Ejecución del nodo ROS ==== Finalmente, probamos nuestro paquete. Para ello, abrimos un terminal y ejecutamos el servidor ROS: roscore En otro terminal, ejecutamos nuestro //publisher// (nodo ROS): rosrun sensor_fake SensorFake_Publisher La salida debería ser algo como: Hello, I am the SensorFake_Publisher Time 1353001026.799379: Sending x [0] y [5] z [10] Time 1353001026.899426: Sending x [1] y [6] z [11] Time 1353001026.999419: Sending x [2] y [7] z [12] En otro terminal, ejecutamos un //listener// de ROS, que recibirá los mensajes de nuestro //publisher// y los mostrará por pantalla. rostopic echo /SensorFake_Topic La salida debería ser algo como: header: seq: 31 stamp: secs: 1353001134 nsecs: 532552707 frame_id: '' timestamp: secs: 1353001134 nsecs: 532516000 x: 1 y: 6 z: 11 --- header: seq: 32 stamp: secs: 1353001134 nsecs: 632531208 frame_id: '' timestamp: secs: 1353001134 nsecs: 632489000 x: 2 y: 7 z: 12 --- ==== Compartir el paquete ==== Si queremos compartir el paquete (por ejemplo, enviarlo por email), debemos borrar la carpeta //${HOME}/ros/sensor_fake/build//. En el ordenador destino, copiamos el paquete (por ejemplo, en //${HOME}/ros//) y ejecutamos los pasos de la Sección "Añadiendo el paquete al workspace". ====== Stage + AMCL + RVIZ ====== En este tutorial veremos: - Cómo simular un robot con Stage. - Cómo ejecutar el algoritmo de localización AMCL. Este algoritmo estimará la posición del robot sobre un mapa en base a la información del simulador. - Cómo visualizar todos los datos con el //rviz//. Para ello, necesitamos instalar: - Stack Stage: //sudo apt-get install ros-groovy-stage// - Nodos AMCL y map_server(stack Navigation): //sudo apt-get install ros-groovy-navigation// - Nodo rviz: //sudo apt-get install ros-groovy-rviz// ==== Archivos de configuración ==== En primer lugar, debemos descargar el archivo {{:inv:world.zip|}}. Podemos descomprimir este archivo en cualquier lugar a nuestro gusto (en adelante, llamaremos //${WORLD_PATH}// a esta carpeta). En particular, nos van a interesar los siguientes archivos: - //${WORLD_PATH}/citius/plantabajacitius.yaml//: archivo descriptor del mapa que utilizaremos en este tutorial. - //${WORLD_PATH}/citius/plantabajacitius.pgm//: imagen que representa dicho mapa. - //${WORLD_PATH}/citius/plantabajacitius.world//: archivo "world" del Stage (utiliza el archivo plantabajacitius.pgm). A continuación, descargamos el archivo {{:inv:amcl_diff_stage.launch.zip|}} y lo extraemos en la carpeta "examples" del nodo AMCL. Para localizar la carpeta del nodo AMCL, hacemos: roscd amcl Este archivo contiene los parámetros que se le pasarán al AMCL. Podemos modificar los parámetros editando el archivo. Finalmente, descargamos el archivo {{:inv:stage_amcl.rviz.zip|}} y lo extraemos en una carpeta a nuestro gusto (en adelante, //${RVIZ_CONFIG}//). Este archivo contiene parámetros de configuración para adaptar el //rviz// (visualizador) a las necesidades de este ejemplo. ==== Ejecución de los nodos (uno por terminal) ==== Arrancamos el //roscore//: roscore Ejecutamos el simulador Stage con un archivo "world". Por ejemplo: rosrun stage stageros ${WORLD_PATH}/citius/plantabajacitius.world Ejecutamos el map_server: rosrun map_server map_server ${WORLD_PATH}/citius/plantabajacitius.yaml Ejecutamos el AMCL con el archivo de configuración descargado: roslaunch amcl amcl_diff_stage.launch AMCL expone un servicio (global_localization) mediante el cual se puede activar el proceso de localización global del robot. En otro terminal, hacemos: rosservice call /global_localization Comprobamos con la herramienta //rxgraph// que todos los nodos están: 1) levantados, 2) comunicándose correctamente. A continuación, podemos visualizar el resultado de los diferentes nodos utilizando la herramienta //rviz//: rosrun rviz rviz ${RVIZ_CONFIG}/stage_amcl.rviz Deberíamos ver algo como: {{ :inv:rviz_localization.png?500 |}}: Ahora podemos mover el robot (pestaña teleop) por el entorno para que se localice. ====== Rosbag ====== Rosbag es una herramienta para grabar, reproducir y modificar logs con los mensajes que recibe el nodo roscore (pose, medidas del láser, transformaciones geométricas, etc.). En terminología ROS, a estos archivos de log se les conoce como bags. ==== Rosbag record ==== ==== Rosbag play ==== ==== Rosbag filter ==== Rosbag nos permite generar nuevos archivos bag a partir de un bag ya existente. Presentamos aquí algunos ejemplos: Generar un bag que sólo contenga mensajes "/RosAria/pose": rosbag filter original.bag filtrado.bag 'topic == "/RosAria/pose"' Generar un bag que sólo contenga mensajes "/RosAria/pose" y "/tf": rosbag filter original.bag filtrado.bag 'topic == "/RosAria/pose" or topic =="/tf"' Generar un bag que contenga todos los mensajes excepto el "/RosAria/pose": rosbag filter original.bag filtrado.bag 'topic != "/RosAria/pose"' ==== Creación de un controlador básico ==== Descargar el siguiente paquete: {{:inv:basicsample.zip|}}. Compilar y ejecutar. Para probar el código con el Stage necesitamos hacer un re-mapping de los topics como si fuera el robot real: //RUTA AL ARCHIVO WORLD //RUTA AL MAPA