#![allow(non_snake_case)]
#![allow(dead_code)]
use crate::{
GetSetString, enums, get_last_error_message,
tle::{self, XA_TLE_AGOMGP},
};
use std::os::raw::c_char;
unsafe extern "C" {
pub fn Sgp4Init(apAddr: i64) -> i32;
pub fn Sgp4GetInfo(infoStr: *const c_char);
pub fn Sgp4LoadFileAll(sgp4InputFile: *const c_char) -> i32;
pub fn Sgp4SaveFile(sgp4File: *const c_char, saveMode: i32, saveForm: i32) -> i32;
pub fn Sgp4InitSat(satKey: i64) -> i32;
pub fn Sgp4RemoveSat(satKey: i64) -> i32;
pub fn Sgp4RemoveAllSats() -> i32;
pub fn Sgp4GetCount() -> i32;
pub fn Sgp4PropMse(
satKey: i64,
mse: f64,
ds50UTC: *mut f64,
pos: *mut [f64; 3],
vel: *mut [f64; 3],
llh: *mut [f64; 3],
) -> i32;
pub fn Sgp4PropDs50UTC(
satKey: i64,
ds50UTC: f64,
mse: *mut f64,
pos: *mut [f64; 3],
vel: *mut [f64; 3],
llh: *mut [f64; 3],
) -> i32;
pub fn Sgp4PropDs50UtcPosVel(satKey: i64, ds50UTC: f64, pos: *mut [f64; 3], vel: *mut [f64; 3]) -> i32;
pub fn Sgp4PropDs50UtcLLH(satKey: i64, ds50UTC: f64, llh: *mut [f64; 3]) -> i32;
pub fn Sgp4PropDs50UtcPos(satKey: i64, ds50UTC: f64, pos: *mut [f64; 3]) -> i32;
pub fn Sgp4GetPropOut(satKey: i64, xf_Sgp4Out: i32, destArr: *mut f64) -> i32;
pub fn Sgp4PropAll(satKey: i64, timeType: i32, timeIn: f64, xa_Sgp4Out: *mut [f64; 64]) -> i32;
pub fn Sgp4PosVelToKep(
yr: i32,
day: f64,
pos: *const [f64; 3],
vel: *const [f64; 3],
posNew: *mut [f64; 3],
velNew: *mut [f64; 3],
xa_kep: *mut [f64; 6],
) -> i32;
pub fn Sgp4PosVelToTleArr(pos: *const [f64; 3], vel: *const [f64; 3], xa_tle: *mut [f64; 64]) -> i32;
pub fn Sgp4ReepochTLE(satKey: i64, reEpochDs50UTC: f64, line1Out: *const c_char, line2Out: *const c_char) -> i32;
pub fn Sgp4ReepochCsv(satKey: i64, reEpochDs50UTC: f64, csvLine: *const c_char) -> i32;
pub fn Sgp4SetLicFilePath(licFilePath: *const c_char);
pub fn Sgp4GetLicFilePath(licFilePath: *const c_char);
pub fn Sgp4GenEphems(
satKey: i64,
startTime: f64,
endTime: f64,
stepSize: f64,
sgp4_ephem: i32,
arrSize: i32,
ephemArr: *mut f64,
genEphemPts: *mut i32,
) -> i32;
pub fn Sgp4GenEphems_OS(
xa_tle: *const [f64; 64],
startTime: f64,
endTime: f64,
stepSize: f64,
sgp4_ephem: i32,
arrSize: i32,
ephemArr: *mut f64,
genEphemPts: *mut i32,
) -> i32;
pub fn Sgp4PropAllSats(satKeys: *const i64, numOfSats: i32, ds50UTC: f64, ephemArr: *mut f64) -> i32;
pub fn XpGetNativeElts(satKey: i64, ds50UTC: f64, xa_eqnx: *mut [f64; 6], xa_eqnx_dot: *mut [f64; 6]) -> i32;
pub fn XpReepochGetNativeElts(
satKey: i64,
reEpochDs50UTC: f64,
csvLine: *const c_char,
xa_eqnx: *mut [f64; 6],
xa_eqnx_dot: *mut [f64; 6],
) -> i32;
}
pub static GP_ERR_NONE: i32 = 0;
pub static GP_ERR_BADFK: i32 = 1;
pub static GP_ERR_ANEGATIVE: i32 = 2;
pub static GP_ERR_ATOOLARGE: i32 = 3;
pub static GP_ERR_EHYPERPOLIC: i32 = 4;
pub static GP_ERR_ENEGATIVE: i32 = 5;
pub static GP_ERR_MATOOLARGE: i32 = 6;
pub static GP_ERR_E2TOOLARGE: i32 = 7;
pub static SGP4_TIMETYPE_MSE: i32 = 0;
pub static SGP4_TIMETYPE_DS50UTC: i32 = 1;
pub static XF_SGP4OUT_REVNUM: i32 = 1;
pub static XF_SGP4OUT_NODAL_AP_PER: i32 = 2;
pub static XF_SGP4OUT_MEAN_KEP: i32 = 3;
pub static XF_SGP4OUT_OSC_KEP: i32 = 4;
pub const XA_SGP4OUT_DS50UTC: usize = 0;
pub const XA_SGP4OUT_MSE: usize = 1;
pub const XA_SGP4OUT_POSX: usize = 2;
pub const XA_SGP4OUT_POSY: usize = 3;
pub const XA_SGP4OUT_POSZ: usize = 4;
pub const XA_SGP4OUT_VELX: usize = 5;
pub const XA_SGP4OUT_VELY: usize = 6;
pub const XA_SGP4OUT_VELZ: usize = 7;
pub const XA_SGP4OUT_LAT: usize = 8;
pub const XA_SGP4OUT_LON: usize = 9;
pub const XA_SGP4OUT_HEIGHT: usize = 10;
pub const XA_SGP4OUT_REVNUM: usize = 11;
pub const XA_SGP4OUT_NODALPER: usize = 12;
pub const XA_SGP4OUT_APOGEE: usize = 13;
pub const XA_SGP4OUT_PERIGEE: usize = 14;
pub const XA_SGP4OUT_MN_A: usize = 15;
pub const XA_SGP4OUT_MN_E: usize = 16;
pub const XA_SGP4OUT_MN_INCLI: usize = 17;
pub const XA_SGP4OUT_MN_MA: usize = 18;
pub const XA_SGP4OUT_MN_NODE: usize = 19;
pub const XA_SGP4OUT_MN_OMEGA: usize = 20;
pub const XA_SGP4OUT_OSC_A: usize = 21;
pub const XA_SGP4OUT_OSC_E: usize = 22;
pub const XA_SGP4OUT_OSC_INCLI: usize = 23;
pub const XA_SGP4OUT_OSC_MA: usize = 24;
pub const XA_SGP4OUT_OSC_NODE: usize = 25;
pub const XA_SGP4OUT_OSC_OMEGA: usize = 26;
pub const XA_SGP4OUT_SIZE: usize = 64;
pub const SGP4_EPHEM_ECI: isize = 1;
pub const SGP4_EPHEM_J2K: isize = 2;
pub static DYN_SS_BASIC: i32 = -1;
pub fn get_ephemeris(
sat_key: i64,
start: f64,
stop: f64,
step: f64,
frame: enums::SGP4OutputEphemerisFrame,
) -> Result<Vec<f64>, String> {
let step_days = step / (24.0 * 60.0);
let num_steps = (((stop - start) / step_days).ceil()) as i32 + 1;
let array_size = num_steps * 7;
let mut ephem_arr = vec![0.0; (array_size) as usize];
let mut gen_ephem_pts = 0;
let result = unsafe {
Sgp4GenEphems(
sat_key,
start,
stop,
step,
frame as i32,
array_size,
ephem_arr.as_mut_ptr(),
&mut gen_ephem_pts,
)
};
match result {
0 => {
ephem_arr.truncate((gen_ephem_pts as usize) * 7);
Ok(ephem_arr)
}
_ => Err(get_last_error_message()),
}
}
pub fn array_to_ephemeris(
xa_tle: &[f64; tle::XA_TLE_SIZE],
start: f64,
stop: f64,
step: f64,
frame: enums::SGP4OutputEphemerisFrame,
) -> Result<Vec<f64>, String> {
let step_days = step / (24.0 * 60.0);
let num_steps = (((stop - start) / step_days).ceil()) as i32 + 1;
let array_size = num_steps * 7;
let mut ephem_arr = vec![0.0; (array_size) as usize];
let mut gen_ephem_pts = 0;
let result = unsafe {
Sgp4GenEphems_OS(
xa_tle,
start,
stop,
step,
frame as i32,
array_size,
ephem_arr.as_mut_ptr(),
&mut gen_ephem_pts,
)
};
match result {
0 => {
ephem_arr.truncate((gen_ephem_pts as usize) * 7);
Ok(ephem_arr)
}
_ => Err(get_last_error_message()),
}
}
pub fn fit_xp_array(
epoch: f64,
posvel: &[f64; 6],
ballistic_coefficient: Option<f64>,
srp_coefficient: Option<f64>,
) -> Result<[f64; tle::XA_TLE_SIZE], String> {
let pos = [posvel[0], posvel[1], posvel[2]];
let vel = [posvel[3], posvel[4], posvel[5]];
let mut xa_tle = [0.0; tle::XA_TLE_SIZE];
xa_tle[tle::XA_TLE_EPOCH] = epoch;
xa_tle[tle::XA_TLE_EPHTYPE] = tle::TLETYPE_XP as f64;
xa_tle[XA_TLE_AGOMGP] = srp_coefficient.unwrap_or(0.0);
xa_tle[tle::XA_TLE_BTERM] = ballistic_coefficient.unwrap_or(0.0);
let result = unsafe { Sgp4PosVelToTleArr(&pos, &vel, &mut xa_tle) };
match result {
0 => Ok(xa_tle),
_ => Err(get_last_error_message()),
}
}
pub fn fit_sgp4_array(epoch: f64, posvel: &[f64; 6], b_star: Option<f64>) -> Result<[f64; tle::XA_TLE_SIZE], String> {
let pos = [posvel[0], posvel[1], posvel[2]];
let vel = [posvel[3], posvel[4], posvel[5]];
let mut xa_tle = [0.0; tle::XA_TLE_SIZE];
xa_tle[tle::XA_TLE_EPOCH] = epoch;
xa_tle[tle::XA_TLE_EPHTYPE] = tle::TLETYPE_SGP4 as f64;
xa_tle[tle::XA_TLE_BSTAR] = b_star.unwrap_or(0.0);
let result = unsafe { Sgp4PosVelToTleArr(&pos, &vel, &mut xa_tle) };
match result {
0 => Ok(xa_tle),
_ => Err(get_last_error_message()),
}
}
pub fn load(sat_key: i64) -> Result<(), String> {
let result = unsafe { Sgp4InitSat(sat_key) };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
pub fn get_positions_velocities(sat_keys: &[i64], ds50_utc: f64) -> Result<Vec<f64>, String> {
let num_of_sats = sat_keys.len() as i32;
let mut ephem_arr = vec![0.0; (num_of_sats * 6) as usize];
let result = unsafe { Sgp4PropAllSats(sat_keys.as_ptr(), num_of_sats, ds50_utc, ephem_arr.as_mut_ptr()) };
match result {
0 => Ok(ephem_arr),
_ => Err(get_last_error_message()),
}
}
pub fn remove(sat_key: i64) -> Result<(), String> {
let result = unsafe { Sgp4RemoveSat(sat_key) };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
pub fn clear() -> Result<(), String> {
let result = unsafe { Sgp4RemoveAllSats() };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
type MSEPosVelLLH = (f64, [f64; 3], [f64; 3], [f64; 3]);
pub fn get_position_velocity_lla(sat_key: i64, ds50_utc: f64) -> Result<MSEPosVelLLH, String> {
let mut mse = 0.0;
let mut pos = [0.0; 3];
let mut vel = [0.0; 3];
let mut llh = [0.0; 3];
let result = unsafe { Sgp4PropDs50UTC(sat_key, ds50_utc, &mut mse, &mut pos, &mut vel, &mut llh) };
match result {
0 => Ok((mse, pos, vel, llh)),
_ => Err(get_last_error_message()),
}
}
pub fn get_position_velocity(sat_key: i64, ds50_utc: f64) -> Result<([f64; 3], [f64; 3]), String> {
let mut pos = [0.0; 3];
let mut vel = [0.0; 3];
let result = unsafe { Sgp4PropDs50UtcPosVel(sat_key, ds50_utc, &mut pos, &mut vel) };
match result {
0 => Ok((pos, vel)),
_ => Err(get_last_error_message()),
}
}
pub fn get_lla(sat_key: i64, ds50_utc: f64) -> Result<[f64; 3], String> {
let mut llh = [0.0; 3];
let result = unsafe { Sgp4PropDs50UtcLLH(sat_key, ds50_utc, &mut llh) };
match result {
0 => Ok(llh),
_ => Err(get_last_error_message()),
}
}
pub fn get_position(sat_key: i64, ds50_utc: f64) -> Result<[f64; 3], String> {
let mut pos = [0.0; 3];
let result = unsafe { Sgp4PropDs50UtcPos(sat_key, ds50_utc, &mut pos) };
match result {
0 => Ok(pos),
_ => Err(get_last_error_message()),
}
}
pub fn get_full_state(sat_key: i64, ds50_utc: f64) -> Result<[f64; XA_SGP4OUT_SIZE], String> {
let mut all = [0.0; XA_SGP4OUT_SIZE];
let result = unsafe { Sgp4PropAll(sat_key, SGP4_TIMETYPE_DS50UTC, ds50_utc, &mut all) };
match result {
0 => Ok(all),
_ => Err(get_last_error_message()),
}
}
pub fn get_equinoctial(sat_key: i64, ds50_utc: f64) -> Result<[f64; 6], String> {
let mut xa_eqnx = [0.0; 6];
let mut xa_eqnx_dot = [0.0; 6];
let result = unsafe { XpGetNativeElts(sat_key, ds50_utc, &mut xa_eqnx, &mut xa_eqnx_dot) };
match result {
0 => Ok(xa_eqnx),
_ => Err(get_last_error_message()),
}
}
pub fn get_dll_info() -> String {
let mut info = GetSetString::new();
unsafe {
Sgp4GetInfo(info.pointer());
}
info.value()
}
pub fn get_count() -> i32 {
unsafe { Sgp4GetCount() }
}
pub fn set_license_directory(file_path: &str) {
let mut lic_file: GetSetString = file_path.into();
unsafe { Sgp4SetLicFilePath(lic_file.pointer()) };
}
pub fn get_license_directory() -> String {
let mut c_str = GetSetString::new();
unsafe { Sgp4GetLicFilePath(c_str.pointer()) };
c_str.value().trim().to_string()
}
pub fn reepoch_tle(sat_key: i64, re_epoch_ds50_utc: f64) -> Result<(String, String), String> {
let mut line1_out = GetSetString::new();
let mut line2_out = GetSetString::new();
let result = unsafe { Sgp4ReepochTLE(sat_key, re_epoch_ds50_utc, line1_out.pointer(), line2_out.pointer()) };
match result {
0 => Ok((
line1_out.value().trim().to_string(),
line2_out.value().trim().to_string(),
)),
_ => Err(get_last_error_message()),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_lock::TEST_LOCK;
use crate::{DLL_VERSION, tle};
use approx::assert_abs_diff_eq;
const SGP4_LINE_1: &str = "1 22222C 15058A 25363.54791667 +.00012345 10000-1 20000-1 2 0900";
const SGP4_LINE_2: &str = "2 22222 30.0000 40.0000 0005000 60.0000 70.0000 1.2345678012345";
const XP_LINE_1: &str = "1 33333U 15058A 25363.54791667 +.00012345 10000-1 20000-1 4 900";
const XP_LINE_2: &str = "2 33333 30.0000 40.0000 0005000 60.0000 70.0000 8.2345678012345";
const EPOCH: f64 = 27757.54791667;
const SGP4_LATITUDE: f64 = 22.536547343263198;
const SGP4_LONGITUDE: f64 = 238.66278387347936;
const SGP4_ALTITUDE: f64 = 30319.722365834336;
const XP_LATITUDE: f64 = 22.580834873791684;
const XP_LONGITUDE: f64 = 238.65305913125454;
const XP_ALTITUDE: f64 = 3977.969361992566;
const SGP4_X: f64 = -33722.20240953347;
const SGP4_Y: f64 = 3451.0939430966114;
const SGP4_Z: f64 = 14050.115953447255;
const SGP4_VX: f64 = -0.7534699464839536;
const SGP4_VY: f64 = -3.0289958981453213;
const SGP4_VZ: f64 = -1.0597673984106273;
const XP_X: f64 = -9515.23633738959;
const XP_Y: f64 = 975.4110099884765;
const XP_Z: f64 = 3961.4106652075125;
const XP_VX: f64 = -1.4191743539251394;
const XP_VY: f64 = -5.702875678562367;
const XP_VZ: f64 = -1.9961866743072767;
const SGP4_MEAN_MOTION: f64 = 1.2345678;
const SGP4_MEAN_INCLINATION: f64 = 30.0;
const SGP4_MEAN_ECCENTRICITY: f64 = 0.0005;
const SGP4_MEAN_RAAN: f64 = 40.0;
const SGP4_MEAN_SMA: f64 = 36705.009522294495;
const SGP4_MEAN_MA: f64 = 70.0;
const SGP4_PERIOD: f64 = 1166.3030603694838;
const SGP4_APOGEE: f64 = 36723.36202705564;
const SGP4_PERIGEE: f64 = 36686.65701753335;
const SGP4_MEAN_ARG_PERIGEE: f64 = 60.0;
const SGP4_OSC_SMA: f64 = 36704.93201233728;
const SGP4_OSC_ECCENTRICITY: f64 = 0.0006084790199714079;
const SGP4_OSC_INCLINATION: f64 = 30.006798162224296;
const SGP4_OSC_MA: f64 = 62.77053792235827;
const SGP4_OSC_RAAN: f64 = 40.02170181812538;
const SGP4_OSC_ARG_PERIGEE: f64 = 67.2046668254525;
const XP_MEAN_MOTION: f64 = 8.2345678;
const XP_MEAN_INCLINATION: f64 = 30.0;
const XP_MEAN_ECCENTRICITY: f64 = 0.0005;
const XP_MEAN_RAAN: f64 = 40.0;
const XP_MEAN_SMA: f64 = 2656.509522294495;
const XP_MEAN_MA: f64 = 70.0;
const XP_PERIOD: f64 = 174.3030603694838;
const XP_APOGEE: f64 = 2673.36202705564;
const XP_PERIGEE: f64 = 2639.65701753335;
const XP_MEAN_ARG_PERIGEE: f64 = 60.0;
const XP_OSC_SMA: f64 = 2656.93201233728;
const XP_OSC_ECCENTRICITY: f64 = 0.0006084790199714079;
const XP_OSC_INCLINATION: f64 = 30.006798162224296;
const XP_OSC_MA: f64 = 62.77053792235827;
const XP_OSC_RAAN: f64 = 40.02170181812538;
const XP_OSC_ARG_PERIGEE: f64 = 67.2046668254525;
#[test]
fn test_ephemeris_generation() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_key = tle::load_lines(SGP4_LINE_1, SGP4_LINE_2);
let xp_key = tle::load_lines(XP_LINE_1, XP_LINE_2);
let start = EPOCH - 1.0;
let stop = EPOCH;
let step = 5.0;
let frame = enums::SGP4OutputEphemerisFrame::TEME;
load(sgp4_key).unwrap();
load(xp_key).unwrap();
let sgp4_ephem_by_key = get_ephemeris(sgp4_key, start, stop, step, frame).unwrap();
let xp_ephem_by_key = get_ephemeris(xp_key, start, stop, step, frame).unwrap();
let (sgp4_xa, _) = tle::get_arrays(sgp4_key).unwrap();
let (xp_xa, _) = tle::get_arrays(xp_key).unwrap();
let sgp4_ephem = array_to_ephemeris(&sgp4_xa, start, stop, step, frame).unwrap();
let xp_ephem = array_to_ephemeris(&xp_xa, start, stop, step, frame).unwrap();
let _ = clear();
let _ = tle::clear();
assert_eq!(sgp4_ephem_by_key, sgp4_ephem);
assert_eq!(xp_ephem_by_key, xp_ephem);
assert_abs_diff_eq!(sgp4_ephem[sgp4_ephem.len() - 6], SGP4_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_ephem[sgp4_ephem.len() - 5], SGP4_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_ephem[sgp4_ephem.len() - 4], SGP4_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_ephem[sgp4_ephem.len() - 3], SGP4_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_ephem[sgp4_ephem.len() - 2], SGP4_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_ephem[sgp4_ephem.len() - 1], SGP4_VZ, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_ephem[xp_ephem.len() - 6], XP_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_ephem[xp_ephem.len() - 5], XP_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_ephem[xp_ephem.len() - 4], XP_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_ephem[xp_ephem.len() - 3], XP_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_ephem[xp_ephem.len() - 2], XP_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_ephem[xp_ephem.len() - 1], XP_VZ, epsilon = 1.0e-9);
assert_eq!(sgp4_ephem.len(), 2023);
assert_eq!(xp_ephem.len(), 2023);
}
#[test]
fn test_fit_arrays() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_posvel = [SGP4_X, SGP4_Y, SGP4_Z, SGP4_VX, SGP4_VY, SGP4_VZ];
let xp_posvel = [XP_X, XP_Y, XP_Z, XP_VX, XP_VY, XP_VZ];
let sgp4_xa = fit_sgp4_array(EPOCH, &sgp4_posvel, Some(0.02)).unwrap();
let xp_xa = fit_xp_array(EPOCH, &xp_posvel, Some(0.02), Some(0.01)).unwrap();
assert_abs_diff_eq!(sgp4_xa[tle::XA_TLE_INCLI], SGP4_MEAN_INCLINATION, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_xa[tle::XA_TLE_ECCEN], SGP4_MEAN_ECCENTRICITY, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_xa[tle::XA_TLE_NODE], SGP4_MEAN_RAAN, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_xa[tle::XA_TLE_MNANOM], SGP4_MEAN_MA, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_xa[tle::XA_TLE_MNMOTN], SGP4_MEAN_MOTION, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_xa[tle::XA_TLE_OMEGA], SGP4_MEAN_ARG_PERIGEE, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_xa[tle::XA_TLE_INCLI], XP_MEAN_INCLINATION, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_xa[tle::XA_TLE_ECCEN], XP_MEAN_ECCENTRICITY, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_xa[tle::XA_TLE_NODE], XP_MEAN_RAAN, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_xa[tle::XA_TLE_MNANOM], XP_MEAN_MA, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_xa[tle::XA_TLE_MNMOTN], XP_MEAN_MOTION, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_xa[tle::XA_TLE_OMEGA], XP_MEAN_ARG_PERIGEE, epsilon = 1.0e-9);
}
#[test]
fn test_prop_all_sats() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_key = tle::load_lines(SGP4_LINE_1, SGP4_LINE_2);
let xp_key = tle::load_lines(XP_LINE_1, XP_LINE_2);
load(sgp4_key).unwrap();
load(xp_key).unwrap();
let sat_keys = vec![sgp4_key, xp_key];
let ephem_arr = get_positions_velocities(&sat_keys, EPOCH).unwrap();
let _ = clear();
let _ = tle::clear();
assert_abs_diff_eq!(ephem_arr[0], SGP4_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[1], SGP4_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[2], SGP4_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[3], SGP4_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[4], SGP4_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[5], SGP4_VZ, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[6], XP_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[7], XP_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[8], XP_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[9], XP_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[10], XP_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(ephem_arr[11], XP_VZ, epsilon = 1.0e-9);
}
#[test]
fn test_get_all_at_ds50() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_key = tle::load_lines(SGP4_LINE_1, SGP4_LINE_2);
let xp_key = tle::load_lines(XP_LINE_1, XP_LINE_2);
load(sgp4_key).unwrap();
load(xp_key).unwrap();
let sgp4_all = get_full_state(sgp4_key, EPOCH).unwrap();
let xp_all = get_full_state(xp_key, EPOCH).unwrap();
let _ = clear();
let _ = tle::clear();
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_DS50UTC], EPOCH, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_MSE], 0.0, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_POSX], SGP4_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_POSY], SGP4_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_POSZ], SGP4_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_VELX], SGP4_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_VELY], SGP4_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_VELZ], SGP4_VZ, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_MN_INCLI], SGP4_MEAN_INCLINATION, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_MN_E], SGP4_MEAN_ECCENTRICITY, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_MN_A], SGP4_MEAN_SMA, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_NODALPER], SGP4_PERIOD, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_APOGEE], SGP4_APOGEE, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_PERIGEE], SGP4_PERIGEE, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_MN_MA], SGP4_MEAN_MA, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_MN_OMEGA], SGP4_MEAN_ARG_PERIGEE, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_MN_NODE], SGP4_MEAN_RAAN, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_OSC_A], SGP4_OSC_SMA, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_OSC_E], SGP4_OSC_ECCENTRICITY, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_OSC_INCLI], SGP4_OSC_INCLINATION, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_OSC_MA], SGP4_OSC_MA, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_OSC_NODE], SGP4_OSC_RAAN, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_all[XA_SGP4OUT_OSC_OMEGA], SGP4_OSC_ARG_PERIGEE, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_POSX], XP_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_POSY], XP_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_POSZ], XP_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_VELX], XP_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_VELY], XP_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_all[XA_SGP4OUT_VELZ], XP_VZ, epsilon = 1.0e-9);
}
#[test]
fn test_get_pos_at_ds50() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_key = tle::load_lines(SGP4_LINE_1, SGP4_LINE_2);
let xp_key = tle::load_lines(XP_LINE_1, XP_LINE_2);
load(sgp4_key).unwrap();
load(xp_key).unwrap();
let sgp4_pos = get_position(sgp4_key, EPOCH).unwrap();
let xp_pos = get_position(xp_key, EPOCH).unwrap();
let _ = clear();
let _ = tle::clear();
assert_abs_diff_eq!(sgp4_pos[0], SGP4_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_pos[1], SGP4_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_pos[2], SGP4_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_pos[0], XP_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_pos[1], XP_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_pos[2], XP_Z, epsilon = 1.0e-9);
}
#[test]
fn test_get_posvel_at_ds50() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_key = tle::load_lines(SGP4_LINE_1, SGP4_LINE_2);
let xp_key = tle::load_lines(XP_LINE_1, XP_LINE_2);
load(sgp4_key).unwrap();
load(xp_key).unwrap();
let (sgp4_pos, sgp4_vel) = get_position_velocity(sgp4_key, EPOCH).unwrap();
let (xp_pos, xp_vel) = get_position_velocity(xp_key, EPOCH).unwrap();
let _ = clear();
let _ = tle::clear();
assert_abs_diff_eq!(sgp4_pos[0], SGP4_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_pos[1], SGP4_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_pos[2], SGP4_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_vel[0], SGP4_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_vel[1], SGP4_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_vel[2], SGP4_VZ, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_pos[0], XP_X, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_pos[1], XP_Y, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_pos[2], XP_Z, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_vel[0], XP_VX, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_vel[1], XP_VY, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_vel[2], XP_VZ, epsilon = 1.0e-9);
}
#[test]
fn test_get_llh_at_ds50() {
let _lock = TEST_LOCK.lock().unwrap();
let sgp4_key = tle::load_lines(SGP4_LINE_1, SGP4_LINE_2);
let xp_key = tle::load_lines(XP_LINE_1, XP_LINE_2);
load(sgp4_key).unwrap();
load(xp_key).unwrap();
let sgp4_lla = get_lla(sgp4_key, EPOCH).unwrap();
let xp_lla = get_lla(xp_key, EPOCH).unwrap();
let _ = clear();
let _ = tle::clear();
assert_abs_diff_eq!(sgp4_lla[0], SGP4_LATITUDE, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_lla[1], SGP4_LONGITUDE, epsilon = 1.0e-9);
assert_abs_diff_eq!(sgp4_lla[2], SGP4_ALTITUDE, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_lla[0], XP_LATITUDE, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_lla[1], XP_LONGITUDE, epsilon = 1.0e-9);
assert_abs_diff_eq!(xp_lla[2], XP_ALTITUDE, epsilon = 1.0e-9);
}
#[test]
fn test_get_dll_info_contains_version() {
let _lock = TEST_LOCK.lock().unwrap();
let info = get_dll_info();
assert!(info.contains(DLL_VERSION));
}
}