#![allow(non_snake_case)]
#![allow(dead_code)]
use std::os::raw::c_char;
use super::{GetSetString, environment, get_last_error_message, time};
unsafe extern "C" {
pub fn AstroFuncGetInfo(infoStr: *const c_char);
pub fn KepToEqnx(xa_kep: *const [f64; 6], xa_eqnx: *mut [f64; 6]);
pub fn KepToPosVel(xa_kep: *const [f64; 6], pos: *mut [f64; 3], vel: *mut [f64; 3]);
pub fn KepToUVW(xa_kep: *const [f64; 6], uBar: *mut [f64; 3], vBar: *mut [f64; 3], wBar: *mut [f64; 3]);
pub fn ClassToEqnx(xa_cls: *const [f64; 6], xa_eqnx: *mut [f64; 6]);
pub fn EqnxToClass(xa_eqnx: *const [f64; 6], xa_cls: *mut [f64; 6]);
pub fn EqnxToKep(xa_eqnx: *const [f64; 6], xa_kep: *mut [f64; 6]);
pub fn EqnxToPosVel(xa_eqnx: *const [f64; 6], pos: *mut [f64; 3], vel: *mut [f64; 3]);
pub fn PosVelToEqnx(pos: *const [f64; 3], vel: *const [f64; 3], xa_eqnx: *mut [f64; 6]);
pub fn PosVelMuToEqnx(pos: *const [f64; 3], vel: *const [f64; 3], mu: f64, xa_eqnx: *mut [f64; 6]);
pub fn PosVelToKep(pos: *const [f64; 3], vel: *const [f64; 3], xa_kep: *mut [f64; 6]);
pub fn PosVelMuToKep(pos: *const [f64; 3], vel: *const [f64; 3], mu: f64, xa_kep: *mut [f64; 6]);
pub fn PosVelToUUVW(
pos: *const [f64; 3],
vel: *const [f64; 3],
uvec: *mut [f64; 3],
vVec: *mut [f64; 3],
wVec: *mut [f64; 3],
);
pub fn PosVelToPTW(
pos: *const [f64; 3],
vel: *const [f64; 3],
uvec: *mut [f64; 3],
vVec: *mut [f64; 3],
wVec: *mut [f64; 3],
);
pub fn SolveKepEqtn(xa_kep: *const [f64; 6]) -> f64;
pub fn CompTrueAnomaly(xa_kep: *const [f64; 6]) -> f64;
pub fn NToA(n: f64) -> f64;
pub fn AToN(a: f64) -> f64;
pub fn KozaiToBrouwer(eccen: f64, incli: f64, nKozai: f64) -> f64;
pub fn BrouwerToKozai(eccen: f64, incli: f64, nBrouwer: f64) -> f64;
pub fn KepOscToMean(xa_OscKep: *const [f64; 6], xa_MeanKep: *mut [f64; 6]);
pub fn XYZToLLH(thetaG: f64, metricPos: *const [f64; 3], metricLLH: *mut [f64; 3]);
pub fn XYZToLLHTime(ds50UTC: f64, metricPos: *const [f64; 3], metricLLH: *mut [f64; 3]);
pub fn LLHToXYZ(thetaG: f64, metricLLH: *const [f64; 3], metricXYZ: *mut [f64; 3]);
pub fn LLHToXYZTime(ds50UTC: f64, metricLLH: *const [f64; 3], metricXYZ: *mut [f64; 3]);
pub fn EFGToECI(
thetaG: f64,
posEFG: *const [f64; 3],
velEFG: *const [f64; 3],
posECI: *mut [f64; 3],
velECI: *mut [f64; 3],
);
pub fn EFGToECITime(
ds50UTC: f64,
posEFG: *const [f64; 3],
velEFG: *const [f64; 3],
posECI: *mut [f64; 3],
velECI: *mut [f64; 3],
);
pub fn ECIToEFG(
thetaG: f64,
posECI: *const [f64; 3],
velECI: *const [f64; 3],
posEFG: *mut [f64; 3],
velEFG: *mut [f64; 3],
);
pub fn ECIToEFGTime(
ds50UTC: f64,
posECI: *const [f64; 3],
velECI: *const [f64; 3],
posEFG: *mut [f64; 3],
velEFG: *mut [f64; 3],
);
pub fn ECRToEFG(
polarX: f64,
polarY: f64,
posECR: *const [f64; 3],
velECR: *const [f64; 3],
posEFG: *mut [f64; 3],
velEFG: *mut [f64; 3],
);
pub fn ECRToEFGTime(
ds50UTC: f64,
posECR: *const [f64; 3],
velECR: *const [f64; 3],
posEFG: *mut [f64; 3],
velEFG: *mut [f64; 3],
);
pub fn EFGToECR(
polarX: f64,
polarY: f64,
posEFG: *const [f64; 3],
velEFG: *const [f64; 3],
posECR: *mut [f64; 3],
velECR: *mut [f64; 3],
);
pub fn EFGToECRTime(
ds50UTC: f64,
posEFG: *const [f64; 3],
velEFG: *const [f64; 3],
posECR: *mut [f64; 3],
velECR: *mut [f64; 3],
);
pub fn EFGPosToLLH(posEFG: *const [f64; 3], metricLLH: *mut [f64; 3]);
pub fn LLHToEFGPos(metricLLH: *const [f64; 3], posEFG: *mut [f64; 3]);
pub fn RotJ2KToDate(
spectr: i32,
nutationTerms: i32,
ds50TAI: f64,
posJ2K: *const [f64; 3],
velJ2K: *const [f64; 3],
posDate: *mut [f64; 3],
velDate: *mut [f64; 3],
);
pub fn RotDateToJ2K(
spectr: i32,
nutationTerms: i32,
ds50TAI: f64,
posDate: *const [f64; 3],
velDate: *const [f64; 3],
posJ2K: *mut [f64; 3],
velJ2K: *mut [f64; 3],
);
pub fn CompSunMoonPos(
ds50ET: f64,
uvecSun: *mut [f64; 3],
sunVecMag: *mut f64,
uvecMoon: *mut [f64; 3],
moonVecMag: *mut f64,
);
pub fn CompSunPos(ds50ET: f64, uvecSun: *mut [f64; 3], sunVecMag: *mut f64);
pub fn CompMoonPos(ds50ET: f64, uvecMoon: *mut [f64; 3], moonVecMag: *mut f64);
pub fn AstroConvFrTo(xf_Conv: i32, frArr: *const [f64; 128], toArr: *mut [f64; 128]);
pub fn RADecToLAD(ra: f64, dec: f64, l: *mut [f64; 3], a_tilde: *mut [f64; 3], d_tilde: *mut [f64; 3]);
pub fn AzElToLAD(az: f64, el: f64, lh: *mut [f64; 3], ah: *mut [f64; 3], dh: *mut [f64; 3]);
pub fn ECIToTopoComps(
theta: f64,
lat: f64,
senPos: *const [f64; 3],
satPos: *const [f64; 3],
satVel: *const [f64; 3],
xa_topo: *mut [f64; 10],
);
pub fn RaDecToAzEl(thetaG: f64, lat: f64, lon: f64, ra: f64, dec: f64, az: *mut f64, el: *mut f64);
pub fn RaDecToAzElTime(ds50UTC: f64, lat: f64, lon: f64, ra: f64, dec: f64, az: *mut f64, el: *mut f64);
pub fn AzElToRaDec(thetaG: f64, lat: f64, lon: f64, az: f64, el: f64, ra: *mut f64, dec: *mut f64);
pub fn AzElToRaDecTime(ds50UTC: f64, lat: f64, lon: f64, az: f64, el: f64, ra: *mut f64, dec: *mut f64);
pub fn RAEToECI(
theta: f64,
astroLat: f64,
xa_rae: *const [f64; 6],
senPos: *const [f64; 3],
satPos: *mut [f64; 3],
satVel: *mut [f64; 3],
);
pub fn GetInitialDrag(semiMajorAxis: f64, eccen: f64, nDot: *mut f64, bstar: *mut f64);
pub fn CovMtxPTWToUVW(
pos: *const [f64; 3],
vel: *const [f64; 3],
ptwCovMtx: *const [[f64; 6]; 6],
uvwCovMtx: *mut [[f64; 6]; 6],
);
pub fn CovMtxUVWToPTW(
pos: *const [f64; 3],
vel: *const [f64; 3],
uvwCovMtx: *const [[f64; 6]; 6],
ptwCovMtx: *mut [[f64; 6]; 6],
);
pub fn EarthObstructionAngles(
earthLimb: f64,
satECI: *const [f64; 3],
senECI: *const [f64; 3],
earthSenLimb: *mut f64,
earthSenSat: *mut f64,
satEarthSen: *mut f64,
);
pub fn IsPointSunlit(ds50ET: f64, ptEci: *const [f64; 3]) -> i32;
pub fn RotRADecl(
nutationTerms: i32,
dir: i32,
ds50UTCIn: f64,
raIn: f64,
declIn: f64,
ds50UTCOut: f64,
raOut: *mut f64,
declOut: *mut f64,
);
pub fn RotRADec_DateToEqnx(
nutationTerms: i32,
yrOfEqnx: i32,
ds50UTCIn: f64,
raIn: f64,
declIn: f64,
raOut: *mut f64,
declOut: *mut f64,
) -> i32;
pub fn RotRADec_EqnxToDate(
nutationTerms: i32,
yrOfEqnx: i32,
ds50UTCIn: f64,
raIn: f64,
declIn: f64,
raOut: *mut f64,
declOut: *mut f64,
) -> i32;
pub fn CovMtxEqnxToUVW(
pos: *const [f64; 3],
vel: *const [f64; 3],
covMtxEqnx: *const [[f64; 6]; 6],
covMtxUVW: *mut [[f64; 6]; 6],
);
pub fn CovMtxUVWToEqnx(
pos: *const [f64; 3],
vel: *const [f64; 3],
covMtxUVW: *const [[f64; 6]; 6],
covMtxEqnx: *mut [[f64; 6]; 6],
);
pub fn CovMtxECIToUVW(
pos: *const [f64; 3],
vel: *const [f64; 3],
covMtxECI: *const [[f64; 6]; 6],
covMtxUVW: *mut [[f64; 6]; 6],
);
pub fn CovMtxUVWToECI(
pos: *const [f64; 3],
vel: *const [f64; 3],
covMtxUVW: *const [[f64; 6]; 6],
covMtxECI: *mut [[f64; 6]; 6],
);
pub fn CovMtxECIToEFG(thetaG: f64, covECI: *const [[f64; 6]; 6], covEFG: *mut [[f64; 6]; 6]);
pub fn CovMtxEFGToECI(thetaG: f64, covEFG: *const [[f64; 6]; 6], covECI: *mut [[f64; 6]; 6]);
pub fn Mtx6x6ToLTA21(symMtx6x6: *const [[f64; 6]; 6], lta21: *mut [f64; 21]);
pub fn LTA21ToMtx6x6(lta21: *const [f64; 21], symMtx6x6: *mut [[f64; 6]; 6]);
pub fn Mtx9x9ToLTA45(symMtx9x9: *const [[f64; 9]; 9], lta45: *mut [f64; 45]);
pub fn LTA45ToMtx9x9(lta45: *const [f64; 45], symMtx9x9: *mut [[f64; 9]; 9]);
pub fn PropCovFrState(
rms: f64,
consider: f64,
stateArray: *const [f64; 54],
cov: *const [[f64; 9]; 9],
propCov: *mut [[f64; 6]; 6],
);
pub fn CovMtxECIToEqnx(
pos: *const [f64; 3],
vel: *const [f64; 3],
covMtxECI: *const [[f64; 9]; 9],
covMtxEqnx: *mut [[f64; 9]; 9],
);
pub fn CovMtxEqnxToECI9x9(
pos: *const [f64; 3],
vel: *const [f64; 3],
covEqnx: *const [[f64; 9]; 9],
covMtxECI: *mut [[f64; 9]; 9],
);
pub fn CovMtxEqnxToUVW9x9(
pos: *const [f64; 3],
vel: *const [f64; 3],
covEqnx: *const [[f64; 9]; 9],
covMtxUVW: *mut [[f64; 9]; 9],
);
pub fn CovMtxUpdate(
rmsIn: f64,
consider: f64,
cov: *const [[f64; 9]; 9],
stateArray: *const [f64; 54],
propCov: *mut [[f64; 6]; 6],
);
pub fn AberrationAnnual(ra: f64, decl: f64, dS50UTC: f64, raDelta: *mut f64, decDelta: *mut f64);
pub fn AberrationDiurnal(
ra: f64,
decl: f64,
dS50UTC: f64,
senPos: *const [f64; 3],
raDelta: *mut f64,
decDelta: *mut f64,
);
pub fn JplSetParameters(jplFile: *const c_char, ds50Start: f64, ds50Stop: f64);
pub fn JplGetParameters(jplFile: *const c_char, ds50Start: *mut f64, ds50Stop: *mut f64);
pub fn JplReset();
pub fn JplCompSunMoonVec(
ds50UTC: f64,
uvecSun: *mut [f64; 3],
sunVecMag: *mut f64,
uvecMoon: *mut [f64; 3],
moonVecMag: *mut f64,
);
pub fn JplCompSunMoonPos(ds50UTC: f64, sunVec: *mut [f64; 3], moonVec: *mut [f64; 3]);
pub fn RemoveJpl();
pub fn TemeEpochToDate(
nutationTerms: i32,
epochDs50TAI: f64,
dateDs50TAI: f64,
posEpoch: *const [f64; 3],
velEpoch: *const [f64; 3],
posDate: *mut [f64; 3],
velDate: *mut [f64; 3],
);
}
pub const XA_KEP_A: usize = 0;
pub const XA_KEP_E: usize = 1;
pub const XA_KEP_INCLI: usize = 2;
pub const XA_KEP_MA: usize = 3;
pub const XA_KEP_NODE: usize = 4;
pub const XA_KEP_OMEGA: usize = 5;
pub static XA_KEP_SIZE: usize = 6;
pub static XA_CLS_N: usize = 0;
pub static XA_CLS_E: usize = 1;
pub static XA_CLS_INCLI: usize = 2;
pub static XA_CLS_MA: usize = 3;
pub static XA_CLS_NODE: usize = 4;
pub static XA_CLS_OMEGA: usize = 5;
pub static XA_CLS_SIZE: usize = 6;
pub const XA_EQNX_AF: usize = 0;
pub const XA_EQNX_AG: usize = 1;
pub const XA_EQNX_CHI: usize = 2;
pub const XA_EQNX_PSI: usize = 3;
pub const XA_EQNX_L: usize = 4;
pub const XA_EQNX_N: usize = 5;
pub const XA_EQNX_SIZE: usize = 6;
pub static XF_CONV_SGP42SGP: i32 = 101;
pub static XA_TOPO_RA: usize = 0;
pub static XA_TOPO_DEC: usize = 1;
pub static XA_TOPO_AZ: usize = 2;
pub static XA_TOPO_EL: usize = 3;
pub static XA_TOPO_RANGE: usize = 4;
pub static XA_TOPO_RADOT: usize = 5;
pub static XA_TOPO_DECDOT: usize = 6;
pub static XA_TOPO_AZDOT: usize = 7;
pub static XA_TOPO_ELDOT: usize = 8;
pub static XA_TOPO_RANGEDOT: usize = 9;
pub static XA_TOPO_SIZE: usize = 10;
pub static XA_RAE_RANGE: usize = 0;
pub static XA_RAE_AZ: usize = 1;
pub static XA_RAE_EL: usize = 2;
pub static XA_RAE_RANGEDOT: usize = 3;
pub static XA_RAE_AZDOT: usize = 4;
pub static XA_RAE_ELDOT: usize = 5;
pub static XA_RAE_SIZE: usize = 6;
pub static YROFEQNX_OBTIME: isize = 0;
pub static YROFEQNX_CURR: isize = 1;
pub static YROFEQNX_2000: isize = 2;
pub static YROFEQNX_1950: isize = 3;
pub fn get_dll_info() -> String {
let mut info = GetSetString::new();
unsafe {
AstroFuncGetInfo(info.pointer());
}
info.value()
}
pub fn sma_to_mean_motion(semi_major_axis: f64) -> f64 {
unsafe { AToN(semi_major_axis) }
}
pub fn keplerian_to_cartesian(xa_kep: &[f64; XA_KEP_SIZE]) -> [f64; 6] {
let mut pos = [0.0; 3];
let mut vel = [0.0; 3];
unsafe {
KepToPosVel(xa_kep, &mut pos, &mut vel);
}
[pos[0], pos[1], pos[2], vel[0], vel[1], vel[2]]
}
pub fn cartesian_to_keplerian(posvel: &[f64; 6]) -> [f64; XA_KEP_SIZE] {
let mut xa_kep = [0.0; XA_KEP_SIZE];
let pos = [posvel[0], posvel[1], posvel[2]];
let vel = [posvel[3], posvel[4], posvel[5]];
unsafe {
PosVelToKep(&pos, &vel, &mut xa_kep);
}
xa_kep
}
pub fn set_jpl_ephemeris_file_path(file_path: &str) {
let mut jpl_path: GetSetString = file_path.into();
let ds50_start = time::year_doy_to_ds50(1960, 1.0);
let ds50_stop = time::year_doy_to_ds50(2050, 1.0);
unsafe {
JplSetParameters(jpl_path.pointer(), ds50_start, ds50_stop);
}
}
pub fn j2000_to_teme(ds50_utc: f64, j2000_posvel: &[f64; 6]) -> [f64; 6] {
let mut pos_teme = [0.0; 3];
let mut vel_teme = [0.0; 3];
let pos_j2000 = [j2000_posvel[0], j2000_posvel[1], j2000_posvel[2]];
let vel_j2000 = [j2000_posvel[3], j2000_posvel[4], j2000_posvel[5]];
let ds50_tai = time::utc_to_tai(ds50_utc);
unsafe {
RotJ2KToDate(0, 106, ds50_tai, &pos_j2000, &vel_j2000, &mut pos_teme, &mut vel_teme);
}
[
pos_teme[0],
pos_teme[1],
pos_teme[2],
vel_teme[0],
vel_teme[1],
vel_teme[2],
]
}
pub fn j2000_to_efg(ds50_utc: f64, j2000_posvel: &[f64; 6]) -> [f64; 6] {
teme_to_efg(ds50_utc, &j2000_to_teme(ds50_utc, j2000_posvel))
}
pub fn j2000_to_ecr(ds50_utc: f64, j2000_posvel: &[f64; 6]) -> [f64; 6] {
teme_to_ecr(ds50_utc, &j2000_to_teme(ds50_utc, j2000_posvel))
}
pub fn teme_to_j2000(ds50_utc: f64, teme_posvel: &[f64; 6]) -> [f64; 6] {
let mut pos_j2000 = [0.0; 3];
let mut vel_j2000 = [0.0; 3];
let ds50_tai = time::utc_to_tai(ds50_utc);
let pos = [teme_posvel[0], teme_posvel[1], teme_posvel[2]];
let vel = [teme_posvel[3], teme_posvel[4], teme_posvel[5]];
unsafe {
RotDateToJ2K(0, 106, ds50_tai, &pos, &vel, &mut pos_j2000, &mut vel_j2000);
}
[
pos_j2000[0],
pos_j2000[1],
pos_j2000[2],
vel_j2000[0],
vel_j2000[1],
vel_j2000[2],
]
}
pub fn teme_to_efg(ds50_utc: f64, teme_posvel: &[f64; 6]) -> [f64; 6] {
let mut pos_efg = [0.0; 3];
let mut vel_efg = [0.0; 3];
let pos = [teme_posvel[0], teme_posvel[1], teme_posvel[2]];
let vel = [teme_posvel[3], teme_posvel[4], teme_posvel[5]];
unsafe {
ECIToEFGTime(ds50_utc, &pos, &vel, &mut pos_efg, &mut vel_efg);
}
[pos_efg[0], pos_efg[1], pos_efg[2], vel_efg[0], vel_efg[1], vel_efg[2]]
}
pub fn efg_to_ecr(ds50_utc: f64, efg_posvel: &[f64; 6]) -> [f64; 6] {
let mut pos_ecr = [0.0; 3];
let mut vel_ecr = [0.0; 3];
let pos_efg = [efg_posvel[0], efg_posvel[1], efg_posvel[2]];
let vel_efg = [efg_posvel[3], efg_posvel[4], efg_posvel[5]];
unsafe {
EFGToECRTime(ds50_utc, &pos_efg, &vel_efg, &mut pos_ecr, &mut vel_ecr);
}
[pos_ecr[0], pos_ecr[1], pos_ecr[2], vel_ecr[0], vel_ecr[1], vel_ecr[2]]
}
pub fn teme_to_ecr(ds50_utc: f64, teme_posvel: &[f64; 6]) -> [f64; 6] {
efg_to_ecr(ds50_utc, &teme_to_efg(ds50_utc, teme_posvel))
}
pub fn ecr_to_efg(ds50_utc: f64, ecr_posvel: &[f64; 6]) -> [f64; 6] {
let mut pos_efg = [0.0; 3];
let mut vel_efg = [0.0; 3];
let pos_ecr = [ecr_posvel[0], ecr_posvel[1], ecr_posvel[2]];
let vel_ecr = [ecr_posvel[3], ecr_posvel[4], ecr_posvel[5]];
unsafe {
ECRToEFGTime(ds50_utc, &pos_ecr, &vel_ecr, &mut pos_efg, &mut vel_efg);
}
[pos_efg[0], pos_efg[1], pos_efg[2], vel_efg[0], vel_efg[1], vel_efg[2]]
}
pub fn efg_to_teme(ds50_utc: f64, efg_posvel: &[f64; 6]) -> [f64; 6] {
let mut pos_teme = [0.0; 3];
let mut vel_teme = [0.0; 3];
let pos_efg = [efg_posvel[0], efg_posvel[1], efg_posvel[2]];
let vel_efg = [efg_posvel[3], efg_posvel[4], efg_posvel[5]];
unsafe {
EFGToECITime(ds50_utc, &pos_efg, &vel_efg, &mut pos_teme, &mut vel_teme);
}
[
pos_teme[0],
pos_teme[1],
pos_teme[2],
vel_teme[0],
vel_teme[1],
vel_teme[2],
]
}
pub fn ecr_to_teme(ds50_utc: f64, ecr_posvel: &[f64; 6]) -> [f64; 6] {
efg_to_teme(ds50_utc, &ecr_to_efg(ds50_utc, ecr_posvel))
}
pub fn ecr_to_j2000(ds50_utc: f64, ecr_posvel: &[f64; 6]) -> [f64; 6] {
teme_to_j2000(ds50_utc, &ecr_to_teme(ds50_utc, ecr_posvel))
}
pub fn efg_to_j2000(ds50_utc: f64, efg_posvel: &[f64; 6]) -> [f64; 6] {
teme_to_j2000(ds50_utc, &efg_to_teme(ds50_utc, efg_posvel))
}
pub fn kozai_to_brouwer(eccentricity: f64, inclination: f64, mean_motion: f64) -> f64 {
unsafe { KozaiToBrouwer(eccentricity, inclination, mean_motion) }
}
pub fn brouwer_to_kozai(eccentricity: f64, inclination: f64, mean_motion: f64) -> f64 {
unsafe { BrouwerToKozai(eccentricity, inclination, mean_motion) }
}
pub fn mean_motion_to_sma(mean_motion: f64) -> f64 {
unsafe { NToA(mean_motion) }
}
pub fn lla_to_teme(ds50_utc: f64, pos_lla: &[f64; 3]) -> [f64; 3] {
let mut pos_teme = [0.0; 3];
unsafe {
LLHToXYZTime(ds50_utc, pos_lla, &mut pos_teme);
}
pos_teme
}
pub fn topo_meme_to_teme(yr_of_equinox: i32, ds50_utc: f64, ra: f64, dec: f64) -> (f64, f64) {
let mut ra_out = 0.0;
let mut dec_out = 0.0;
unsafe {
RotRADec_EqnxToDate(106, yr_of_equinox, ds50_utc, ra, dec, &mut ra_out, &mut dec_out);
}
(ra_out, dec_out)
}
pub fn topo_teme_to_meme(yr_of_equinox: i32, ds50_utc: f64, ra: f64, dec: f64) -> (f64, f64) {
let mut ra_out = 0.0;
let mut dec_out = 0.0;
unsafe {
RotRADec_DateToEqnx(106, yr_of_equinox, ds50_utc, ra, dec, &mut ra_out, &mut dec_out);
}
(ra_out, dec_out)
}
pub fn osculating_to_mean(xa_osc: &[f64; XA_KEP_SIZE]) -> [f64; XA_KEP_SIZE] {
let mut xa_mean = [0.0; XA_KEP_SIZE];
unsafe {
KepOscToMean(xa_osc, &mut xa_mean);
}
xa_mean
}
pub fn equinoctial_to_keplerian(xa_eqnx: &[f64; XA_EQNX_SIZE]) -> [f64; XA_KEP_SIZE] {
let mut xa_kep = [0.0; XA_KEP_SIZE];
unsafe {
EqnxToKep(xa_eqnx, &mut xa_kep);
}
xa_kep
}
pub fn keplerian_to_equinoctial(xa_kep: &[f64; XA_KEP_SIZE]) -> [f64; XA_EQNX_SIZE] {
let mut xa_eqnx = [0.0; XA_EQNX_SIZE];
unsafe {
KepToEqnx(xa_kep, &mut xa_eqnx);
}
xa_eqnx
}
pub fn covariance_equinoctial_to_uvw(teme_posvel: &[f64; 6], cov_eqnx: &[[f64; 6]; 6]) -> [[f64; 6]; 6] {
let mut cov_uvw = [[0.0; 6]; 6];
let pos = [teme_posvel[0], teme_posvel[1], teme_posvel[2]];
let vel = [teme_posvel[3], teme_posvel[4], teme_posvel[5]];
unsafe {
CovMtxEqnxToUVW(&pos, &vel, cov_eqnx, &mut cov_uvw);
}
cov_uvw
}
pub fn covariance_uvw_to_teme(teme_posvel: &[f64; 6], cov_uvw: &[[f64; 6]; 6]) -> [[f64; 6]; 6] {
let mut cov_teme = [[0.0; 6]; 6];
let pos = [teme_posvel[0], teme_posvel[1], teme_posvel[2]];
let vel = [teme_posvel[3], teme_posvel[4], teme_posvel[5]];
unsafe {
CovMtxUVWToECI(&pos, &vel, cov_uvw, &mut cov_teme);
}
cov_teme
}
pub fn gst_ra_dec_to_az_el(gst: f64, lla: &[f64; 3], ra: f64, dec: f64) -> [f64; 2] {
let mut az = 0.0;
let mut el = 0.0;
unsafe {
RaDecToAzEl(gst, lla[0], lla[1], ra, dec, &mut az, &mut el);
}
[az, el]
}
pub fn time_ra_dec_to_az_el(ds50_utc: f64, lla: &[f64; 3], ra: f64, dec: f64) -> [f64; 2] {
let mut az = 0.0;
let mut el = 0.0;
unsafe {
RaDecToAzElTime(ds50_utc, lla[0], lla[1], ra, dec, &mut az, &mut el);
}
[az, el]
}
pub fn horizon_to_teme(
lst: f64,
lat: f64,
sensor_teme: &[f64; 3],
xa_rae: &[f64; XA_RAE_SIZE],
) -> Result<[f64; 6], String> {
let mut teme_pos = [0.0; 3];
let mut teme_vel = [0.0; 3];
unsafe {
RAEToECI(lst, lat, xa_rae, sensor_teme, &mut teme_pos, &mut teme_vel);
}
if teme_pos.iter().all(|&x| x == 0.0) && teme_vel.iter().all(|&x| x == 0.0) {
Err(get_last_error_message())
} else {
Ok([
teme_pos[0],
teme_pos[1],
teme_pos[2],
teme_vel[0],
teme_vel[1],
teme_vel[2],
])
}
}
pub fn gst_teme_to_lla(gst: f64, teme_pos: &[f64; 3]) -> [f64; 3] {
let mut pos_lla = [0.0; 3];
unsafe {
XYZToLLH(gst, teme_pos, &mut pos_lla);
}
pos_lla
}
pub fn time_teme_to_lla(ds50_utc: f64, teme_pos: &[f64; 3]) -> [f64; 3] {
let mut pos_lla = [0.0; 3];
unsafe {
XYZToLLHTime(ds50_utc, teme_pos, &mut pos_lla);
}
pos_lla
}
pub fn efg_to_lla(efg_pos: &[f64; 3]) -> Result<[f64; 3], String> {
let mut pos_lla = [0.0; 3];
if efg_pos.iter().all(|&x| x == 0.0) {
return Err("Input EFG position is zero vector.".to_string());
}
unsafe {
EFGPosToLLH(efg_pos, &mut pos_lla);
}
if pos_lla.iter().all(|&x| x == 0.0) {
Err(get_last_error_message())
} else {
Ok(pos_lla)
}
}
pub fn teme_to_topo(
lst: f64,
lat: f64,
sen_teme_pos: &[f64; 3],
sat_teme_posvel: &[f64; 6],
) -> Result<[f64; XA_TOPO_SIZE], String> {
let mut xa_topo = [0.0; XA_TOPO_SIZE];
let sat_pos = [sat_teme_posvel[0], sat_teme_posvel[1], sat_teme_posvel[2]];
let sat_vel = [sat_teme_posvel[3], sat_teme_posvel[4], sat_teme_posvel[5]];
unsafe {
ECIToTopoComps(lst, lat, sen_teme_pos, &sat_pos, &sat_vel, &mut xa_topo);
}
if xa_topo.iter().all(|&x| x == 0.0) {
Err(get_last_error_message())
} else {
Ok(xa_topo)
}
}
pub fn get_jpl_sun_and_moon_position(ds50utc: f64) -> ([f64; 3], [f64; 3]) {
let mut sun_pos = [0.0; 3];
let mut moon_pos = [0.0; 3];
unsafe {
JplCompSunMoonPos(ds50utc, &mut sun_pos, &mut moon_pos);
}
(sun_pos, moon_pos)
}
pub fn point_is_sunlit(ds50_tt: f64, teme_pos: &[f64; 3]) -> bool {
unsafe { IsPointSunlit(ds50_tt, teme_pos) == 1 }
}
pub fn get_earth_obstruction_angles(sat_teme_pos: &[f64; 3], sensor_teme_pos: &[f64; 3]) -> (f64, f64, f64) {
let mut earth_sensor_limb = 0.0;
let mut earth_sensor_sat = 0.0;
let mut sat_earth_sensor = 0.0;
unsafe {
EarthObstructionAngles(
environment::get_earth_radius(),
sat_teme_pos,
sensor_teme_pos,
&mut earth_sensor_limb,
&mut earth_sensor_sat,
&mut sat_earth_sensor,
);
}
(earth_sensor_limb, earth_sensor_sat, sat_earth_sensor)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::environment::{XF_GEOMOD_WGS72, XF_GEOMOD_WGS84};
use crate::test_lock::TEST_LOCK;
use crate::{DLL_VERSION, environment};
use approx::assert_abs_diff_eq;
#[test]
fn test_get_dll_info_contains_version() {
let _lock = TEST_LOCK.lock().unwrap();
let info = get_dll_info();
assert!(info.contains(DLL_VERSION));
}
#[test]
fn test_keplerian_to_equinoctial() {
let _lock = TEST_LOCK.lock().unwrap();
let kep = [26558.482, 0.006257, 54.935, 234.764, 165.472, 217.612];
let eqnx = keplerian_to_equinoctial(&kep);
assert_abs_diff_eq!(eqnx[0], 0.005756008409, epsilon = 1.0e-12);
assert_abs_diff_eq!(eqnx[1], 0.002453246053, epsilon = 1.0e-12);
assert_abs_diff_eq!(eqnx[2], 0.130405060328, epsilon = 1.0e-12);
assert_abs_diff_eq!(eqnx[3], -0.503224317374, epsilon = 1.0e-12);
assert_abs_diff_eq!(eqnx[4], 617.8480000000, epsilon = 1.0e-12);
assert_abs_diff_eq!(eqnx[5], 2.005848298418, epsilon = 1.0e-12);
}
#[test]
fn test_equinoctial_to_keplerian() {
let _lock = TEST_LOCK.lock().unwrap();
let eqnx = [
0.005756008409,
0.002453246053,
0.130405060328,
-0.503224317374,
617.8480000,
2.005848298418,
];
let kep = equinoctial_to_keplerian(&eqnx);
assert_abs_diff_eq!(kep[0], 26558.4820, epsilon = 1.0e-4);
assert_abs_diff_eq!(kep[1], 0.0062570000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[2], 54.9350000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[3], 234.7640000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[4], 165.4720000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[5], 217.6120000, epsilon = 1.0e-7);
}
#[test]
fn test_keplerian_to_cartesian() {
let _lock = TEST_LOCK.lock().unwrap();
let kep = [26558.482, 0.006257, 54.935, 234.764, 165.472, 217.612];
let posvel = keplerian_to_cartesian(&kep);
assert_abs_diff_eq!(posvel[0], -3032.21272487, epsilon = 1.0e-7);
assert_abs_diff_eq!(posvel[1], -15025.7763831, epsilon = 1.0e-7);
assert_abs_diff_eq!(posvel[2], 21806.4954366, epsilon = 1.0e-7);
assert_abs_diff_eq!(posvel[3], 3.754350020203, epsilon = 1.0e-7);
assert_abs_diff_eq!(posvel[4], -0.889562019024, epsilon = 1.0e-7);
assert_abs_diff_eq!(posvel[5], -0.114933710268, epsilon = 1.0e-7);
}
#[test]
fn test_cartesian_to_keplerian() {
let _lock = TEST_LOCK.lock().unwrap();
let posvel = [
-3032.21272487,
-15025.7763831,
21806.4954366,
3.7543500202,
-0.889562019026,
-0.114933710268,
];
let kep = cartesian_to_keplerian(&posvel);
assert_abs_diff_eq!(kep[0], 26558.4820, epsilon = 1.0e-4);
assert_abs_diff_eq!(kep[1], 0.0062570000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[2], 54.9350000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[3], 234.7640000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[4], 165.4720000, epsilon = 1.0e-7);
assert_abs_diff_eq!(kep[5], 217.6120000, epsilon = 1.0e-7);
}
#[test]
fn test_mean_motion_conversions() {
let _lock = TEST_LOCK.lock().unwrap();
let mean_motion = 1.0027382962;
let semi_major_axis = mean_motion_to_sma(mean_motion);
assert_abs_diff_eq!(semi_major_axis, 42164.171420, epsilon = 1.0e-6);
let mean_motion_back = sma_to_mean_motion(42164.17142);
assert_abs_diff_eq!(mean_motion_back, mean_motion, epsilon = 1.0e-7);
}
#[test]
fn test_kozai_brouwer_conversions() {
let _lock = TEST_LOCK.lock().unwrap();
let kozai = 14.2024103100000;
let brouwer = 14.2107268431215;
let ecc = 1.1127E-002;
let inc = 99.4371000000000;
let to_brouwer = kozai_to_brouwer(ecc, inc, kozai);
assert_abs_diff_eq!(to_brouwer, brouwer, epsilon = 1.0e-7);
let to_kozai = brouwer_to_kozai(ecc, inc, brouwer);
assert_abs_diff_eq!(to_kozai, kozai, epsilon = 1.0e-7);
}
#[test]
fn test_osculating_to_mean() {
let _lock = TEST_LOCK.lock().unwrap();
let osc = [7200.0, 0.006257, 54.935, 234.764, 165.472, 217.612];
let mean = osculating_to_mean(&osc);
assert_abs_diff_eq!(mean[0], 7206.06814087, epsilon = 1.0e-7);
assert_abs_diff_eq!(mean[1], 0.00646986051778, epsilon = 1.0e-7);
assert_abs_diff_eq!(mean[2], 54.9518948032, epsilon = 1.0e-7);
assert_abs_diff_eq!(mean[3], 232.98566416, epsilon = 1.0e-7);
assert_abs_diff_eq!(mean[4], 165.473342418, epsilon = 1.0e-7);
assert_abs_diff_eq!(mean[5], 219.392452222, epsilon = 1.0e-7);
}
#[test]
fn test_gst_teme_to_lla() {
let _lock = TEST_LOCK.lock().unwrap();
environment::set_geopotential_model(XF_GEOMOD_WGS84);
let xyz = [6524.834, 6862.875, 6448.296];
let llh = gst_teme_to_lla(0.0, &xyz);
environment::set_geopotential_model(XF_GEOMOD_WGS72);
assert_abs_diff_eq!(llh[0], 34.352495, epsilon = 1.0e-5);
assert_abs_diff_eq!(llh[1], 46.446417, epsilon = 1.0e-5);
assert_abs_diff_eq!(llh[2], 5085.218731, epsilon = 1.0e-5);
}
#[test]
fn test_efg_to_lla() {
let _lock = TEST_LOCK.lock().unwrap();
environment::set_geopotential_model(XF_GEOMOD_WGS84);
let efg = [6524.834, 6862.875, 6448.296];
let llh = efg_to_lla(&efg).unwrap();
environment::set_geopotential_model(XF_GEOMOD_WGS72);
assert_abs_diff_eq!(llh[0], 34.352495, epsilon = 1.0e-5);
assert_abs_diff_eq!(llh[1], 46.446417, epsilon = 1.0e-5);
assert_abs_diff_eq!(llh[2], 5085.218731, epsilon = 1.0e-5);
}
}