Example #1
0
def test_atmospheric_drag():
    # http://farside.ph.utexas.edu/teaching/celestial/Celestialhtml/node94.html#sair (10.148)
    # given the expression for \dot{r} / r, aproximate \Delta r \approx F_r * \Delta t

    R = Earth.R.to(u.km).value
    k = Earth.k.to(u.km**3 / u.s**2).value

    # parameters of a circular orbit with h = 250 km (any value would do, but not too small)
    orbit = Orbit.circular(Earth, 250 * u.km)
    r0, _ = orbit.rv()
    r0 = r0.to(u.km).value

    # parameters of a body
    C_D = 2.2  # dimentionless (any value would do)
    A = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value  # km^2
    m = 100  # kg
    B = C_D * A / m

    # parameters of the atmosphere
    rho0 = Earth.rho0.to(u.kg / u.km**3).value  # kg/km^3
    H0 = Earth.H0.to(u.km).value
    tof = 100000  # s

    dr_expected = -B * rho0 * np.exp(-(norm(r0) - R) / H0) * np.sqrt(k * norm(r0)) * tof
    # assuming the atmospheric decay during tof is small,
    # dr_expected = F_r * tof (Newton's integration formula), where
    # F_r = -B rho(r) |r|^2 sqrt(k / |r|^3) = -B rho(r) sqrt(k |r|)

    r, v = cowell(orbit, tof, ad=atmospheric_drag, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0)

    assert_quantity_allclose(norm(r) - norm(r0), dr_expected, rtol=1e-2)
Example #2
0
def test_cowell_propagation_circle_to_circle():
    # From [Edelbaum, 1961]
    accel = 1e-7

    def constant_accel(t0, u, k):
        v = u[3:]
        norm_v = (v[0]**2 + v[1]**2 + v[2]**2)**.5
        return accel * v / norm_v

    ss = Orbit.circular(Earth, 500 * u.km)
    tof = 20 * ss.period

    r0, v0 = ss.rv()
    k = ss.attractor.k

    r, v = cowell(k.to(u.km**3 / u.s**2).value,
                  r0.to(u.km).value,
                  v0.to(u.km / u.s).value,
                  tof.to(u.s).value,
                  ad=constant_accel)

    ss_final = Orbit.from_vectors(Earth,
                       r * u.km,
                       v * u.km / u.s)

    da_a0 = (ss_final.a - ss.a) / ss.a
    dv_v0 = abs(norm(ss_final.v) - norm(ss.v)) / norm(ss.v)
    assert_almost_equal(da_a0.value, 2 * dv_v0.value, decimal=4)

    dv = abs(norm(ss_final.v) - norm(ss.v))
    accel_dt = accel * u.km / u.s**2 * tof
    assert_almost_equal(dv.value, accel_dt.value, decimal=4)
Example #3
0
def test_cowell_propagation_circle_to_circle():
    # From [Edelbaum, 1961]
    accel = 1e-7

    def constant_accel(t0, u, k):
        v = u[3:]
        norm_v = (v[0]**2 + v[1]**2 + v[2]**2)**.5
        return accel * v / norm_v

    ss = Orbit.circular(Earth, 500 * u.km)
    tof = 20 * ss.period

    r, v = cowell(ss,
                  tof.to(u.s).value,
                  ad=constant_accel)

    ss_final = Orbit.from_vectors(
        Earth, r * u.km, v * u.km / u.s)

    da_a0 = (ss_final.a - ss.a) / ss.a
    dv_v0 = abs(norm(ss_final.v) - norm(ss.v)) / norm(ss.v)
    assert_quantity_allclose(da_a0, 2 * dv_v0, rtol=1e-2)

    dv = abs(norm(ss_final.v) - norm(ss.v))
    accel_dt = accel * u.km / u.s**2 * tof
    assert_quantity_allclose(dv, accel_dt, rtol=1e-2)
Example #4
0
def test_leo_geo_numerical(inc_0):
    edelbaum_accel = guidance_law(k, a_0, a_f, inc_0, inc_f, f)

    _, t_f = extra_quantities(k, a_0, a_f, inc_0, inc_f, f)

    # Retrieve r and v from initial orbit
    s0 = Orbit.circular(Earth, a_0 * u.km - Earth.R, inc_0 * u.rad)
    r0, v0 = s0.rv()

    # Propagate orbit
    r, v = cowell(k,
                  r0.to(u.km).value,
                  v0.to(u.km / u.s).value,
                  t_f,
                  ad=edelbaum_accel,
                  nsteps=1000000)

    sf = Orbit.from_vectors(Earth,
                            r * u.km,
                            v * u.km / u.s,
                            s0.epoch + t_f * u.s)

    assert_allclose(sf.a.to(u.km).value, a_f, rtol=1e-5)
    assert_allclose(sf.ecc.value, 0.0, atol=1e-2)
    assert_allclose(sf.inc.to(u.rad).value, inc_f, atol=1e-3)
Example #5
0
def test_pqw_for_circular_equatorial_orbit():
    ss = Orbit.circular(Earth, 600 * u.km)
    expected_p = [1, 0, 0] * u.one
    expected_q = [0, 1, 0] * u.one
    expected_w = [0, 0, 1] * u.one
    p, q, w = ss.pqw()
    assert_allclose(p, expected_p)
    assert_allclose(q, expected_q)
    assert_allclose(w, expected_w)
Example #6
0
def test_sample_custom_body_raises_warning_and_returns_coords():
    # See https://github.com/poliastro/poliastro/issues/649
    orbit = Orbit.circular(Moon, 100 * u.km)

    with pytest.warns(
        UserWarning, match="returning only cartesian coordinates instead"
    ):
        coords = orbit.sample(10)

    assert isinstance(coords, CartesianRepresentation)
    assert len(coords) == 10
Example #7
0
def test_hohmann_maneuver():
    # Data from Vallado, example 6.1
    alt_i = 191.34411 * u.km
    alt_f = 35781.34857 * u.km
    ss_i = Orbit.circular(Earth, alt_i)
    expected_dv = 3.935224 * u.km / u.s
    expected_t_trans = 5.256713 * u.h

    man = Maneuver.hohmann(ss_i, Earth.R + alt_f)

    assert_quantity_allclose(ss_i.apply_maneuver(man).ecc, 0 * u.one, atol=1e-14 * u.one)
    assert_quantity_allclose(man.get_total_cost(), expected_dv, rtol=1e-5)
    assert_quantity_allclose(man.get_total_time(), expected_t_trans, rtol=1e-5)
Example #8
0
def test_bielliptic_maneuver():
    # Data from Vallado, example 6.2
    alt_i = 191.34411 * u.km
    alt_b = 503873.0 * u.km
    alt_f = 376310.0 * u.km
    ss_i = Orbit.circular(Earth, alt_i)
    expected_dv = 3.904057 * u.km / u.s
    expected_t_trans = 593.919803 * u.h

    man = Maneuver.bielliptic(ss_i, Earth.R + alt_b, Earth.R + alt_f)

    assert_allclose(ss_i.apply_maneuver(man).ecc, 0 * u.one, atol=1e-12 * u.one)
    assert_quantity_allclose(man.get_total_cost(), expected_dv, rtol=1e-5)
    assert_quantity_allclose(man.get_total_time(), expected_t_trans, rtol=1e-6)
Example #9
0
def test_hohmann_maneuver():
    # Data from Vallado, example 6.1
    alt_i = 191.34411 * u.km
    alt_f = 35781.34857 * u.km
    ss_i = Orbit.circular(Earth, alt_i)
    expected_dv = 3.935224 * u.km / u.s
    expected_t_trans = 5.256713 * u.h
    man = Maneuver.hohmann(ss_i, Earth.R + alt_f)
    assert_almost_equal(ss_i.apply_maneuver(man).ecc, 0)
    assert_almost_equal(man.get_total_cost().to(u.km / u.s).value,
                        expected_dv.value,
                        decimal=5)
    assert_almost_equal(man.get_total_time().to(u.h).value,
                        expected_t_trans.value,
                        decimal=5)
Example #10
0
def test_bielliptic_maneuver():
    # Data from Vallado, example 6.2
    alt_i = 191.34411 * u.km
    alt_b = 503873.0 * u.km
    alt_f = 376310.0 * u.km
    ss_i = Orbit.circular(Earth, alt_i)
    expected_dv = 3.904057 * u.km / u.s
    expected_t_trans = 593.919803 * u.h
    man = Maneuver.bielliptic(ss_i, Earth.R + alt_b, Earth.R + alt_f)
    assert_almost_equal(ss_i.apply_maneuver(man).ecc, 0)
    assert_almost_equal(man.get_total_cost().to(u.km / u.s).value,
                        expected_dv.value,
                        decimal=5)
    assert_almost_equal(man.get_total_time().to(u.h).value,
                        expected_t_trans.value,
                        decimal=2)
Example #11
0
def test_leo_geo_numerical(inc_0):
    f = 3.5e-7  # km / s2

    a_0 = 7000.0  # km
    a_f = 42166.0  # km
    inc_f = 0.0  # rad

    k = Earth.k.to(u.km**3 / u.s**2).value

    a_d, _, t_f = change_a_inc(k, a_0, a_f, inc_0, inc_f, f)

    # Retrieve r and v from initial orbit
    s0 = Orbit.circular(Earth, a_0 * u.km - Earth.R, inc_0 * u.rad)

    # Propagate orbit
    sf = s0.propagate(t_f * u.s, method=cowell, ad=a_d, rtol=1e-6)

    assert_allclose(sf.a.to(u.km).value, a_f, rtol=1e-3)
    assert_allclose(sf.ecc.value, 0.0, atol=1e-2)
    assert_allclose(sf.inc.to(u.rad).value, inc_f, atol=2e-3)
Example #12
0
def test_geosync_has_proper_period():
    expected_period = 1436  # min
    ss = Orbit.circular(Earth, alt=42164 * u.km - Earth.R)
    assert_almost_equal(ss.period.to(u.min).value, expected_period, decimal=0)
Example #13
0
import numpy as np
import matplotlib.pyplot as plt
plt.ion()  # To immediately show plots
from astropy import units as u
from poliastro.bodies import Earth, Mars, Sun
from poliastro.twobody import Orbit
plt.style.use("seaborn")  # Recommended
h = 625*u.km
r_circ = Earth.R + h
circ = Orbit.circular(Earth,h)
T_circ = circ.state.period
N = 9
delay = T_circ/N
T_ph = T_circ + delay
a_ph = np.power(T_ph/2/np.pi * np.sqrt(Earth.k),(2/3))
rp=Earth.R + h
ra = 2*a_ph - rp
e_ph = (ra-rp)/(ra+rp)
phasing = Orbit.from_classical(Earth,a_ph,e_ph,0*u.deg,0*u.deg,0*u.deg,0*u.deg)
from poliastro.plotting import OrbitPlotter
op = OrbitPlotter()
op.plot(circ, label="Final circular orbit")
op.plot(phasing, label="Phasing orbit")
    B = x * A_over_m  #Min kommentar: Skrev in x istället för C_D
    # parameters of the atmosphere
    rho0 = rho0_earth.to(u.kg / u.km**3).value  # kg/km^3
    H0 = H0_earth.to(
        u.km
    ).value  #Min kommentar: Ändras atmosfärens egenskaper ju högre radien är i det här programmet?

    #[<matplotlib.lines.Line2D at 0x7ffb5f511048>]

    #Orbital Decay
    #If atmospheric drag causes the orbit to fully decay, additional code is needed to stop the integration when the satellite reaches the surface.

    #Please note that you will likely want to use a more sophisticated atmosphere model than the one in atmospheric_drag for these sorts of computations.

    orbit = Orbit.circular(
        Earth, 230 * u.km, epoch=Time(0.0, format="jd", scale="tdb")
    )  #Min kommentar: Här tror jag att jag kan ändra på värdet hos radien på omloppsbanan
    tofs = TimeDelta(
        np.linspace(0 * u.h, 100 * u.d, num=200)
    )  #Min kommentar: Här tror jag deltatiden beskrivs, att den mäter mellan noll timmar till ett max antal dagar, samt att den mäter 2000 gånger.

    from poliastro.twobody.events import LithobrakeEvent
    lithobrake_event = LithobrakeEvent(R)
    events = [lithobrake_event]

    rr = propagate(
        orbit,
        tofs,
        method=cowell,
        ad=atmospheric_drag_exponential,
        R=R,
Example #15
0
import plotly.io as pio

pio.renderers.default = "notebook_connected"

R = Earth.R.to(u.km).value
k = Earth.k.to(u.km**3 / u.s**2).value

C_D = 2.2
A_over_m = (((4 * np.pi * 0.0144) / 4.0) * (u.m**2) / (48 * u.kg)).to_value(
    u.km**2 / u.kg)
B = C_D * A_over_m
#rho0 = rho0_earth.to(u.kg / u.km ** 3).value
#H0 = H0_earth.to(u.km).value

orbit = Orbit.circular(Earth,
                       200 * u.km,
                       epoch=Time(0.0, format="jd", scale="tdb"))
tofs = TimeDelta(np.linspace(0 * u.h, 100000000 * u.d, num=200))

from poliastro.twobody.events import LithobrakeEvent

lithobrake_event = LithobrakeEvent(R)
events = [lithobrake_event]

coesa76 = COESA76()

rr, _ = cowell(
    Earth.k,
    orbit.r,
    orbit.v,
    tofs,
Example #16
0
# In[2]:

import plotly.io as pio
pio.renderers.default = "notebook_connected"

# ### Atmospheric drag ###
# The poliastro package now has several commonly used natural perturbations. One of them is atmospheric drag! See how one can monitor decay of the near-Earth orbit over time using our new module poliastro.twobody.perturbations!

# In[3]:

R = Earth.R.to(u.km).value
k = Earth.k.to(u.km**3 / u.s**2).value

orbit = Orbit.circular(Earth,
                       250 * u.km,
                       epoch=Time(0.0, format="jd", scale="tdb"))

# parameters of a body
C_D = 2.2  # dimentionless (any value would do)
A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value(u.km**2 /
                                                              u.kg)  # km^2/kg
B = C_D * A_over_m

# parameters of the atmosphere
rho0 = rho0_earth.to(u.kg / u.km**3).value  # kg/km^3
H0 = H0_earth.to(u.km).value

tofs = TimeDelta(np.linspace(0 * u.h, 100000 * u.s, num=2000))

rr = propagate(
Example #17
0
def test_circular_has_proper_semimajor_axis():
    alt = 500 * u.km
    attractor = Earth
    expected_a = Earth.R + alt
    ss = Orbit.circular(attractor, alt)
    assert ss.a == expected_a
Example #18
0
def test_orbit_representation():
    ss = Orbit.circular(Earth, 600 * u.km, 20 * u.deg)
    expected_str = "6978 x 6978 km x 20.0 deg orbit around Earth (\u2641)"

    assert str(ss) == repr(ss) == expected_str
Example #19
0
def test_geosync_has_proper_period():
    expected_period = 1436 * u.min

    ss = Orbit.circular(Earth, alt=42164 * u.km - Earth.R)

    assert_quantity_allclose(ss.period, expected_period, rtol=1e-4)
Example #20
0
def test_circular_has_proper_semimajor_axis():
    alt = 500 * u.km
    attractor = Earth
    expected_a = Earth.R + alt
    ss = Orbit.circular(attractor, alt)
    assert ss.a == expected_a
Example #21
0
                   iss_f_kep.argp,
                   rtol=rtol,
                   atol=1e-08 * u.rad)
assert np.allclose(iss_f_num.nu, iss_f_kep.nu, rtol=rtol, atol=1e-08 * u.rad)

# ## Numerical validation
#
# According to [Edelbaum, 1961], a coplanar, semimajor axis change with tangent thrust is defined by:
#
# $$\frac{\operatorname{d}\!a}{a_0} = 2 \frac{F}{m V_0}\operatorname{d}\!t, \qquad \frac{\Delta{V}}{V_0} = \frac{1}{2} \frac{\Delta{a}}{a_0}$$
#
# So let's create a new circular orbit and perform the necessary checks, assuming constant mass and thrust (i.e. constant acceleration):

# In[18]:

ss = Orbit.circular(Earth, 500 * u.km)
tof = 20 * ss.period

ad = constant_accel_factory(1e-7)

r, v = cowell(ss.attractor.k, ss.r, ss.v, [tof] * u.s, ad=ad)

ss_final = Orbit.from_vectors(Earth, r[0], v[0], ss.epoch + tof)

# In[19]:

da_a0 = (ss_final.a - ss.a) / ss.a
da_a0

# In[20]:
def test_atmospheric_demise():
    # Test an orbital decay that hits Earth. No analytic solution.
    R = Earth.R.to(u.km).value

    orbit = Orbit.circular(Earth, 230 * u.km)
    t_decay = 48.2179 * u.d  # not an analytic value

    # Parameters of a body
    C_D = 2.2  # dimentionless (any value would do)
    A_over_m = ((np.pi / 4.0) * (u.m**2) / (100 * u.kg)).to_value(
        u.km**2 / u.kg)  # km^2/kg

    # Parameters of the atmosphere
    rho0 = rho0_earth.to(u.kg / u.km**3).value  # kg/km^3
    H0 = H0_earth.to(u.km).value  # km

    tofs = [365] * u.d  # Actually hits the ground a bit after day 48

    lithobrake_event = LithobrakeEvent(R)
    events = [lithobrake_event]

    def f(t0, u_, k):
        du_kep = func_twobody(t0, u_, k)
        ax, ay, az = atmospheric_drag_exponential(t0,
                                                  u_,
                                                  k,
                                                  R=R,
                                                  C_D=C_D,
                                                  A_over_m=A_over_m,
                                                  H0=H0,
                                                  rho0=rho0)
        du_ad = np.array([0, 0, 0, ax, ay, az])
        return du_kep + du_ad

    rr, _ = cowell(
        Earth.k,
        orbit.r,
        orbit.v,
        tofs,
        events=events,
        f=f,
    )

    assert_quantity_allclose(norm(rr[0].to(u.km).value), R,
                             atol=1)  # Below 1km

    assert_quantity_allclose(lithobrake_event.last_t, t_decay, rtol=1e-2)

    # Make sure having the event not firing is ok
    tofs = [1] * u.d
    lithobrake_event = LithobrakeEvent(R)
    events = [lithobrake_event]

    rr, _ = cowell(
        Earth.k,
        orbit.r,
        orbit.v,
        tofs,
        events=events,
        f=f,
    )

    assert lithobrake_event.last_t == tofs[-1]
Example #23
0
def test_propagation_custom_body_works():
    # See https://github.com/poliastro/poliastro/issues/649
    orbit = Orbit.circular(Moon, 100 * u.km)
    orbit.propagate(1 * u.h)
Example #24
0
def start_date_optimal(H, date0, date1, m, Isp, step):

    delta_v = 0 * u.km / u.s
    v_out = 0 * u.km / u.s
    m_prop = 0 * u.kg
    date_in = date0
    date_out = date0

    step_one0 = True
    x1 = []
    x2 = []
    x3 = []
    x4 = []
    while date0 < date1:
        epoch0 = date0.jyear
        ss0 = Orbit.circular(Earth, H, epoch=epoch0)
        vsE = ss0.rv()[1]

        dvEV, date_arrivalV, vsV = transit_opt1.transit_optimal(
            date0, transit_minEV, transit_maxEV, Earth, Venus, vsE, step)

        dvVJ, date_arrivalJ, vsJ = transit_opt1.transit_optimal(
            date_arrivalV, transit_minVJ, transit_maxVJ, Venus, Jupiter, vsV,
            step)

        dvJU, date_arrivalU, vsU = transit_opt1.transit_optimal(
            date_arrivalJ, transit_minJU, transit_maxJU, Jupiter, Uranus, vsJ,
            step)

        #koszty paliwa:
        m_pJU = m * (math.exp((dvJU) / Isp) - 1)
        m_pVJ = (m + m_pJU) * (math.exp((dvVJ) / Isp) - 1)
        m_pEV = (m + m_pJU + m_pVJ) * (math.exp((dvEV) / Isp) - 1)

        dv_total = (dvEV) + (dvVJ) + (dvJU)
        m_p = m_pEV + m_pVJ + m_pJU

        x1.append(date0.iso[0:10])
        x2.append(int((date_arrivalU - date0).jd))
        x3.append(float(dv_total / u.km * u.s))
        x4.append(int(m_p / u.kg))
        print(
            date0.iso[0:10], ', %i days, %.3f km/s, %i kg' % (int(
                (date_arrivalU - date0).jd), float(
                    dv_total / u.km * u.s), int(m_p / u.kg)))

        if step_one0:
            delta_v = dv_total
            m_prop = m_p
            v_out = vsU
            date_out = date_arrivalU

            step_one0 = False
        else:
            if dv_total < delta_v:
                delta_v = dv_total
                m_prop = m_p
                v_out = vsU
                date_in = date0
                date_out = date_arrivalU

        date0 += step * u.day

    lista = {'1': x1, '2': x2, '3': x3, '4': x4}
    #lista = pd.DataFrame(lista)

    return delta_v, v_out, date_in, date_out, m_prop, lista
Example #25
0
def test_geosync_has_proper_period():
    expected_period = 1436 * u.min

    ss = Orbit.circular(Earth, alt=42164 * u.km - Earth.R)

    assert_quantity_allclose(ss.period, expected_period, rtol=1e-4)
Example #26
0
def test_propagation_custom_body_works():
    # See https://github.com/poliastro/poliastro/issues/649
    orbit = Orbit.circular(Moon, 100 * u.km)
    orbit.propagate(1 * u.h)
Example #27
0
def test_orbit_representation():
    ss = Orbit.circular(Earth, 600 * u.km, 20 * u.deg, epoch=Time("2018-09-08 09:04:00", scale="tdb"))
    expected_str = "6978 x 6978 km x 20.0 deg (GCRS) orbit around Earth (\u2641) at epoch 2018-09-08 09:04:00.000 (TDB)"

    assert str(ss) == repr(ss) == expected_str
Example #28
0
from poliastro.ephem import build_ephem_interpolant
from poliastro.core.elements import rv2coe
from poliastro.atmosphere import COESA76

from poliastro.constants import rho0_earth, H0_earth
from poliastro.core.perturbations import atmospheric_drag_exponential, atmospheric_drag_model, third_body, J2_perturbation
from poliastro.bodies import Earth, Moon
from poliastro.twobody import Orbit
from poliastro.plotting import OrbitPlotter3D
import plotly.io as pio
pio.renderers.default = "notebook_connected"
from poliastro.twobody.events import LithobrakeEvent

R = Earth.R.to(u.km).value

orbit = Orbit.circular(Earth, 300 * u.km)
t_decay = 7.17 * u.d

# parameters of a body
C_D = 2.2  # dimentionless (any value would do)
#A_over_m = ((np.pi / 4.0) * (u.m ** 2) / (100 * u.kg)).to_value(
#u.km ** 2 / u.kg
#)  # km^2/kg
A_over_m = (((4 * np.pi * 0.0144) / 4.0) * (u.m**2) / (48 * u.kg)).to_value(
    u.km**2 / u.kg)

tofs = [365] * u.d

lithobrake_event = LithobrakeEvent(R)
events = [lithobrake_event]