---
weight: 4
title: "Apuntes de Robot Operating System (ROS)"
date: 2023-02-27T16:42:06+0100
draft: false
summary: "Apuntes de ROS"
categories:
- notes
tags:
- ros
- docker
- robot
---

## ¿Qué es ROS?

{{< admonition type=info title="Referencias" open=true >}}

- [ROS2 vs ROS1](https://medium.com/@oelmofty/ros2-how-is-it-better-than-ros1-881632e1979a)
- [ROS1 vs ROS2](https://roboticsbackend.com/ros1-vs-ros2-practical-overview) Practical Overview from Robotics Backend
- [Robot Operating System 2: Design, architecture, and uses in the wild](https://www.science.org/doi/10.1126/scirobotics.abm6074)

{{< /admonition >}}


_Robot Operating System_ (ROS) es un _framework_ para programar __robots__, nos da facilidades para programar tareas de diferentes tipos como navegación (usando el stack de navegación de ROS), manipulación (usando _moveit_), percepción (usando por ejemplo [PCL]^(Point Cloud Library))

### Conceptos básicos de ROS

__Nodos__

: Son los procesos básicos en ROS, cada nodo representa un proceso independiente dentro del _ROS stack_. Los nodos pueden comunicarse entre si de tres maneras:

  - ___ROS topics___ (_publisher/subscriber_) posibilitan a un nodo a publicar mensajes para que los lean otros nodos que se suscriban al _topic_
  - ___ROS services___ (_request/response_) posibilita que un nodo cliente lance peticiones (_request_) a otro nodo servidor solicitando un servicio. Una vez que se completa la tarea el nodo servidor responde (_response_) enviando el resultado de la petición.

  - ___ROS actions___ (_action/feedback/result_) Con este método un nodo cliente puede enviar una petición de acción a otro nodo servidor. Mientras el servidor está ejecutando la acción envía información continuamente al cliente del progreso de la acción. Una vez completada la tarea, el servidor envia el resultado al cliente, este sería el producto final de la acción. Las "acciones" se parecen a los servicios, la diferencia es la realimentación continua que el servidor da al cliente mientras ejecuta la acción.

___Parameter Server  _

: En este servidor podemos almacenar parámetros globales que todos los nodos pueden consultar.

### ROS1 y ROS2

_ROS Noetic_ es la última versión de ROS 1, y está destinada a ser la última versión de ROS 1. _ROS Noetic_ utiliza ya Python 3 y está basada en Ubuntu 20.04. Hay un montón de literatura, tutoriales y ejemplos basados en ROS1 pero creo que lo mejor es centrarse directamente en ROS2.

ROS2 es la nueva versión de ROS. La motivación principal de ROS2 es ser un sistema operativo orientado a ser usado en el mundo real y no un sistema operativo de investigación y desarrollo como era ROS1, sus objetivos declarados son:

__Seguridad__

: Tiene que ser seguro y usar la encriptación adecuada siempre que sea necesario.

__Sistemas Embebidos__

: ROS2 tiene que poder ejecutarse en sistemas embebidos.

__Diversidad de red__

: Es necesario que pueda conectarse y comunicarse usando todo tipo de redes desde LAN a redes satelitales, para adecuarse a cualquier entorno en el que se usen robots.

__Computación en Tiempo Real__

: Tiene que ser capaz de llevar a cabo [RTC]^(Real Time Computing) de forma fiable, dado que esta es crucial para la robótica.

__Orientado al producto__

: Tiene que cumplir con los estándares industriales para usarlo en productos comerciales


ROS2 implica cambiar muchas cosas:

- Usa [DDS](https://en.wikipedia.org/wiki/Data_Distribution_Service) como protocolo de red para todas las comunicaciones.
  - Prescinde del _ROS Master_ que actuaba como coordinador de nodos en ROS1. Usa funcionalidades del protocolo [DDS]^(Data Distribution Service) para que los nodos se descubran.
  - Es más robusto frente a problemas de comunicación que ROS1, también gracias a la funcionalidad de DDS
- ROS2 es multiplataforma, corre de forma nativa en Linux, Windows y MacOS
- Los nodos de ROS2 pueden correr en un mismo proceso y su ciclo de vida es gestionable
- Las bibliotecas de ROS2 comparten una implementación común (escrita en C)
- Incluye un bridge (_ROS1 bridge_) para facilitar la comunicación con, y migración de, antiguos sistemas.

## Tutoriales de ROS2

- <https://docs.ros.org/en/humble/Tutorials.html> Los tutos oficiales
- <https://ubuntu.com/tutorials/getting-started-with-ros-2#1-overview>
- <https://www.tutorialspoint.com/market/course/ros2_for_beginners_ros_foxy/index.jsp> (de pago en tutorialspoint)
- <https://www.udemy.com/course/ros2-for-beginners/?couponCode=FEB_2023> de pago en Udemy
- <https://www.youtube.com/watch?v=0aPbWsyENA8> Lista en youtube aparentemente del mismo autor
- <https://www.youtube.com/watch?v=Gg25GfA456o> Un curso condensado del mismo autor

### El tutorial oficial

1. Empezar con [las instrucciones de instalación](https://docs.ros.org/en/humble/Installation.html)
2. Seguir con [los tutoriales](https://docs.ros.org/en/humble/Tutorials.html)

## Probando ROS2 con Docker





## Probar ROS1 con Docker

{{< admonition type=info title="Referencias" open=true >}}

- [Docker and Ros](https://roboticseabass.com/2021/04/21/docker-and-ros/) by Robotic Sea Bass
- [Getting Started with ROS and Docker](https://wiki.ros.org/docker/Tutorials/Docker) de la wiki de ROS
- [Gráficos en Docker](https://wiki.ros.org/docker/Tutorials/GUI) de la wiki de ROS
- [Install ROS Noetic with Docker](https://varhowto.com/install-ros-noetic-docker/)

{{< /admonition >}}


Gracias a Docker podemos usar ROS fácilmente en cualquier linux (aunque no sea Ubuntu)

Lanzar un completo _ROS Noetic_ en Docker es tan simple como:

```bash
docker pull osrf/ros:noetic-desktop-full

# Si queremos una sesión interactiva:
docker run -it osrf/ros:noetic-desktop-full bash
```


Imágenes Docker de ROS disponibles:

__noetic-ros-core__

: Esta imagen nos permite usar paquetes básicos de ROS: podremos publicar y suscribirnos a nodos ROS, invocar servicios ROS y lazar ficheros ROS.

__noetic-ros-base__

: Basada en la anterior. Añade algunos paquetes esenciales como: _actionlib_, _dynamic reconfigure_, _nodelets_ y  _pluginlib_.

__noetic-robot__

: Basada en __noetic-ros-base__ añade los metapaquetes `robot`y `viz`, así como la mayor parte de los paquetes utilizados en los tutoriales oficiales. Esta sería la imagen mínima para hacer los tutoriales. También sería la imagen ideal para instalar en un robot.

__noetic-perception__

: Esta imagen incluye [PCL]^(Point Cloud Library), la biblioteca `perception_pcl` y bibliotecas relacionadas con el procesamiento de imágenes como:

    - `image_common`
    - `image_pipeline`
    - `image_transport_plugins`
    - `laser_pipeline`00

__noetic-desktop__


: Es similar a la anterior (__noetic-robot__) pero no está basada en ella.

__noetic-desktop-full__

: Basada en la anterior pero además añade paquetes de percepción y simulación, tales como `Gazebo` y `PCL`.


## Experimento

```bash
# Si queremos una sesión interactiva:
docker run -it osrf/ros:noetic-desktop-full bash

```

Dentro del contenedor actualizamos

```bash
apt update
apt upgrade
apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential
apt install python3-rosdep
```



Un dockerfile:

```dockerfile
FROM: osrf/ros:noetic-desktop-full


RUN: apt-get update && apt-get upgrade -y
RUN: apt-get install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential python3-rosdep



```

```bash
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'


# Lanzar Xephyr en el DISPLAY :1
Xephyr -ac -screen 800x600 -br -reset -terminate 2> /dev/null :1 &

docker run -it --name correMundos pabloImage roscore



world_files=`docker exec -it correMundos 'ls' '-1' '/opt/ros/noetic/share/stage/worlds/' |grep '\.world' `

if [ ${#world_files[@]} -eq 0 ]; then
  echo "No se encontraron archivos con la extensión .world en este directorio."
else
  echo "Archivos .world encontrados:"
  for i in "${!world_files[@]}"; do
    echo "$((i+1)): ${world_files[i]}"
  done

  read -p "Ingrese el número del archivo que desea ejecutar: " selection
  case $selection in
    [1-${#world_files[@]}])
      selected_file=${world_files[$((selection-1))]}
      echo "Ejecutando archivo $selected_file..."
      docker exec -it correMundos "rosrun stage_ros stageros /opt/ros/noetic/share/stage/worlds/$selected_file"
      ;;
    *)
      echo "Selección inválida. Saliendo del programa."
      ;;
  esac
fi

```
