B9: Arquitectura RoboCup — Vision + Brain¶
La arquitectura del robocup_demo¶
El sistema robocup_demo de Booster tiene tres módulos:
vision/ ──── YOLOv8 TensorRT ────► /vision/ball_pos, /vision/field_state
brain/ ──── decisión + estrategia ► /cmd_vel, /sport/kick
game_controller/ ── paquetes árbitro ► /game_controller/state
El código está en /opt/booster/robocup_demo/ — léelo, no lo compiles.
ls /opt/booster/robocup_demo/
# brain/ game_controller/ scripts/ vision/ config/
cat /opt/booster/robocup_demo/vision/src/vision_node.cpp | head -60
Ejercicio: rastreador de pelota con visión¶
Combina detección YOLO (B7) con locomoción (B2) para seguir la pelota:
#!/usr/bin/env python3
import rclpy, numpy as np
from rclpy.node import Node
from sensor_msgs.msg import Image
from geometry_msgs.msg import TwistStamped
from ultralytics import YOLO
class BallTracker(Node):
BALL_CLASS = 32
def __init__(self):
super().__init__('ball_tracker')
self.model = YOLO('yolov8n.pt')
self.create_subscription(Image, '/camera/image_raw', self.callback, 10)
self.pub = self.create_publisher(TwistStamped, '/cmd_vel', 10)
def callback(self, msg):
bgr = np.frombuffer(msg.data, dtype=np.uint8).reshape(msg.height, msg.width, 3)
results = self.model(bgr, verbose=False, classes=[self.BALL_CLASS])
cmd = TwistStamped()
cmd.header.stamp = self.get_clock().now().to_msg()
if results[0].boxes:
box = results[0].boxes[0]
cx = float((box.xyxy[0][0] + box.xyxy[0][2]) / 2)
error = (cx - msg.width / 2) / msg.width
cmd.twist.angular.z = -error * 1.0
cmd.twist.linear.x = 0.12
self.pub.publish(cmd)
Tarea¶
Agrega un servicio /sport/dance1 para celebrar cuando el robot llegue a menos de
0.5 m de la pelota (usa el canal de profundidad de B6).