Tutorial · Principiante · 1 hora
Instalar ROS 2 en Raspberry Pi y compilar un espacio de trabajo
ROS 2 en una Raspberry Pi: el sistema operativo adecuado, instalación con apt, compilación con colcon y red Wi-Fi para comunicar robot y portátil.
Introducción
Nada de ROS 2 es difícil hasta que intentas instalarlo en un robot, y en ese momento fallan a la vez tres cosas sin relación entre sí: el sistema operativo no es el correcto, el espacio de trabajo no compila en la memoria de la Pi, y el portátil no ve los nodos del robot. Ninguna de ellas es un problema de ROS en sí, y por eso los tutoriales oficiales no te avisan de ellas.
Esto te lleva desde una tarjeta SD en blanco hasta ros2 topic list funcionando desde tu portátil contra nodos que se ejecutan en el robot.
Elige el sistema operativo, no solo la placa
Los binarios de ROS 2 se compilan para Ubuntu, no para Raspberry Pi OS. Raspberry Pi OS está basado en Debian, así que los paquetes de apt sencillamente no están ahí, y cualquier apaño — compilar desde el código fuente, Docker, conda — te cuesta horas antes de haber escrito una sola línea de código de robot.
Así que instala Ubuntu Server 24.04 LTS (64 bits) y hazlo coincidir con la versión de ROS 2 compilada contra él. En el momento de escribir esto, esa pareja es Jazzy Jalisco, con soporte hasta 2029; consulta la página de instalación para lo que esté vigente cuando leas esto y sustituye el nombre en todo el texto.
Tres cosas que dejar bien en el momento de grabar la imagen:
- 64 bits. Los paquetes arm64 de ROS 2 existen; los armhf no.
- Server, no Desktop. Un robot no tiene monitor, y el entorno de escritorio se come la RAM que querrías para visión.
- Pi 4 con 4 GB, o una Pi 5. Una placa de 2 GB ejecuta ROS 2 sin problema pero no puede compilarlo cómodamente.
Instala ROS 2 desde apt
Añade la fuente apt de ROS 2 y luego instala. La configuración del repositorio es la parte que cambia entre versiones, así que esto es la forma más que un fragmento que haya que memorizar:
sudo apt update && sudo apt install -y software-properties-common curl
sudo add-apt-repository universe
# Fetch and install the package that registers the ROS 2 apt repository and key.
export ROS_APT_SOURCE_VERSION=$(curl -s \
https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest \
| grep -F "tag_name" | awk -F\" '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb \
"https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo $VERSION_CODENAME)_all.deb"
sudo apt install -y /tmp/ros2-apt-source.deb
sudo apt update
sudo apt install -y ros-jazzy-ros-base ros-dev-tools
Fíjate en ros-base, no en desktop. El metapaquete de escritorio se arrastra RViz y las GUIs de demostración, que un robot sin pantalla nunca va a ejecutar y que tardan muchísimo en instalarse en una tarjeta SD. La visualización va en tu portátil, donde instalas el ros-jazzy-desktop completo.
ros-dev-tools es lo que te da colcon y rosdep. Inicializa rosdep una vez:
sudo rosdep init # skip if it says the file already exists
rosdep update
Carga el underlay y luego tu overlay
ROS 2 no hace nada hasta que su entorno está cargado, y aquí es donde vive la mayor parte de la confusión inicial.
source /opt/ros/jazzy/setup.bash
Ese es el underlay — la distribución instalada. Tu propio espacio de trabajo, una vez compilado, es un overlay por encima de él. Cargar un overlay trae implícitamente el underlay contra el que se compiló.
echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc
Meter el underlay en .bashrc es estándar y seguro. Meter tu overlay ahí es una trampa que conviene evitar pronto: el día que tengas dos espacios de trabajo, o que recompiles contra otra distribución, cada terminal nueva arrancará en silencio con un entorno obsoleto y te depurarás una fantasma durante una tarde. Carga el overlay explícitamente, terminal a terminal, en la terminal que lo necesite.
Crea un espacio de trabajo y un paquete
Un espacio de trabajo de colcon es un directorio con un src/ dentro. Esa es toda la especificación.
mkdir -p ~/ros2_ws/src && cd ~/ros2_ws
ros2 pkg create --build-type ament_python --license Apache-2.0 my_robot
Luego compila y úsalo como overlay:
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -y
colcon build --symlink-install
source install/setup.bash
Usa --symlink-install. Enlaza tus ficheros Python en el espacio de instalación en lugar de copiarlos, así que editar un nodo surte efecto la siguiente vez que lo ejecutas en vez de tras recompilar. En una Pi, donde una recompilación es lenta, esa es la diferencia entre iterar y esperar.
Tras la compilación, ~/ros2_ws contiene build/, install/ y log/ junto a src/. Solo src/ va al control de versiones.
Compila sin quedarte sin memoria en la Pi
colcon build compila los paquetes en paralelo, un proceso por núcleo, y cada compilación de C++ puede llevar casi un gigabyte. En una Pi de cuatro núcleos eso son cuatro compiladores pesados a la vez, y la compilación muere con un mensaje sobre un proceso terminado — o la placa entera se queda colgada.
MAKEFLAGS="-j1" colcon build --parallel-workers 1 --symlink-install
Más lento, y termina. Los paquetes en Python puro no tienen ese problema; muerde en cuanto compilas algo que lleve C++. Añadir un par de gigabytes de swap también funciona, aunque en una tarjeta SD es lentísimo.
Habla con el robot desde tu portátil
ROS 2 no tiene maestro. Los nodos se encuentran entre sí por descubrimiento DDS a través de la red, lo que significa que un portátil y una Pi en la misma LAN pueden formar un único grafo sin ninguna configuración — cuando funciona.
Pon el mismo dominio en las dos máquinas:
export ROS_DOMAIN_ID=42 # any value 0–101; the same on every machine
El dominio particiona la red. Dos robots en la misma sala en el dominio por defecto se oirán mutuamente los topics y pelearán por ellos, que es una forma memorable de aprender para qué sirve este ajuste.
Verifícalo desde el portátil, con un talker ejecutándose en la Pi:
ros2 topic list
ros2 node list
ros2 topic echo /chatter
Haz que el descubrimiento sobreviva al Wi-Fi
ros2 topic list sin mostrar nada mientras la Pi está publicando claramente es el fallo de red de ROS 2 más habitual, y casi nunca es culpa de ROS.
El descubrimiento usa multidifusión, y muchos puntos de acceso no la reenvían. Los routers Wi-Fi de consumo limitan la tasa o descartan la multidifusión con frecuencia, y los modos de «aislamiento de clientes» o de red de invitados bloquean directamente el tráfico entre clientes. Los nodos están corriendo; los paquetes que los presentarían nunca llegan.
Resuélvelo en este orden:
- ¿Misma subred? Un portátil en 5 GHz y una Pi en un SSID de invitados no están en la misma red, por parecidas que parezcan las direcciones.
- ¿El mismo
ROS_DOMAIN_ID, en la terminal que está ejecutando realmente el nodo? Unexporten una terminal no llega a otra, y no llega a un servicio de systemd. - Prueba por cable. Si Ethernet funciona y el Wi-Fi no, has demostrado que es multidifusión y no ROS.
- Revisa el cortafuegos.
sudo ufw allow in proto udp from <subnet>en los dos extremos, o desactívalo mientras pruebas. - Recurre a un servidor de descubrimiento. Fast DDS puede usar un punto final conocido en lugar de multidifusión — pon
ROS_DISCOVERY_SERVERa la dirección del robot en las dos máquinas. Esta es la respuesta fiable en una red que no controlas.
Una más, y es una silenciosa: mantén los relojes sincronizados. TF2 compara marcas de tiempo entre máquinas, y una Pi sin RTC arranca con una hora equivocada. Instala chrony en los dos extremos, o cada búsqueda de transformación falla con un error de extrapolación que parece un fallo de ROS.
Arranca los nodos del robot al iniciar
Un robot al que hay que conectarse por SSH para arrancarlo es un robot que está apagado. Una unidad de systemd lo arregla:
# /etc/systemd/system/my-robot.service
[Unit]
Description=Robot bringup
After=network-online.target
[Service]
User=ubuntu
Environment=ROS_DOMAIN_ID=42
ExecStart=/bin/bash -lc 'source /opt/ros/jazzy/setup.bash && \
source /home/ubuntu/ros2_ws/install/setup.bash && \
ros2 launch my_robot bringup.launch.py'
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl enable --now my-robot
journalctl -u my-robot -f
La línea Environment= importa más de lo que parece. systemd no lee tu .bashrc, así que un servicio no hereda ninguna de las variables ROS que tiene tu shell interactivo — que es exactamente la razón por la que un robot que funciona por SSH se calla cuando se arranca solo.
Cuando va mal
| Síntoma | Normalmente |
|---|---|
ros2: command not found |
El underlay nunca se cargó en esta terminal |
ros2 topic list vacío desde el portátil |
Multidifusión bloqueada, o ROS_DOMAIN_ID distintos |
| Compilación terminada a mitad sin error | Sin memoria — limita los workers en paralelo |
| Tu cambio de código no tuvo efecto | Compilado sin --symlink-install, o overlay no recargado |
| Paquete no encontrado después de compilarlo | Overlay no cargado, o cargado antes de que terminara la compilación |
| Errores de TF sobre extrapolación al futuro | Relojes no sincronizados entre máquinas |
| Funciona por SSH, muerto al arrancar | Servicio de systemd sin el entorno de ROS |
Con el entorno comportándose, la siguiente pregunta es qué poner en él — que es un problema de diseño más que de instalación. Nodos, topics, servicios y acciones cubre cómo elegir entre los patrones de comunicación, y marcos de coordenadas TF2 cubre la parte que te pilla después de eso.
Explora el grafo
Forma parte de estos montajes
Proyectos y rutas de aprendizaje que incluyen este tutorial.
Lecturas adicionales