Robótica · TUBE — Telemetry Under Bounded Error

Os terabytes de rosbags do seu robô, com erro máximo garantido por amostra.

Não é compressão com perda "aceitável na média". É um contrato: |erro| ≤ ε, em toda amostra, verificado na decodificação.

O TUBE comprime telemetria de robôs — juntas, IMU, odometria, poses — dentro de um tubo de raio ε em volta do sinal original. Vocês escolhem o ε por canal (tipicamente abaixo do ruído do próprio sensor); o codec garante que a reconstrução nunca sai do tubo. Medido em voos, braços e bags reais, contra os compressores publicados e instaláveis que conseguimos rodar.

123×

drone real PX4, com seek

37×

manipulador real ALOHA, 14 juntas

21×

robô real ROS2/MCAP, via rosgate

≤ 1,00

erro/ε em toda amostra, verificado

ε — sinal original ▬ tubo de raio ε — reconstrução: |erro| ≤ ε em toda amostra
A geometria da garantia: a reconstrução (linha contínua) vive dentro do tubo de raio ε em volta do sinal original. Não é média, nem percentil — é pior caso, por construção.
O problema

O ROS2 move as mensagens. E depois?

O que fica em aberto é o destino dos terabytes — e a pergunta forense que ninguém consegue responder sem varrer tudo.

Um robô em operação gera rosbags na casa dos gigabytes por hora. Multiplique por frota e por meses de retenção: o custo de armazenar, e a banda robô→nuvem, viram a conta que cresce mais rápido que a operação.

Comprimir com zstd ajuda, mas trata o sinal como bytes opacos: paga a taxa cheia do ruído do sensor e não sabe nada sobre o que o dado significa. Comprimir com perda genérica (downsampling, float32) destrói exatamente o que importa numa investigação: ninguém sabe dizer quanto erro foi introduzido em cada amostra.

E quando algo dá errado em campo, a pergunta é sempre a mesma: "quando a junta 3 excedeu X rad? quando a corrente do motor passou de Y?" — hoje, responder isso significa decodificar o log inteiro.

Retenção

Rosbags brutos são grandes demais para guardar por anos — e apagar é abrir mão da evidência.

Banda robô→nuvem

Uplink de frota é caro e limitado. O que não cabe no link fica no robô — ou se perde.

Forense

"Quando o sinal passou de X?" deveria ser uma query barata, com resposta em que se pode confiar — não uma varredura completa.

Como funciona

O tubo de raio ε

Cada canal declara quanto erro tolera. O codec transforma essa declaração em contrato.

A engenharia do robô assina os bounds por canal — junta ±0,001 rad, giroscópio ±0,002 rad/s, corrente ±10 mA. A regra da casa: ε abaixo do ruído do sensor significa perda abaixo do que o sensor já mente. A partir daí, cinco mecanismos empilhados fazem a taxa:

1

Quantização com garantia

Uma régua cujo menor traço é o erro que vocês aceitaram

O valor é quantizado em passos de 2×ε — o que garante, por construção, |original − reconstruído| ≤ ε. Erro máximo determinístico, não métrica média.

2

Deadband

Sensor parado não fala

Só transmite quando o valor sai da banda do último valor transmitido. Robô segurando pose ≈ zero bytes de payload. No manipulador ALOHA, 67% das amostras ficam dentro da banda.

3

Keyframe / GOP

Como vídeo: quadros-chave e diferenças

A cada N amostras viaja um valor absoluto. Cada bloco decodifica sozinho: seek real sem descomprimir o resto, e perda de pacote limitada ao bloco.

4

Predição por trecho

O codec aprende o movimento e transmite só a surpresa

Regressão, Lorenzo ou modelo sazonal — escolhidos por trecho, antes da quantização, sem propagar ruído. O residual de um movimento previsível custa frações de bit.

5

Codificação de entropia

O que sobra, empacotado no mínimo de bits

Range coder adaptativo com dois estágios à escolha do canal. Em robótica, onde zeros dominam após o deadband, o estágio bitplane rende −23%.

O contrato — E o contrato é conferido dos dois lados: toda decodificação verifica erro máximo contra o bound, caso a caso — a coluna maxerr/ε ≤ 1,00 dos nossos benchmarks não é suposição, é medição. Fazemos o mesmo com os concorrentes que rodamos.

Resultados medidos

Resultados medidos

Benchmark aberto, seed fixa, dados reais públicos (PX4, LeRobot/ALOHA, FAST-LIVO via MCAP, CMU mocap). Os números abaixo usam o formato com seek — o que faz sentido para arquivamento e streaming. O formato batch é ainda menor.

Caso Bound assinado (ε) Bruto TUBE Taxa (com seek) Deadband
Drone real (PX4 — IMU, EKF, motores) Voo real de quadricóptero. SZ3 fica 2,5× atrás mesmo afinado. IMU no ruído do sensor · EKF ±2 cm · PWM exato 1,4 MB 12,1 KB 123× 86%
Manipulador real (ALOHA bimanual, 14 juntas) Robô de tarefa segura pose boa parte do tempo — o melhor regime robótico. ZFP fica 8,8× atrás. juntas ±0,001 rad — abaixo do backlash do servo 6,7 MB 186,4 KB 37× 67%
Robô real (ROS2/MCAP, IMU Livox) Lido de rosbag2/MCAP nativo pelo nosso leitor rosgate (MCAP + CDR próprios, sem ROS instalado). Dispositivo handheld de SLAM — gira o tempo todo; robô de tarefa deve render mais. gyro ±0,002 rad/s · accel ±0,05 m/s² 1,4 MB 68,8 KB 21× 49%
Mocap real (CMU, esqueleto de 62 DOFs @ 120 Hz) Replay de animação/biomecânica/VR em ~2,3 KB/s. O modo cross-channel explora a cadeia cinemática: −8% adicional em batch. juntas ±0,05° · root ±2 mm — abaixo do ruído do mocap óptico 5,0 MB 237,5 KB 22× 42%
Replay de corpos rígidos (sintético, 200 corpos @ 60 Hz) O mundo do robô como stream de poses — mapa/replay compartilhado com bound métrico. posição ±2 mm · yaw ±0,001 rad 11,0 MB 217,8 KB 52× 89%

Em todos os casos, erro máximo medido na reconstrução = 1,00× o bound ou menos — a garantia cumprida em toda amostra, coberta por teste de propriedade.

Contra o que existe publicado e instalável

Rodamos os concorrentes de verdade, nos mesmos canais, com o mesmo bound absoluto por canal — e verificamos a garantia deles decodificando, não assumindo. Os 15 casos do benchmark incluem os robóticos acima, mais satélite, ECG real, carro (CAN), medidores e replay de game.

Concorrente O que é Resultado, mesmo bound, garantia conferida
SZ3 (afinado) Referência acadêmica de compressão error-bounded — re-medido dando a ele best-of de algoritmo por canal e layout 2D TUBE menor nos 15 de 15 casos; nos robóticos, SZ3 fica 1,4×–2,5× atrás
ZFP (LLNL) Compressor error-bounded para campos científicos, modo fixed-accuracy 7–50× atrás em série temporal 1D ruidosa — não é o habitat dele, e os números mostram
Swinging Door O algoritmo dos historians industriais (PI System, ~30 anos de produção), mesmo bound TUBE 1,8×–10,1× menor nos 15 casos — até nosso formato com seek ganha em todos
ModelarDB O vizinho mais próximo em contrato: lossy com bound por amostra (crate oficial, Rust) TUBE 2,1×–9,5× menor — e o ModelarDB viola o próprio bound (interno f32): em canais de valores grandes, erro de até 10⁸× o bound declarado
BUFF (PVLDB 2021) Encoder canônico de float com precisão limitada, consultável in-situ TUBE 1,55×–255× menor — o preço da grade decimal e da cegueira temporal, em números

A frase que defendemos — nem mais, nem menos: melhor taxa com garantia por amostra contra tudo que é publicado e instalável que conseguimos rodar — SZ3 (afinado), ZFP, swinging door, ModelarDB e BUFF — com a garantia verificada dos dois lados.

O achado do ModelarDB é o argumento inteiro em miniatura: o concorrente mais próximo em contrato não honra o contrato em telemetria float64 real. Nós conferimos o bound em toda decodificação — a deles e a nossa.

Forense no domínio comprimido

"Quando a junta excedeu X?" — respondida no arquivo comprimido, com carimbo

Um índice de 2–4 bytes por bloco viaja ao lado do stream (que não muda um byte). A query de threshold poda os blocos irrelevantes com prova de exclusão, e cada amostra dos blocos tocados sai carimbada com a garantia herdada do ε:

definite

O valor original está acima do threshold — garantido por construção.

possible

A ±ε da fronteira — a zona de incerteza é explícita e mínima.

excluído, com prova

Abaixo do threshold, garantido — sem nem decodificar o bloco.

por que isso importa

Zone maps de bancos colunares operam sobre dado lossless e pagam a taxa cheia; sketches dão erro probabilístico. Aqui a resposta vem com garantia determinística — é o que um laudo de incidente exige.

Caso Query (threshold no p97) Blocos tocados Bytes decodificados Speedup
Manipulador ALOHA quando left_waist excedeu o p97? 15/215 9% 10,8×
Carro (CAN) quando a velocidade excedeu o p97? 2/20 10% 6,4×
Mocap CMU quando root.0 excedeu o p97? 4/42 12% 8,8×
Satélite quando a temperatura excedeu o p97? 25/288 8% 12,8×
Robô ROS2 (IMU) quando gyro_x excedeu o p97? 40/102 41% 2,3×

A leitura honesta está na última linha: a poda só existe quando o evento é localizado. Exceedance de junta em robô de tarefa é evento localizado (9% dos bytes tocados); giroscópio ruidoso de dispositivo em movimento contínuo cruza o threshold em quase todo bloco (41%). Quando não há o que podar, o índice não atrapalha — 2–4 bytes por bloco e a query equivale ao decode completo.

Como começar

Como começar: degraus reversíveis, com gates numéricos

O princípio — Nenhum degrau toca o robô ou o caminho de controle. O TUBE não substitui nem modifica o ROS2 — entra ao lado, como qualquer ferramenta. Cada degrau é reversível (remover = apagar um binário ou um launch), tem critério de decisão numérico combinado antes, e o seguinte só acontece se o anterior provar valor nos dados de vocês.

0

POC sem instalação

Esforço de vocês Enviar 1 rosbag .mcap (10–30 min de operação real) + meia hora de um engenheiro para assinar os bounds

Em ~1 semana devolvemos o bag de vocês como caso do benchmark aberto: tamanho TUBE vs MCAP+zstd vs gzip, erro máximo verificado na reconstrução, e uma pergunta forense de vocês respondida no domínio comprimido — com o carimbo. Relatório de 1 página com a leitura honesta, incluindo onde não ganhou.

Gate: taxa ≥ alvo combinado vs MCAP+zstd e a query funcionando no dado de vocês. Se não passar, o plano morre aqui — barato para todos.
1

rosgate — CLI offline, read-only

Esforço de vocês Rodar um binário sobre os próprios bags, quando quiserem

Ferramenta única em Go puro, sem ROS instalado: archive (comprime + indexa), query (forense com prova) e verify (confere o bound, canal a canal, contra o bag original). Os bounds ficam num YAML versionado por vocês — o ε é decisão de engenharia de vocês, não nossa.

Gate: engenheiros usam sem fricção e o verify os convence do contrato.
2

tube_bridge — dual-write, 1 robô, 30 dias

Esforço de vocês 1 robô rodando o nó em paralelo com o rosbag atual

Nó ROS2 comum que assina os tópicos do YAML e grava arquivo + índice ao lado do gravador atual. O caminho de controle não passa por ele; se o nó morrer, o robô nem percebe. CPU/RAM medidos e publicados em tópico de diagnóstico; reconstruções auditadas contra o bag bruto. Rollback = remover o nó do launch.

Gate: economia ≥ alvo, zero incidente, auditoria de reconstrução limpa.
3

Retenção de produção

Esforço de vocês Mudança de política de retenção — decisão de negócio

Bruto vive numa janela curta (7–30 dias); longo prazo vira TUBE + índice, consultável e com garantia declarada. Plugin C++ nativo do rosbag2 é opcional e só se justifica com os volumes reais do degrau 2.

Decisão tomada com os números do degrau 2 — não com esta página.
Limites honestos

Limites honestos

A cultura do projeto: hipótese refutada vira documentação, não rodapé. É assim que os números acima merecem confiança.

O encode é lento — por projeto

Como em codec de vídeo, a assimetria é deliberada: a decodificação é passada única e rápida (25–72 milhões de amostras/s por núcleo); o encode do formato batch paga uma busca exaustiva de modelos (0,03–0,4 Ma/s). O formato com seek codifica 10–80× mais rápido e é o indicado para gravação contínua — um robô gera milhares de amostras/s, ordens de grandeza abaixo do medido. No degrau 2, medimos no hardware de vocês.

Ninguém comprime ruído — nem nós

Quando o bound é apertado ao nível do ruído do sensor (ECG real a ±1 LSB do conversor, IMU no ruído de fundo), o stream é dominado por aleatoriedade e nenhum preditor ajuda. O ganho cai para o piso honesto (19× no ECG real, 21× no IMU handheld). Quem escolhe o ε escolhe o ponto entre perícia e taxa — é decisão de política, não de código.

Hipóteses refutadas, e registradas

Estimamos 30–80× para medidores de energia "como no satélite" — a medição devolveu 7,2–14×, e o porquê (consumo residencial é ruidoso) está documentado no benchmark. A hipótese de que o modo cross-channel ganharia na cadeia cinemática do manipulador também foi refutada: empate exato com o formato por canal. O relatório do degrau 0 trata os dados de vocês com a mesma régua.

A poda do índice depende do sinal

Threshold em sinal que cruza o limiar em todo bloco não poda nada (giroscópio ruidoso: 41% dos bytes; no drone, 91%). O índice nunca atrapalha, mas o speedup só aparece quando o evento é raro e localizado — como exceedance de junta em robô de tarefa.

Onde não competimos

Velocidade de encode em batch, maturidade de ecossistema e campos multidimensionais (o habitat do ZFP/SZ3 em HPC) não são o nosso jogo. E os bounds dos benchmarks foram escolhidos com folga realista, mas ainda não validados com engenheiros do domínio de cada caso — o degrau 0 existe exatamente para isso.

Leituras

Notas técnicas da mesma investigação

O que aprendemos construindo e medindo o TUBE — publicado com a mesma régua dos benchmarks: número medido, limite declarado.

Mande um rosbag. Devolvemos números.

O degrau 0 não instala nada: um .mcap (ou .db3) de 10–30 minutos de operação representativa, meia hora de um engenheiro para assinar os bounds por canal, e em ~1 semana vocês recebem o relatório medido — taxa vs MCAP+zstd, garantia verificada na reconstrução e uma query forense de vocês respondida com carimbo. Incluindo onde não ganhou.

Benchmark aberto e reproduzível — os 15 casos, os concorrentes e a verificação de bound rodam em CI.