import os
from pathlib import Path
import numpy as np
from Basilisk.topLevelModules import pyswice
from Basilisk.utilities.supportDataTools.dataFetcher import DataFile, get_path
from benchmarks.comparative.implementations.basilisk.base import (
build_task_result,
jd_to_spice_et_string,
time_iterations,
)
_KERNELS_LOADED = False
_HIGH_PREC_PCK = Path(os.environ.get("BSK_HIGH_PREC_PCK", str(Path.home() / ".cache" / "bsk-data" / "earth_latest_high_prec.bpc")))
def _ensure_kernels() -> None:
global _KERNELS_LOADED
if _KERNELS_LOADED:
return
pyswice.furnsh_c(str(get_path(DataFile.EphemerisData.naif0012))) pyswice.furnsh_c(str(get_path(DataFile.EphemerisData.pck00010))) if not _HIGH_PREC_PCK.exists():
raise RuntimeError(
f"High-precision Earth PCK not found at {_HIGH_PREC_PCK}. "
"Run `just _bench-compare-build-basilisk` to download it."
)
pyswice.furnsh_c(str(_HIGH_PREC_PCK)) _KERNELS_LOADED = True
def _jd_to_et(jd: float) -> float:
et_arr = pyswice.new_doubleArray(1)
pyswice.str2et_c(jd_to_spice_et_string(jd), et_arr)
return pyswice.doubleArray_getitem(et_arr, 0)
def _sxform(from_frame: str, to_frame: str, et: float) -> np.ndarray:
xform_arr = pyswice.new_doubleArray(36)
pyswice.sxform_c(from_frame, to_frame, et, xform_arr)
flat = [pyswice.doubleArray_getitem(xform_arr, i) for i in range(36)]
return np.array(flat, dtype=float).reshape(6, 6)
def state_eci_to_ecef(params: dict, iterations: int):
_ensure_kernels()
cases = params["cases"]
et_state_pairs = []
for case in cases:
et = _jd_to_et(case["jd"])
state = np.array(case["state"], dtype=float) et_state_pairs.append((et, state))
def run():
results = []
for et, state in et_state_pairs:
sxform = _sxform("J2000", "ITRF93", et)
s_km = np.concatenate([state[:3] / 1000.0, state[3:6] / 1000.0])
ecef_km = sxform @ s_km
ecef = np.concatenate([ecef_km[:3] * 1000.0, ecef_km[3:6] * 1000.0])
results.append(ecef.tolist())
return results
times, results = time_iterations(run, iterations)
return build_task_result(
"frames.state_eci_to_ecef",
iterations,
times,
results,
extra_metadata={"implementation": "pyswice", "earth_fixed_frame": "ITRF93"},
)
def state_ecef_to_eci(params: dict, iterations: int):
_ensure_kernels()
cases = params["cases"]
et_state_pairs = []
for case in cases:
et = _jd_to_et(case["jd"])
state = np.array(case["state"], dtype=float)
et_state_pairs.append((et, state))
def run():
results = []
for et, state in et_state_pairs:
sxform = _sxform("ITRF93", "J2000", et)
s_km = np.concatenate([state[:3] / 1000.0, state[3:6] / 1000.0])
eci_km = sxform @ s_km
eci = np.concatenate([eci_km[:3] * 1000.0, eci_km[3:6] * 1000.0])
results.append(eci.tolist())
return results
times, results = time_iterations(run, iterations)
return build_task_result(
"frames.state_ecef_to_eci",
iterations,
times,
results,
extra_metadata={"implementation": "pyswice", "earth_fixed_frame": "ITRF93"},
)