Comunicación principal de ROS2
06 Nodo
06 Nodos
6.1 Resumen de los nodos
6.1.1 Qué es un nodo
Un nodo es la unidad de cálculo más básica en ROS 2. Un nodo es un proceso que utiliza la API de ROS 2 para comunicarse con otros nodos. Cada nodo es normalmente responsable de funciones específicas, como leer datos de sensores, procesar datos, controlar implementadores, etc.
6.1.2 Características de los nodos
| Características | Anotaciones |
|---|---|
| Ligero | Un ejecutable puede contener múltiples nodos |
| Distribución | El nodo puede ejecutarse en diferentes máquinas. |
| Desacoplado | Comunicaciones entre nodos a través de interfaz, no directamente dependientes |
| Agrupable | Múltiples nodos para ejecutar funciones complejas |
| Ciclo de vida independiente | Iniciar y cerrar cada nodo de forma independiente |
6.1.3 Reglas de nomenclatura de nodos
El nombre de nodo debe ser único (en el mismo espacio de nombres)
Solo pueden incluirse letras, números y guiones bajos
Distingue entre mayúsculas y minúsculas
Uso recomendado de nombre descriptivo
Ejemplo de nombre:
| Nombre del nodo | Evaluación |
|---|---|
| Camera_driver | Excelente. |
| path_planner | Excelente. |
| Node1 | No recomendado (sin descripción) |
| Oh, my-node. | Inválido (con guion) |
6.2 Caso de nodo Hello World
6.2.1 Crear paquete python
workspace reemplaza la ruta real del workspace
cd workspace/src
ros2 pkg create pkg_helloworld_py --build-type ament_python --dependencies rclpy --node-name helloworld6.2.2 Preparación de códigos
import rclpy # ROS 2 Python client library
from rclpy.node import Node # ROS 2 node class
import time
class HelloWorldNode(Node):
def __init__(self, name):
super().__init__(name)
while rclpy.ok():
self.get_logger().info("Hello World")
time.sleep(0.5)
def main(args=None):
rclpy.init(args=args)
node = HelloWorldNode("helloworld")
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()colcon build --packages-select pkg_helloworld_py
source install/setup.bash
ros2 run pkg_helloworld_py helloworld6.3 Próximos pasos
1.07 Comunicación de tópicos
2.08 Comunicaciones de servicios
07 Comunicación de tópicos
07 Comunicación de tópicos (Topics)
7.1 Resumen de las comunicaciones de tópicos
7.1.1 ¿Qué es la comunicación de tópicos?
El tópico (Topic) es el mecanismo para la comunicación asincrónica entre los nodos de ROS 2, utilizando el modo de publicación/suscripción (Pub/Sub). El nodo emisor emite noticias al tópico, y el nodo suscriptor recibe información del tópico, y ninguno necesita conocer al otro.
7.1.2 Características de las comunicaciones de tópicos
| Características | Descripción | Aplicar escena |
|---|---|---|
| Comunicaciones asíncronas | El emisor no espera la respuesta del suscriptor | Flujo de datos del sensor |
| Múltiples a múltiples | Múltiples publicadores y suscriptores | Difusión de datos |
| Acoplamiento débil | Desacoplamiento | Diseño modular |
| Transferencia de flujo | Flujos de datos en curso | Monitoreo continuo |
7.1.3 Reglas de nomenclatura de tópicos
| Regla | Anotaciones |
|---|---|
| Debe comenzar (espacio de nombres global) o nombre relativo | |
| Use letras minúsculas, números y guiones bajos | |
| Use / para separar niveles de espacio de nombres | |
| Evite retener nombres |
Ejemplo de nombre:
| Nombre del sujeto | Evaluación |
|---|---|
| /cmd_vel | Estándares, recomendado |
| /camera/image_raw | Nivel claro. Recomendado. |
| /sensor/front_camera/image | Espacio de nombres, recomendado. |
| /MyTopic | No recomendado (mayúsculas) |
| add_vel | Nombre relativo (espacio de nombres del nodo agregado) |
7.2 Casos de comunicación
7.2.1 Nuevo paquete funcional
cd ~/workspaces/src
ros2 pkg create pkg_topic --build-type ament_python --dependencies rclpy --node-name publisher_demo7.2.2 El autor logra
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class Topic_Pub(Node):
def __init__(self,name):
super().__init__(name)
self.pub = self.create_publisher(String,"/topic_demo",1)
self.timer = self.create_timer(1,self.pub_msg)
def pub_msg(self):
msg = String()
msg.data = "Hi,I send a message."
self.pub.publish(msg)
def main():
rclpy.init()
pub_demo = Topic_Pub("publisher_node")
rclpy.spin(pub_demo)
pub_demo.destroy_node()
rclpy.shutdown()7.2.3 Editar archivos de configuración
7.2.4 Compilador del paquete funcional
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash7.2.5 Ejecutar nodo de publicación
ros2 run pkg_topic publisher_demo
ros2 topic list
ros2 topic echo /topic_demo7.2.6 Crear un suscriptor
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class Topic_Sub(Node):
def __init__(self,name):
super().__init__(name)
self.sub = self.create_subscription(String,"/topic_demo",self.sub_callback,1)
def sub_callback(self,msg):
self.get_logger().info(msg.data)
def main():
rclpy.init()
sub_demo = Topic_Sub("subscriber_node")
rclpy.spin(sub_demo)
sub_demo.destroy_node()
rclpy.shutdown()7.2.7 Editar archivos de configuración
7.2.8 Compilador del paquete funcional
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash7.2.9 Nodos operativos
ros2 run pkg_topic publisher_demo
ros2 run pkg_topic subscriber_demo7.3 Próximos pasos
1.08 Comunicaciones de servicio
2.09 Comunicaciones de acción
08 Comunicaciones de servicio
08 Comunicaciones de servicio (Services)
8.1 Descripción general de las comunicaciones de servicios
8.1.1 Qué es la comunicación de servicios
El servicio (Service) es el mecanismo para la comunicación sincronizada entre los nodos en ROS 2, utilizando el modelo cliente/servidor (Client/Server). El cliente envía la solicitud, el servicio la maneja y devuelve la respuesta.
8.1.2 Servicios vs tópicos
| Característica | Servicios | Tópicos |
|---|---|---|
| Modo de comunicación | Sincrónico (solicitud-respuesta) | Asincrónico (publicación-suscripción) |
| Conexión | Uno a uno. | Múltiple a múltiple. |
| Aplicar escena | Consulta de operaciones cortas | Flujos de datos en curso |
| Bloqueo | Cliente bloquea esperando. | Sin bloqueo. |
| Valor de retorno | Debemos devolver la respuesta. | Sin respuesta |
8.1.3 Definición del tipo de servicio
# File: example interfaces/srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum8.2 Ejemplos de comunicaciones de servicios
8.2.1 Nuevo paquete funcional
ros2 pkg create pkg_service --build-type ament_python --dependencies rclpy --node-name server_demo8.2.2 Crear un extremo de servicio
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts
class Service_Server(Node):
def __init__(self,name):
super().__init__(name)
self.srv = self.create_service(AddTwoInts, '/add_two_ints', self.Add2Ints_callback)
def Add2Ints_callback(self,request,response):
response.sum = request.a + request.b
print("response.sum = ",response.sum)
return response
def main():
rclpy.init()
server_demo = Service_Server("publisher_node")
rclpy.spin(server_demo)
server_demo.destroy_node()
rclpy.shutdown()ros2 interface show example_interfaces/srv/AddTwoInts8.2.3 Editar archivos de configuración
'server_demo = pkg_service.server_demo:main',8.2.4 Compilador del paquete funcional
colcon build --packages-select pkg_service
source install/setup.bash
ros2 run pkg_service server_demoros2 service list
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 1,b: 4}"8.2.5 Crear cliente
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts
class Service_Client(Node):
def __init__(self,name):
super().__init__(name)
self.client = self.create_client(AddTwoInts,'/add_two_ints')
while not self.client.wait_for_service(timeout_sec=1.0):
print("service not available, waiting again...")
self.request = AddTwoInts.Request()
def send_request(self):
self.request.a = 10
self.request.b = 90
self.future = self.client.call_async(self.request)
def main():
rclpy.init()
service_client = Service_Client("client_node")
service_client.send_request()
while rclpy.ok():
rclpy.spin_once(service_client)
if service_client.future.done():
try:
response = service_client.future.result()
print("Result = ",response.sum)
except Exception as e:
service_client.get_logger().info('Service call failed %r' % (e,))
break
service_client.destroy_node()
rclpy.shutdown()8.2.6 Editar archivos de configuración
'client_demo = pkg_service.client_demo:main'8.2.7 Compilador del paquete funcional
cd ~/workspace
colcon build --packages-select pkg_service
source install/setup.bash
ros2 run pkg_service server_demosource install/setup.bash
ros2 run pkg_service client_demo8.3 Próximos pasos
1.09 Comunicaciones de acción - Aprender comunicaciones de acción (tarea larga)
- 10 Transformación de coordenadas TF2 - Crear tipo de servicio personalizado
09 Comunicaciones de acción
09 Comunicaciones de acción (Actions)
9.1 Resumen de las comunicaciones de acción
9.1.1 ¿Qué es la comunicación de movimiento?
La acción es el mecanismo de comunicación utilizado en ROS 2 para manejar asignaciones largas. Similar a los servicios, las acciones son un modo cliente-servidor, pero soportan:
-
Retroalimentación en tiempo real durante la ejecución del mandato
-
El cliente puede cancelar una asignación activa.
-
Adapta para manejar operaciones que pueden tomar segundos a minutos.
9.1.2 Acción vs servicios
| Característica | Servicio | Acción |
|---|---|---|
| Duración de la aplicación | Operación corta (ms-s) | Misiones largas (segundos-minutos) |
| Retroalimentación | Sin retroalimentación en tiempo real | Enviar retroalimentación de forma continua |
| Cancelar | No soportado | Pero cancelar. |
| Bloqueo | Bloqueo del cliente | Deshabilitar |
| Aplicar escena | Consulta, operaciones simples | Navegación, captura |
9.2 Casos de comunicaciones de acción
9.2.1 Nuevo kit funcional
ros2 pkg create --build-type ament_cmake pkg_interfacesint64 num
---
int64 sum
---
float64 progress<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>action_msgs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"action/Progress.action")cd ~/workspace
colcon build --packages-select pkg_interfacesros2 interface show pkg_interfaces/action/Progressros2 pkg create pkg_action --build-type ament_python --dependencies rclpy pkg_interfaces --node-name action_server_demo4. Realización del extremo del servicio
4.1 Crear un proveedor de servicios
import time
import rclpy
from rclpy.action import ActionServer
from rclpy.node import Node
from pkg_interfaces.action import Progress
class Action_Server(Node):
def __init__(self):
super().__init__('progress_action_server')
self._action_server = ActionServer(
self,
Progress,
'get_sum',
self.execute_callback)
self.get_logger().info('The action server has started!')
def execute_callback(self, goal_handle):
self.get_logger().info('Starting task execution...')
feedback_msg = Progress.Feedback()
total = 0
for i in range(1, goal_handle.request.num + 1):
total += i
feedback_msg.progress = i / goal_handle.request.num
self.get_logger().info('Continuous feedback: %.2f' % feedback_msg.progress)
goal_handle.publish_feedback(feedback_msg)
time.sleep(1)
goal_handle.succeed()
result = Progress.Result()
result.sum = total
self.get_logger().info('Task completed!')
return result
def main(args=None):
rclpy.init(args=args)
Progress_action_server = Action_Server()
rclpy.spin(Progress_action_server)
Progress_action_server.destroy_node()
rclpy.shutdown()4.2 Editar archivos de configuración
'action_server_demo = pkg_action.action_server_demo:main',4.3 Compilador del paquete funcional
cd ~/workspace
colcon build --packages-select pkg_action
source install/setup.bash
ros2 run pkg_action action_server_demoros2 action list
ros2 action send_goal /get_sum pkg_interfaces/action/Progress "{num: 10}"