use crate::mathtypes::*;
pub fn point_gravity(
r: &Vector3, s: &Vector3, mu: f64,
) -> Vector3 {
let sr = s - r;
let srnorm2 = sr.norm_squared();
let srnorm = srnorm2.sqrt();
let snorm2 = s.norm_squared();
let snorm = snorm2.sqrt();
mu * (sr / (srnorm * srnorm2) - s / (snorm * snorm2))
}
pub fn point_gravity_and_partials(
r: &Vector3, s: &Vector3, mu: f64,
) -> (Vector3, Matrix3) {
let rs = r - s;
let rsnorm2 = rs.norm_squared();
let rsnorm = rsnorm2.sqrt();
let snorm2 = s.norm_squared();
let snorm = snorm2.sqrt();
let rsnorm3 = rsnorm2 * rsnorm;
(
-mu * (rs / rsnorm3 + s / (snorm * snorm2)),
-mu * (Matrix3::eye() / rsnorm3
- 3.0 * rs * rs.transpose() / (rsnorm2 * rsnorm3)),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_point_gravity_known() {
let mu_moon = 4.9048695e12; let s_moon = numeris::vector![384_400.0e3, 0.0, 0.0]; let r_sat = numeris::vector![42_164.0e3, 0.0, 0.0];
let accel = point_gravity(&r_sat, &s_moon, mu_moon);
let mag = accel.norm();
assert!(
mag > 1.0e-7 && mag < 1.0e-4,
"Lunar perturbation at GEO = {:.3e}, expected ~1e-6",
mag
);
}
#[test]
fn test_point_gravity_partials() {
let mu = 4.9048695e12;
let s = numeris::vector![384_400.0e3, 50_000.0e3, 20_000.0e3];
let r = numeris::vector![42_164.0e3, 1000.0e3, 500.0e3];
let dr = numeris::vector![10.0, 20.0, -15.0];
let (accel0, partials) = point_gravity_and_partials(&r, &s, mu);
let accel1 = point_gravity(&(r + dr), &s, mu);
let predicted = accel0 + partials * dr;
let err = (accel1 - predicted).norm() / accel1.norm();
assert!(
err < 1.0e-6,
"Partial derivative error = {:.3e}, expected < 1e-6",
err
);
}
}