def test_parabolic_elements_fail_early(): attractor = Earth ecc = 1.0 * u.one _d = 1.0 * u.AU # Unused distance _a = 1.0 * u.deg # Unused angle with pytest.raises(ValueError) as excinfo: Orbit.from_classical(attractor, _d, ecc, _a, _a, _a, _a) assert ("ValueError: For parabolic orbits use Orbit.parabolic instead" in excinfo.exconly())
def test_bad_inclination_raises_exception(): _d = 1.0 * u.AU # Unused distance _ = 0.5 * u.one # Unused dimensionless value _a = 1.0 * u.deg # Unused angle bad_inc = 200 * u.deg _body = Sun # Unused body with pytest.raises(ValueError) as excinfo: Orbit.from_classical(_body, _d, _, bad_inc, _a, _a, _a) assert ("ValueError: Inclination must be between 0 and 180 degrees" in excinfo.exconly())
def test_bad_hyperbolic_raises_exception(): bad_a = 1.0 * u.AU ecc = 1.5 * u.one _a = 1.0 * u.deg # Unused angle _inc = 100 * u.deg # Unused inclination _body = Sun # Unused body with pytest.raises(ValueError) as excinfo: Orbit.from_classical(_body, bad_a, ecc, _inc, _a, _a, _a) assert ("Hyperbolic orbits have negative semimajor axis" in excinfo.exconly())
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: Orbit.from_classical(Sun, _d, _, _a, _a, _a, wrong_angle) assert ("UnitsError: Argument 'nu' to function 'from_classical' must be in units convertible to 'rad'." in excinfo.exconly())
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: Orbit.from_classical(Sun, _d, _, _a, _a, _a, wrong_angle) assert ( "UnitsError: Argument 'nu' to function 'from_classical' must be in units convertible to 'rad'." in excinfo.exconly())
def test_bad_inclination_raises_exception(): _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 bad_inc = 200 * u.deg with pytest.raises(ValueError) as excinfo: Orbit.from_classical(_body, _d, _, bad_inc, _a, _a, _a) assert ("ValueError: Inclination must be between 0 and 180 degrees" in excinfo.exconly())
def test_bad_hyperbolic_raises_exception(): bad_a = 1.0 * u.AU ecc = 1.5 * u.one _inc = 100 * u.deg # Unused inclination _a = 1.0 * u.deg # Unused angle _body = Sun # Unused body with pytest.raises(ValueError) as excinfo: Orbit.from_classical(_body, bad_a, ecc, _inc, _a, _a, _a) assert "Hyperbolic orbits have negative semimajor axis" in excinfo.exconly( )
def test_mean_motion(ecc): _a = 0.0 * u.rad tof = 1.0 * u.min if ecc < 1.0: orbit = Orbit.from_classical(Earth, 10000 * u.km, ecc * u.one, _a, _a, _a, 1.0 * u.rad) else: orbit = Orbit.from_classical(Earth, -10000 * u.km, ecc * u.one, _a, _a, _a, 1.0 * u.rad) orbit_cowell = orbit.propagate(tof, method=cowell) orbit_mean_motion = orbit.propagate(tof, method=mean_motion) assert_quantity_allclose(orbit_cowell.r, orbit_mean_motion.r) assert_quantity_allclose(orbit_cowell.v, orbit_mean_motion.v)
def test_sso_disposal_numerical(ecc_0, ecc_f): a_0 = Earth.R.to(u.km).value + 900 # km f = 2.4e-7 # km / s2, assumed constant k = Earth.k.decompose([u.km, u.s]).value _, t_f = extra_quantities(k, a_0, ecc_0, ecc_f, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical(Earth, a_0 * u.km, ecc_0 * u.one, 0 * u.deg, 0 * u.deg, 0 * u.deg, 0 * u.deg) r0, v0 = s0.rv() optimal_accel = guidance_law(s0, ecc_f, f) # Propagate orbit r, v = cowell(k, r0.to(u.km).value, v0.to(u.km / u.s).value, t_f, ad=optimal_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.ecc.value, ecc_f, rtol=1e-4, atol=1e-4)
def test_propagating_to_certain_nu_is_correct(): # take an elliptic orbit a = 1.0 * u.AU ecc = 1.0 / 3.0 * u.one _a = 0.0 * u.rad nu = 10 * u.deg elliptic = Orbit.from_classical(Sun, a, ecc, _a, _a, _a, nu) elliptic_at_perihelion = elliptic.propagate_to_anomaly(0.0 * u.rad) r_per, _ = elliptic_at_perihelion.rv() elliptic_at_aphelion = elliptic.propagate_to_anomaly(np.pi * u.rad) r_ap, _ = elliptic_at_aphelion.rv() assert_quantity_allclose(norm(r_per), a * (1.0 - ecc)) assert_quantity_allclose(norm(r_ap), a * (1.0 + ecc)) # TODO: Test specific values assert elliptic_at_perihelion.epoch > elliptic.epoch assert elliptic_at_aphelion.epoch > elliptic.epoch # test 10 random true anomaly values for _ in range(10): nu = np.random.uniform(low=0.0, high=2 * np.pi) elliptic = elliptic.propagate_to_anomaly(nu * u.rad) r, _ = elliptic.rv() assert_quantity_allclose(norm(r), a * (1.0 - ecc ** 2) / (1 + ecc * np.cos(nu)))
def test_soyuz_standard_gto_numerical(): # Data from Soyuz Users Manual, issue 2 revision 0 r_a = (Earth.R + 35950 * u.km).to(u.km).value r_p = (Earth.R + 250 * u.km).to(u.km).value a = (r_a + r_p) / 2 # km ecc = r_a / a - 1 argp_0 = (178 * u.deg).to(u.rad).value # rad argp_f = (178 * u.deg + 5 * u.deg).to(u.rad).value # rad f = 2.4e-7 # km / s2 k = Earth.k.decompose([u.km, u.s]).value optimal_accel = guidance_law(f) _, t_f = extra_quantities(k, a, ecc, argp_0, argp_f, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical(Earth, a * u.km, (r_a / a - 1) * u.one, 6 * u.deg, 188.5 * u.deg, 178 * u.deg, 0 * u.deg) 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=optimal_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.argp.to(u.rad).value, argp_f, rtol=1e-4)
def test_penumbra_event_crossing(): expected_penumbra_t = Time("2020-01-01 00:04:26.060", scale="utc") # From Orekit. attractor = Earth tof = 2 * u.d epoch = Time("2020-01-01", scale="utc") orbit = Orbit.from_classical( attractor=attractor, a=6828137.0 * u.m, ecc=0.0073 * u.one, inc=87.0 * u.deg, raan=20.0 * u.deg, argp=10.0 * u.deg, nu=0 * u.deg, epoch=epoch, ) penumbra_event = PenumbraEvent(orbit, terminal=True) events = [penumbra_event] rr, _ = cowell( attractor.k, orbit.r, orbit.v, [tof] * u.s, events=events, ) assert expected_penumbra_t.isclose(epoch + penumbra_event.last_t, atol=1 * u.s)
def test_geo_cases_beta_dnd_delta_v(ecc_0, inc_f, expected_beta, expected_delta_V): a = 42164 # km ecc_f = 0.0 inc_0 = 0.0 # rad, baseline argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 * (u.km / u.s**2) inc_f = np.radians(inc_f) expected_beta = np.radians(expected_beta) s0 = Orbit.from_classical( attractor=Earth, a=a * u.km, ecc=ecc_0 * u.one, inc=inc_0 * u.deg, raan=0 * u.deg, argp=argp * u.deg, nu=0 * u.deg, ) beta = beta_change_ecc_inc(ecc_0=ecc_0, ecc_f=ecc_f, inc_0=inc_0, inc_f=inc_f, argp=argp) _, delta_V, _ = change_ecc_inc(ss_0=s0, ecc_f=ecc_f, inc_f=inc_f * u.rad, f=f) assert_allclose(delta_V.to_value(u.km / u.s), expected_delta_V, rtol=1e-2) assert_allclose(beta, expected_beta, rtol=1e-2)
def test_geo_cases_numerical(ecc_0, ecc_f): a = 42164 # km inc_0 = 0.0 inc_f = 20.0 * u.deg argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 * (u.km / u.s**2) # Initial orbit s0 = Orbit.from_classical( attractor=Earth, a=a * u.km, ecc=ecc_0 * u.one, inc=inc_0 * u.deg, raan=0 * u.deg, argp=argp * u.deg, nu=0 * u.deg, ) a_d, _, t_f = change_ecc_inc(ss_0=s0, ecc_f=ecc_f, inc_f=inc_f, f=f) # Propagate orbit def f_geo(t0, u_, k): du_kep = func_twobody(t0, u_, k) ax, ay, az = a_d(t0, u_, k) du_ad = np.array([0, 0, 0, ax, ay, az]) return du_kep + du_ad sf = s0.propagate(t_f, method=cowell, f=f_geo, rtol=1e-8) assert_allclose(sf.ecc.value, ecc_f, rtol=1e-2, atol=1e-2) assert_allclose(sf.inc.to_value(u.rad), inc_f.to_value(u.rad), rtol=1e-1)
def test_solar_pressure(): # based on example 12.9 from Howard Curtis solar_system_ephemeris.set('de432s') j_date = 2438400.5 * u.day tof = 600 * u.day sun_r = build_ephem_interpolant(Sun, 365 * u.day, (j_date, j_date + tof), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') drag_force_orbit = [10085.44 * u.km, 0.025422 * u.one, 88.3924 * u.deg, 45.38124 * u.deg, 227.493 * u.deg, 343.4268 * u.deg] initial = Orbit.from_classical(Earth, *drag_force_orbit, epoch=epoch) # in Curtis, the mean distance to Sun is used. In order to validate against it, we have to do the same thing sun_normalized = functools.partial(normalize_to_Curtis, sun_r=sun_r) r, v = cowell(initial, np.linspace(0, (tof).to(u.s).value, 4000), rtol=1e-8, ad=radiation_pressure, R=Earth.R.to(u.km).value, C_R=2.0, A=2e-4, m=100, Wdivc_s=Sun.Wdivc.value, star=sun_normalized) delta_as, delta_eccs, delta_incs, delta_raans, delta_argps, delta_hs = [], [], [], [], [], [] for ri, vi in zip(r, v): orbit_params = rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi) delta_eccs.append(orbit_params[1] - drag_force_orbit[1].value) delta_incs.append((orbit_params[2] * u.rad).to(u.deg).value - drag_force_orbit[2].value) delta_raans.append((orbit_params[3] * u.rad).to(u.deg).value - drag_force_orbit[3].value) delta_argps.append((orbit_params[4] * u.rad).to(u.deg).value - drag_force_orbit[4].value) # averaging over 5 last values in the way Curtis does for check in solar_pressure_checks: index = int(1.0 * check['t_days'] / tof.to(u.day).value * 4000) delta_ecc, delta_inc, delta_raan, delta_argp = np.mean(delta_eccs[index - 5:index]), \ np.mean(delta_incs[index - 5:index]), np.mean(delta_raans[index - 5:index]), \ np.mean(delta_argps[index - 5:index]) assert_quantity_allclose([delta_ecc, delta_inc, delta_raan, delta_argp], check['deltas_expected'], rtol=1e-1, atol=1e-4)
def test_sso_disposal_numerical(ecc_0, ecc_f): a_0 = Earth.R.to(u.km).value + 900 # km f = 2.4e-7 # km / s2, assumed constant # Retrieve r and v from initial orbit s0 = Orbit.from_classical( attractor=Earth, a=a_0 * u.km, ecc=ecc_0 * u.one, inc=0 * u.deg, raan=0 * u.deg, argp=0 * u.deg, nu=0 * u.deg, ) a_d, _, t_f = change_ecc_quasioptimal(s0, ecc_f, f) # Propagate orbit def f_ss0_disposal(t0, u_, k): du_kep = func_twobody(t0, u_, k) ax, ay, az = a_d(t0, u_, k) du_ad = np.array([0, 0, 0, ax, ay, az]) return du_kep + du_ad sf = s0.propagate(t_f * u.s, method=cowell, f=f_ss0_disposal, rtol=1e-8) assert_allclose(sf.ecc.value, ecc_f, rtol=1e-4, atol=1e-4)
def test_LOS_event(): t_los = 2327.165 * u.s r2 = np.array([-500, 1500, 4012.09]) << u.km v2 = np.array([5021.38, -2900.7, 1000.354]) << u.km / u.s orbit = Orbit.from_vectors(Earth, r2, v2) tofs = [100, 500, 1000, 2000] << u.s # Propagate the secondary body to generate its position coordinates. rr, vv = cowell( Earth.k, orbit.r, orbit.v, tofs, ) pos_coords = rr # Trajectory of the secondary body. orb = Orbit.from_classical(Earth, 16000 * u.km, 0.53 * u.one, 5 * u.deg, 5 * u.deg, 10 * u.deg, 30 * u.deg) los_event = LosEvent(Earth, pos_coords, terminal=True) events = [los_event] tofs = [1, 5, 10, 100, 1000, 2000, 3000, 5000] << u.s r, v = cowell( Earth.k, orb.r, orb.v, tofs, events=events, ) assert_quantity_allclose(los_event.last_t, t_los)
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params['body'] solar_system_ephemeris.set('de432s') j_date = 2454283.0 * u.day tof = (test_params['tof']).to(u.s).value body_r = build_ephem_interpolant(body, test_params['period'], (j_date, j_date + test_params['tof']), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') initial = Orbit.from_classical(Earth, *test_params['orbit'], epoch=epoch) r, v = cowell(initial, np.linspace(0, tof, 400), rtol=1e-10, ad=third_body, k_third=body.k.to(u.km**3 / u.s**2).value, third_body=body_r) incs, raans, argps = [], [], [] for ri, vi in zip(r, v): angles = Angle(rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi)[2:5] * u.rad) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]) assert_quantity_allclose([(raan_f * u.rad).to(u.deg) - test_params['orbit'][3], (inc_f * u.rad).to(u.deg) - test_params['orbit'][2], (argp_f * u.rad).to(u.deg) - test_params['orbit'][4]], [test_params['raan'], test_params['inc'], test_params['argp']], rtol=1e-1)
def test_umbra_event_crossing(): expected_umbra_t = Time("2020-01-01 00:04:51.328", scale="utc") # From Orekit. attractor = Earth tof = 2 * u.d epoch = Time("2020-01-01", scale="utc") coe = ( 6828137.0 * u.m, 0.0073 * u.one, 87.0 * u.deg, 20.0 * u.deg, 10.0 * u.deg, 0 * u.deg, ) orbit = Orbit.from_classical(attractor, *coe, epoch=epoch) umbra_event = UmbraEvent(orbit, terminal=True) events = [umbra_event] rr, _ = cowell( attractor.k, orbit.r, orbit.v, [tof] * u.s, events=events, ) assert expected_umbra_t.isclose(epoch + umbra_event.last_t, atol=1 * u.s)
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params['body'] with solar_system_ephemeris.set('builtin'): j_date = 2454283.0 * u.day tof = (test_params['tof']).to(u.s).value body_r = build_ephem_interpolant(body, test_params['period'], (j_date, j_date + test_params['tof']), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') initial = Orbit.from_classical(Earth, *test_params['orbit'], epoch=epoch) r, v = cowell(initial, np.linspace(0, tof, 400), rtol=1e-10, ad=third_body, k_third=body.k.to(u.km**3 / u.s**2).value, third_body=body_r) incs, raans, argps = [], [], [] for ri, vi in zip(r, v): angles = Angle(rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi)[2:5] * u.rad) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]) assert_quantity_allclose([(raan_f * u.rad).to(u.deg) - test_params['orbit'][3], (inc_f * u.rad).to(u.deg) - test_params['orbit'][2], (argp_f * u.rad).to(u.deg) - test_params['orbit'][4]], [test_params['raan'], test_params['inc'], test_params['argp']], rtol=1e-1)
def test_solar_pressure(): # based on example 12.9 from Howard Curtis with solar_system_ephemeris.set('builtin'): j_date = 2438400.5 * u.day tof = 600 * u.day sun_r = build_ephem_interpolant(Sun, 365 * u.day, (j_date, j_date + tof), rtol=1e-2) epoch = Time(j_date, format='jd', scale='tdb') drag_force_orbit = [10085.44 * u.km, 0.025422 * u.one, 88.3924 * u.deg, 45.38124 * u.deg, 227.493 * u.deg, 343.4268 * u.deg] initial = Orbit.from_classical(Earth, *drag_force_orbit, epoch=epoch) # in Curtis, the mean distance to Sun is used. In order to validate against it, we have to do the same thing sun_normalized = functools.partial(normalize_to_Curtis, sun_r=sun_r) r, v = cowell(initial, np.linspace(0, (tof).to(u.s).value, 4000), rtol=1e-8, ad=radiation_pressure, R=Earth.R.to(u.km).value, C_R=2.0, A=2e-4, m=100, Wdivc_s=Sun.Wdivc.value, star=sun_normalized) delta_eccs, delta_incs, delta_raans, delta_argps = [], [], [], [] for ri, vi in zip(r, v): orbit_params = rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi) delta_eccs.append(orbit_params[1] - drag_force_orbit[1].value) delta_incs.append((orbit_params[2] * u.rad).to(u.deg).value - drag_force_orbit[2].value) delta_raans.append((orbit_params[3] * u.rad).to(u.deg).value - drag_force_orbit[3].value) delta_argps.append((orbit_params[4] * u.rad).to(u.deg).value - drag_force_orbit[4].value) # averaging over 5 last values in the way Curtis does for check in solar_pressure_checks: index = int(1.0 * check['t_days'] / tof.to(u.day).value * 4000) delta_ecc, delta_inc, delta_raan, delta_argp = np.mean(delta_eccs[index - 5:index]), \ np.mean(delta_incs[index - 5:index]), np.mean(delta_raans[index - 5:index]), \ np.mean(delta_argps[index - 5:index]) assert_quantity_allclose([delta_ecc, delta_inc, delta_raan, delta_argp], check['deltas_expected'], rtol=1e-1, atol=1e-4)
def init_state_obj(seed=None): if not (seed == None): np.random.seed(seed) t_init = time.Time(datetime(2020, 3, 15, 0, 0, 0), scale='utc') a = (Earth.R.value + 200000) * u.m # (Quantity) – Semi-major axis. ecc = np.random.uniform( 0.001, 0.3) * u.dimensionless_unscaled # (Quantity) – Eccentricity. inc = np.random.uniform(0, 180) * u.degree # (Quantity) – Inclination raan = np.random.uniform( 0, 360) * u.degree # (Quantity) – Right ascension of the ascending node. argp = np.random.uniform( 0, 360) * u.degree # (Quantity) – Argument of the pericenter. nu = np.random.uniform(0, 360) * u.degree # (Quantity) – True anomaly. epoch = t_init # (Time, optional) – Epoch, default to J2000. plane = Planes.EARTH_EQUATOR # Fundamental plane of the frame. return Orbit.from_classical(Earth, a, ecc, inc, raan, argp, nu, epoch=epoch, plane=plane)
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 = Orbit.from_classical(Sun, _d, _, _a, _a, _a, _a) p, _, _ = ss.pqw() assert_allclose(p, ss.e_vec / ss.ecc)
def _compute_results_array(a, ecc_0, ecc_f, inc_0, inc_f, argp, f): k = Earth.k.decompose([u.km, u.s]).value _, _, t_f = extra_quantities(k, a, ecc_0, ecc_f, inc_0, inc_f, argp, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical( Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg ) r0, v0 = s0.rv() combined_ei_accel = guidance_law(s0, ecc_f, inc_f, f) # Propagate orbit with ProgressResultsCallback(t_f) as res: cowell( k, r0.to(u.km).value, v0.to(u.km / u.s).value, t_f, ad=combined_ei_accel, callback=res, nsteps=1000000 ) return res.get_results() # ~70 k rows, 7 columns, 3 MB in memory
def test_soyuz_standard_gto_numerical(): # Data from Soyuz Users Manual, issue 2 revision 0 r_a = (Earth.R + 35950 * u.km).to(u.km).value r_p = (Earth.R + 250 * u.km).to(u.km).value a = (r_a + r_p) / 2 # km ecc = r_a / a - 1 argp_0 = (178 * u.deg).to(u.rad).value # rad argp_f = (178 * u.deg + 5 * u.deg).to(u.rad).value # rad f = 2.4e-7 # km / s2 k = Earth.k.to(u.km**3 / u.s**2).value a_d, _, t_f = change_argp(k, a, ecc, argp_0, argp_f, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical( Earth, a * u.km, (r_a / a - 1) * u.one, 6 * u.deg, 188.5 * u.deg, 178 * u.deg, 0 * u.deg ) # Propagate orbit sf = s0.propagate(t_f * u.s, method=cowell, ad=a_d, rtol=1e-8) assert_allclose(sf.argp.to(u.rad).value, argp_f, rtol=1e-4)
def test_bielliptic_maneuver(nu): # Data from Vallado, example 6.2 alt_i = 191.34411 * u.km alt_b = 503873.0 * u.km alt_f = 376310.0 * 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.904057 * u.km / u.s expected_t_pericenter = ss_i.time_to_anomaly(0 * u.deg) expected_t_trans = 593.919803 * u.h expected_total_time = expected_t_pericenter + expected_t_trans 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_total_time, rtol=1e-6)
def test_geo_cases_numerical(ecc_0, ecc_f): a = 42164 # km inc_0 = 0.0 # rad, baseline inc_f = (20.0 * u.deg).to(u.rad).value # rad argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 # km / s2 k = Earth.k.decompose([u.km, u.s]).value _, _, t_f = extra_quantities(k, a, ecc_0, ecc_f, inc_0, inc_f, argp, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical(Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg) r0, v0 = s0.rv() optimal_accel = guidance_law(s0, ecc_f, inc_f, f) # Propagate orbit r, v = cowell(k, r0.to(u.km).value, v0.to(u.km / u.s).value, t_f, ad=optimal_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.ecc.value, ecc_f, rtol=1e-2, atol=1e-2) assert_allclose(sf.inc.to(u.rad).value, inc_f, rtol=1e-1)
def validate_coe2rv(): # Initial COE of the orbit a, ecc, inc, raan, argp, nu = 8788e3, 0.1712, 2.6738, 4.4558, 0.3502, 0.4965 # Build Orekit orbit k = C.IAU_2015_NOMINAL_EARTH_GM epoch_00 = AbsoluteDate.J2000_EPOCH gcrf_frame = FramesFactory.getGCRF() ss0_orekit = KeplerianOrbit(a, ecc, inc, argp, raan, nu, PositionAngle.TRUE, gcrf_frame, epoch_00, k) # Build poliastro orbit ss0_poliastro = Orbit.from_classical( Earth, a * u.m, ecc * u.one, inc * u.rad, raan * u.rad, argp * u.rad, nu * u.rad, ) # Retrieve Orekit final state vectors r_orekit = ss0_orekit.getPVCoordinates().position.toArray() * u.m v_orekit = ss0_orekit.getPVCoordinates().velocity.toArray() * u.m / u.s # Retrieve poliastro final state vectors r_poliastro, v_poliastro = ss0_poliastro.rv() # Assert final state vector assert_quantity_allclose(r_poliastro, r_orekit) assert_quantity_allclose(v_poliastro, v_orekit)
def setup(self): from poliastro.twobody import Orbit self.a_ini = 8970.667 * u.km self.ecc_ini = 0.25 * u.one self.raan_ini = 1.047 * u.rad self.nu_ini = 0.0 * u.rad self.argp_ini = 1.0 * u.rad self.inc_ini = 0.2618 * u.rad self.k = Earth.k.to(u.km**3 / u.s**2).value self.orbit = Orbit.from_classical( Earth, self.a_ini, self.ecc_ini, self.inc_ini, self.raan_ini, self.argp_ini, self.nu_ini, ) self.tof = [1.0] * u.min self.a_J2J3 = lambda t0, u_, k_: J2_perturbation( t0, u_, k_, J2=Earth.J2.value, R=Earth.R.to( u.km).value) + J3_perturbation( t0, u_, k_, J3=Earth.J3.value, R=Earth.R.to(u.km).value)
def test_geo_cases_beta_dnd_delta_v(ecc_0, inc_f, expected_beta, expected_delta_V): a = 42164 # km ecc_f = 0.0 inc_0 = 0.0 # rad, baseline argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 # km / s2, unused inc_f = np.radians(inc_f) expected_beta = np.radians(expected_beta) s0 = Orbit.from_classical( Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg, ) _, delta_V, beta, _ = change_inc_ecc(s0, ecc_f, inc_f, f) assert_allclose(delta_V, expected_delta_V, rtol=1e-2) assert_allclose(beta, expected_beta, rtol=1e-2)
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_geo_cases_numerical(ecc_0, ecc_f): a = 42164 # km inc_0 = 0.0 # rad, baseline inc_f = (20.0 * u.deg).to(u.rad).value # rad argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 # km / s2 # Retrieve r and v from initial orbit s0 = Orbit.from_classical( Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg, ) a_d, _, _, t_f = change_inc_ecc(s0, ecc_f, inc_f, f) # Propagate orbit def f_geo(t0, u_, k): du_kep = func_twobody(t0, u_, k) ax, ay, az = a_d(t0, u_, k) du_ad = np.array([0, 0, 0, ax, ay, az]) return du_kep + du_ad sf = s0.propagate(t_f * u.s, method=cowell, f=f_geo, rtol=1e-8) assert_allclose(sf.ecc.value, ecc_f, rtol=1e-2, atol=1e-2) assert_allclose(sf.inc.to(u.rad).value, inc_f, rtol=1e-1)
def test_solar_pressure(t_days, deltas_expected, sun_r): # based on example 12.9 from Howard Curtis with solar_system_ephemeris.set("builtin"): j_date = 2_438_400.5 * u.day tof = 600 * u.day epoch = Time(j_date, format="jd", scale="tdb") initial = Orbit.from_classical( Earth, 10085.44 * u.km, 0.025422 * u.one, 88.3924 * u.deg, 45.38124 * u.deg, 227.493 * u.deg, 343.4268 * u.deg, epoch=epoch, ) # in Curtis, the mean distance to Sun is used. In order to validate against it, we have to do the same thing sun_normalized = functools.partial(normalize_to_Curtis, sun_r=sun_r) rr, vv = cowell( Earth.k, initial.r, initial.v, np.linspace(0, (tof).to(u.s).value, 4000) * u.s, rtol=1e-8, ad=radiation_pressure, R=Earth.R.to(u.km).value, C_R=2.0, A_over_m=2e-4 / 100, Wdivc_s=Wdivc_sun.value, star=sun_normalized, ) delta_eccs, delta_incs, delta_raans, delta_argps = [], [], [], [] for ri, vi in zip(rr.to(u.km).value, vv.to(u.km / u.s).value): orbit_params = rv2coe(Earth.k.to(u.km**3 / u.s**2).value, ri, vi) delta_eccs.append(orbit_params[1] - initial.ecc.value) delta_incs.append((orbit_params[2] * u.rad).to(u.deg).value - initial.inc.value) delta_raans.append((orbit_params[3] * u.rad).to(u.deg).value - initial.raan.value) delta_argps.append((orbit_params[4] * u.rad).to(u.deg).value - initial.argp.value) # averaging over 5 last values in the way Curtis does index = int(1.0 * t_days / tof.to(u.day).value * 4000 # type: ignore ) delta_ecc, delta_inc, delta_raan, delta_argp = ( np.mean(delta_eccs[index - 5:index]), np.mean(delta_incs[index - 5:index]), np.mean(delta_raans[index - 5:index]), np.mean(delta_argps[index - 5:index]), ) assert_quantity_allclose( [delta_ecc, delta_inc, delta_raan, delta_argp], deltas_expected, rtol=1e0, # TODO: Excessively low, rewrite test? atol=1e-4, )
def test_propagating_to_certain_nu_is_correct(): # Take an elliptic orbit a = 1.0 * u.AU ecc = 1.0 / 3.0 * u.one _a = 0.0 * u.rad nu = 10 * u.deg elliptic = Orbit.from_classical(attractor=Sun, a=a, ecc=ecc, inc=_a, raan=_a, argp=_a, nu=nu) elliptic_at_perihelion = elliptic.propagate_to_anomaly(0.0 * u.rad) r_per, _ = elliptic_at_perihelion.rv() elliptic_at_aphelion = elliptic.propagate_to_anomaly(np.pi * u.rad) r_ap, _ = elliptic_at_aphelion.rv() assert_quantity_allclose(norm(r_per), a * (1.0 - ecc)) assert_quantity_allclose(norm(r_ap), a * (1.0 + ecc)) # TODO: Test specific values assert elliptic_at_perihelion.epoch > elliptic.epoch assert elliptic_at_aphelion.epoch > elliptic.epoch # Test 10 random true anomaly values # TODO: Rework this test for nu in np.random.uniform(low=-np.pi, high=np.pi, size=10): elliptic = elliptic.propagate_to_anomaly(nu * u.rad) r, _ = elliptic.rv() assert_quantity_allclose(norm(r), a * (1.0 - ecc**2) / (1 + ecc * np.cos(nu)))
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_escape_velocity(): # TEST CASE 1: # This is circular orbit, the escape velocity must be the same everywhere. # Escape velocity for position on the ground is 11.179km/s (source BMW2, page 30) o1 = Orbit.circular(Earth, 0*u.km) v,vp,va = interplanetary.escape_vel(o1, False) assert v == vp == va assert np.abs(v - 11179 * u.m/u.s) < 1 * u.m / u.s assert np.abs(vp - 11179 * u.m/u.s) < 1 * u.m / u.s assert np.abs(va - 11179 * u.m/u.s) < 1 * u.m / u.s # TEST CASE 2: # Escape velocity for position at the altitude of 7000km is 7719km/s (source BMW2, page 30) o2 = Orbit.circular(Earth, 7000*u.km) v,vp,va = interplanetary.escape_vel(o2, False) assert v == vp == va assert np.abs(v - 7719 * u.m/u.s) < 1 * u.m / u.s assert np.abs(vp - 7719 * u.m/u.s) < 1 * u.m / u.s assert np.abs(va - 7719 * u.m/u.s) < 1 * u.m / u.s o3 = Orbit.from_classical(Earth, Earth.R + 16000 * u.km, 0.5*u.one, 0*u.deg, 0*u.deg, 0*u.deg, 0*u.deg) print_orb(o3) v,vp,va = interplanetary.escape_vel(o3, False) print(v, vp, va)
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 = J2000 ss = Orbit.from_classical(_body, _d, _, _a, _a, _a, _a) assert ss.epoch == expected_epoch
def test_sample_numpoints(): _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 ss = Orbit.from_classical(_body, _d, _, _a, _a, _a, _a) positions = ss.sample(values=50) assert len(positions) == 50
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 = Orbit.from_classical(Sun, _d, _, _a, _a, _a, _a) dt = 1 * u.h dv = [0, 0, 0] * u.km / u.s orbit_new = ss.apply_maneuver([(dt, dv)]) assert orbit_new.epoch == ss.epoch + dt
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 = Orbit.from_classical(Sun, _d, _, _a, _a, _a, _a) dt = 0 * u.s dv = [0, 0, 0] * u.km / u.s orbit_new = ss.apply_maneuver([(dt, dv)]) assert_allclose(orbit_new.r.to(u.km).value, ss.r.to(u.km).value) assert_allclose(orbit_new.v.to(u.km / u.s).value, ss.v.to(u.km / u.s).value)
def test_sso_disposal_time_and_delta_v(ecc_0, ecc_f): a_0 = Earth.R.to(u.km).value + 900 # km f = 2.4e-7 # km / s2, assumed constant expected_t_f = 29.697 # days, reverse-engineered expected_delta_V = 0.6158 # km / s, lower than actual result s0 = Orbit.from_classical(Earth, a_0 * u.km, ecc_0 * u.one, 0 * u.deg, 0 * u.deg, 0 * u.deg, 0 * u.deg) _, delta_V, t_f = change_ecc_quasioptimal(s0, ecc_f, f) assert_allclose(delta_V, expected_delta_V, rtol=1e-4) assert_allclose(t_f / 86400, expected_t_f, rtol=1e-4)
def test_sample_with_nu_value(): _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 ss = Orbit.from_classical(_body, _d, _, _a, _a, _a, _a) expected_r = [ss.r] positions = ss.sample(values=ss.nu + [360] * u.deg) r = positions.data.xyz.transpose() assert_quantity_allclose(r, expected_r, rtol=1.e-7)
def test_3rd_body_Curtis(test_params): # based on example 12.11 from Howard Curtis body = test_params["body"] with solar_system_ephemeris.set("builtin"): j_date = 2454283.0 * u.day tof = (test_params["tof"]).to(u.s).value body_r = build_ephem_interpolant( body, test_params["period"], (j_date, j_date + test_params["tof"]), rtol=1e-2, ) epoch = Time(j_date, format="jd", scale="tdb") initial = Orbit.from_classical(Earth, *test_params["orbit"], epoch=epoch) rr, vv = cowell( Earth.k, initial.r, initial.v, np.linspace(0, tof, 400) * u.s, rtol=1e-10, ad=third_body, k_third=body.k.to(u.km ** 3 / u.s ** 2).value, third_body=body_r, ) incs, raans, argps = [], [], [] for ri, vi in zip(rr.to(u.km).value, vv.to(u.km / u.s).value): angles = Angle( rv2coe(Earth.k.to(u.km ** 3 / u.s ** 2).value, ri, vi)[2:5] * u.rad ) # inc, raan, argp angles = angles.wrap_at(180 * u.deg) incs.append(angles[0].value) raans.append(angles[1].value) argps.append(angles[2].value) # averaging over 5 last values in the way Curtis does inc_f, raan_f, argp_f = ( np.mean(incs[-5:]), np.mean(raans[-5:]), np.mean(argps[-5:]), ) assert_quantity_allclose( [ (raan_f * u.rad).to(u.deg) - test_params["orbit"][3], (inc_f * u.rad).to(u.deg) - test_params["orbit"][2], (argp_f * u.rad).to(u.deg) - test_params["orbit"][4], ], [test_params["raan"], test_params["inc"], test_params["argp"]], rtol=1e-1, )
def test_sso_disposal_numerical(ecc_0, ecc_f): a_0 = Earth.R.to(u.km).value + 900 # km f = 2.4e-7 # km / s2, assumed constant # Retrieve r and v from initial orbit s0 = Orbit.from_classical(Earth, a_0 * u.km, ecc_0 * u.one, 0 * u.deg, 0 * u.deg, 0 * u.deg, 0 * u.deg) a_d, _, t_f = change_ecc_quasioptimal(s0, ecc_f, f) # Propagate orbit sf = s0.propagate(t_f * u.s, method=cowell, ad=a_d, rtol=1e-8) assert_allclose(sf.ecc.value, ecc_f, rtol=1e-4, atol=1e-4)
def test_propagation_hyperbolic_zero_time_returns_same_state(): ss0 = Orbit.from_classical( Earth, -27112.5464 * u.km, 1.25 * u.one, 0 * u.deg, 0 * u.deg, 0 * u.deg, 0 * u.deg, ) r0, v0 = ss0.rv() tof = 0 * u.s ss1 = ss0.propagate(tof) r, v = ss1.rv() assert_allclose(r.value, r0.value) assert_allclose(v.value, v0.value)
def test_geo_cases_numerical(ecc_0, ecc_f): a = 42164 # km inc_0 = 0.0 # rad, baseline inc_f = (20.0 * u.deg).to(u.rad).value # rad argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 # km / s2 # Retrieve r and v from initial orbit s0 = Orbit.from_classical( Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg ) a_d, _, _, t_f = change_inc_ecc(s0, ecc_f, inc_f, f) # Propagate orbit sf = s0.propagate(t_f * u.s, method=cowell, ad=a_d, rtol=1e-8) assert_allclose(sf.ecc.value, ecc_f, rtol=1e-2, atol=1e-2) assert_allclose(sf.inc.to(u.rad).value, inc_f, rtol=1e-1)
def test_geo_cases_beta_dnd_delta_v(ecc_0, inc_f, expected_beta, expected_delta_V): a = 42164 # km ecc_f = 0.0 inc_0 = 0.0 # rad, baseline argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 # km / s2, unused inc_f = np.radians(inc_f) expected_beta = np.radians(expected_beta) s0 = Orbit.from_classical( Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg ) _, delta_V, beta, _ = change_inc_ecc(s0, ecc_f, inc_f, f) assert_allclose(delta_V, expected_delta_V, rtol=1e-2) assert_allclose(beta, expected_beta, rtol=1e-2)
def test_J3_propagation_Earth(test_params): # Nai-ming Qi, Qilong Sun, Yong Yang, (2018) "Effect of J3 perturbation on satellite position in LEO", # Aircraft Engineering and Aerospace Technology, Vol. 90 Issue: 1, # pp.74-86, https://doi.org/10.1108/AEAT-03-2015-0092 a_ini = 8970.667 * u.km ecc_ini = 0.25 * u.one raan_ini = 1.047 * u.rad nu_ini = 0.0 * u.rad argp_ini = 1.0 * u.rad inc_ini = test_params['inc'] k = Earth.k.to(u.km**3 / u.s**2).value orbit = Orbit.from_classical(Earth, a_ini, ecc_ini, inc_ini, raan_ini, argp_ini, nu_ini) tof = (10.0 * u.day).to(u.s).value r_J2, v_J2 = cowell(orbit, np.linspace(0, tof, int(1e+3)), ad=J2_perturbation, J2=Earth.J2.value, R=Earth.R.to(u.km).value, rtol=1e-8) a_J2J3 = lambda t0, u_, k_: J2_perturbation(t0, u_, k_, J2=Earth.J2.value, R=Earth.R.to(u.km).value) + \ J3_perturbation(t0, u_, k_, J3=Earth.J3.value, R=Earth.R.to(u.km).value) r_J3, v_J3 = cowell(orbit, np.linspace(0, tof, int(1e+3)), ad=a_J2J3, rtol=1e-8) a_values_J2 = np.array([rv2coe(k, ri, vi)[0] / (1.0 - rv2coe(k, ri, vi)[1] ** 2) for ri, vi in zip(r_J2, v_J2)]) a_values_J3 = np.array([rv2coe(k, ri, vi)[0] / (1.0 - rv2coe(k, ri, vi)[1] ** 2) for ri, vi in zip(r_J3, v_J3)]) da_max = np.max(np.abs(a_values_J2 - a_values_J3)) ecc_values_J2 = np.array([rv2coe(k, ri, vi)[1] for ri, vi in zip(r_J2, v_J2)]) ecc_values_J3 = np.array([rv2coe(k, ri, vi)[1] for ri, vi in zip(r_J3, v_J3)]) decc_max = np.max(np.abs(ecc_values_J2 - ecc_values_J3)) inc_values_J2 = np.array([rv2coe(k, ri, vi)[2] for ri, vi in zip(r_J2, v_J2)]) inc_values_J3 = np.array([rv2coe(k, ri, vi)[2] for ri, vi in zip(r_J3, v_J3)]) dinc_max = np.max(np.abs(inc_values_J2 - inc_values_J3)) assert_quantity_allclose(dinc_max, test_params['dinc_max'], rtol=1e-1, atol=1e-7) assert_quantity_allclose(decc_max, test_params['decc_max'], rtol=1e-1, atol=1e-7) try: assert_quantity_allclose(da_max * u.km, test_params['da_max']) except AssertionError as exc: pytest.xfail('this assertion disagrees with the paper')
def test_soyuz_standard_gto_numerical(): # Data from Soyuz Users Manual, issue 2 revision 0 r_a = (Earth.R + 35950 * u.km).to(u.km).value r_p = (Earth.R + 250 * u.km).to(u.km).value a = (r_a + r_p) / 2 # km ecc = r_a / a - 1 argp_0 = (178 * u.deg).to(u.rad).value # rad argp_f = (178 * u.deg + 5 * u.deg).to(u.rad).value # rad f = 2.4e-7 # km / s2 k = Earth.k.decompose([u.km, u.s]).value optimal_accel = guidance_law(f) _, t_f = extra_quantities(k, a, ecc, argp_0, argp_f, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical( Earth, a * u.km, (r_a / a - 1) * u.one, 6 * u.deg, 188.5 * u.deg, 178 * u.deg, 0 * u.deg ) 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=optimal_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.argp.to(u.rad).value, argp_f, rtol=1e-4)
def test_geo_cases_numerical(ecc_0, ecc_f): a = 42164 # km inc_0 = 0.0 # rad, baseline inc_f = (20.0 * u.deg).to(u.rad).value # rad argp = 0.0 # rad, the method is efficient for 0 and 180 f = 2.4e-7 # km / s2 k = Earth.k.decompose([u.km, u.s]).value _, _, t_f = extra_quantities(k, a, ecc_0, ecc_f, inc_0, inc_f, argp, f) # Retrieve r and v from initial orbit s0 = Orbit.from_classical( Earth, a * u.km, ecc_0 * u.one, inc_0 * u.deg, 0 * u.deg, argp * u.deg, 0 * u.deg ) r0, v0 = s0.rv() optimal_accel = guidance_law(s0, ecc_f, inc_f, f) # Propagate orbit r, v = cowell(k, r0.to(u.km).value, v0.to(u.km / u.s).value, t_f, ad=optimal_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.ecc.value, ecc_f, rtol=1e-2, atol=1e-2) assert_allclose(sf.inc.to(u.rad).value, inc_f, rtol=1e-1)
"""Example data. """ from astropy import time from astropy import units as u from poliastro.bodies import Sun, Earth from poliastro.twobody import Orbit # Taken from Plyades (c) 2012 Helge Eichhorn (MIT License) iss = Orbit.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 = Orbit.from_classical( Earth, 26600 * u.km, 0.75 * u.one, 63.4 * u.deg, 0 * u.deg, 270 * u.deg, 80 * u.deg ) churi = Orbit.from_classical( Sun, 3.46250 * u.AU, 0.64 * u.one, 7.04 * u.deg, 50.1350 * u.deg, 12.8007 * u.deg, 63.89 * u.deg, time.Time("2015-11-05 12:00", scale='utc') )
from poliastro.twobody import Orbit iss = Orbit.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"), ) """ISS orbit example Taken from Plyades (c) 2012 Helge Eichhorn (MIT License) """ molniya = Orbit.from_classical( Earth, 26600 * u.km, 0.75 * u.one, 63.4 * u.deg, 0 * u.deg, 270 * u.deg, 80 * u.deg ) """Molniya orbit example""" _r_a = Earth.R + 35950 * u.km _r_p = Earth.R + 250 * u.km _a = (_r_a + _r_p) / 2 soyuz_gto = Orbit.from_classical( Earth, _a, _r_a / _a - 1, 6 * u.deg, 188.5 * u.deg, 178 * u.deg, 0 * u.deg ) """Soyuz geostationary transfer orbit (GTO) example Taken from Soyuz User's Manual, issue 2 revision 0 """