Tutorial 06: Environmental Perturbations
This tutorial demonstrates how to model and simulate non-gravitational and third-body environmental perturbations in OpenGNC.
Theory Prerequisites
1. Atmospheric Drag
The drag acceleration opposes the spacecraft’s velocity relative to the rotating atmosphere:
\[
\mathbf{a}_{drag} = -\frac{1}{2} \rho v_{rel}^2 \frac{C_D A}{m} \hat{\mathbf{v}}_{rel}
\]
where \(\rho\) is local density, \(C_D\) is drag coefficient, \(A\) is area, and \(m\) is mass.
2. Solar Radiation Pressure (SRP)
The force exerted by solar photons. It pushes away from the Sun:
\[
\mathbf{a}_{srp} = - \nu P_{sun} C_R \frac{A}{m} \hat{\mathbf{u}}_{sun}
\]
where \(\nu\) is the shadow function (1 in sunlight, 0 in eclipse), \(P_{sun}\) is radiation pressure at distance, and \(C_R\) is reflectivity coefficient.
3. Third-Body Gravity
Gravitational pull from other celestial bodies (Sun, Moon):
\[
\mathbf{a}_{3B} = \sum \mu_k \left( \frac{\mathbf{s}_k - \mathbf{r}}{|\mathbf{s}_k - \mathbf{r}|^3} - \frac{\mathbf{s}_k}{|\mathbf{s}_k|^3} \right)
\]
import numpy as np
import matplotlib.pyplot as plt
from opengnc.disturbances.drag import LumpedDrag
from opengnc.environment.density import HarrisPriester
from opengnc.disturbances.srp import Canonball
from opengnc.disturbances.gravity import ThirdBodyGravity, TwoBodyGravity
from opengnc.propagators.cowell import CowellPropagator
print("Environment modules loaded.")
Environment modules loaded.
1. Atmospheric Drag & Density
Let’s evaluate the atmospheric density and resulting drag acceleration at different altitudes and compare them.
density_model = HarrisPriester()
drag_model = LumpedDrag(density_model)
# Spacecraft Properties
mass = 4.0 # 4 kg (3U CubeSat)
area = 0.03 # 0.03 m^2 cross section
cd = 2.2 # Drag coefficient
# State: 400km Altitude
r_400 = np.array([6778137.0, 0.0, 0.0])
v_400 = np.array([0.0, 7670.0, 0.0])
jd = 2451545.0
a_drag = drag_model.get_acceleration(r_400, v_400, jd, mass, area, cd)
print(f"Drag at 400km: Accordance Vector: {a_drag} m/s^2")
print(f"Magnitude: {np.linalg.norm(a_drag):.6e} m/s^2")
Drag at 400km: Accordance Vector: [-0.00000000e+00 -2.74518523e-06 -0.00000000e+00] m/s^2
Magnitude: 2.745185e-06 m/s^2
2. Solar Radiation Pressure (SRP)
Evaluating are drag acceleration vs SRP at equivalent conditions.
srp_model = Canonball()
cr = 1.3 # Reflectivity
a_srp = srp_model.get_acceleration(r_400, jd, mass, area, cr)
print(f"SRP Accel Vector: {a_srp} m/s^2")
print(f"Magnitude: {np.linalg.norm(a_srp):.6e} m/s^2")
print(f"\nRatio (Drag/SRP): {np.linalg.norm(a_drag)/np.linalg.norm(a_srp):.2f}x")
print("At 400km LEO, Atmospheric Drag dominates heavily. SRP becomes relevant at higher altitudes (MEO/GEO).")
SRP Accel Vector: [-8.00476320e-09 4.01254285e-08 1.73962601e-08] m/s^2
Magnitude: 4.446073e-08 m/s^2
Ratio (Drag/SRP): 61.74x
At 400km LEO, Atmospheric Drag dominates heavily. SRP becomes relevant at higher altitudes (MEO/GEO).
3. Third-Body Gravity
Lastly, let’s see the acceleration from the Moon and Sun.
third_body = ThirdBodyGravity()
a_3b = third_body.get_acceleration(r_400, jd)
print(f"Third-Body Accel Vector: {a_3b} m/s^2")
print(f"Magnitude: {np.linalg.norm(a_3b):.6e} m/s^2")
Third-Body Accel Vector: [5.58127159e-08 5.88545936e-07 1.51971346e-07] m/s^2
Magnitude: 6.104070e-07 m/s^2
4. Total Disturbance Propagation
We can aggregate these and feed into a propagator.
propagator = CowellPropagator()
# Combined Perturbations Function
def environmental_perturbations(t, r, v):
# Note: t is local inside integrator loop relative to integration start
curr_jd = jd + (t / 86400.0)
acc_drag = drag_model.get_acceleration(r, v, curr_jd, mass, area, cd)
acc_srp = srp_model.get_acceleration(r, curr_jd, mass, area, cr)
acc_3b = third_body.get_acceleration(r, curr_jd)
return acc_drag + acc_srp + acc_3b
# Propagate short window
r_f, v_f = propagator.propagate(r_400, v_400, 3600, perturbation_acc_fn=environmental_perturbations, dt_step=60)
print(f"\nPropagated position after 1 hour: {r_f} m")
Propagated position after 1 hour: [-4.06313714e+06 -5.43038765e+06 1.11069242e-01] m