def test_hohmann_maneuver(nu): # Data from Vallado, example 6.1 alt_i = 191.34411 * u.km alt_f = 35781.34857 * u.km _a = 0 * u.deg ss_i = Orbit.from_classical(Earth, Earth.R + alt_i, ecc=0 * u.one, inc=_a, raan=_a, argp=_a, nu=nu) # Expected output expected_dv = 3.935224 * u.km / u.s expected_t_pericenter = ss_i.time_to_anomaly(0 * u.deg) expected_t_trans = 5.256713 * u.h expected_total_time = expected_t_pericenter + expected_t_trans man = Maneuver.hohmann(ss_i, Earth.R + alt_f) assert_quantity_allclose(man.get_total_cost(), expected_dv, rtol=1e-5) assert_quantity_allclose(man.get_total_time(), expected_total_time, rtol=1e-5) assert_quantity_allclose(ss_i.apply_maneuver(man).ecc, 0 * u.one, atol=1e-14 * u.one)
def test_plot_maneuver(): # Data from Vallado, example 6.1 alt_i = 191.34411 * u.km alt_f = 35781.34857 * u.km _a = 0 * u.deg ss_i = Orbit.from_classical( attractor=Earth, a=Earth.R + alt_i, ecc=0 * u.one, inc=_a, raan=_a, argp=_a, nu=_a, ) # Create the maneuver man = Maneuver.hohmann(ss_i, Earth.R + alt_f) # Plot the maneuver fig, ax = plt.subplots() plotter = StaticOrbitPlotter(ax=ax) plotter.plot(ss_i, label="Initial orbit", color="blue") plotter.plot_maneuver(ss_i, man, label="Hohmann maneuver", color="red") return fig
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)
def test_repr_maneuver(): alt_f = 35781.34857 * u.km r = [-6045, -3490, 2500] * u.km v = [-3.457, 6.618, 2.533] * u.km / u.s alt_b = 503873.0 * u.km alt_fi = 376310.0 * u.km ss_i = Orbit.from_vectors(Earth, r, v) expected_hohmann_manuever = "Number of impulses: 2, Total cost: 3.060548 km / s" expected_bielliptic_maneuver = "Number of impulses: 3, Total cost: 3.122556 km / s" assert repr(Maneuver.hohmann(ss_i, Earth.R + alt_f)) == expected_hohmann_manuever assert (repr(Maneuver.bielliptic(ss_i, Earth.R + alt_b, Earth.R + alt_fi)) == expected_bielliptic_maneuver)
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)
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)
def maneuver_phasing_form_orbit(part_of_period, orbit, plot=False, intermediate=True): period = (orbit.period).value time_maneuver = part_of_period * period semi_major_axis_maneuver = semi_major_axis_from_period(time_maneuver) delta_v = linear_velocity((orbit.a).value, (orbit.a).value) - \ linear_velocity((orbit.a).value, semi_major_axis_maneuver) a_ph = semi_major_axis_maneuver ss_i = orbit hoh = Maneuver.hohmann(ss_i, a_ph * u.km) ss_a, ss_f = ss_i.apply_maneuver(hoh, intermediate=intermediate) if plot: fig, ax = plt.subplots() # (figsize=(4, 4)) plotter = StaticOrbitPlotter(ax) plotter.plot(ss_i, label="Initial orbit", color="red") plotter.plot(ss_a, label="Phasing orbit", color="blue") plt.savefig("figures/ManeuverPhasing, t_man=" + str(part_of_period) + ".png") return 2 * delta_v, period * part_of_period, ss_a, ss_f
earth = Orbit.from_body_ephem(Earth) #plot(earth) earth_30d = earth.propagate(30 * u.day) #plot(earth_30d) from poliastro.maneuver import Maneuver dv = [5, 0, 0] * u.m / u.s man = Maneuver.impulse(dv) man = Maneuver((0 * u.s, dv)) ss_i = Orbit.circular(Earth, alt=700 * u.km) ss_i #plot(ss_i) hoh = Maneuver.hohmann(ss_i, 36000 * u.km) hoh.get_total_cost() hoh.get_total_time() print(hoh.get_total_cost()) print(hoh.get_total_time()) hoh.impulses[0] hoh[0] tuple(val.decompose([u.km, u.s]) for val in hoh[1]) ss_f = ss_i.apply_maneuver(hoh) #plot(ss_f) from poliastro.plotting import OrbitPlotter op = OrbitPlotter()
ZOOM = True R = np.linspace(2, 75, num=100) Rstar = [15.58, 40, 60, 100, 200, np.inf] hohmann_data = np.zeros_like(R) bielliptic_data = np.zeros((len(R), len(Rstar))) ss_i = Orbit.circular(Earth, 1.8 * u.km) r_i = ss_i.a v_i = np.sqrt(ss_i.v.dot(ss_i.v)) for ii, r in enumerate(R): r_f = r * r_i man = Maneuver.hohmann(ss_i, r_f) hohmann_data[ii] = (man.get_total_cost() / v_i).decompose().value for jj, rstar in enumerate(Rstar): r_b = rstar * r_i man = Maneuver.bielliptic(ss_i, r_b, r_f) bielliptic_data[ii, jj] = ( man.get_total_cost() / v_i).decompose().value idx_max = np.argmax(hohmann_data) ylims = (0.35, 0.6) # In[3]:
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
import numpy as np import matplotlib.pyplot as plt from astropy import time from astropy import units as u from poliastro.util import norm from poliastro.bodies import Earth, Jupiter, Sun from poliastro.twobody import Orbit from poliastro.plotting import OrbitPlotter, plot from poliastro.maneuver import Maneuver from common import * from tools import Earth_to_Jupiter plt.style.use("seaborn") # Recommended # Minimum Delta-V to reach Jupiter with Hohmann transfer hoh = Maneuver.hohmann(ss_Earth, R_J) dv_min = hoh[0][1] # DeltaV to obtain Solar escape velocity # (considering tangent burn) escape_v = np.sqrt(2 * Sun.k / R_E) dv_escape = escape_v - norm(v_Earth) # DeltaV of New Horizons mission dv_NH_1 = 16.26 * u.km / u.s ss_trans, t, T, t_trans = Earth_to_Jupiter(dv_NH_1) print("Time from now to the next launch window = %2.3f d" % t.to(u.d).value) print("Time between launch windows = %2.3f d" % T.to(u.d).value) print("Transfer time from Earth to Jupiter = %2.3f d" % t_trans.to(u.d).value)
def validate_3D_hohmann(): # Initial orbit state vectors, final radius and time of flight # This orbit has an inclination of 22.30 [deg] so the maneuver will not be # applied on an equatorial orbit. See associated GMAT script: # gmat_validate_hohmann3D.script rx_0, ry_0, rz_0 = 7200e3, -1000.0e3, 0.0 vx_0, vy_0, vz_0 = 0.0, 8.0e3, 3.25e3 rf_norm = 35781.35e3 tof = 19800.00 # Build the initial Orekit orbit k = C.IAU_2015_NOMINAL_EARTH_GM r0_vec = Vector3D(rx_0, ry_0, rz_0) v0_vec = Vector3D(vx_0, vy_0, vz_0) rv_0 = PVCoordinates(r0_vec, v0_vec) epoch_00 = AbsoluteDate.J2000_EPOCH gcrf_frame = FramesFactory.getGCRF() ss_0 = KeplerianOrbit(rv_0, gcrf_frame, epoch_00, k) # Final desired orbit radius and auxiliary variables a_0, ecc_0 = ss_0.getA(), ss_0.getE() rp_norm = a_0 * (1 - ecc_0) vp_norm = np.sqrt(2 * k / rp_norm - k / a_0) a_trans = (rp_norm + rf_norm) / 2 # Compute the magnitude of Hohmann's deltaV dv_a = np.sqrt(2 * k / rp_norm - k / a_trans) - vp_norm dv_b = np.sqrt(k / rf_norm) - np.sqrt(2 * k / rf_norm - k / a_trans) # Convert previous magnitudes into vectors within the TNW frame, which # is aligned with local velocity vector dVa_vec, dVb_vec = [ Vector3D(float(dV), float(0), float(0)) for dV in (dv_a, dv_b) ] # Local orbit frame: X-axis aligned with velocity, Z-axis towards momentum attitude_provider = LofOffset(gcrf_frame, LOFType.TNW) # Setup impulse triggers; default apside detector stops on increasing g # function (aka at perigee) at_apoapsis = ApsideDetector(ss_0).withHandler(StopOnDecreasing()) at_periapsis = ApsideDetector(ss_0) # Build the impulsive maneuvers; ISP is only related to fuel mass cost ISP = float(300) imp_A = ImpulseManeuver(at_periapsis, attitude_provider, dVa_vec, ISP) imp_B = ImpulseManeuver(at_apoapsis, attitude_provider, dVb_vec, ISP) # Generate the propagator and add the maneuvers propagator = KeplerianPropagator(ss_0, attitude_provider) propagator.addEventDetector(imp_A) propagator.addEventDetector(imp_B) # Apply the maneuver by propagating the orbit epoch_ff = epoch_00.shiftedBy(tof) rv_f = propagator.propagate(epoch_ff).getPVCoordinates(gcrf_frame) # Retrieve orekit final state vectors r_orekit, v_orekit = ( rv_f.getPosition().toArray() * u.m, rv_f.getVelocity().toArray() * u.m / u.s, ) # Build initial poliastro orbit and apply the maneuver r0_vec = [rx_0, ry_0, rz_0] * u.m v0_vec = [vx_0, vy_0, vz_0] * u.m / u.s ss0_poliastro = Orbit.from_vectors(Earth, r0_vec, v0_vec) man_poliastro = Maneuver.hohmann(ss0_poliastro, rf_norm * u.m) # Retrieve propagation time after maneuver has been applied tof_prop = tof - man_poliastro.get_total_time().to(u.s).value ssf_poliastro = ss0_poliastro.apply_maneuver(man_poliastro).propagate( tof_prop * u.s) # Retrieve poliastro final state vectors r_poliastro, v_poliastro = ssf_poliastro.rv() # Assert final state vectors assert_quantity_allclose(r_poliastro, r_orekit, rtol=1e-6) assert_quantity_allclose(v_poliastro, v_orekit, rtol=1e-6)