tutoriales.com

Control Robótico con ROS: Construyendo un Sistema de Navegación Simple para Robots Móviles

Este tutorial te guiará en la creación de un sistema de navegación simple para robots móviles utilizando ROS (Robot Operating System). Explorarás los conceptos clave de ROS, configurarás sensores y actuarás sobre un robot virtual o físico para la navegación autónoma básica. ¡Prepárate para dar tus primeros pasos en la robótica avanzada!

Intermedio25 min de lectura11 views
Reportar error

Introducción a la Navegación Robótica con ROS 🤖

¡Bienvenido al emocionante mundo de la robótica y el sistema operativo para robots (ROS)! En este tutorial, nos embarcaremos en un viaje para construir un sistema de navegación simple para robots móviles. ROS es una poderosa suite de herramientas, librerías y convenciones que facilita la creación de aplicaciones robóticas complejas y distribuidas. Si alguna vez soñaste con que tu robot se moviera de forma autónoma, ¡estás en el lugar correcto!

La navegación robótica es una de las áreas más fascinantes y desafiantes de la robótica. Implica que un robot pueda moverse de un punto A a un punto B en un entorno desconocido o semi-desconocido, evitando obstáculos y planificando su propia ruta. Con ROS, este proceso se vuelve modular y manejable.

¿Qué es ROS y por qué usarlo para navegación? 🎯

ROS (Robot Operating System) no es un sistema operativo en el sentido tradicional, sino un meta-sistema operativo que proporciona funcionalidades similares a las de un sistema operativo en un clúster de computadoras conectadas. Ofrece servicios como abstracción de hardware, comunicación entre procesos, administración de paquetes y herramientas para la visualización y depuración.

Ventajas de ROS para la Navegación:

  • Modularidad: Permite construir sistemas complejos a partir de componentes pequeños e independientes (nodos).
  • Reusabilidad: Gran cantidad de paquetes existentes para diversas funcionalidades (sensores, actuadores, algoritmos de navegación, etc.).
  • Comunidad: Una comunidad global activa que contribuye con código, soporte y documentación.
  • Abstracción de Hardware: Permite que el mismo código funcione con diferentes plataformas robóticas.
💡 Consejo: Piensa en ROS como el "pegamento" que une todos los componentes de tu robot (sensores, motores, algoritmos) de una manera organizada y escalable.

🛠️ Requisitos Previos e Instalación

Antes de sumergirnos en la navegación, necesitamos preparar nuestro entorno. Asegúrate de tener lo siguiente:

  • Sistema Operativo: Ubuntu (preferiblemente 20.04 LTS o 22.04 LTS, dependiendo de la versión de ROS).
  • Conocimientos Básicos: Familiaridad con la línea de comandos de Linux y conceptos básicos de programación (Python o C++).
  • Hardware (Opcional): Un robot móvil diferencial (como un TurtleBot o un robot DIY con ROS) o un simulador como Gazebo.

Instalación de ROS Noetic (Ubuntu 20.04 LTS) o ROS Foxy/Humble (Ubuntu 22.04 LTS)

Para este tutorial, asumiremos ROS Noetic (Ubuntu 20.04), pero los conceptos son fácilmente adaptables a versiones más recientes como Foxy o Humble. Si ya tienes ROS instalado, puedes saltarte esta sección.

  1. Configurar fuentes de paquetes:
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
  1. Configurar claves:
sudo apt install curl # si no lo tienes instalado
curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
  1. Actualizar índice de paquetes:
sudo apt update
  1. Instalar ROS Desktop Full:
sudo apt install ros-noetic-desktop-full # Para ROS Noetic
# o
# sudo apt install ros-foxy-desktop-full # Para ROS Foxy
# sudo apt install ros-humble-desktop-full # Para ROS Humble
  1. Inicializar rosdep:
sudo rosdep init
rosdep update
  1. Configurar el entorno de ROS:
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
(Asegúrate de cambiar `noetic` por `foxy` o `humble` si instalaste otra versión).
🔥 Importante: Reinicia tu terminal o ejecuta `source ~/.bashrc` después de la instalación para que los comandos de ROS estén disponibles.

🗺️ Conceptos Clave de Navegación en ROS

La navegación en ROS se basa en varios paquetes y conceptos interconectados que trabajan juntos para permitir que un robot se mueva de forma autónoma. Aquí están los pilares:

1. Sistema de Coordenadas y Transformaciones (TF) ✨

Los robots tienen múltiples sensores y actuadores, cada uno con su propio sistema de coordenadas. tf es un sistema que mantiene un árbol de relaciones de coordenadas espaciales entre marcos de referencia, permitiendo transformar puntos, vectores, etc., entre diferentes marcos en cualquier momento. Es fundamental para saber dónde está el robot en relación con el mundo y dónde están sus sensores.

Ejemplo de Marcos TF:

  • map: El marco de referencia del mundo, donde se construye el mapa.
  • odom: El marco de referencia para la odometría del robot (posición y orientación estimadas a corto plazo).
  • base_link: El centro del robot (su chasis).
  • laser_frame: El marco donde está montado el sensor LiDAR.
Árbol de Transformaciones (TF) map odom base_link laser_frame camera_link Global Odometría Sensor LiDAR Sensor Visual

2. Odometría (Odometry) 🚶

La odometría es la estimación de la posición y orientación de un robot a lo largo del tiempo, generalmente basada en la lectura de los encoders de las ruedas. Es una forma de localización relativa.

  • Pros: Sencilla de implementar, funciona bien a corto plazo.
  • Contras: Acumula errores con el tiempo (deriva), especialmente en superficies irregulares o con deslizamiento.

3. Mapeo y Localización Simultánea (SLAM) 🌍

SLAM (Simultaneous Localization and Mapping) es el proceso por el cual un robot construye un mapa de un entorno desconocido mientras se localiza simultáneamente dentro de ese mapa. Es un problema complejo pero crucial para la navegación autónoma.

Paquetes ROS comunes para SLAM:

  • gmapping: SLAM basado en LiDAR, usa filtros de partículas (partícula filtrada).
  • cartographer: SLAM 2D y 3D, de Google, robusto y eficiente.
  • Hector SLAM: SLAM basado en LiDAR de alta frecuencia, no requiere odometría inicial.

4. Navegación (ROS Navigation Stack) 🧭

El navigation stack de ROS es un conjunto de paquetes que proporciona la funcionalidad para que un robot se mueva de forma autónoma desde un punto A a un punto B. Utiliza la información de odometría, sensores (LiDAR, cámaras) y un mapa para planificar rutas y evitar obstáculos.

Componentes clave del Navigation Stack:

  • move_base: El nodo principal que orquesta todos los demás componentes para la navegación.
  • global_planner: Planifica una ruta "global" desde el inicio hasta el objetivo en el mapa estático.
  • local_planner: Planifica rutas "locales" y ajusta la trayectoria para evitar obstáculos dinámicos en tiempo real.
  • costmap_2d: Crea mapas de costo que representan la probabilidad de colisión en diferentes áreas del entorno. Hay un costmap global (para el global_planner) y uno local (para el local_planner).
📌 Nota: El `navigation stack` es altamente configurable y se adapta a diferentes tipos de robots y entornos.

⚙️ Configurando el Entorno de Navegación

Para este tutorial, utilizaremos un robot virtual en Gazebo. Esto nos permite experimentar sin la necesidad de hardware físico. Asumiremos que tenemos un modelo de robot diferencial básico con un sensor LiDAR (o un sensor de profundidad simulado).

1. Creación del Workspace y Paquete 📦

Primero, crearemos un catkin workspace y un paquete ROS para nuestro proyecto de navegación.

cd ~/
mkdir -p catkin_ws/src
cd catkin_ws/src
catkin_init_workspace
catkin_create_pkg my_robot_navigation rospy tf nav_msgs geometry_msgs sensor_msgs # Ajusta las dependencias según necesites
cd ..
catkin_make
source devel/setup.bash

2. Simulación de Robot en Gazebo

Necesitamos un modelo de robot en Gazebo que publique mensajes de odometría (nav_msgs/Odometry), datos de láser (sensor_msgs/LaserScan) y que pueda recibir comandos de velocidad (geometry_msgs/Twist).

Normalmente, esto implica:

  • Un archivo URDF (Unified Robot Description Format) que describe la geometría, cinemática y sensores del robot.
  • Archivos de lanzamiento (.launch) para Gazebo que cargan el modelo del robot y los plugins necesarios (ej. gazebo_ros_diff_drive para el control diferencial y gazebo_ros_laser para el LiDAR).

Para simplificar, usaremos el turtlebot3_simulations como base. Puedes instalarlo con:

sudo apt install ros-noetic-turtlebot3-simulations ros-noetic-turtlebot3-navigation

Una vez instalado, podemos lanzar el robot en un entorno de Gazebo.

export TURTLEBOT3_MODEL=burger # O waffle, o waffle_pi
roslaunch turtlebot3_gazebo turtlebot3_world.launch

Esto abrirá Gazebo con un TurtleBot3 en un mundo predefinido. Abre otra terminal y verifica los tópicos:

rostopic list

Deberías ver tópicos como /odom, /scan, /cmd_vel, etc.

⚠️ Advertencia: Asegúrate de que `TURTLEBOT3_MODEL` esté exportado correctamente en cada nueva terminal, o añádelo a tu `~/.bashrc`.

3. Configuración del navigation stack

El navigation stack se configura a través de varios archivos .yaml y .launch.

Los archivos .yaml más importantes son:

  • costmap_common_params.yaml: Parámetros comunes para los costmaps global y local (tamaño del robot, sensores).
  • global_costmap_params.yaml: Parámetros específicos para el costmap global.
  • local_costmap_params.yaml: Parámetros específicos para el costmap local.
  • base_local_planner_params.yaml: Parámetros para el planificador local (DWA, Trajectory Rollout, etc.).

Estos archivos suelen estar en el paquete my_robot_navigation/config.

Ejemplo costmap_common_params.yaml (simplificado):

robot_radius: 0.18 # Radio del robot en metros

footprint: [[-0.105, -0.105], [-0.105, 0.105], [0.105, 0.105], [0.105, -0.105]] # Huella poligonal

laser_scan_sensor:
  sensor_frame: base_scan
  topic: scan
  observation_sources: laser_scan_sensor
  data_type: LaserScan
  clearing: true
  marking: true

obstacle_layer:
  observation_sources: laser_scan_sensor
  laser_scan_sensor: {sensor_frame: base_scan, data_type: LaserScan, topic: scan, marking: true, clearing: true}

Ejemplo global_costmap_params.yaml:

global_costmap:
  global_frame: map
  robot_base_frame: base_footprint
  update_frequency: 1.0
  publish_frequency: 1.0
  static_map: true
  transform_tolerance: 0.5

Ejemplo local_costmap_params.yaml:

local_costmap:
  global_frame: odom
  robot_base_frame: base_footprint
  update_frequency: 5.0
  publish_frequency: 2.0
  static_map: false
  rolling_window: true
  width: 3.0
  height: 3.0
  resolution: 0.05

Ejemplo base_local_planner_params.yaml (usando DWA Planner):

DWAPlannerROS:
  max_vel_x: 0.2
  min_vel_x: -0.2
  max_vel_theta: 1.0
  min_vel_theta: -1.0
  acc_lim_x: 2.5
  acc_lim_theta: 3.2

  # Goal Tolerance Parameters
  yaw_goal_tolerance: 0.05
  xy_goal_tolerance: 0.10

  # Forward Simulation Parameters
  sim_time: 1.7
  sim_granularity: 0.025
  goal_distance_bias: 32.0
  path_distance_bias: 24.0
  occdist_scale: 0.02

  # Trajectory Scoring Parameters
  pdist_scale: 0.6
  gdist_scale: 0.8
  occdist_scale: 0.01

4. Lanzamiento de Navegación 🚀

Para lanzar el navigation stack completo, necesitamos un archivo .launch que cargue todos los parámetros y los nodos necesarios (principalmente move_base).

Crea un archivo my_robot_navigation/launch/my_robot_navigation.launch:

<launch>
  <!-- Carga de parámetros del navigation stack -->
  <rosparam file="$(find my_robot_navigation)/config/costmap_common_params.yaml" command="load" ns="global_costmap" />
  <rosparam file="$(find my_robot_navigation)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
  <rosparam file="$(find my_robot_navigation)/config/local_costmap_params.yaml" command="load" />
  <rosparam file="$(find my_robot_navigation)/config/global_costmap_params.yaml" command="load" />
  <rosparam file="$(find my_robot_navigation)/config/base_local_planner_params.yaml" command="load" />

  <!-- Nodo move_base -->
  <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
    <param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
    <remap from="cmd_vel" to="cmd_vel"/>
    <remap from="odom" to="odom"/>
    <param name="global_costmap/laser_scan_sensor/topic" value="scan"/>
    <param name="local_costmap/laser_scan_sensor/topic" value="scan"/>
  </node>
</launch>

🗺️ Mapeo y Localización (SLAM) con GMapping

Para que el robot navegue, necesita un mapa del entorno. Usaremos gmapping para crear un mapa 2D del mundo de Gazebo.

1. Lanzar GMapping

En una nueva terminal, lanza el nodo gmapping. Si estás usando el TurtleBot3, ya hay un archivo de lanzamiento para esto.

export TURTLEBOT3_MODEL=burger
roslaunch turtlebot3_slam turtlebot3_slam.launch slam_methods:=gmapping

Esto iniciará gmapping y también rviz (Robot Visualization) para que puedas ver el proceso de mapeo.

LaserScan Odometry GMapping Node TF Tree map

2. Explorar el Entorno para Crear el Mapa

Ahora, necesitas mover el robot para que explore el entorno y gmapping pueda construir el mapa. Puedes hacerlo manualmente usando un joystick, publicando mensajes /cmd_vel o usando un nodo de teleoperación.

Para teleoperar el TurtleBot3:

export TURTLEBOT3_MODEL=burger
roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch

Mientras mueves el robot, observa RVIZ. Deberías ver cómo se construye el mapa en la ventana "Map".

💡 Consejo: Asegúrate de explorar todas las áreas relevantes del entorno para crear un mapa completo y preciso.

3. Guardar el Mapa

Una vez que estés satisfecho con el mapa, guárdalo:

rosrun map_server map_saver -f ~/catkin_ws/src/my_robot_navigation/maps/my_gazebo_map

Esto creará dos archivos: my_gazebo_map.pgm (la imagen del mapa) y my_gazebo_map.yaml (metadatos del mapa).


🚀 Navegación Autónoma: ¡Movimiento!

Con un mapa guardado, el siguiente paso es la navegación autónoma. Ahora usaremos el navigation stack con nuestro mapa estático.

1. Lanzar el Mapa y el Nodo amcl (Localización Adaptativa)

amcl (Adaptive Monte Carlo Localization) es un algoritmo de localización probabilística que utiliza un filtro de partículas para localizar un robot en un mapa estático conocido. Es crucial para corregir la deriva de la odometría.

Para lanzar el mapa y amcl, puedes usar un archivo de lanzamiento como este (o el proporcionado por TurtleBot3):

<launch>
  <!-- Mapa estático -->
  <arg name="map_file" default="$(find my_robot_navigation)/maps/my_gazebo_map.yaml"/>
  <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" />

  <!-- Nodo AMCL -->
  <include file="$(find amcl)/examples/amcl_diff.launch">
    <arg name="initial_pose_x" value="0.0"/>
    <arg name="initial_pose_y" value="0.0"/>
    <arg name="initial_pose_a" value="0.0"/>
    <arg name="odom_frame_id" value="odom"/>
    <arg name="base_frame_id" value="base_footprint"/>
    <arg name="global_frame_id" value="map"/>
  </include>

  <!-- Nodo de navegación (move_base) -->
  <include file="$(find my_robot_navigation)/launch/my_robot_navigation.launch"/>

  <!-- RVIZ para visualización -->
  <node pkg="rviz" type="rviz" name="rviz" args="-d $(find my_robot_navigation)/rviz/my_navigation.rviz"/>
</launch>

Guarda esto como my_robot_navigation/launch/start_navigation.launch. Asegúrate de que los archivos .yaml de move_base y el archivo .rviz estén configurados correctamente. Para el .rviz, puedes empezar con una configuración básica y añadir los displays de Map, RobotModel, LaserScan, Path y PoseArray (para AMCL).

Lanza el robot en Gazebo (si no está ya activo) y luego tu pila de navegación:

export TURTLEBOT3_MODEL=burger
roslaunch turtlebot3_gazebo turtlebot3_world.launch # Si no está activo
roslaunch my_robot_navigation start_navigation.launch

2. Localización Inicial en RVIZ

Cuando amcl se inicia, el robot no sabe dónde está en el mapa. Necesitas "darle una pista" de su posición inicial.

  1. En RVIZ, haz clic en el botón "2D Pose Estimate" (generalmente una flecha con un cuadrado).
  2. Haz clic y arrastra en el mapa para indicar la posición y orientación aproximadas del robot.

Verás un "enjambre" de flechas (partículas) que se concentrarán a medida que el robot se mueva y amcl refine su posición.

3. Establecer un Objetivo de Navegación

Una vez que el robot esté localizado, puedes darle un objetivo:

  1. En RVIZ, haz clic en el botón "2D Nav Goal" (generalmente una flecha con una 'G').
  2. Haz clic y arrastra en el mapa para indicar la posición y orientación final deseada para el robot.

El navigation stack calculará una ruta global, y el planificador local comenzará a mover el robot, ajustando su trayectoria para evitar obstáculos.

📌 Nota: Si el robot no se mueve o se comporta de forma errática, revisa los parámetros de los costmaps, los planners y asegúrate de que todos los tópicos de los sensores estén siendo publicados correctamente.

4. Monitoreo y Depuración

  • rqt_graph: Visualiza el grafo de nodos y tópicos de ROS para entender el flujo de datos.
  • rostopic echo /cmd_vel: Verifica qué comandos de velocidad está enviando el move_base.
  • rostopic hz /scan: Comprueba la frecuencia de publicación de los sensores.
  • rosrun tf tf_echo map odom: Muestra la transformación entre los marcos map y odom, crucial para verificar la localización.

📈 Optimizando la Navegación

La navegación es un campo complejo y la optimización es clave para un rendimiento robusto.

1. Parámetros del Costmap

  • robot_radius o footprint: Ajusta estos valores para que representen con precisión el tamaño de tu robot y evite colisiones.
  • inflation_radius: Define qué tan lejos de un obstáculo el robot comenzará a considerarlo como un "costo" para planificar.
  • observation_sources: Asegúrate de que todos los sensores relevantes (LiDAR, cámaras de profundidad) estén configurados para marcar y/o borrar obstáculos en el costmap.

2. Parámetros del Planificador Local (DWA Planner)

El DWAPlannerROS tiene muchos parámetros para controlar el comportamiento del robot. Experimenta con ellos cuidadosamente.

ParámetroDescripciónImpacto
---------
max_vel_xVelocidad lineal máxima en XVelocidad máxima del robot
max_vel_thetaVelocidad angular máxima en ZCapacidad de giro del robot
---------
acc_lim_xAceleración lineal máxima en XSuavidad de las aceleraciones/frenadas
sim_timeTiempo de simulación para evaluar trayectoriasCuanto más largo, más "vista" hacia el futuro
---------
path_distance_biasPondera qué tan cerca debe estar de la ruta globalAyuda a seguir la ruta planificada
occdist_scalePondera la proximidad a obstáculosEvitar colisiones
80% Optimización

3. Integración de Sensores Adicionales

Para entornos más complejos, podrías necesitar:

  • Cámaras de profundidad (Kinect, RealSense): Para detectar obstáculos por encima o por debajo del plano del LiDAR.
  • Sensores ultrasónicos/IR: Para detección de corto alcance.
  • IMU: Para una mejor estimación de la orientación del robot.
¿Por qué la odometría sola no es suficiente?La odometría basada en encoders de ruedas es propensa a errores acumulativos debido al deslizamiento, las imperfecciones del suelo o el simple redondeo de valores. A largo plazo, la posición reportada por la odometría se "desvía" de la posición real. Por eso es crucial combinarla con un sensor externo (LiDAR, cámara) y un algoritmo de localización como AMCL o SLAM.

Conclusión y Próximos Pasos ✅

¡Felicidades! Has completado un viaje intensivo a través de la configuración de un sistema de navegación simple para robots móviles utilizando ROS. Hemos cubierto desde la instalación de ROS hasta la configuración de la simulación, el mapeo con gmapping, la localización con amcl y, finalmente, la navegación autónoma con el move_base.

Este es solo el comienzo. La robótica con ROS es un campo vasto y en constante evolución. Aquí hay algunos pasos para continuar tu aprendizaje:

  1. Explora otros algoritmos SLAM: Investiga Cartographer o Hector SLAM para ver sus ventajas en diferentes escenarios.
  2. Integrar con Hardware Real: Aplica estos conceptos a un robot físico (ej. TurtleBot3, tu propio robot DIY).
  3. Navegación en Entornos Dinámicos: Aprende sobre cómo manejar objetos en movimiento y personas en el entorno del robot.
  4. Planificación de Misiones: Desarrolla scripts para enviar múltiples objetivos de navegación secuencialmente.
  5. Percepción Avanzada: Incorpora visión por computadora para reconocimiento de objetos y detección de semántica del entorno.
Paso 1: Dominar los conceptos de TF y ROS Topics/Nodes.
Paso 2: Experimentar con diferentes configuraciones del `navigation stack`.
Paso 3: Implementar en un robot físico.
Paso 4: Explorar técnicas de navegación más avanzadas.

La robótica es una disciplina que recompensa la perseverancia y la experimentación. ¡Sigue construyendo, aprendiendo y haciendo que tus robots cobren vida!

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!