PTENES
MÓDULO 4.1 · FUNDAMENTO

🧩 ROS 2 sin miedo

ROS 2 parece enorme porque trae muchas cosas listas para usar. Para empezar solo necesitas cinco ideas: nodo, tópico, mensaje, servicio y acción. En este módulo eliges la distro, instalas (o ejecutas en Docker), lees el grafo desde la terminal y escribes tu primer nodo en Python.

6
Temas
Intermedio
Nivel
Fundamentos
Tipo
Solo la PC
Hardware necesario
0%
0 de 0 temas leídos · Sección 1 de 6

Contenido detallado

1

🧠 Qué es ROS 2 y por qué usarlo

Hasta la Ruta 3, el robot era uno o dos programas que escribías completos. Cuando se incorporan LiDAR, mapas, cámara y navegación, un solo programa se vuelve imposible de mantener. El ROS 2 (Robot Operating System 2) resuelve esto: cada tarea se convierte en un programa pequeño y todos intercambian datos por nombre, sin saber quién está del otro lado ni en qué computadora. A pesar de su nombre, no es un sistema operativo: funciona sobre Linux, como un conjunto de bibliotecas y herramientas.

🌱 ¿Eres nuevo aquí?

Middleware es el software «intermedio»: está entre tus programas y la red y se encarga de entregar los mensajes. En ROS 2, esa función la cumple DDS (Data Distribution Service), un estándar industrial que descubre automáticamente quién publica y quién se suscribe a cada dato. Un paquete es la unidad de código que instalas o escribes: un controlador de LiDAR, Nav2, tu robot.

DDS: entrega mensajes por nombre controlador LiDARpublica /scan cámarapublica /image navegaciónse suscribe a /scan base (ESP32)se suscribe a /cmd_vel RViz en la PCotra computadora

Cómo leer: cada recuadro ámbar es un programa independiente (un nodo). Ninguno se comunica directamente con otro: todos se conectan a la franja cian. La navegación solicita «/scan» y lo recibe del controlador de LiDAR sin saber quién es. El recuadro punteado está en otra computadora de la red y participa de la misma manera.

✓ Usa ROS 2 cuando

  • ✓El robot tiene LiDAR, mapas o navegación.
  • ✓Hay más de una computadora (Pi, PC, ESP32) trabajando en conjunto.
  • ✓Quieres simular antes de construir.

✗ No necesitas ROS 2 para

  • ✗Un seguidor de línea o un rover que esquiva obstáculos (Rutas 1 y 2).
  • ✗Un ESP32 por sí solo, sin una computadora cerca.
  • ✗Un prototipo para un fin de semana con un solo sensor.

Por qué aprender

ROS 2 es el lenguaje común de la robótica de investigación y de buena parte de la industria. Al aprender lo básico, puedes usar gratis controladores de sensores, slam_toolbox para crear mapas y Nav2 para la navegación, en vez de escribirlo todo desde cero.

Conceptos clave

Middleware
entrega los mensajes
DDS
descubre quién habla
Grafo de ROS
nodos + conexiones
Paquete
unidad de código
2

📅 Qué distro elegir: Lyrical o Jazzy

ROS 2 se publica en distribuciones (distros), con nombres de tortugas, una por año. Las de número par, que se publican en mayo, son LTS (soporte prolongado, cinco años) y corresponden a una versión LTS de Ubuntu. En octubre de 2026 hay dos buenas opciones: Lyrical Luth, publicada el 22/05/2026 para Ubuntu 26.04 y con soporte hasta mayo de 2031, y Jazzy Jalisco, la LTS anterior, para Ubuntu 24.04, con soporte hasta 2029 y más tutoriales y paquetes listos para usar.

202220242026202820302032 hoy (oct/2026) Humble · fin may/2027 Jazzy · Ubuntu 24.04 · Harmonic Lyrical · Ubuntu 26.04 · Jetty

Cómo leer: cada barra representa el período en el que la distro recibe correcciones. La línea cian indica el día de hoy. Humble (línea gris punteada) termina en menos de un año: no empieces con esa versión. Jazzy y Lyrical te servirán por años; cada una incluye Ubuntu y Gazebo de la misma pareja.

Si tú...Elige
vas a empezar desde cero hoy, en una PC nuevaLyrical (Ubuntu 26.04, Gazebo Jetty)
sigues un tutorial, libro o robot que requiere JazzyJazzy (Ubuntu 24.04, Gazebo Harmonic)
necesitas un paquete que aún no está disponible para LyricalJazzy, o Lyrical en Docker para probar
tienes un proyecto antiguo en HumblePlanea migrar a Jazzy antes de mayo/2027

🌱 ¿Eres nuevo aquí?

En este curso, los comandos usan <distro> como parte variable: reemplázala por lyrical o jazzy, siempre en minúsculas. Ejemplo: source /opt/ros/jazzy/setup.bash. El resto del comando es igual en ambas.

Por qué aprender

La mayoría de los «no funciona» en ROS se deben a mezclas: un tutorial de una distro, un paquete de otra y Gazebo de una tercera. Elegir la distro al principio y mantener la combinación Ubuntu ↔ ROS ↔ Gazebo evita este tipo de fallas.

Conceptos clave

Distro
versión de ROS con nombre propio
LTS
cinco años de soporte
Pareja oficial
Ubuntu ↔ ROS ↔ Gazebo
<distro>
lyrical o jazzy
3

📦 Instalar (Ubuntu, Docker o Pi)

Hay tres opciones. En Ubuntu (en la PC o en una máquina virtual), instalas paquetes listos para usar y obtienes el mejor rendimiento en Gazebo. Con Docker, ejecutas un contenedor que ya incluye ROS, en cualquier Linux (y en Windows o macOS, aunque configurar las ventanas gráficas requiere más ajustes). En Raspberry Pi 5, lo más directo es instalar Ubuntu de la misma versión que la distro; en Raspberry Pi OS, usa Docker.

Paso a paso en Ubuntu

1

Comprueba Ubuntu

Lyrical requiere Ubuntu 26.04; Jazzy requiere 24.04. Compruébalo con lsb_release -a.

2

Agrega el repositorio de ROS

Sigue la sección «Setup Sources» de la página oficial de instalación de tu distro en docs.ros.org. Este paso cambia de vez en cuando; copia las instrucciones de ahí, no de tutoriales antiguos.

3

Instala y activa

Ejecuta el bloque de abajo. El paquete desktop incluye RViz2, ejemplos y herramientas; ros-dev-tools incluye colcon y rosdep.

Objetivo: instalar ROS 2 y dejarlo activado automáticamente en cada terminal nueva.

terminal (Ubuntu)
# después de configurar el repositorio desde la página oficial
sudo apt update && sudo apt upgrade -y
sudo apt install -y ros-<distro>-desktop ros-dev-tools
# activa ROS en cada terminal nueva
echo "source /opt/ros/<distro>/setup.bash" >> ~/.bashrc
source ~/.bashrc
# prueba: dos nodos de ejemplo, uno en cada terminal
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_py listener

Cómo verificar

  • ✓talker imprime "Publishing: 'Hello World: 1'", "...: 2"; listener imprime "I heard: [Hello World: 1]".
  • ✓printenv ROS_DISTRO muestra lyrical o jazzy.
  • ✗¿«ros2: command not found»? Falta ejecutar source en esta terminal.

Opción rápida con Docker: la imagen oficial osrf/ros:<distro>-desktop ya incluye todo. Las opciones de DISPLAY permiten que el contenedor abra ventanas (RViz, turtlesim) en tu Linux. Revisa las etiquetas disponibles en Docker Hub antes de descargar.

terminal (Docker en Linux)
# permite que el contenedor use la pantalla (ejecútalo una vez por sesión)
xhost +local:docker
docker run -it --rm --net=host \
  -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \
  -v ~/ros2_ws:/root/ros2_ws \
  osrf/ros:<distro>-desktop
# dentro del contenedor, ROS ya está activado:
ros2 run turtlesim turtlesim_node

Cómo verificar: abre una ventana azul con una tortuga en el centro. La carpeta ~/ros2_ws de tu PC aparece dentro del contenedor en /root/ros2_ws, así que el código que escribas no desaparece cuando se cierre el contenedor.

💡 ¿Y en Raspberry Pi 5?

Graba Ubuntu Server de la versión correspondiente (26.04 para Lyrical, 24.04 para Jazzy) con Raspberry Pi Imager e instala ros-<distro>-ros-base (sin las herramientas gráficas). Visualiza en la PC: RViz y Gazebo son demasiado pesados para la Pi. Si quieres conservar Raspberry Pi OS de la Ruta 3, usa la imagen ros:<distro>-ros-base en Docker.

Por qué aprender

Instalarlo correctamente una vez te ahorra horas después. Docker también es la solución para el aula: todos los estudiantes ejecutan exactamente la misma imagen, sin diferencias entre máquinas.

Conceptos clave

desktop
ROS + herramientas gráficas
ros-base
ligero, para el robot
source
activa ROS en la terminal
Contenedor
el mismo entorno en todas las PC
4

🔗 Nodos, tópicos, mensajes

Un nodo es un proceso que hace una cosa: leer el LiDAR, girar los motores, planificar la ruta. Los nodos se comunican por tópicos, canales con nombres como /cmd_vel o /scan. Quien envía es el publisher; quien recibe es el subscriber. Un tópico puede tener varios de cada lado. El contenido tiene un formato fijo; el mensaje: /cmd_vel usa geometry_msgs/msg/Twist, con velocidad lineal y angular.

🌱 ¿Eres nuevo aquí?

Twist es el mensaje de «quiero moverme así»: linear.x en metros por segundo (hacia adelante) y angular.z en radianes por segundo (girar; positivo es en sentido antihorario visto desde arriba). Un robot diferencial ignora los otros cuatro campos. QoS (calidad de servicio) es el acuerdo de entrega de cada tópico, como «guardar los últimos 10 mensajes».

teleop /cmd_vel base lidar /scan slam rviz2 publicase suscribe Twist: linear.x, angular.z

Cómo leer: los rectángulos son nodos (programas); las cápsulas cian son tópicos (canales). La flecha sale de quien publica y llega a quien se suscribe. Observa que /scan tiene dos suscriptores: el mismo dato del láser alimenta el mapa y la pantalla sin ningún código adicional.

Objetivo: inspeccionar un grafo real con turtlesim. Abre tres terminales (todas con ROS activado).

terminal
# terminal 1: el simulador de la tortuga
ros2 run turtlesim turtlesim_node
# terminal 2: conduce con las flechas del teclado
ros2 run turtlesim turtle_teleop_key
# terminal 3: observa el grafo
ros2 node list
ros2 topic list -t
ros2 topic info /turtle1/cmd_vel
ros2 interface show geometry_msgs/msg/Twist
ros2 topic echo /turtle1/pose
# publica tú mismo: la tortuga se mueve en círculo
ros2 topic pub --rate 2 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0}, angular: {z: 0.8}}"

Cómo verificar

  • ✓ros2 node list muestra /turtlesim e /teleop_turtle.
  • ✓topic info dice «Publisher count: 1, Subscription count: 1» (2 publishers cuando topic pub esté en ejecución).
  • ✓O echo imprime x, y y theta mientras cambian cuando la tortuga se mueve. Para ver el grafo dibujado, ejecuta rqt_graph.

Por qué aprender

Cuando el robot no se mueve, el primer paso siempre es el mismo: ros2 topic echo /cmd_vel. Si el comando llega, la falla está en el motor; si no llega, está en quien publica. Leer el grafo desde la terminal es la herramienta de diagnóstico más usada de toda la ruta.

Conceptos clave

Nodo
un proceso, una tarea
Tópico
canal con nombre
Mensaje
formato del dato
topic echo
ver lo que circula
5

🔁 Servicios, acciones y parámetros

El tópico es un flujo continuo, sin respuesta. Para los otros casos, ROS 2 tiene tres elementos más. Un servicio es una pregunta y respuesta rápida: «crea una tortuga aquí», «guarda el mapa». Una acción es una tarea prolongada con progreso y posibilidad de cancelarla: «ve a la cocina» (todo Nav2 funciona así). Un parámetro es un ajuste del nodo que cambias sin volver a compilar: velocidad máxima, nombre del puerto serial, color del fondo.

tópico servicio acción ABclienteservidorclienteservidor sin respuesta solicitudrespuestarápido, una sola vez objetivoprogresoresultadoprolongado, cancelable

Cómo leer: las líneas verticales son los dos lados de la conversación, y el tiempo avanza hacia abajo. En el tópico, A solo envía. En el servicio, el cliente espera una única respuesta. En la acción, el servidor envía avances (línea discontinua) mientras trabaja y, al final, el resultado.

terminal (con turtlesim abierto)
# servicio: crea una segunda tortuga
ros2 service list
ros2 service call /spawn turtlesim/srv/Spawn "{x: 2.0, y: 2.0, theta: 0.0, name: 'robo2'}"
# parámetro: cambia el color del fondo sin reiniciar
ros2 param list /turtlesim
ros2 param set /turtlesim background_r 150
# acción: gira hasta 90 grados (1,57 rad) y muestra el progreso
ros2 action list
ros2 action send_goal --feedback /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"

Cómo verificar: aparece una tortuga nueva en (2, 2); el fondo se vuelve violáceo; la terminal de la acción imprime varias líneas «Feedback: remaining: ...» y termina con «Goal finished with status: SUCCEEDED».

✓ Patrón correcto

  • ✓Lectura de sensor y velocidad: tópico.
  • ✓Activar un relé, guardar el mapa: servicio.
  • ✓Ir a un punto, girar el brazo: acción.

✗ Solución improvisada común

  • ✗Servicio que tarda 30 s (bloquea a quien lo llamó).
  • ✗Tópico «/pronto» para simular una respuesta.
  • ✗Constante en el código que debería ser un parámetro.

Por qué aprender

En el módulo 4.5 enviarás el robot hasta un punto mediante una acción de Nav2 y, en el 4.4, guardarás el mapa mediante un servicio. Reconocer el patrón hace que la documentación de estos paquetes sea fácil de entender.

Conceptos clave

Servicio
solicitud → respuesta
Acción
objetivo, progreso, resultado
Parámetro
ajuste sin volver a compilar
.srv / .action
formatos de interfaz
6

🐍 Tu primer nodo en Python (rclpy) publicando y escuchando

Ahora escribes tus nodos. En Python, la biblioteca es rclpy. Cada nodo sigue el mismo patrón: inicia rclpy, crea un objeto Node, registra publishers, subscribers y timers, y entrega el control a spin, que espera eventos y llama a tus funciones. Vas a crear un paquete meu_robo con dos nodos: falante publica una frase dos veces por segundo; ouvinte recibe e imprime.

falantetimer 0,5 spublicar()create_publisher /conversastd_msgs/String ouvintecreate_subscriptionao_receber(msg)imprime en el log spin() mantiene vivos los dos nodos mientras esperan eventos

Cómo leer: el reloj (timer) del falante llama a publicar(), que envía una String al tópico. El ouvinte no pregunta nada: ROS llama a ao_receber() cada vez que llega un mensaje. Ese «tú no llamas, te llaman» es el callback.

Objetivo: crear el workspace y el paquete. El comando ros2 pkg create genera la estructura; después solo tienes que reemplazar los archivos por los bloques de abajo.

terminal
mkdir -p ~/ros2_ws/src && cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python --license MIT meu_robo --dependencies rclpy std_msgs
# crea los dos nodos dentro de la carpeta de código del paquete
touch meu_robo/meu_robo/falante.py meu_robo/meu_robo/ouvinte.py
meu_robo/meu_robo/falante.py
# Nodo que publica una frase en el tópico /conversa dos veces por segundo
import rclpy
from rclpy.node import Node
from rclpy.executors import ExternalShutdownException
from std_msgs.msg import String

class Falante(Node):
    def __init__(self):
        super().__init__('falante')
        self.pub = self.create_publisher(String, 'conversa', 10)  # cola de 10 mensajes
        self.contador = 0
        self.timer = self.create_timer(0.5, self.publicar)        # llama a publicar() cada 0,5 s

    def publicar(self):
        msg = String()
        msg.data = f'¡Hola desde el robot #{self.contador}'
        self.pub.publish(msg)
        self.get_logger().info(f'Publicado: {msg.data}')
        self.contador += 1

def main(args=None):
    rclpy.init(args=args)
    no = Falante()
    try:
        rclpy.spin(no)
    except (KeyboardInterrupt, ExternalShutdownException):
        pass
    finally:
        no.destroy_node()
        rclpy.try_shutdown()

if __name__ == '__main__':
    main()
meu_robo/meu_robo/ouvinte.py
# Nodo que se suscribe a /conversa e imprime cada mensaje recibido
import rclpy
from rclpy.node import Node
from rclpy.executors import ExternalShutdownException
from std_msgs.msg import String

class Ouvinte(Node):
    def __init__(self):
        super().__init__('ouvinte')
        self.sub = self.create_subscription(String, 'conversa', self.ao_receber, 10)

    def ao_receber(self, msg):
        self.get_logger().info(f'Escuché: {msg.data}')

def main(args=None):
    rclpy.init(args=args)
    no = Ouvinte()
    try:
        rclpy.spin(no)
    except (KeyboardInterrupt, ExternalShutdownException):
        pass
    finally:
        no.destroy_node()
        rclpy.try_shutdown()

if __name__ == '__main__':
    main()

O setup.py indica a ROS qué comandos ofrece el paquete (los entry_points), e o package.xml enumera las dependencias. Reemplaza los dos archivos generados por las versiones mínimas de abajo.

meu_robo/setup.py
from setuptools import find_packages, setup

package_name = 'meu_robo'

setup(
    name=package_name,
    version='0.1.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages', ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='voce',
    maintainer_email='voce@exemplo.com',
    description='Primeros nodos del curso de robótica',
    license='MIT',
    entry_points={
        'console_scripts': [
            'falante = meu_robo.falante:main',
            'ouvinte = meu_robo.ouvinte:main',
        ],
    },
)
meu_robo/package.xml
<?xml version="1.0"?>
<package format="3">
  <name>meu_robo</name>
  <version>0.1.0</version>
  <description>Primeiros nos do curso de robotica</description>
  <maintainer email="voce@exemplo.com">voce</maintainer>
  <license>MIT</license>
  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <export>
    <build_type>ament_python</build_type>
  </export>
</package>
terminal
cd ~/ros2_ws
colcon build --symlink-install
source install/setup.bash
ros2 run meu_robo falante        # terminal 1
ros2 run meu_robo ouvinte        # terminal 2 (vuelve a ejecutar source en esa terminal)

Cómo verificar

  • ✓colcon termina con "Summary: 1 package finished".
  • ✓Terminal 1: "[falante]: Publicado: ¡Hola desde el robot #0", "#1"... Terminal 2: "[ouvinte]: Escuché: ¡Hola desde el robot #3".
  • ✓En una tercera terminal, ros2 topic hz /conversa muestra cerca de 2 Hz.
  • ✗¿"Package 'meu_robo' not found"? Te faltó ejecutar source install/setup.bash en esa terminal.

💡 Desafío

Cambia el falante para que publique geometry_msgs/msg/Twist en /turtle1/cmd_vel (agrega geometry_msgs a package.xml) y haz que la tortuga dibuje un cuadrado: avanza 2 s, gira 90 grados y repite. Eso es exactamente lo que hace un nodo de navegación con tu robot.

Por qué aprender

Este patrón (clase Node, publisher, subscriber, timer, spin) es la base de todos los nodos de la ruta: el que calcula la odometría en el 4.3 y el que envía el robot a un punto en el 4.5. Cambian los tipos de mensaje y la lógica del callback; la estructura es la misma.

Conceptos clave

rclpy
ROS 2 en Python
Callback
ROS te llama
entry_points
nombre del ros2 run
colcon build
compila e instala

✅ Resumen del módulo

✓
ROS 2 es un grafo de programas pequeños que intercambian datos por nombre, mediante DDS, en una o varias computadoras.
✓
Lyrical para empezar desde cero; Jazzy si tu material lo requiere; Humble no, porque llega a su fin en mayo de 2027.
✓
Instalación: repositorio desde la página oficial, ros-<distro>-desktop, o Docker osrf/ros:<distro>-desktop.
✓
Tópico para un flujo, servicio para una pregunta, acción para una tarea larga, parámetro para un ajuste.
✓
Nodo en rclpy: Node + publisher/subscriber + timer + spin, empaquetado con setup.py y compilado con colcon.

Para profundizar

Siguiente módulo

4.2 · Describir y simular el robot: URDF, marcos TF, RViz2 y el robot en movimiento en Gazebo.