Maskinöversättning, inte granskad av en modersmålstalare. Engelska är referensen.

TidssynkroniseringRedigera på GitHubKälla: docs/CLOCK-LOG-FORMATS.md

Klockloggsformat

src/clock_log.rs läser en uppmätt klocklogg till en enda normaliserad fasserie: ett likformigt nät av (time_s, phase_s)-sampel, med samplingsintervallet tau0 angivet eller funnet, varje lucka räknad och loggens enheter namngivna. Åtta format läses, vart och ett en dokumenterad delmängd. Allt utanför delmängden avvisas med ett fel som namnger det som hittades, i stället för att läsas ungefärligt.

Förkortningar. RINEX är Receiver Independent Exchange Format. TICC är TAPR:s (Tucson Amateur Packet Radio) tidsintervallräknare. ADEV är den överlappande Allan-deviationen, TDEV tidsdeviationen och MTIE det maximala tidsintervallfelet. tau0 är samplingsintervallet i sekunder.

Var en logg kan användas#

  • telecom-timing: [series.clock_log] i stället för series.samples eller series.csv_path. Loggens fas, i ns, är den tidsfelserie som kontrolleras mot maskerna, och rapporten får ett block clock_log som anger hur den lästes.
  • Slaget clock: en tabell [clock_log] lägger till ett block measured i körningen: hur loggen lästes, SHA-256 för tabellen (input_sha256; körningens scenario_hash omfattar inte tabellen) och för fassampeln, samt den överlappande ADEV, TDEV och MTIE vid oktavvisa medelvärdesfaktorer. Den kräver runs = 1. Den simulerade holdovern är oförändrad.

Utan tabellen tolkas, hashas och redovisas båda slagen precis som förut.

[clock_log]                 # or [series.clock_log] in a telecom-timing scenario
format = "ticc"             # "rinex-clk", "timelab", "ticc", "ptp4l", "phc2sys", "ts2phc",
                            # "chrony-tracking" or "chrony-statistics"
path = "logs/ticc.txt"      # or text = "..." inline (the only choice in WebAssembly)
channel = "chA"             # TICC: needed when the log holds more than one channel
gaps = "linear"             # "refuse" (default), "longest" or "linear"
# clock = "G08"             # RINEX, linuxptp, chrony: needed when the log holds more than one clock or source
# tau0_s = 1.0              # overrides a header and the detected spacing
# units = "ns"              # TimeLab phase units: s (default), ms, us, ns, ps
# data = "phase"            # TimeLab: phase (default) or frequency

Formaten#

rinex-clk: RINEX clock-filer, versionerna 2,00 och 3,00 till 3,04 (inklusive namnfältet på nio tecken i 3,04). Posten RINEX VERSION / TYPE kontrolleras och varje annan version avvisas, med angivande av den version som hittades: IGS publicerar klockformatet (rinex_clock300.txt, 302, 304) upp till 3,04, och dokumenten RINEX 4,00, 4,01 och 4,02 definierar bara observations-, navigerings- och meteorologiska filer, så det finns ingen version 4,00 av klockfilen att läsa. Rubriken läses bara för sin TIME SYSTEM ID och hoppas över fram till END OF HEADER. Av dataposterna behålls bara posterna AS (satellit) och AR (mottagare eller station) för en klocka, vald med namn. Deras första värdefält, klockbiasen i sekunder, är fasen. Fortsättningsrader och posterna CR, DR och MS hoppas över. Epokerna är postens kalenderfält, som sekunder från 1980-01-06 00:00:00 i filens eget tidssystem, utan omvandling.

timelab: ASCII-fas- eller frekvensloggar i TimeLab-stil, den vanliga textform som TimeLab exporterar och som dess ASCII-import och Stable32 läser. Det finns en avläsning per rad: antingen en enda kolumn med likformigt tau0, eller två kolumner time value. Kolumner kan avgränsas med blanksteg, kommatecken eller semikolon.

  • Rader som börjar med #, ; eller % är kommentarer. En kommentar av formen key = value (eller key: value) anger tau0 (s), units (s, ms, us, ns eller ps, för fas), data (phase eller frequency) eller time_units (s eller mjd, för den första av två kolumner).
  • En inledande icke-numerisk rad tas som kolumnrubrik.
  • Frekvensdata (relativ frekvens) godtas bara som en enda kolumn. De integreras till fas som x[i+1] = x[i] + y[i]·tau0 (NIST SP 1065, 2008, §4,1).
  • TimeLabs binära projektfiler och projektfiler av typen .tim läses inte.

ticc: loggar från räknaren TAPR TICC (TICC Operation Manual, revisionerna från 23 november 2016 och 15 december 2025, "measurement modes"). Varje datafält är sekunder med 12 decimaler (11 som standard från firmware 20251101: varje antal upp till 15 läses). En tidsstämpel läses från sin decimaltext som ett helt antal femtosekunder, inte som ett binärt flyttal, så att fasen i en logg som tagits dagar efter att räknaren startade behåller räknarens egen upplösning: en tidsstämpel av typen f64 vid 3.0e5 s har ett avstånd på 5.8e-11 s, ungefär räknarens 60 ps.

  • Rader i tidsstämpelläge (<seconds> chA, <seconds> chB) och TimeLab-lägets pseudotidsstämpelkanal (chC) är tidsstämplar för händelser. Fasen för den valda kanalen är dess tidsstämpel minus den nominella takten: x[k] = t[k] − t[0] − n[k]·tau0, där n[k] är det hela antalet tau0 sedan den första händelsen. En missad händelse är en lucka.
  • Rader i intervalläge (<seconds> TI(A->B), eller valfri etikett som börjar med TI) läses direkt som fas, en avläsning per tau0. Scenariot måste ange tau0_s, eftersom raden inte bär någon tid.
  • Paired Timestamp mode skriver ut samma rader i kanalordning och läses som Timestamp mode; 3-Corner Hat mode lägger till den syntetiserade chC, läst som ovan.
  • Utdata i Period mode och Debug mode avvisas. En kanal vars avläsningar inte ökar rapporteras som Period mode. Binary Timestamp mode är inte text, och en fil i det läget avvisas med ett meddelande som säger så.
  • Rader som börjar med #, och rader som inte är <number> <label> (till exempel startmenyn), hoppas över och räknas.

loggar från linuxptp och chrony#

Dessa fem format läser det som en tidsdaemon i drift skriver om sin egen klocka. De är till för att kontrollera en tidskedja i efterhand (en boundary-klocka, en grandmasters PHC, en chrony-klient) med samma skattare som för de andra loggarna. De läser inte en daemons konfiguration, och ingenting här pratar med en daemon.

ptp4l, phc2sys, ts2phc: servoraderna från linuxptp, där varje format bara läser rader från sitt eget program. En avläsning är en rad av formen

ptp4l[5003.000]: master offset         40 s2 freq   +1480 path delay       497
phc2sys[7000.000]: CLOCK_REALTIME phc offset       -30 s2 freq    +100 delay   1200
ts2phc[8000.000]: /dev/ptp0 offset          3 s2 freq         -2
  • Tidsstämpeln är den första [seconds.fraction] på raden (daemonens monotona klocka). Den läses också efter ett syslog-prefix, där ett process-id som ptp4l[812]: saknar bråkdel och inte tas.
  • Fasen är den loggade offset, i nanosekunder, omvandlad till sekunder. Det är daemonens uppmätta tidsfel hos sin slavklocka mot sin referens, som loggat: positivt när slaven ligger före. Det är felet som återstår under servostyrning, inte driften hos en fritt gående klocka.
  • Orden mellan tidsstämpeln och offset namnger källan (master, eth0 master för ett prefix [eth0], CLOCK_REALTIME phc, /dev/ptp0). En logg med mer än en källa behöver clock = "<that text>"; felet listar dem.
  • Avläsningar innan servot först redovisar s2 (låst) utelämnas och räknas i n_skipped_lines: s0 och s1 är de olåsta tillstånden och stegtillstånden, vilkas förskjutningar är transienter vid inkoppling. Ett servo som aldrig når s2 avvisas. En rad utan tillståndsfält läses som den är.
  • Sammanfattningsrader (rms ... max ...), meddelanden om delay och selected best master samt rader från andra program hoppas över och räknas.
  • Tidsstämplar som går bakåt (en omstartad daemon) avvisas; dela upp loggen.

chrony-tracking, chrony-statistics: chronys filer log tracking och log statistics, lästa efter kolumnposition. En avläsning är en rad med minst 14 kolumner (tracking) eller 13 (statistics) som börjar med ett UTC-datum och en tid i formen YYYY-MM-DD HH:MM:SS. Kolumnrubrikraden hoppas över och räknas; regeln ==== under den hoppas över utan att räknas.

  • Tracking: kolumn 7, den lokala förskjutningen vid klockuppdateringen, i sekunder. IP-adressen eller referens-id:t ändras med den valda källan, så utan clock läses varje rad som en enda lokal klocka. clock = "<id>" behåller ett referens-id.
  • Statistics: kolumn 5, den skattade förskjutningen hos en källa, i sekunder. Det finns en serie per källadress, och loggen behöver clock = "<address>" när den innehåller fler än en.
  • Epoker är sekunder från 1980-01-06 00:00:00 UTC, utan hantering av skottsekunder. Chrony skriver en rad per uppdatering eller per källsampel, så avståndet är inte likformigt. tau0 är medianavståndet; en avläsning under en halv tau0 efter den som behölls före den tas bort och räknas i n_duplicates, och ett längre avstånd är en lucka, vilket gaps = "refuse" redovisar. Ange tau0_s och gaps = "linear" för en logg med ett stadigt pollintervall.

Kolumnerna i chrony och radlayouterna i linuxptp är de som anges i daemonernas publika dokumentation. Testfilerna i tests/fixtures/clock_log/linuxptp_chrony/ är skrivna för Kshana med påhittade värden (se dess NOTICE.md); ingen verklig logg har lästs, så en layout som skiljer sig mellan daemonversioner kan fortfarande avvisas eller misstolkas. En rad som inte stämmer hoppas över och räknas, aldrig gissas.

tau0 och luckor#

När loggen bär tidsstämplar och inget tau0 anges är tau0 medianavståndet mellan på varandra följande tidsstämplar, avrundat till fyra värdesiffror, och källan redovisas som median-spacing. En räknares avstånd skiljer sig från det nominella med referensens frekvensförskjutning, miljondelar eller mindre (10^6). Ett tau0_s i scenariot gäller alltid (källa input), därefter en huvudkommentar tau0 (källa header).

Sampel placeras på nätet t0 + i·tau0, och en saknad epok är en lucka. Avläsningar som ligger mer än 1 % av tau0 från nätet tas bort och räknas, liksom dubbletter (den första behålls). Lucklinjen är en av:

  • refuse (standard): varje lucka är ett fel som räknar luckorna;
  • longest: behåll den längsta luckfria sekvensen;
  • linear: fyll inre luckor med linjär interpolation och redovisa antalet fyllda.

Skattarna behöver ett luckfritt register, vilket är därför luckor löses här.

Din egen klocka#

En tabell [clock_log] på klocktypen redovisar hur stabil din egen klocka var, bredvid simuleringen: scenarios/clock-measured-log.toml (kshana example clock-measured-log) är clock-holdover.toml med ett utdrag på 96 avläsningar från en IGS-satellitklocka som en inbäddad TimeLab-logg. Ersätt text med path och format för din egen fil. Blocket measured i resultatet innehåller hur loggen lästes (format, tau0 och varifrån den kom, varje glapp) och dess ADEV, TDEV och MTIE; det ändrar inte simuleringen.

Styr holdovern med din egen klocka: [clock_fit]#

[clock_log]                      # the measured series, as above
format = "ticc"
path = "my-clock.txt"
channel = "chA"

[clock_fit]
replaces = "classical"           # or "quantum": the simulated clock whose noise the log replaces

Loggen anpassas med enhetskortets förfarande i src/clock_library/card.rs (konditionering, kvadratisk term borttagen, brusidentifiering med lagg 1, viktade minsta kvadrater i vitt PM, vitt FM, flicker-FM och slumpvandrings-FM vid de medelvärdestider som har minst 30 frihetsgrader). Den namngivna klockan tar sedan q_wf = h_0 / 2, q_rw = 2 pi^2 h_-2, flicker_floor = sqrt(2 ln 2 h_-1) och den anpassade drift; y0 förblir som scenariot har det, eftersom en logg bär sin referens offset, inte klockans efter styrning. Vitt fasbrus anpassas och redovisas men simuleras inte. Resultatet får ett block fitted (koefficienterna, anpassningspunkterna, de värden körningen använde, vad som utelämnades, loggens SHA-256) och klockan får id:t measured:<12 hex of the phase hash>. Med runs > 1 drar ensemblen från den anpassade klockan (blocket measured kräver runs = 1). En anpassning utan frekvensbrus, en logg som är för kort för att anpassas och en replaces som inte är quantum eller classical är fel som säger så. scenarios/clock-fitted-log.toml är ett exempel (6 timmar av en IGS-satellitklocka).

Vad jämförelsen på känt brus (tests/fixtures/clock_fit/RESULTS.md) visar, och vad man bör ha i åtanke:

  • Nådda: nivån för vitt FM återfinns inom 5 % på varje syntetisk post som har det; det anpassade kortet återger den verkliga Allan-deviationen inom en faktor 1,35 vid varje medelvärdestid det anpassades vid; brusexponenten som anpassningen identifierar är lika med allantools vid varje punkt (på posten 5071A, sedan det fassteg som konditioneringen tar bort också har tagits bort ur allantools indata).
  • Inte nådda, och fastlåsta av testet: slumpvandrings-FM återfinns bara när det dominerar de längsta medelvärdestiderna i posten, och även då i en av tre poster i en serie på 131 072 s med en övergång vid 3 000 s gav anpassningen den till flicker-FM och till driften. Uppdelningen mellan slumpvandrings-FM och flicker-FM är inte tillförlitlig utifrån en enda post. Körningen återger loggens stabilitet över de medelvärdestider som loggen täcker; bortom dem divergerar de två valen (flicker-FM är ett konstant golv, slumpvandrings-FM växer som kvadratroten av medelvärdestiden).
  • MODELLED: ett vad-händer-om för den klockans brus så som loggen visar det, inte en kalibrering av klockan och inte en förutsägelse av dess framtida beteende.

En felaktigt formad logg är ett fel som namnger vad som hittades (raden, versionen, den saknade väljaren), aldrig ett partiellt resultat: tests/clock_log_real_allantools.rs låser fast 24 sådana fall.

Evidens#

MODELLED. Detta är en tolk, och dess utdata matar skattare som är validerade på annat håll mot allantools. Enhetstesterna i src/clock_log.rs använder små handskrivna loggar, och för formaten linuxptp och chrony fixturerna i tests/fixtures/clock_log/linuxptp_chrony/. tests/clock_log_allantools.rs kör den jämförelse som förhandsregistrerades i tests/fixtures/clock_log/PREREGISTRATION.md: tre syntetiska loggar med frö, en per format, återinlästa av en oberoende läsare skriven utifrån den här sidan av samma författare, med ADEV, TDEV och MTIE kontrollerade mot allantools 2024,6; den jämförelsen täcker bara de tre första formaten, och läsarna för linuxptp och chrony har tolktester men ingen jämförelse mot oberoende referens. Loggarna i den jämförelsen är syntetiska, så ingenting där beskriver en verklig klocka eller räknare; jämförelsen på uppmätta serier beskrivs nedan.

På uppmätta data#

tests/clock_log_real_allantools.rs kör den jämförelse som förhandsregistrerades i tests/fixtures/clock_log_real/PREREGISTRATION.md (incheckad före varje fixtur eller körning) på fyra uppmätta serier: Stable32-filen PHASE.DAT, de första 65 536 avläsningarna av en 5071A-cesiumklocka mot en vätemaser, och klockorna för IGS-satelliten G01 (30 s) och stationen ABMF (300 s) från IGS slutliga klocka för 2026-08-02, som ett medföljande utsnitt med sin NOTICE. De två första har ingen rätt till vidaredistribution: loggarna som skrivits från dem ligger i den git-ignorerade realdata-cache/ (scripts/gen_clock_log_real_ref.py), och testet säger så och godkänns när de saknas om inte KSHANA_REQUIRE_REALDATA=1. Varje logg läses av motorn och av en oberoende läsare, och ADEV, TDEV och MTIE jämförs med allantools 2024,6. Redovisat i tests/fixtures/clock_log_real/RESULTS.md: på den levererade läsaren föll TICC-loggarna, rubrikens version och fem felmeddelanden på de trösklar som fastställts i förväg; de rättades och jämförelsen kördes om oförändrad. Nådd, utom för ett par: MTIE för en frekvenslogg avviker från allantools, eftersom allantools integrerar frekvensen minus dess medelvärde (fastlåst som NOT MET; jämförelsen på lika villkor nås). Raden förblir MODELLED: TICC-loggarna är uppmätta klockdata som vårt skript har kodat om till räknarens layout (ingen verklig TICC-inspelning hittades), och referensläsaren har samma författare som motorns.