Il formato esatto dei file SPK di SPICE Toolkit (chiamati anche file BSP) è chiamato DAF ( File di array a doppia precisione ). È un formato binario costituito da blocchi consecutivi di 1.024 byte. Il primo record è sempre il record del file , quindi ha alcuni blocchi che fungono da area dei commenti , poi ha gli record dell'array e infine una raccolta di record di dati .
[FILE RECORD] (1024 byte) [PRIMO BLOCCO DI COMMENTO] (1024 byte) ... [ULTIMO BLOCCO DI COMMENTO] (1024 byte) [PRIMO BLOCCO DI SUMMARY RECORDS] (1024 byte) ... [ULTIMO BLOCCO DI REGISTRI DI SOMMARIO] (1024 byte) [PRIMO BLOCCO DI REGISTRI DI NOME] (1024 byte) ... [ULTIMO BLOCCO DI REGISTRI DI NOME] (1024 byte) [PRIMO BLOCCO DI REGISTRI DI ELEMENTI] (1024 byte) ... [ULTIMO BLOCCO DI REGISTRI DI ELEMENTI] (1024 byte)
Tutti i dati binari di SPICE sono memorizzati in formato DAF (non solo le effemeridi). Il tipo specifico di dati (ovvero la semantica dei record) dipende dalle informazioni memorizzate nei record di riepilogo e dai record dell'elemento. Devi sapere che tipo di dati stai leggendo per interpretare correttamente i record.
Esistono molti tipi di effemeridi . I pianeti sono spesso di Tipo II ; i satelliti sono spesso di Tipo III ; i veicoli spaziali sono spesso di Tipo I . I tipi II e III rappresentano i polinomi di Chebyshev e la loro differenza è se usano la derivata del polinomio di Chebyshev per calcolare la velocità (Tipo II) o se viene utilizzato un polinomio separato per calcolare la velocità (Tipo III).
In altre parole: un file SPK di tipo II ti fornirà un polinomio di un certo ordine il cui valore rappresenta la posizione e la cui derivata rappresenta la velocità. Un file SPK di tipo III fornirà un polinomio per la posizione e un polinomio diverso per la velocità. Entrambi i tipi sono polinomi di Chebyshev.
Per i file SPK, i record di riepilogo ti diranno dove inizia e finisce ogni record, il tipo di effemeridi, l'intervallo di tempo, il frame, il target e l'osservatore. Ogni record specifico (che molto probabilmente conterrà più di un blocco) avrà il seguente aspetto:
+ --------------- + | Record 1 | + --------------- + | Record 2 | + --------------- +. . . + --------------- + | Record N | + --------------- + | INIT | + --------------- + | INTLEN | + --------------- + | RSIZE | + --------------- + | N | + --------------- +
e ogni record ha il seguente aspetto
+ ------ ------------ + | MID | + ------------------ + | RAGGIO | + ------------------ + | Coefficienti X | + ------------------ + | Coefficienti Y | + ------------------ + | Coefficienti Z | + ------------------ +
per Tipo II e simili
+ --- --------------- + | MID | + ------------------ + | RAGGIO | + ------------------ + | Coefficienti X | + ------------------ + | Coefficienti Y | + ------------------ + | Coefficienti Z | + ------------------ + | Coefficienti X '| + ------------------ + | Coefficienti Y '| + ------------------ + | Coefficienti Z '| + ------------------ +
per Tipo III.
Il grado del polinomio è (RSIZE - 2) / 3-1
. MID
ti dice il punto medio dell'intervallo (tempo delle effemeridi), e RADIUS
ti dice la metà della dimensione dell'intervallo. Quindi il suo intervallo di tempo è [MID - RADIUS, MID + RADIUS]
.
Per ottenere la posizione si valuta semplicemente Chebyshev al momento corrispondente. Per la velocità si valuta la derivata o un polinomio diverso. Ricorda di normalizzare il tempo prima di valutare e de-normalizzare il tempo dopo la valutazione (questo mi ha procurato molte volte).
Trattare direttamente con DAF può essere un'esperienza gratificante (ad esempio: ho un analizzatore di effemeridi ad alte prestazioni thread-safe), ma è facile sbagliare. E dopo molto lavoro hai solo una posizione o velocità in un dato fotogramma che devi ancora ruotare / tradurre / ecc (per il quale devi reinventare SPICE o fare affidamento su di esso).
A meno che tu non abbia una buona ragione per non farlo, attieniti a SPICE.
Un semplice script Python
Ho appena creato uno script Python che potrebbe aiutare qualcuno iniziare con il formato binario DAF. Eseguirà semplicemente il dump delle informazioni sul record del file e dei contenuti (riepiloghi degli array) contenuti in un DAF.
import mmapimport structRECLEN = 1024def peek_spk (mem): # record file è sempre la prima # stringa data locidw = mem [0: 8] locifn = mem [16:16 + 60] locfmt = mem [88: 88 + 8] ftpstr = mem [699: 699 + 28] # endianness fmt = "<" if locfmt == "LTL-IEEE" else ">" int_fmt = fmt + "I" nd, = struct.unpack_from (int_fmt, mem, offset = 8) ni, = struct.unpack_from (int_fmt, mem, offset = 12) fward, = struct .unpack_from (int_fmt, mem, offset = 76) bward, = struct.unpack_from (int_fmt, mem, offset = 80) free, = struct.unpack_from (int_fmt, mem, offset = 84) print "locidw {0}". formato (locidw) print "nd {0}". format (nd) print "ni {0}". format (ni) print "locifn {0}". format (locifn) print "fward {0}". format (fward ) print "bward {0}". format (bward) print "free {0}". format (free) print "locfmt {0}". format (l ocfmt) print "ftpstr {0}". format (repr (ftpstr)) # facciamo solo il primo record di riepilogo ... dobbiamo leggere nd # double e ni interi a partire da offset fward offset = (fward - 1) * RECLEN sum_fmt = fmt + nd * "d" + ni * "I" size = nd + (ni + 1) / 2 # divisione intera mentre True: nxt, prv, nsum = struct.unpack_from (fmt + "ddd", mem , offset = offset) offset + = 24 # salta tre doppi
for n in range (int (nsum)): print struct.unpack_from (sum_fmt, mem, offset = offset) offset + = size * 8 if nxt == 0: breakdef peek (path): print "peeking into {0}" .format (percorso) con open (percorso, "rb") come fp: mem = mmap.mmap (fp.fileno (), 0, access = mmap.PROT_READ) peek_spk (mem) if __name__ == "__main__": import sys per il percorso in sys.argv [1:]: peek (percorso)
Ad esempio: eseguirlo per jup310.bsp dà
sbirciare in / data / spice / jup310.bsplocidw DAF / SPK nd 2ni 6locifn NIO2SPK
fward 6bward 6free 122077514locfmt LTL-IEEEftpstr 'FTPSTR: \ r: \ n: \ r \ n: \ r \ x00: \ x81: \ x10 \ xce : ENDFTP '(- 3155716758.8160305, 3155716867.183885, 501, 5, 1, 3, 897, 7208500) (- 3155716758.8160305, 3155716867.183885, 502, 5, 1, 3, 7208501, 1436740475, - 3155716758.8160305, 3155716867.183885, 502, 5, 1, 3, 7208501, 14367385, 508 , 3, 14367405, 19140106) (- 3155716758.8160305, 3155716867.183885, 504, 5, 1, 3, 19140107, 22451778) (- 3155716758.8160305, 3155716867.183885 , 505, 5, 1, 3, 22451779, 44074360) (- 3155716758.8160305, 3155716867.183885, 514, 5, 1, 3, 44074361, 65696942) (- 3155716758.8160305, 3155716867.183885, 515, 5, 1, 3, 9069 -3155716758.8160305, 3155716867.183885, 516, 5, 1, 3, 90825889, 115954834) (- 3155716758.8160305, 3155716867.183885, 599, 5, 1, 3, 115954835, 120922238, - 3155716758.8160305, 3155716867.183885, 599, 5, 1, 3, 115954835, 120922238) (- 3155730867, 3155730867, 3155730867, 3155730867 , 121109489) (- 3155716758.8160305, 3155716867.183885, 5, 0, 1, 2, 121109490, 121168877) (- 3155716758.8160305, 3155716867.183885, 10, 0, 1, 2, 121168878, 121328760567, 3155138716, 3155138716, 3155138671, 31551 3867, 315513867, 315513867, , 2, 121328727, 122077513)
Ciò significa che jup310 contiene record che si estendono su ET (-3155716758.8160305, 3155716867.183885) per alcune lune di Giove (da 501 a 519) relative al baricentro di Giove (5), in formato J2000 (1), e sono di tipo 3. Altri record sono per i baricentri della Terra, Giove e del Sole (3, 5 e 10) rispetto al Baricentro del Sistema Solare (0) in J200 (1) e sono di tipo 2.
Ogni record ti dice dove nel file inizia e finisce ogni array. Puoi estendere lo script per passare a ciascuna posizione e leggere l'intero record per una successiva interpolazione.
Software disponibile
Ho creato rapidamente una semplice implementazione in Python che può leggere e lavorare direttamente con Tipi II e III. Si confronta bene con CSPICE.
https://gist.github.com/arrieta/c2b56f1e2277a6fede6d1afbc85095fb