Maschinelle Übersetzung, nicht von einem Muttersprachler geprüft. Englisch ist die maßgebliche Fassung.

Ausgaben und ExporteAuf GitHub bearbeitenQuelle: docs/ANIMATION.md

Animationsexport

--animate macht aus der Zeitreihe eines Laufs etwas, das sich bewegt: eine animierte Scalable-Vector-Graphics-Datei (SVG), einen einzelnen eigenständigen HyperText-Markup-Language-Player (HTML) oder eine nummerierte Folge von SVG-Einzelbildern für einen Videokodierer. Eine Kampagne läuft als ihre Phasen (jamming, spoofing, holdover, Integritätsalarm) mit markierten Alarmen; ein Spektrumlauf spielt seinen Wasserfall Zeile für Zeile ab; ein Überflug in niedriger Erdumlaufbahn (LEO) spielt seine Verbindung je Band ab und, mit einem Spoofer, die Monitorstatistiken Epoche für Epoche.

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

Code: src/animation.rs. Tests: tests/animation.rs.

Was es ist und was nicht#

Der Exporter liest das Ergebnisdokument, das der Lauf bereits geschrieben hat. Er führt die Physik nicht erneut aus, er tastet nicht neu ab, glättet nicht und interpoliert nicht zwischen Abtastwerten (abgesehen von dem einen geraden Streckenabschnitt, der eine Kurve am Cursor beendet), und er fügt keine eigene Zahl hinzu. Eine Animation ist daher genau so gut wie der Lauf dahinter. Ihre Stufe ist MODELLED, interne Konsistenz: Sie ist eine Darstellung, nie ein Nachweis, und trägt keine eigene Zeile der Verifikationsmatrix.

Ausgaben#

Jedes Format wird neben das Szenario geschrieben, neben die üblichen result.json, chart.svg und report.html:

Format Geschrieben als Was es enthält
svg <scenario>.animation.svg Eine SVG, animiert mit Cascading-Style-Sheets-Keyframes (CSS) und ohne Skript: Die Kurven werden hinter einem laufenden Zeitcursor gezeichnet, Ereignisse erscheinen zu ihrem Zeitpunkt, Wasserfallzeilen werden in Zeitreihenfolge aufgedeckt. Sie läuft in Schleife, mit 1,5 s Haltezeit auf dem fertigen Bild.
html <scenario>.animation.html Eine Datei mit Inline-Skript und -Stil und ohne externe Ressource: Wiedergabe und Pause, ein Scrubber, Geschwindigkeit (0.25x bis 4x), jedes Feld an einem synchronen Cursor, ein Live-Wert je Kurve, der Phasenstreifen und eine Ereignisliste, die per Klick springt. Die Leertaste startet oder pausiert, die Pfeiltasten schreiten, Home und End springen.
frames <scenario>.frames/ frame_0000.svg, frame_0001.svg, … und manifest.json.

--animate ist wiederholbar und nimmt eine kommagetrennte Liste (--animate svg,html) oder all entgegen. --animate-fps (1 bis 60, Standard 12) und --animate-duration (0,5 s bis 600 s, Standard 8 s) legen die Wiedergabe fest; die Einzelbildfolge ist auf 7.200 Einzelbilder begrenzt.

Wenn --export im selben Befehl läuft, listet der HTML-Player die daneben geschriebenen Exportdateien (CZML, KML, GeoJSON, STK, SigMF) als relative Links zu diesen Nachbardateien auf; ein Link wird nur für einen reinen Dateinamen geschrieben, sodass keiner den Ordner verlassen oder das Netz erreichen kann. Der erweiterte Bericht (report.html) bettet die animierte Zeichnung ein, sobald das Ergebnis eine Zeitreihe hat, gleich ob --animate lief oder nicht.

Wenn --animate läuft, erhält result.json einen animation-Block: die Formate, Bilder pro Sekunde (fps), Dauer, Einzelbildzahl, die Zeitspanne, die Feldtitel, die JSON-Pfade, aus denen jede Kurve gelesen wurde (sources), und jede gefundene, aber nicht gezeichnete Reihe (omitted). Ohne --animate ist das Ergebnis byteidentisch mit einem einfachen Lauf.

Die Einzelbildfolge#

Die Folge hat genau round(duration × fps) Einzelbilder. Einzelbild i zeigt die Zeitleiste bis t_start + (t_end − t_start) × i / (n − 1), sodass das erste Einzelbild der Anfang und das letzte das fertige Bild ist. manifest.json hält fps, duration_s, frame_count, frame_pattern (frame_%04d.svg), die Pixelgröße, t_start, t_end, die Missionszeit jedes Einzelbilds (frame_times), die Phasen, die Ereignisse und die Quellen fest. Ein erneuter Export in dasselbe Verzeichnis entfernt zuerst jedes dort bereits vorhandene frame_NNNN.svg (und sonst nichts), sodass eine kürzere Folge nie Einzelbilder einer längeren zurücklässt, die der Kodierer lesen könnte.

Die Einzelbilder sind SVG, nicht Portable Network Graphics (PNG). Ein mit der Bibliothek librsvg gebautes ffmpeg liest sie direkt, mit der Rate, mit der die Folge geschrieben wurde (24 im Beispiel oben; das fps des Manifests):

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

Ein ffmpeg ohne librsvg bricht mit „no decoder found for: svg“ ab. Rastern Sie die Einzelbilder zuerst, zum Beispiel mit rsvg-convert, und kodieren Sie die 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

Barrierefreiheit und Farbschema#

  • Farbschema. Der Player folgt prefers-color-scheme und zeichnet neu, wenn es sich ändert; die animierte SVG trägt unter derselben Media Query eine helle Variante ihrer Palette. Die Einzelbilder verwenden die dunkle Palette der statischen Diagramme, weil ein Video kein Schema hat.
  • Reduzierte Bewegung. Unter prefers-reduced-motion: reduce schaltet die animierte SVG jede Animation ab und zeigt das fertige Bild (ihre Basisstile sind der Endzustand, sodass nichts verborgen ist), und der Player öffnet pausiert auf dem fertigen Bild, statt zu spielen; der Benutzer kann weiterhin scrubben oder Play drücken.
  • Die SVG hat ein <title> und ein <desc>; die Bedienelemente des Players sind beschriftete Schaltflächen, ein Bereichseingabefeld mit gesprochenem Zeitwert und eine Auswahl.

Was als Zeitreihe zählt#

Die Ergebnisdokumente unterscheiden sich von Art zu Art, sodass der Exporter die Formen erkennt, die die Engine ausgibt, statt einer Liste von Arten:

  1. Ein Array von Datensätzen mit einem Zeitfeld (t, t_s, t_hours, t_min, t_days oder k in einem epochs-Array), das entlang des Arrays streng ansteigt. Jedes andere numerische Feld wird zu einer Kurve; dasselbe Feld unter zwei Wurzeln (quantum.series[].error_ns und classical.series[].error_ns) teilt sich ein Feld.
  2. Ein Objekt mit einem streng ansteigenden Zeit-Array (t_s, t, times_s, …) neben Arrays gleicher Länge: benachbarte numerische Arrays, eine channels-Map aus {unit, values}-Datensätzen (die campaign-Zeitleiste), ein Array von Datensätzen, die solche Arrays enthalten (die spectrum-Bänder, die Satellitenspuren einer Konstellation), und ein zweidimensionales Array, dessen Zeilen zur Zeitachse passen, mit einer benachbarten *_hz-Frequenzachse (der spectrum-Wasserfall).
  3. Neben diesem Zeit-Array werden phases (name, t0_s, t1_s) zum Phasenstreifen und events (t_s, label, alarm) zu den Markierungen. Auch die *_t_s-Skalare eines Bandes (sein erster Verlust der Signalverfolgung, sein niedrigstes Verhältnis von Trägerleistung zu Rauschdichte) werden markiert.

Kurven mit einer Einheit teilen sich ein Feld, wenn ihre Größenordnungen innerhalb eines Faktors von 100 liegen, sodass ein Schutzintervall von 50 ns einen Fehler von 2 ns nicht einebnet. Es werden höchstens 6 Felder mit je 6 Kurven gezeichnet; der Rest wird unter omitted aufgeführt. Kurven mit mehr als 2.400 Abtastwerten werden mit einer gleichmäßigen Schrittweite ausgedünnt, die den letzten Abtastwert erhält, und ein Wasserfall mit mehr als 96 × 120 Zellen wird herunter gemittelt (in Leistung, bei Dezibelzellen, sodass ein schmalbandiger Störer nicht verdünnt wird).

Eine Art, deren Ergebnis keine dieser Formen enthält (ein Linkbudget, eine Geometrie für eine einzelne Epoche, eine reine Monte-Carlo-Statistikzusammenfassung oder der Telekom-holdover, dessen Ergebnis den Hash der Aufzeichnung veröffentlicht, nicht die Aufzeichnung selbst), wird mit no time series to animate abgelehnt, und es wird nichts geschrieben. Mit kshana 0.40.0 lassen sich 94 der 193 ausführbaren Szenariodateien (jede Datei außer einer Studiensuite) animieren, und 99 werden abgelehnt. cargo test --test animation -- --nocapture gibt die Zählung aus.

Unter den LEO-Arten lässt sich jedes mitgelieferte leo-pass-, leo-pnt-chain- und leo-ppp-Szenario animieren. leo-pvt lässt sich in seinen Modi Doppler, gemeinsame Positionierung und Zeitgebung animieren (ein Zeitgebungslauf braucht trace = true, wodurch jede Zeile ihren Zeitfehler und ihr vorhergesagtes Sigma in jeder Epoche meldet) und wird in seinem Polarabdeckungsmodus abgelehnt. leo-navmsg lässt sich in seinem Update mitten im Überflug animieren und wird für die Analysen zu Kodierung, Anpassungsintervall und Modellvergleich abgelehnt. Ergebnisse von leo-signal und ntn-positioning tragen keine Zeitachse und werden abgelehnt.

Determinismus#

Die Ausgabe ist eine reine Funktion des Ergebnisdokuments und der Optionen: keine Uhr, keine Zufallszahl, keine Hash-Map-Iteration, kein Datei- oder Netzzugriff in der Bibliothek und nirgends ein Zeitstempel, sodass dasselbe Szenario mit demselben Seed und denselben Optionen byteidentische Dateien ergibt. Das Modul wird unverändert für WebAssembly gebaut; nur die Befehlszeilenschnittstelle schreibt Dateien.

Nutzung als Bibliothek#

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 animiert ein Ergebnisdokument, das Sie bereits haben, und extract_timeline gibt zurück, was gezeichnet würde, ohne es darzustellen.

Grenzen#

  • Das Python-Wheel und das WebAssembly-Modul stellen den Exporter noch nicht bereit; er ist von der Befehlszeile, von der Rust-Bibliothek und vom Werkzeug animate_scenario des Model-Context-Protocol-Servers (MCP) erreichbar (das höchstens 120 Einzelbilder in einer Antwort zurückgibt).
  • Die Achsen sind linear. Eine Reihe, die viele Dekaden überspannt (das Fehlerwachstum einer Uhr von 0,1 ns auf eine Mikrosekunde), erscheint flach bis spät im Lauf.
  • Die animierte SVG beruht auf CSS-Animation eines Clip-Rechtecks; aktuelle Chromium-, Firefox- und Safari-Engines spielen sie ab, während ein Betrachter ohne CSS-Animation das fertige Bild zeigt.
  • Sweep-, Monte-Carlo- und Compose-Kampagnen tragen keine Zeitachse und werden abgelehnt; die zusammenfassenden Statistiken eines Sweeps oder Ensembles sind keine Zeitreihe. Eine verkettete Kampagne lässt sich animieren.