Orbit Ingest
The ingest stage converts raw satellite ephemerides into a uniformly sampled, body-fixed orbit
catalogue that downstream simulation and estimation stages consume. The implementation lives in
src/orbit_processing.py and relies on SPICE frame transformations exposed through spiceypy,
furnished by the kernels referenced in the scenario file.
Processing flow
Running poetry run acons ingest … executes the following steps for every satellite entry listed
under orbits:
- Furnish SPICE kernels –
src/spice_support.py:furnish_kernelsloads the kernel list fromspice.kernels. A leapseconds kernel (LSK), a frame kernel (FK) for the inertial frame, and a binary/polynomial frame kernel (PCK/CK/BC) for the body-fixed frame are the minimum set. - Resolve the ingest timeline –
get_time_configaccepts absolute UTC/JD values or offsets in seconds from the first sample in the ephemerides (viatime.start_seconds/time.end_seconds). The helperbuild_time_gridcreates an inclusive Julian Date grid with the configured cadence. - Load and normalise ephemerides –
load_orbit_csvexpects comma-separated files with at leastjd,x_m,y_m,z_m,vx_mps,vy_mps,vz_mps. Columns are interpreted in the frame named byframes.input(typicallyJ2000). An optionalepoch_scolumn is recomputed if missing. - Interpolation onto the grid –
resample_states_leapfrogapplies a constant-acceleration leapfrog interpolator so every satellite has state vectors aligned to the ingest grid. - Frame conversion –
transform_statescallsspice.sxformviaspiceypyto obtain the 6×6 state transformation fromframes.inputtoframes.body_fixedat each epoch. Julian Dates are first converted to ephemeris time usingspice.unitim. - Export artefacts – a parquet file per satellite (
<sat_id>_orbit.parquet) plus an aggregateorbits_manifest.parquetare written to the ingest run directory. Each record contains epoch-relative seconds, Julian Date, ephemeris time, and body-fixed position/velocity. Quick-look plots are produced from both the input-frame states (plots/input_frame/) and the converted body-fixed orbits (plots/output_frame/) whenreporting.enable_plotsis true so you can inspect the transformation results.
If the ingest window extends outside the supplied ephemeris coverage, the interpolator raises an error with the offending timestamps, prompting you to widen the source data or tighten the ingest interval.
Required inputs
- SPICE kernels: At minimum furnish
- an LSK (e.g.
naif0012.tls) for TDB↔UTC conversions, - an FK describing the inertial frame used by the ephemerides (e.g.
moon_080317.tffor the Moon PA frame definitions), - a body orientation kernel (binary PCK or CK). For Moon and Mars these are typically binary
PCKs (
*.bpc), whereas Earth commonly uses high-accuracy CK/ITRF solutions. The exact mix depends on the frames you transform between; consult NAIF documentation if you need high-fidelity orientation or tidal models. - Ephemeris files: One CSV per satellite holding inertial states. The filename stem becomes the
satellite identifier unless overridden by
orbits[].id. Keep epochs monotonically increasing; gaps larger than the ingest cadence lead to constant-acceleration interpolation across the gap. - Scenario file: Defines
frames.input,frames.body_fixed, ingest cadence (time.step_seconds), and optional relative start/end offsets. The receiver block provides body radius for plotting but does not influence the state conversion.
Adapting to other bodies
Only the scenario configuration and SPICE kernel list need to change to ingest orbits for a different central body.
- Mars: Set
frames.body_fixed: "IAU_MARS"(or the appropriate Mars-fixed frame) and furnish:naif0012.tls, the NAIF Mars frame kernelpck00011.tpc(used by ACONS for the Mars IAU transformations), and a binary orientation kernel such asmar097.bsp/mar097.bpcthat carries the body-fixed rotation. Provide Mars-centric inertial ephemerides (e.g. inJ2000). Update receiver geometry with Mars’ mean radius if you are plotting surface references. - Earth: Choose a body-fixed frame compatible with your SPICE set—
ITRF93,IAU_EARTH, orEARTH_FIXED. Furnish an Earth FK (e.g.earth_latest_high_prec.tf) plus the appropriate high-precision Earth orientation kernels (earth_latest_high_prec.bpcor EOP CKs). Ensure the inertial ephemerides align with the same inertial frame (usuallyJ2000). Because Earth orientation files can be time-limited, verify the ingest timeline remains within the kernel span.
For any new body the workflow is:
frames:
input: "J2000"
body_fixed: "IAU_MARS" # or the target body's fixed frame
spice:
kernels:
- data/SPICE/naif0012.tls
- data/SPICE/pck00011.tpc # Mars frame definitions
orbits:
- path: ephemeris/MARS_SAT1.csv
- path: ephemeris/MARS_SAT2.csv
After updating the scenario file and placing the kernels in data/SPICE/, rerun
poetry run acons ingest pointing to the modified configuration. The ingest stage reuses the same
Python code regardless of the target body; all differences are encapsulated by the supplied SPICE
assets and ephemerides.