Tradução automática, não revista por um falante nativo. O inglês é a referência.

Saídas e exportaçõesEditar no GitHubFonte: docs/ANIMATION.md

Exportação de animação

--animate transforma a série temporal de uma execução em algo que se move: um arquivo Scalable Vector Graphics (SVG) animado, um único player HyperText Markup Language (HTML) autocontido, ou uma sequência numerada de quadros SVG para um codificador de vídeo. Uma campanha é reproduzida como suas fases (jamming, spoofing, holdover, alarme de integridade) com seus alarmes marcados; uma execução de espectro reproduz sua cascata linha por linha; uma passagem em órbita baixa da Terra (LEO) reproduz seu enlace por banda e, com um spoofer, as estatísticas do monitor época a época.

kshana scenarios/campaign-jam-spoof-holdover-integrity.toml --animate all
kshana scenarios/l-band-waterfall-jamming.toml --animate html
kshana scenarios/clock-holdover.toml --animate frames --animate-fps 24 --animate-duration 10

Código: src/animation.rs. Testes: tests/animation.rs.

O que é e o que não é#

O exportador lê o documento de resultado que a execução já gravou. Ele não executa de novo a física, não reamostra, não suaviza nem interpola entre amostras (exceto pelo único segmento de reta que termina um traço no cursor), e não acrescenta nenhum número próprio. Uma animação é, portanto, exatamente tão boa quanto a execução que está por trás dela. Seu nível é MODELLED, consistência interna: é uma renderização, nunca evidência, e não traz linha própria na matriz de verificação.

Saídas#

Cada formato é gravado ao lado do cenário, junto com os habituais result.json, chart.svg e report.html:

Formato Gravado como O que contém
svg <scenario>.animation.svg Um SVG animado com keyframes de Cascading Style Sheets (CSS) e sem script: os traços se desenham atrás de um cursor de tempo em movimento, os eventos aparecem em seu instante, as linhas da cascata se revelam em ordem de tempo. Ele se repete em laço, com uma pausa de 1,5 s na imagem finalizada.
html <scenario>.animation.html Um arquivo com script e estilo embutidos e sem recurso externo: reproduzir e pausar, um controle deslizante de posição, velocidade (0.25x a 4x), todos os painéis em um cursor sincronizado, um valor ao vivo por traço, a faixa de fases e uma lista de eventos que salta ao clicar. A barra de espaço reproduz ou pausa, as setas avançam e recuam, Home e End saltam.
frames <scenario>.frames/ frame_0000.svg, frame_0001.svg, … e manifest.json.

--animate é repetível e aceita uma lista separada por vírgulas (--animate svg,html) ou all. --animate-fps (1 a 60, padrão 12) e --animate-duration (0,5 s a 600 s, padrão 8 s) definem a reprodução; a sequência de quadros é limitada a 7.200 quadros.

Quando --export é executado no mesmo comando, o player HTML lista os arquivos de exportação gravados ao lado dele (CZML, KML, GeoJSON, STK, SigMF) como links relativos a esses arquivos irmãos; um link só é gravado para um nome de arquivo simples, de modo que nenhum pode sair da pasta nem alcançar a rede. O relatório avançado (report.html) incorpora o desenho animado sempre que o resultado tem uma série temporal, quer --animate tenha sido executado ou não.

Quando --animate é executado, result.json ganha um bloco animation: os formatos, quadros por segundo (fps), duração, número de quadros, o intervalo de tempo, os títulos dos painéis, os caminhos JSON de onde cada traço foi lido (sources) e qualquer série encontrada mas não desenhada (omitted). Sem --animate, o resultado é idêntico byte a byte ao de uma execução simples.

A sequência de quadros#

A sequência tem exatamente round(duration × fps) quadros. O quadro i mostra a linha do tempo até t_start + (t_end − t_start) × i / (n − 1), de modo que o primeiro quadro é o início e o último é a imagem finalizada. manifest.json registra fps, duration_s, frame_count, frame_pattern (frame_%04d.svg), o tamanho em pixels, t_start, t_end, o tempo de missão de cada quadro (frame_times), as fases, os eventos e as fontes. Uma nova exportação no mesmo diretório remove primeiro todo frame_NNNN.svg já existente ali (e nada mais), de modo que uma sequência mais curta nunca deixa para trás quadros de uma mais longa para o codificador ler.

Os quadros são SVG, e não Portable Network Graphics (PNG). Um ffmpeg compilado com a biblioteca librsvg os lê diretamente, na taxa com que a sequência foi gravada (24 no exemplo acima; o fps do manifesto):

ffmpeg -framerate 24 -i clock-holdover.frames/frame_%04d.svg -pix_fmt yuv420p clock-holdover.mp4

Um ffmpeg sem librsvg para com "no decoder found for: svg". Rasterize os quadros primeiro, por exemplo com rsvg-convert, e codifique os PNGs:

for f in clock-holdover.frames/frame_*.svg; do rsvg-convert "$f" -o "${f%.svg}.png"; done
ffmpeg -framerate 24 -i clock-holdover.frames/frame_%04d.png -pix_fmt yuv420p clock-holdover.mp4

Acessibilidade e tema#

  • Esquema de cores. O player segue prefers-color-scheme e se redesenha quando ele muda; o SVG animado traz uma variante clara de sua paleta sob a mesma media query. Os quadros usam a paleta escura dos gráficos estáticos, porque um vídeo não tem esquema.
  • Movimento reduzido. Sob prefers-reduced-motion: reduce, o SVG animado desliga todas as animações e mostra a imagem finalizada (seus estilos base são o estado final, de modo que nada fica oculto), e o player abre pausado na imagem finalizada em vez de reproduzir; o usuário ainda pode arrastar o controle ou pressionar Play.
  • O SVG tem um <title> e um <desc>; os controles do player são botões rotulados, uma entrada de intervalo com um valor de tempo falado e uma lista de seleção.

O que conta como série temporal#

Os documentos de resultado diferem de um tipo de cenário para outro, de modo que o exportador reconhece as formas que o motor emite, e não uma lista de tipos de cenário:

  1. Um array de registros com um campo de tempo (t, t_s, t_hours, t_min, t_days ou k em um array epochs) que cresce estritamente ao longo do array. Todo outro campo numérico se torna um traço; o mesmo campo sob duas raízes (quantum.series[].error_ns e classical.series[].error_ns) compartilha um painel.
  2. Um objeto com um array de tempo estritamente crescente (t_s, t, times_s, …) ao lado de arrays de mesmo comprimento: arrays numéricos irmãos, um mapa channels de registros {unit, values} (a linha do tempo de campaign), um array de registros que contêm tais arrays (as bandas de spectrum, as trilhas de satélites de uma constelação) e um array bidimensional cujas linhas correspondem ao eixo de tempo, com um eixo de frequência irmão *_hz (a cascata de spectrum).
  3. Ao lado desse array de tempo, phases (name, t0_s, t1_s) tornam-se a faixa de fases e events (t_s, label, alarm) tornam-se os marcadores. Os escalares *_t_s de uma banda (sua primeira perda de travamento, sua menor relação portadora/densidade de ruído) também são marcados.

Traços com unidade compartilham um painel quando suas magnitudes estão dentro de um fator de 100, de modo que uma guarda de 50 ns não achata um erro de 2 ns. No máximo 6 painéis de 6 traços são desenhados; o resto é listado em omitted. Traços com mais de 2.400 amostras são reduzidos por um passo uniforme que mantém a última amostra, e uma cascata com mais de 96 × 120 células é calculada em média (em potência, para células em decibéis, de modo que um jammer estreito não seja diluído).

Um tipo de cenário cujo resultado não contém nenhuma destas formas (um orçamento de enlace, uma geometria de época única, um resumo de Monte Carlo apenas estatístico, ou o holdover de telecomunicações, cujo resultado publica o hash do registro, mas não o registro) é recusado com no time series to animate, e nada é gravado. Com o kshana 0.40.0, 94 dos 193 arquivos de cenário executáveis (todos, exceto uma suíte de estudo) geram animação e 99 são recusados. cargo test --test animation -- --nocapture imprime o levantamento.

Entre os tipos de cenário LEO, todo cenário incluído leo-pass, leo-pnt-chain e leo-ppp anima. leo-pvt anima em seus modos Doppler, de posicionamento conjunto e de temporização (uma execução de temporização precisa de trace = true, o que faz cada linha informar seu erro de tempo e sigma previsto em toda época) e é recusado em seu modo de cobertura polar. leo-navmsg anima sua atualização no meio da passagem e é recusado para as análises de codificação, de intervalo de ajuste e de comparação de modelos. Os resultados de leo-signal e ntn-positioning não trazem eixo de tempo e são recusados.

Determinismo#

A saída é uma função pura do documento de resultado e das opções: sem relógio, sem número aleatório, sem iteração de hash-map, sem acesso a arquivo ou rede na biblioteca e sem carimbo de tempo em lugar algum, de modo que o mesmo cenário, a mesma semente e as mesmas opções dão arquivos idênticos byte a byte. O módulo é compilado para WebAssembly sem alterações; apenas a interface de linha de comando grava arquivos.

Uso como biblioteca#

use kshana::animation::{AnimationFormat, AnimationOptions};
let anim = kshana::api::animate_toml(src, AnimationFormat::Html, &AnimationOptions::default())?;
std::fs::write("run.html", &anim.files[0].content)?;

kshana::animation::animate_result anima um documento de resultado que você já tem, e extract_timeline retorna o que seria desenhado sem renderizá-lo.

Limites#

  • O wheel do Python e o módulo WebAssembly ainda não expõem o exportador; ele é acessível pela linha de comando, pela biblioteca Rust e pela ferramenta animate_scenario do servidor Model Context Protocol (MCP) (que retorna no máximo 120 quadros em uma resposta).
  • Os eixos são lineares. Uma série que abrange muitas décadas (o crescimento do erro de um relógio de 0,1 ns a um microssegundo) parece plana até tarde na execução.
  • O SVG animado depende de animação CSS de um retângulo de recorte; os motores atuais Chromium, Firefox e Safari o reproduzem, enquanto um visualizador sem animação CSS mostra a imagem finalizada.
  • Campanhas de varredura, Monte Carlo e composição não trazem eixo de tempo e são recusadas; as estatísticas resumidas de uma varredura ou de um conjunto não são uma série temporal. Uma campanha encadeada anima.