Conteúdo detalhado
🔹 ROS2 vs ROS1: DDS, tempo real, segurança
ROS2 reescreveu o middleware sobre DDS (Data Distribution Service): comunicação descentralizada (sem roscore único), QoS configurável, suporte a tempo real e segurança (SROS2). Os blocos são nós que conversam por tópicos (pub/sub), serviços (req/resp) e ações (objetivos longos com feedback).
📊 Primitivas de comunicação
- Tópico — fluxo contínuo, muitos-para-muitos (ex: imagens, juntas).
- Serviço — chamada síncrona única (ex: "ligar gripper").
- Ação — objetivo de longa duração com feedback/cancelamento (ex: "mover para pose").
- Parâmetro — config em runtime por nó.
⚡ Dica prática
Use tópico para fluxo contínuo (imagens, juntas), serviço para chamadas pontuais e ação para "mover para a pose X" — onde você precisa de feedback de progresso e poder cancelar. Escolher a primitiva errada (ex: tópico para um goal único) gera código frágil.
DDS
Transporte descentralizado.
Nó
Unidade de processo.
Ação
Goal longo + feedback.
SROS2
Segurança e auth.
🔹 Anatomia de um sistema: percepção, planejamento, controle
Um sistema ROS2 decompõe o robô em nós com responsabilidade única: drivers de câmera/RGB-D, nó de percepção, planejador, controlador de junta. Essa modularidade permite trocar a "policy" sem mexer no driver do braço — exatamente onde o VLA entra.
📊 Nós típicos de uma célula VLA
- /camera — driver RealSense publica RGB + depth.
- /vla_node — inferência da policy, publica ações.
- /robot_state_publisher + /tf2 — árvore de frames.
- /controller_manager — ros2_control executa trajetória.
# inspecionar o sistema vivo
ros2 node list
ros2 topic list
ros2 topic hz /camera/color/image_raw # checar frequência
ros2 topic echo /joint_states --once
ros2 run rqt_graph rqt_graph # visualizar o grafo
⚡ Dica prática
Antes de escrever código, mapeie o grafo com rqt_graph e confira a hz de cada tópico. Câmera a 60 Hz mas /joint_states a 10 Hz vira gargalo silencioso na sincronização.
Percepção
Nó de visão/RGB-D.
Planejamento
VLA ou MoveIt2.
Controle
ros2_control / driver.
Modularidade
Trocar policy isolada.
🔹 Integrar um VLA: nó de inferência, sincronização, QoS
O VLA vira um nó rclpy que assina câmera + estado, roda o forward e publica o comando. Imagem e estado precisam vir do mesmo instante: use message_filters (ApproximateTimeSynchronizer) e escolha a QoS certa — BEST_EFFORT para imagem (descarta atrasados), RELIABLE para comandos.
import rclpy
from rclpy.node import Node
from message_filters import Subscriber, ApproximateTimeSynchronizer
from sensor_msgs.msg import Image, JointState
from rclpy.qos import QoSProfile, ReliabilityPolicy
class VLANode(Node):
def __init__(self):
super().__init__("vla_node")
qos = QoSProfile(depth=1, reliability=ReliabilityPolicy.BEST_EFFORT)
img = Subscriber(self, Image, "/camera/color/image_raw", qos_profile=qos)
st = Subscriber(self, JointState, "/joint_states")
sync = ApproximateTimeSynchronizer([img, st], queue_size=2, slop=0.02)
sync.registerCallback(self.on_obs)
def on_obs(self, img, state):
action = self.policy(preprocess(img), state.position) # forward VLA
self.pub.publish(to_cmd(action)) # ação chunked
rclpy.init(); rclpy.spin(VLANode())
✓ Fazer
- ✓Sincronizar imagem+estado por timestamp (slop pequeno).
- ✓QoS BEST_EFFORT/depth=1 para sensores de alta taxa.
- ✓Rodar inferência em thread/callback group separado.
✗ Evitar
- ✗Casar QoS incompatível (RELIABLE vs BEST_EFFORT) — não conecta.
- ✗Bloquear o executor com forward pesado no callback principal.
- ✗Usar imagem e estado de instantes diferentes.
rclpy
API Python do ROS2.
message_filters
Sync por timestamp.
QoS
Reliability/depth.
callback group
Concorrência segura.
🔹 tf2 e frames: pose do modelo → comando do braço
O VLA prevê uma pose num frame — geralmente da câmera. O braço espera comandos no frame da base. tf2 mantém a árvore de transformações temporizada (base_link → camera_link → tool0) e converte poses entre frames respeitando o timestamp.
from tf2_ros import Buffer, TransformListener
import tf2_geometry_msgs
buf = Buffer(); TransformListener(buf, node)
# transformar a pose prevista (frame da câmera) -> frame base do braço
pose_base = buf.transform(pose_cam, "base_link", timeout=Duration(seconds=0.1))
# agora a pose está no frame que o controlador entende
📊 Erros clássicos de frame
- Calibração mão-olho ruim — câmera↔base errada desloca tudo.
- Timestamp errado — transformar com TF antigo/futuro causa salto.
- Convenção de eixos — REP-103: x para frente, z para cima.
tf2
Árvore de frames.
Mão-olho
Calibração câmera↔base.
REP-103
Convenção de eixos.
Timestamp
TF temporizado.
🔹 MoveIt2 e controladores: trajetória, limites, segurança
MoveIt2 faz planejamento de movimento com checagem de colisão, cinemática (IK/FK) e time parameterization respeitando limites de junta. Em VLA reativo de alta frequência, muitas vezes você ignora o planner e envia setpoints direto via ros2_control — mas MoveIt2 entra para approach seguro e detecção de colisão.
Planejar (MoveIt2)
OMPL/Pilz gera trajetória livre de colisão; útil para o movimento de aproximação.
Controlar (ros2_control)
JointTrajectoryController executa; VLA pode injetar setpoints reativos.
Proteger
Limites de velocidade/torque, e-stop por hardware, workspace bounds.
MoveIt2
Planejamento + colisão.
ros2_control
Camada de controlador.
IK/FK
Cinemática.
E-stop
Segurança física.
🔹 Latência e tempo real: do frame ao torque, jitter, watchdogs
A cadeia câmera → inferência → tf2 → controlador → torque tem um orçamento de latência. Pior que latência alta é o jitter (variância): um loop irregular desestabiliza o controle. Use kernel PREEMPT_RT, prioridade de tempo real e watchdogs que param o braço se o comando atrasar.
# watchdog: se não chegar comando em 100ms, freia
self.create_timer(0.1, self.watchdog)
def watchdog(self):
if (self.now() - self.last_cmd) > 0.1:
self.hold_position() # fail-safe
# medir latência fim-a-fim do pipeline
ros2 topic delay /arm_command
⚡ Dica prática
Action chunking (do M2.1) é seu aliado: prever K passos amortiza a inferência e tolera o jitter da rede ROS, mantendo o loop de torque suave mesmo que o VLA re-infira só a cada N ciclos.
Latência
Frame → torque.
Jitter
Variância do loop.
PREEMPT_RT
Kernel tempo real.
Watchdog
Fail-safe por timeout.
✓ Fazer
- ✓Medir latência fim-a-fim e o jitter (p99), não só a média.
- ✓Watchdog que freia o braço se o comando atrasar.
- ✓Action chunking para tolerar jitter da rede ROS.
✗ Evitar
- ✗Loop de controle sem kernel RT em tarefa crítica.
- ✗Enviar torque sem timeout/limite de segurança.
- ✗Otimizar latência média ignorando picos de jitter.
✅ Resumo do módulo
Próximo módulo
2.5 — Hardware: braços, garras, sensores RGB-D e compute de borda Jetson, o corpo onde o ROS2 roda.