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 = State.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, constant_accel) ss_final = State.from_vectors(Earth, r * u.km, v * u.km / u.s, ss.epoch + tof) 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)
def test_perifocal_points_to_perigee(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle ss = State.from_classical(Sun, _d, _, _a, _a, _a, _a) p, _, _ = ss.pqw() assert_almost_equal(p, ss.e_vec / ss.ecc)
def test_parabolic_has_zero_energy(): attractor = Earth _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle ss = State.parabolic(attractor, _d, _a, _a, _a, _a) assert_almost_equal(ss.energy.value, 0.0)
def test_state_raises_unitserror_if_rv_units_are_wrong(): _d = [1.0, 0.0, 0.0] * u.AU wrong_v = [0.0, 1.0e-6, 0.0] * u.AU with pytest.raises(u.UnitsError) as excinfo: ss = State.from_vectors(Sun, _d, wrong_v) assert ("UnitsError: Units must be consistent" in excinfo.exconly())
def test_parabolic_has_infinite_semimajor_axis(): attractor = Earth _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle expected_a = np.inf * u.km ss = State.parabolic(attractor, _d, _a, _a, _a, _a) assert_equal(ss.a, expected_a)
def test_parabolic_has_proper_eccentricity(): attractor = Earth _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle expected_ecc = 1.0 * u.one ss = State.parabolic(attractor, _d, _a, _a, _a, _a) assert_almost_equal(ss.ecc, expected_ecc)
def test_default_time_for_new_state(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle _body = Sun # Unused body expected_epoch = time.Time("J2000", scale='utc') ss = State.from_classical(_body, _d, _, _a, _a, _a, _a) assert ss.epoch == expected_epoch
def test_apply_maneuver_changes_epoch(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle ss = State.from_classical(Sun, _d, _, _a, _a, _a, _a) dt = 1 * u.h dv = [0, 0, 0] * u.km / u.s ss_new = ss.apply_maneuver([(dt, dv)]) assert ss_new.epoch == ss.epoch + dt
def test_pqw_for_circular_equatorial_orbit(): ss = State.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_almost_equal(p, expected_p) assert_almost_equal(q, expected_q) assert_almost_equal(w, expected_w)
def test_state_raises_unitserror_if_elements_units_are_wrong(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle wrong_angle = 1.0 * u.AU with pytest.raises(u.UnitsError) as excinfo: ss = State.from_classical(Sun, _d, _, _a, _a, _a, wrong_angle) assert ("UnitsError: Units must be consistent" in excinfo.exconly())
def test_propagation_hyperbolic(): # Data from Curtis, example 3.5 r0 = [Earth.R.to(u.km).value + 300, 0, 0] * u.km v0 = [0, 15, 0] * u.km / u.s ss0 = State.from_vectors(Earth, r0, v0) tof = 14941 * u.s ss1 = ss0.propagate(tof) r, v = ss1.rv() assert_almost_equal(norm(r).to(u.km).value, 163180, decimal=-1) assert_almost_equal(norm(v).to(u.km/u.s).value, 10.51, decimal=2)
def test_state_has_elements_given_in_constructor(): # Mars data from HORIZONS at J2000 a = 1.523679 * u.AU ecc = 0.093315 * u.one p = a * (1 - ecc**2) inc = 1.85 * u.deg raan = 49.562 * u.deg argp = 286.537 * u.deg nu = 23.33 * u.deg ss = State.from_classical(Sun, p, ecc, inc, raan, argp, nu) assert ss.coe() == (p, ecc, inc, raan, argp, nu)
def test_perigee_and_apogee(): expected_r_a = 500 * u.km expected_r_p = 300 * u.km a = (expected_r_a + expected_r_p) / 2 ecc = expected_r_a / a - 1 p = a * (1 - ecc**2) _a = 1.0 * u.deg # Unused angle ss = State.from_classical(Earth, p, ecc, _a, _a, _a, _a) assert_almost_equal(ss.r_a.to(u.km).value, expected_r_a.to(u.km).value) assert_almost_equal(ss.r_p.to(u.km).value, expected_r_p.to(u.km).value)
def test_apply_zero_maneuver_returns_equal_state(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle ss = State.from_classical(Sun, _d, _, _a, _a, _a, _a) dt = 0 * u.s dv = [0, 0, 0] * u.km / u.s ss_new = ss.apply_maneuver([(dt, dv)]) assert_almost_equal(ss_new.r.to(u.km).value, ss.r.to(u.km).value) assert_almost_equal(ss_new.v.to(u.km / u.s).value, ss.v.to(u.km / u.s).value)
def test_propagation(): # Data from Vallado, example 2.4 r0 = [1131.340, -2282.343, 6672.423] * u.km v0 = [-5.64305, 4.30333, 2.42879] * u.km / u.s ss0 = State.from_vectors(Earth, r0, v0) tof = 40 * u.min ss1 = ss0.propagate(tof) r, v = ss1.rv() assert_array_almost_equal(r.value, [-4219.7527, 4363.0292, -3958.7666], decimal=1) assert_array_almost_equal(v.value, [3.689866, -1.916735, -6.112511], decimal=4)
def test_convert_from_coe_to_rv(): # Data from Vallado, example 2.5 attractor = Earth r = [6524.384, 6862.875, 6448.296] * u.km v = [4.901327, 5.533756, -1.976341] * u.km / u.s ss = State.from_vectors(Earth, r, v) p, ecc, inc, raan, argp, nu = ss.coe() assert_almost_equal(p.to(u.km).value, 11067.79, decimal=0) assert_almost_equal(ecc.value, 0.832853, decimal=4) assert_almost_equal(inc.to(u.deg).value, 87.870, decimal=2) assert_almost_equal(raan.to(u.deg).value, 227.89, decimal=1) assert_almost_equal(argp.to(u.deg).value, 53.38, decimal=2) assert_almost_equal(nu.to(u.deg).value, 92.335, decimal=2)
def test_propagation_zero_time_returns_same_state(): # Bug #50 r0 = [1131.340, -2282.343, 6672.423] * u.km v0 = [-5.64305, 4.30333, 2.42879] * u.km / u.s ss0 = State.from_vectors(Earth, r0, v0) tof = 0 * u.s ss1 = ss0.propagate(tof) r, v = ss1.rv() assert_array_almost_equal(r.value, r0.value) assert_array_almost_equal(v.value, v0.value)
def test_convert_from_rv_to_coe(): # Data from Vallado, example 2.6 attractor = Earth p = 11067.790 * u.km ecc = 0.83285 * u.one inc = 87.87 * u.deg raan = 227.89 * u.deg argp = 53.38 * u.deg nu = 92.335 * u.deg expected_r = [6525.344, 6861.535, 6449.125] # km expected_v = [4.902276, 5.533124, -1.975709] # km / s r, v = State.from_classical(Earth, p, ecc, inc, raan, argp, nu).rv() assert_array_almost_equal(r.value, expected_r, decimal=1) assert_array_almost_equal(v.value, expected_v, decimal=5)
def test_hohmann_maneuver(): # Data from Vallado, example 6.1 alt_i = 191.34411 * u.km alt_f = 35781.34857 * u.km ss_i = State.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)
def test_state_has_individual_elements(): a = 1.523679 * u.AU ecc = 0.093315 * u.one p = a * (1 - ecc**2) inc = 1.85 * u.deg raan = 49.562 * u.deg argp = 286.537 * u.deg nu = 23.33 * u.deg ss = State.from_classical(Sun, p, ecc, inc, raan, argp, nu) assert ss.a == a assert ss.ecc == ecc assert ss.inc == inc assert ss.raan == raan assert ss.argp == argp assert ss.nu == nu
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 = State.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)
# coding: utf-8 """Example data. """ from astropy import time from astropy import units as u from poliastro.bodies import Earth from poliastro.twobody import State # Taken from Plyades (c) 2012 Helge Eichhorn (MIT License) iss = State.from_vectors(Earth, [8.59072560e2, -4.13720368e3, 5.29556871e3] * u.km, [7.37289205, 2.08223573, 4.39999794e-1] * u.km / u.s, time.Time("2013-03-18 12:00", scale='utc')) molniya = State.from_classical(Earth, 26600 * u.km, 0.75 * u.one, 63.4 * u.deg, 0 * u.deg, 270 * u.deg, 80 * u.deg)
rr_earth, vv_earth = ephem.planet_ephem(ephem.EARTH, times_vector) rr_earth[:, 0] vv_earth[:, 0] rr_mars, vv_mars = ephem.planet_ephem(ephem.MARS, times_vector) rr_mars[:, 0] vv_mars[:, 0] # Compute the transfer orbit! r0 = rr_earth[:, 0] rf = rr_mars[:, -1] (va, vb), = iod.lambert(Sun.k, r0, rf, tof) ss0_trans = State.from_vectors(Sun, r0, va, date_launch) ssf_trans = State.from_vectors(Sun, rf, vb, date_arrival) # Extract whole orbit of Earth, Mars and transfer (for plotting) rr_trans = np.zeros_like(rr_earth) rr_trans[:, 0] = r0 for ii in range(1, len(jd_vec)): tof = (jd_vec[ii] - jd_vec[0]) * u.day rr_trans[:, ii] = ss0_trans.propagate(tof).r # Better compute backwards jd_init = (date_arrival - 1 * u.year).jd jd_vec_rest = np.linspace(jd_init, jd_launch, num=N) times_rest = time.Time(jd_vec_rest, format='jd') rr_earth_rest, _ = ephem.planet_ephem(ephem.EARTH, times_rest)
def test_geosync_has_proper_period(): expected_period = 1436 # min ss = State.circular(Earth, alt=42164 * u.km - Earth.R) assert_almost_equal(ss.period.to(u.min).value, expected_period, decimal=0)
def test_circular_has_proper_semimajor_axis(): alt = 500 * u.km attractor = Earth expected_a = Earth.R + alt ss = State.circular(attractor, alt) assert ss.a == expected_a
def test_state_has_rv_given_in_constructor(): r = [1.0, 0.0, 0.0] * u.AU v = [0.0, 1.0e-6, 0.0] * u.AU / u.s ss = State.from_vectors(Sun, r, v) assert ss.rv() == (r, v)
def create_states(attractor, rad_init, rad_final, unit): ssi = State.circular(attractor, alt=rad_init.value * unit) hoh = Maneuver.hohmann(ssi, r_f=rad_final.value * unit) ssa, ssf = ssi.apply_maneuver(hoh, intermediate=True) return ssi, ssa, ssf, hoh
def test_state_has_attractor_given_in_constructor(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle ss = State.from_classical(Sun, _d, _, _a, _a, _a, _a) assert ss.attractor == Sun