def plot_solar_system(outer=True, epoch=None, use_3d=False): """ Plots the whole solar system in one single call. .. versionadded:: 0.9.0 Parameters ------------ outer : bool, optional Whether to print the outer Solar System, default to True. epoch : ~astropy.time.Time, optional Epoch value of the plot, default to J2000. use_3d : bool, optional Produce 3D plot, default to False. """ bodies = [Mercury, Venus, Earth, Mars] if outer: bodies.extend([Jupiter, Saturn, Uranus, Neptune]) if use_3d: op = OrbitPlotter3D() # type: Union[OrbitPlotter3D, OrbitPlotter2D] else: op = OrbitPlotter2D() op.set_frame(*Orbit.from_body_ephem(Earth, epoch).pqw()) # type: ignore for body in bodies: orb = Orbit.from_body_ephem(body, epoch) op.plot(orb, label=str(body)) return op
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_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)
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)
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: Orbit.from_vectors(Sun, _d, wrong_v) assert ("UnitsError: Argument 'v' to function 'from_vectors' must be in units convertible to 'm / s'." in excinfo.exconly())
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)
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_from_ephem_raises_warning_if_time_is_not_tdb_with_proper_time(recwarn): body = Earth epoch = Time("2017-09-29 07:31:26", scale="utc") expected_epoch_string = "2017-09-29 07:32:35.182" # epoch.tdb.value Orbit.from_body_ephem(body, epoch) w = recwarn.pop(TimeScaleWarning) assert expected_epoch_string in str(w.message)
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_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_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_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_propagation_mean_motion_parabolic(): # example from Howard Curtis (3rd edition), section 3.5, problem 3.15 p = 2.0 * 6600 * u.km _a = 0.0 * u.deg orbit = Orbit.parabolic(Earth, p, _a, _a, _a, _a) orbit = orbit.propagate(0.8897 / 2.0 * u.h, method=mean_motion) _, _, _, _, _, nu0 = rv2coe(Earth.k.to(u.km**3 / u.s**2).value, orbit.r.to(u.km).value, orbit.v.to(u.km / u.s).value) assert_quantity_allclose(nu0, np.deg2rad(90.0), rtol=1e-4) orbit = Orbit.parabolic(Earth, p, _a, _a, _a, _a) orbit = orbit.propagate(36.0 * u.h, method=mean_motion) assert_quantity_allclose(norm(orbit.r), 304700.0 * u.km, rtol=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.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_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 = Orbit.parabolic(attractor, _d, _a, _a, _a, _a) assert_almost_equal(ss.energy.value, 0.0)
def hill_radius(body, a=None, e=None): """Approximated radius of the Hill Sphere of Influence (SOI) for a body. Parameters ---------- body : `~poliastro.bodies.Body` Astronomical body which the SOI's radius is computed for. a : float, optional Semimajor axis of the body's orbit, default to None (will be computed from ephemerides). e : float, optional Eccentricity of the body's orbit, default to 0 (will be computed from ephemerides). Returns ------- astropy.units.quantity.Quantity Approximated radius of the Sphere of Influence (SOI) [m] """ # Compute semimajor and eccentricity axis at epoch J2000 for the body if it was not # introduced by the user if a is None or e is None: ss = Orbit.from_body_ephem(body, J2000_TDB) a = a if a is not None else ss.a e = e if e is not None else ss.ecc mass_ratio = body.k / (3 * body.parent.k) r_SOI = a * (1 - e) * (mass_ratio ** (1 / 3)) return r_SOI.decompose()
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 compute_soi(body, a=None): """Approximated radius of the Laplace Sphere of Influence (SOI) for a body. Parameters ---------- body : `~poliastro.bodies.Body` Astronomical body which the SOI's radius is computed for. a : float, optional Semimajor axis of the body's orbit, default to None (will be computed from ephemerides). Returns ------- astropy.units.quantity.Quantity Approximated radius of the Sphere of Influence (SOI) [m] """ # Compute semimajor axis at epoch J2000 for the body if it was not # introduced by the user if a is None: try: a = Orbit.from_body_ephem(body, J2000).a except KeyError: raise RuntimeError( """To compute the semimajor axis for Moon and Pluto use the JPL ephemeris: >>> from astropy.coordinates import solar_system_ephemeris >>> solar_system_ephemeris.set("jpl")""") r_SOI = a * (body.k / body.parent.k) ** (2 / 5) return r_SOI.decompose()
def test_J2_propagation_Earth(): # from Curtis example 12.2: r0 = np.array([-2384.46, 5729.01, 3050.46]) # km v0 = np.array([-7.36138, -2.98997, 1.64354]) # km/s orbit = Orbit.from_vectors(Earth, r0 * u.km, v0 * u.km / u.s) tofs = [48.0] * u.h rr, vv = cowell( Earth.k, orbit.r, orbit.v, tofs, ad=J2_perturbation, J2=Earth.J2.value, R=Earth.R.to(u.km).value, ) k = Earth.k.to(u.km ** 3 / u.s ** 2).value _, _, _, raan0, argp0, _ = rv2coe(k, r0, v0) _, _, _, raan, argp, _ = rv2coe(k, rr[0].to(u.km).value, vv[0].to(u.km / u.s).value) raan_variation_rate = (raan - raan0) / tofs[0].to(u.s).value argp_variation_rate = (argp - argp0) / tofs[0].to(u.s).value raan_variation_rate = (raan_variation_rate * u.rad / u.s).to(u.deg / u.h) argp_variation_rate = (argp_variation_rate * u.rad / u.s).to(u.deg / u.h) assert_quantity_allclose(raan_variation_rate, -0.172 * u.deg / u.h, rtol=1e-2) assert_quantity_allclose(argp_variation_rate, 0.282 * u.deg / u.h, rtol=1e-2)
def test_cowell_works_with_small_perturbations(): r0 = [-2384.46, 5729.01, 3050.46] * u.km v0 = [-7.36138, -2.98997, 1.64354] * u.km / u.s r_expected = [ 13179.39566663877121754922, -13026.25123408228319021873, -9852.66213692844394245185, ] * u.km v_expected = ( [2.78170542314378943516, 3.21596786944631274352, 0.16327165546278937791] * u.km / u.s ) initial = Orbit.from_vectors(Earth, r0, v0) def accel(t0, state, k): v_vec = state[3:] norm_v = (v_vec * v_vec).sum() ** 0.5 return 1e-5 * v_vec / norm_v final = initial.propagate(3 * u.day, method=cowell, ad=accel) assert_quantity_allclose(final.r, r_expected) assert_quantity_allclose(final.v, v_expected)
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_orbit_accepts_ecliptic_plane(): r = [1E+09, -4E+09, -1E+09] * u.km v = [5E+00, -1E+01, -4E+00] * u.km / u.s ss = Orbit.from_vectors(Sun, r, v, plane=Planes.EARTH_ECLIPTIC) assert ss.frame.is_equivalent_frame(HeliocentricEclipticJ2000(obstime=J2000))
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)
def test_parabolic_has_proper_eccentricity(): attractor = Earth _d = 1.0 * u.AU # Unused distance _a = 1.0 * u.deg # Unused angle expected_ecc = 1.0 * u.one ss = Orbit.parabolic(attractor, _d, _a, _a, _a, _a) assert_allclose(ss.ecc, expected_ecc)
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 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_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 = Orbit.parabolic(attractor, _d, _a, _a, _a, _a) assert_almost_equal(ss.ecc, expected_ecc)
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 j3_earth(initial, time, f_time): # perturbation for oblateness R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value #s0 = Orbit.from_classical(Earth, x[0] * u.km, x[1] * u.one, x[4] * u.deg, * u.deg, x[3] * u.deg, 0 * u.deg, epoch=Time(0, format='jd', scale='tdb')) #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 = ((np.pi / 4.0) * (u.m**2)).to(u.km**2).value # km^2 m = 100 # kg B = C_D * A / m J3 = Earth.J3.value print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: J3 = input("Enter J3 constant:") R = input("Enter radius of earth in km:") datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) rr = propagate(initial, tofs, method=cowell, ad=J3_perturbation, J3=J3, R=R) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
# a: semieix major # ecc: excentricitat # inc: inclinacio respecte la horizontal(sera 0 en totes les orbites # ja que es troben en el mateix pla per guio del treball) # raan: inclinacio respecte la vertical # argp: argument del periheli # nu: posicio punt a = 0.999855 * u.AU ecc = 0 * u.one inc = 0 * u.deg raan = 0 * u.deg argp = 0 * u.deg nu = 0 * u.deg Terra = Orbit.from_classical(Sun, a, ecc, inc, raan, argp, nu) a = 5.20336301 * u.AU ecc = 0 * u.one inc = 0 * u.deg raan = 0 * u.deg argp = 0 * u.deg nu = 163 * u.deg Jupiter = Orbit.from_classical(Sun, a, ecc, inc, raan, argp, nu) a = 9.53707032 * u.AU ecc = 0 * u.one inc = 0 * u.deg raan = 0 * u.deg argp = 0 * u.deg
"""Example data. """ from astropy import time, units as u from poliastro.bodies import Earth, Sun 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
def get_vectors_from_orbit(ss: Orbit, delta_seconds: float) -> np.array: ss = ss.propagate(delta_seconds * u.s) return np.concatenate([ss.r.to_value(), ss.v.to_value()])
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
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
from poliastro.twobody import Orbit from poliastro.maneuver import Maneuver # In[2]: 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)
def propagate_to_desc_node(o: Orbit): """ Propagates the orbit to the descending node.""" _, dn, _, _ = calculate_nodes_dist(o) o_f = o.propagate_to_anomaly(dn) return o_f
def propagate_to_asc_node(o: Orbit): """ Propagates the orbit to the ascending node.""" an, _, _, __ = calculate_nodes_dist(o) o_f = o.propagate_to_anomaly(an) return o_f
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=2e-4, m=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_sample_big_orbits(method): # See https://github.com/poliastro/poliastro/issues/265 ss = Orbit.from_vectors(Sun, [-9018878.6, -94116055, 22619059] * u.km, [-49.950923, -12.948431, -4.2925158] * u.km / u.s) times, positions = ss.sample(15, method=method) assert len(times) == len(positions) == 15
def atmd_earth(initial, time, f_time): # perturbation for atmospheric drag R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value #s0 = Orbit.from_classical(Earth, x[0] * u.km, x[1] * u.one, x[4] * u.deg, * u.deg, x[3] * u.deg, 0 * u.deg, epoch=Time(0, format='jd', scale='tdb')) #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 = ((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 print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: m = input("Enter mass of the body in kg:") R = input("Enter radius of earth in km:") C_D = input("Enter C_D(dimension):") H0 = input("Enter atmospheric parameter H0:") #rho0=input("Enter atmospheric parameter rho0:") R = R * u.km H0 = H0 * u.km #rho0=rho0*(u.kg / u.km ** 3) datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) #print("tofs:") #print(tofs) #print("ie:") #print(initial.epoch.iso) rr = propagate( initial, tofs, method=cowell, ad=atmospheric_drag, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0, ) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def custom(initial, choice, state, time, f_time): # requires modification and validation R = Earth.R.to(u.km).value k = Earth.k.to(u.km**3 / u.s**2).value #s0 = Orbit.from_classical(Earth, x[0] * u.km, x[1] * u.one, x[4] * u.deg, * u.deg, x[3] * u.deg, 0 * u.deg, epoch=Time(0, format='jd', scale='tdb')) #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 = ((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 #J2,J3 parameters J3 = Earth.J3.value J2 = Earth.J2.value datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) if (choice == '7'): rr = propagate( initial, tofs, method=cowell, ad=accel, #k=k, ) elif (choice == '5'): rr = propagate( initial, tofs, method=cowell, ad=a_d_1, #k=k, J2=J2, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0) elif (choice == '6'): rr = propagate( initial, tofs, method=cowell, ad=a_d_2, #k=k, J3=J3, R=R, C_D=C_D, A=A, m=m, H0=H0, rho0=rho0) else: pass print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) print("") #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
def go_to_mars(offset=0., tof_=6000.): # Initial data N = 50 date_launch = time.Time('2011-11-26 15:02', scale='utc') + offset * u.day #date_arrival = time.Time('2012-08-06 05:17', scale='utc') tof = tof_ * u.h # Calculate vector of times from launch and arrival date_arrival = date_launch + tof dt = (date_arrival - date_launch) / N # Idea from http://docs.astropy.org/en/stable/time/#getting-started times_vector = date_launch + dt * np.arange(N + 1) rr_earth, vv_earth = get_body_ephem("earth", times_vector) rr_mars, vv_mars = get_body_ephem("mars", times_vector) # Compute the transfer orbit! r0 = rr_earth[:, 0] rf = rr_mars[:, -1] (va, vb), = iod.lambert(Sun.k, r0, rf, tof) ss0_trans = Orbit.from_vectors(Sun, r0, va, date_launch) ssf_trans = Orbit.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(times_vector)): tof = (times_vector[ii] - times_vector[0]).to(u.day) rr_trans[:, ii] = ss0_trans.propagate(tof).r # Better compute backwards date_final = date_arrival - 1 * u.year dt2 = (date_final - date_launch) / N times_rest_vector = date_launch + dt2 * np.arange(N + 1) rr_earth_rest, _ = get_body_ephem("earth", times_rest_vector) rr_mars_rest, _ = get_body_ephem("mars", times_rest_vector) # Plot figure fig = plt.gcf() ax = plt.gca() ax.cla() def plot_body(ax, r, color, size, border=False, **kwargs): """Plots body in axes object. """ return ax.plot(*r[:, None], marker='o', color=color, ms=size, mew=int(border), **kwargs) # I like color color_earth0 = '#3d4cd5' color_earthf = '#525fd5' color_mars0 = '#ec3941' color_marsf = '#ec1f28' color_sun = '#ffcc00' color_orbit = '#888888' color_trans = '#444444' # Plotting orbits is easy! ax.plot(*rr_earth.to(u.km).value, color=color_earth0) ax.plot(*rr_mars.to(u.km).value, color=color_mars0) ax.plot(*rr_trans.to(u.km).value, color=color_trans) ax.plot(*rr_earth_rest.to(u.km).value, ls='--', color=color_orbit) ax.plot(*rr_mars_rest.to(u.km).value, ls='--', color=color_orbit) # But plotting planets feels even magical! plot_body(ax, np.zeros(3), color_sun, 16) plot_body(ax, r0.to(u.km).value, color_earth0, 8) plot_body(ax, rr_earth[:, -1].to(u.km).value, color_earthf, 8) plot_body(ax, rr_mars[:, 0].to(u.km).value, color_mars0, 8) plot_body(ax, rf.to(u.km).value, color_marsf, 8) # Add some text #ax.text(-0.75e8, -3.5e8, -1.5e8, "MSL mission:\nfrom Earth to Mars", size=20, ha='center', va='center', bbox={"pad": 30, "lw": 0, "fc": "w"}) ax.text(r0[0].to(u.km).value * 1.4, r0[1].to(u.km).value * 0.4, r0[2].to(u.km).value * 1.25, f"Earth at launch\n({date_launch.datetime:%b %d})", ha="left", va="bottom", backgroundcolor='#ffffff') ax.text(rf[0].to(u.km).value * 0.7, rf[1].to(u.km).value * 1.1, rf[2].to(u.km).value, f"Mars at arrival\n({date_arrival.datetime:%b %d})", ha="left", va="top", backgroundcolor='#ffffff') ax.text(-1.9e8, 8e7, 0, "Transfer\norbit", ha="right", va="center", backgroundcolor='#ffffff') # Tune axes ax.set_xlim(-3e8, 3e8) ax.set_ylim(-3e8, 3e8) ax.set_zlim(-3e8, 3e8) ax.view_init(30, 260)
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)
def halley(): return Orbit.from_vectors( Sun, [-9018878.63569932, -94116054.79839276, 22619058.69943215] * u.km, [-49.95092305, -12.94843055, -4.29251577] * u.km / u.s, )
def test_orbit_from_ephem_with_no_epoch_is_today(): # This is not that obvious http://stackoverflow.com/q/6407362/554319 body = Earth ss = Orbit.from_body_ephem(body) assert (time.Time.now() - ss.epoch).sec < 1
"""Example data. """ from astropy import time, units as u from poliastro.bodies import Earth, Sun 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( attractor=Earth, a=26600 * u.km, ecc=0.75 * u.one, inc=63.4 * u.deg, raan=0 * u.deg, argp=270 * u.deg, nu=80 * u.deg, ) """Molniya orbit example"""
julianday = np.empty([0]) i = 0 for i in range(yd.shape[1]): mon, day, hr, minute, sec = daysToMonDayHrMinSec(yd[0, i], yd[1, i]) julianday = np.hstack( [julianday, jday(yd[0, i], mon, day, hr, minute, sec)]) epoch_tles = Time(julianday, format='jd', scale='ut1') #Estimate mean state and state covariance from TLEs nu = D_to_nu(coe[5, yd.shape[1] - 1]) Xf_tle_n = Orbit.from_classical(Earth, coe[0, yd.shape[1] - 1] * u.m, coe[1, yd.shape[1] - 1] * u.one, coe[2, yd.shape[1] - 1] * u.deg, coe[3, yd.shape[1] - 1] * u.deg, coe[4, yd.shape[1] - 1] * u.deg, nu * u.deg, epoch=epoch_tles[yd.shape[1] - 1]) Xf_n = mean_motion(Earth.k, Xf_tle_n.r, Xf_tle_n.v, np.linspace(0, 0, num=1) * u.s) # fill orbit i = 0 X_res = np.empty((6, 1)) for i in range(yd.shape[1] - 1): nu = D_to_nu(coe[5, i]) X0_tle_i = Orbit.from_classical(Earth, coe[0, i] * u.m, coe[1, i] * u.one, coe[2, i] * u.deg,
def get_orbital_elements_from_vectors(x, y, z, Vx, Vy, Vz, total_seconds): r = [x, y, z] * u.km v = [Vx, Vy, Vz] * u.km / u.s dt = datetime(2014, 1, 1) + timedelta(seconds=total_seconds) ss = Orbit.from_vectors(Earth, r, v, epoch=Time(dt)) return ss
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)
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 get_orbit_from_orbital_elements(orbital_elements: np.array, seconds_from_01_01: float) -> Orbit: return Orbit.from_classical(Earth, orbital_elements[0] * u.km, orbital_elements[1] * u.one, orbital_elements[2] * u.rad, \ orbital_elements[3] * u.rad, orbital_elements[4] * u.rad, orbital_elements[5] * u.rad,\ epoch=Time(datetime(2014, 1, 1) + timedelta(seconds=seconds_from_01_01)))
a = 6878.137 * u.km ecc = 0 * u.one #inc = 0.872699533 * u.rad #raan = 6.280724393 * u.rad #argp = 0 * u.rad #nu = 6.280986192 * u.rad # noinspection PyUnresolvedReferences inc = 50.002 * u.deg # noinspection PyUnresolvedReferences raan = 359.859 * u.deg # noinspection PyUnresolvedReferences argp = 0 * u.deg # noinspection PyUnresolvedReferences nu = 359.874 * u.deg date_epoch = Time("2019-09-01 00:00", scale='utc') ss = Orbit.from_classical(Earth, a, ecc, inc, raan, argp, nu, date_epoch) # 2448122.5 # Simulation Loop Starts for delta_t in range(0, 60000, 100): print("Quaternion after ", delta_t, "milliseconds is: "), for i in range(0, 4): q[i] = q[i] + (rate_of_change[i] * delta_t * 0.001) mod_q = math.sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2) for i in range(0, 4): q[i] = q[i] / mod_q print(" ", q[i], " "), print("") print() # q conjugate q_star = [q[0], -q[1], -q[2], -q[3]]
from bodies import Earth, Sun from poliastro.twobody import Orbit from matplotlib import pylab as plt import mpl_scatter_density # Data for Mars at J2000 from JPL HORIZONS a = 1.523679 * u.AU #a = 1.0779 * u.AU ecc = 0.093315 * u.one inc = 1.85 * u.deg raan = 49.562 * u.deg #this is Right ascension of the ascending node argp = 286.537 * u.deg nu = 23.33 * u.deg #True anomaly mars = Orbit.from_classical(Sun, a, ecc, inc, raan, argp, nu) #then plot from poliastro.plotting import StaticOrbitPlotter #op = OrbitPlotter() #op.plot(mars, label="Mars") #----------- #plot multiple #redefining the elements here, sorry that's sloppy a = 1.0779 * u.AU ecc = 0.8268 * u.one inc = 22.852 * u.deg raan = 88.0822 * u.deg
time_obj = Time(time, format="iso", scale="utc") time_p_obj = Time(time_p, format="iso", scale="utc") #print("chk:") #print(time_obj.tdb.jd) nu = time2truean(x0[0], x0[1], mu, time_obj.tdb.jd, x0[2]) eccentric_anomaly = truean2eccan(x0[1], nu) nu = np.rad2deg(nu) kep_i = (x0[0], x0[1], x0[4], x0[3], x0[5], nu) kep_i = np.asarray(kep_i) initial_state = kep_state(kep_i.reshape(-1, 1)) initial = Orbit.from_classical(Earth, x0[0] * u.km, x0[1] * u.one, x0[4] * u.deg, x0[5] * u.deg, x0[3] * u.deg, nu * u.deg, epoch=Time(time, format='iso', scale='utc')) else: obs_arr = [int(item) for item in args.obs_array.split(',')] x0 = gauss_method_sat(args.file_path, obs_arr=obs_arr, bodyname=args.body_name, r2_root_ind_vec=args.root_index, refiters=args.iterations, plot=False) time = Time(x0[7], format='jd').iso
def third_body_moon( initial, time, f_time): # propogate under perturbation of a third body(moon) # database keeping positions of bodies in Solar system over time x_ephem = "de432s" questions = [ inquirer.List( 'Ephemerides', message= "Select ephemerides[de432s(default,small in size,faster)','de430(more precise)]:", choices=['de432s', 'de430'], ), ] answers = inquirer.prompt(questions) x_ephem = answers["Ephemerides"] solar_system_ephemeris.set(x_ephem) #epoch = Time(time, format='iso', scale='utc') # setting the exact event date is important epoch = Time(time, format='iso').jd f_time_1 = Time(f_time, format='iso').jd # create interpolant of 3rd body coordinates (calling in on every iteration will be just too slow) #check body_r = build_ephem_interpolant( Moon, 28 * u.day, (epoch * u.day, f_time_1 * u.day), rtol=1e-2 #check ) k_third = Moon.k.to(u.km**3 / u.s**2).value x = 400 print( "Use default constants or you want to customize?\n1.Default.\n2.Custom." ) check = input() if (check == '1'): pass else: k_third = input("Enter moon's gravity:") x = input( "Multiply Moon's gravity by X times so that effect is visible,input X:" ) datetimeFormat = '%Y-%m-%d %H:%M:%S.%f' diff =datetime.strptime(str(f_time), datetimeFormat)\ - datetime.strptime(str(time), datetimeFormat) print("Time difference:") print(diff) tofs = TimeDelta(f_time - time) tofs = TimeDelta(np.linspace(0, 31 * u.day, num=1)) # multiply Moon gravity by x so that effect is visible :) rr = propagate( initial, tofs, method=cowell, rtol=1e-6, ad=third_body, k_third=x * k_third, third_body=body_r, ) print("") print("Positions and velocity vectors are:") #print(str(rr.x)) #print([float(s) for s in re.findall(r'-?\d+\.?\d*',str(rr.x))]) r = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.z))][0]] * u.km v = [[float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_x))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_y))][0], [float(s) for s in re.findall(r'-?\d+\.?\d*', str(rr.v_z))][0]] * u.km / u.s f_orbit = Orbit.from_vectors(Earth, r, v) print(r) print(v) #f_orbit.plot() print("") print("Orbital elements:") print(f_orbit.classical()) #print("") #print(f_orbit.ecc) plotOrbit((f_orbit.a.value), (f_orbit.ecc.value), (f_orbit.inc.value), (f_orbit.raan.value), (f_orbit.argp.value), (f_orbit.nu.value))
date_launch = time.Time("2011-11-26 15:02", scale="utc").tdb date_arrival = time.Time("2012-08-06 05:17", scale="utc").tdb # To compute the transfer orbit, we have the useful function `lambert` : according to a theorem with the same name, *the transfer orbit between two points in space only depends on those two points and the time it takes to go from one to the other*. We could make use of the raw algorithms available in `poliastro.iod` for solving this but working with the `poliastro.maneuvers` is even easier! # # We just need to create the orbits for each one of the planets at the specific departure and arrival dates. # In[5]: earth = Ephem.from_body(Earth, time_range(date_launch, end=date_arrival)) mars = Ephem.from_body(Mars, time_range(date_launch, end=date_arrival)) # In[6]: # Solve for departure and target orbits ss_earth = Orbit.from_ephem(Sun, earth, date_launch) ss_mars = Orbit.from_ephem(Sun, mars, date_arrival) # We can now solve for the maneuver that will take us from Earth to Mars. After solving it, we just need to apply it to the departure orbit to solve for the transfer one. # In[7]: # Solve for the transfer maneuver man_lambert = Maneuver.lambert(ss_earth, ss_mars) # Get the transfer and final orbits ss_trans, ss_target = ss_earth.apply_maneuver(man_lambert, intermediate=True) # Let's plot this transfer orbit in 3D! # In[8]:
# print ("a: " + str(perDiff(a, aJPL)) + "%") # print ("e: " + str(perDiff(e, eJPL)) + "%") # print ("i: " + str(perDiff(i, iJPL)) + "%") # print ("Lon ascending node: " + str(perDiff(lOmega[0], lOmegaJPL)) + "%") # print ("Perihelion: " + str(perDiff(aPerihelion, omegaJPL)) + "%") # print ("M: " + str(perDiff(M, MJPL)) + "%") a = a * units.AU ecc = e * units.one inc = i * units.deg raan = lOmega[0] * units.deg argp = aPerihelion * units.deg nu = v * units.deg epoch = time.Time(t2, format='jd', scale='utc') earth_orbit = Orbit.from_body_ephem(Earth) earth_orbit = earth_orbit.propagate(time.Time(t2, format='jd', scale='tdb'), rtol=1e-10) magellan_orbit = neows.orbit_from_name('2018ez2') magellan_orbit = magellan_orbit.propagate(time.Time(t2, format='jd', scale='tdb'), rtol=1e-10) estimated_orbit = Orbit.from_classical(Sun, a, ecc, inc, raan, argp, nu, epoch) op = OrbitPlotter() op.plot(earth_orbit, label='Earth') op.plot(magellan_orbit, label='2018 EZ2') op.plot(estimated_orbit, label='Estimated') plt.show()
def propagate_to_periapsis(o: Orbit): """ Propagate given orbit to its periapsis. """ if o.nu != 0 * u.deg: o_f = o.propagate_to_anomaly(0 * u.deg) return o_f return o